using System; using System.Collections.Generic; using JetBrains.Application; using JetBrains.Application.Progress; using JetBrains.ProjectModel; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.Tree; using JetBrains.ReSharper.UnitTestExplorer; using JetBrains.Util.DataStructures; using MbUnit.ReSharperRunner.Elements; namespace MbUnit.ReSharperRunner.Explorer { internal class MbUnitFileExplorer : IRecursiveElementProcessor { private readonly string assemblyPath; private readonly UnitTestElementLocationConsumer elementConsumer; private readonly IFile file; private readonly Dictionary2 fixtures; private readonly CheckForInterrupt interrupted; private readonly Dictionary2 orders; private readonly IProject project; private readonly IUnitTestProvider testProvider; private FileHelper helper; public MbUnitFileExplorer(IUnitTestProvider testProvider, UnitTestElementLocationConsumer consumer, IFile file, CheckForInterrupt interrupted) { fixtures = new Dictionary2(); orders = new Dictionary2(); if (file == null) { throw new ArgumentNullException("file"); } if (testProvider == null) { throw new ArgumentNullException("testProvider"); } elementConsumer = consumer; this.testProvider = testProvider; this.file = file; helper = new FileHelper(file); this.interrupted = interrupted; project = this.file.ProjectFile.GetProject(); assemblyPath = UnitTestManager.GetOutputAssemblyPath(project).FullPath; } #region IRecursiveElementProcessor Members public bool InteriorShouldBeProcessed(IElement element) { if (element is ITypeMemberDeclaration) { return (element is ITypeDeclaration); } return true; } public void ProcessBeforeInterior(IElement element) { var declaration = element as IDeclaration; if (declaration != null) { MbUnitTestElementBase testElement = null; IDeclaredElement declaredElement = declaration.DeclaredElement; var testClass = declaredElement as IClass; if ((testClass != null) && FileHelper.IsTestFixture(testClass)) { MbUnitTestFixtureElement fixtureElement; if (!fixtures.ContainsKey(testClass)) { fixtureElement = new MbUnitTestFixtureElement(testProvider, project, testClass.CLRName, assemblyPath, FileHelper.GetTestFixtureName(testClass)); fixtures.Add(testClass, fixtureElement); orders.Add(testClass, 0); var categories = new List(); helper.CollectTestFixtureCategories(testClass, ref categories); fixtureElement.AssignCategories(categories); } else { fixtureElement = fixtures[testClass]; } testElement = fixtureElement; int order = 0; AppendTests(fixtureElement, testClass.GetSuperTypes(), ref order); } IMethod method = declaredElement as IMethod; if ((method != null) && FileHelper.IsTestMethod(method)) { ITypeElement type = method.GetContainingType(); if (type != null) { MbUnitTestFixtureElement fixtureElement = fixtures[type]; if (fixtureElement != null) { int order = orders[type] + 1; orders[type] = order; testElement = new MbUnitTestElement(testProvider, fixtureElement, project, type.CLRName, FileHelper.GetMethodName(method), FileHelper.GetTestName(method)); List testCategories = new List(); CopyTestCategories(fixtureElement, testCategories); helper.CollectTestMethodCategories(method, ref testCategories); testElement.AssignCategories(testCategories); if (helper.HasChildTest(method)) { foreach (string childName in helper.GetChildNames(method)) { MbUnitChildTestElement childElement = new MbUnitChildTestElement((MbUnitTestElement) testElement, testProvider, project, type.CLRName, childName, FileHelper.GetTestName(method)); // childElement.AssignCategories(testCategories); } } } } } if (testElement != null) { UnitTestElementDisposition disposition = new UnitTestElementDisposition(testElement, file.ProjectFile, declaration.GetNameRange(), declaration.GetDocumentRange().TextRange); elementConsumer(disposition); } } } public void ProcessAfterInterior(IElement element) { } public bool ProcessingIsFinished { get { if (interrupted()) { throw new ProcessCancelledException(); } return false; } } #endregion private void AppendTests(MbUnitTestFixtureElement fixtureElement, IEnumerable types, ref int order) { foreach (IDeclaredType type in types) { ITypeElement typeElement = type.GetTypeElement(); if (typeElement != null) { foreach (ITypeMember member in typeElement.GetMembers()) { IMethod method = member as IMethod; if (method != null && FileHelper.IsTestMethod(method)) { MbUnitTestElement testElement = new MbUnitTestElement(testProvider, fixtureElement, project, typeElement.CLRName, FileHelper.GetMethodName(method), FileHelper.GetTestName((ITypeMember) typeElement)); List testCategories = new List(); CopyTestCategories(fixtureElement, testCategories); helper.CollectTestMethodCategories(method, ref testCategories); testElement.AssignCategories(testCategories); if (helper.HasChildTest(method)) { foreach (string childName in helper.GetChildNames(method)) { MbUnitChildTestElement childElement = new MbUnitChildTestElement(testElement, testProvider, project, typeElement.CLRName, childName, FileHelper.GetTestName((ITypeMember) typeElement)); // childElement.AssignCategories(testCategories); } } } } AppendTests(fixtureElement, type.GetSuperTypes(), ref order); } } } private void CopyTestCategories(UnitTestElement fixtureElement, ICollection testCategories) { foreach (UnitTestElementCategory category in fixtureElement.GetCategories()) { testCategories.Add(category.Name); } } } }