private void FileTemplateSelectFromList(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (_solution == null) { ResharperHelper.AppendLineToOutputWindow(_solution.Locks, "Unable to identify current solution."); DisplayLoadProjectTip(); return; } var project = _solution.GetAllCodeProjects().FirstOrDefault(); if (project == null) { ResharperHelper.AppendLineToOutputWindow(_solution.Locks, "Unable to identify a code project."); DisplayLoadProjectTip(); return; } var scope = _scopeManager.EnumerateRealScopePoints(new TemplateAcceptanceContext(new ProjectFolderWithLocation(project))); scope = scope.Distinct().Where(s => s is InLanguageSpecificProject).ToList(); var template = _templatesUiHelper.ChooseTemplate( FileTemplatesManager.Instance.QuickListSupports, scope, project.ToDataContext(), TemplateApplicability.File); if (template != null) { ((TextBox)sender).Text = template.Description; } }
public override void Execute(Action <DaemonStageResult> commiter) { if (!_mappedOnceThisSession) { //not a nice solution but I needed a way to ensure the testcop key mappings are put in place _mappedOnceThisSession = true; ResharperHelper.ForceKeyboardBindings(); } if (File.GetProject().IsTestProject() == false) { return;//only apply rules with projects we recognise as test projects } // Running visitor against the PSI var elementProcessor = new TestFileAnalysisElementProcessor(this, _myDaemonProcess, _settings); File.ProcessDescendants(elementProcessor); // Checking if the daemon is interrupted by user activity if (_myDaemonProcess.InterruptFlag) { throw new ProcessCancelledException(); } // Commit the result into document commiter(new DaemonStageResult(elementProcessor.Highlightings)); }
private void MultiTestClassAndNamespaceTextChanged(object sender, TextChangedEventArgs e) { var outcomeTexBox = regExOutcome; Regex regEx; tbSuffixGuidance.Text = string.Format("The configuration below defines that the namespace of all " + "test assemblies must match the RegEx '{0}'. Use brackets to extract the associated code project namespace." , testNamespaceRegExTextBox.Text); try { outcomeTexBox.Text = ""; regEx = new Regex(testNamespaceRegExTextBox.Text); } catch (Exception) { return; } if (regEx.GetGroupNames().Count() < 2) { regExOutcome.Text = "RegEx must contain at least one regex group ()."; return; } if (_solution != null) { ResharperHelper.ProtectActionFromReEntry(_lifetime, "TestcopOptionsPage", () => { var testProjects = _solution.GetAllCodeProjects().Select(p => p).Where(p => regEx.IsMatch(p.GetDefaultNamespace() ?? "")).ToList(); outcomeTexBox.Text = testProjects.Any() ? "" : "Warning: the regex does not match the NAMESPACE of any loaded projects."; }).Invoke(); } }
public override IList <TestCopProjectItem> GetAssociatedProject(IProject currentProject, string className, string currentTypeNamespace, IList <Tuple <string, bool> > subDirectoryElements) { const string warningMessage = "Not Supported: More than one code project has a default namespace of "; string subNameSpace = currentTypeNamespace.RemoveLeading(currentProject.GetDefaultNamespace()); var filePatterns = AssociatedFileNames(Settings, className); if (currentProject.IsTestProject()) { var nameSpaceOfAssociateProject = GetNameSpaceOfAssociatedCodeProject(currentProject); var matchedCodeProjects = currentProject.GetSolution().GetNonTestProjects().Where( p => p.GetDefaultNamespace() == nameSpaceOfAssociateProject).ToList(); if (matchedCodeProjects.Count() > 1) { ResharperHelper.AppendLineToOutputWindow(warningMessage + nameSpaceOfAssociateProject); } return(matchedCodeProjects.Select(p => new TestCopProjectItem(p, TestCopProjectItem.ProjectItemTypeEnum.Code, subNameSpace, subDirectoryElements, filePatterns)).ToList()); } var matchedTestProjects = currentProject.GetSolution().GetTestProjects().Where( p => GetNameSpaceOfAssociatedCodeProject(p) == currentProject.GetDefaultNamespace()).ToList(); return(matchedTestProjects.Select(p => new TestCopProjectItem(p, TestCopProjectItem.ProjectItemTypeEnum.Tests, subNameSpace, subDirectoryElements, filePatterns)).ToList()); }
public void Test(string testName) { const string altRegEx = "^(.*?)\\.?(Integration)*Tests$"; ExecuteWithinSettingsTransaction((settingsStore => { RunGuarded( () => { ClearRegExSettingsPriorToRun(settingsStore); settingsStore.SetValue <TestFileAnalysisSettings, bool>( s => s.FindOrphanedProjectFiles, true); settingsStore.SetValue <TestFileAnalysisSettings, string>( s => s.TestProjectToCodeProjectNameSpaceRegEx, altRegEx); settingsStore.SetValue <TestFileAnalysisSettings, string>( s => s.TestProjectToCodeProjectNameSpaceRegExReplace, "$1"); } ); DoTestFiles(testName); Lifetimes.Using(lifetime => { using (var cookie = LoadedTestSolution.CreateTransactionCookie(DefaultAction.Rollback, this.GetType().Name, new ProgressIndicator(lifetime))) { ResharperHelper.ProtectActionFromReEntry(lifetime, "X", actionToRun); } }); })); }
private void ProjectNameRegexTextChanged(object sender, TextChangedEventArgs e) { TextBlock outcomeTexBox = regExProjectOutcome; Regex regEx; tbProjectSuffixGuidance.Text = $"The configuration below defines that the project name of all test assemblies must match the RegEx '{this.testProjectNameRegExTextBox.Text}'. " + "Use brackets to extract the associated code project name. The namespace of the project and associated test project must be the same. "; try { outcomeTexBox.Text = ""; regEx = new Regex(testProjectNameRegExTextBox.Text); } catch (Exception) { return; } if (regEx.GetGroupNames().Length < 2) { outcomeTexBox.Text = "RegEx must contain at least one regex group ()."; return; } if (_solution != null) { ResharperHelper.ProtectActionFromReEntry(_lifetime, "TestCopOptionsPage", () => { List <IProject> testProjects = _solution.GetAllCodeProjects().Select(p => p).Where(p => regEx.IsMatch(p.Name ?? "")).ToList(); outcomeTexBox.Text = testProjects.Any() ? "" : "Warning: the regex does not match the NAME of any loaded projects."; }).Invoke(); } }
public override ValidationResult Validate(object value, CultureInfo cultureInfo) { ValidationResult result = ValidationResult.ValidResult; var action = ResharperHelper.ProtectActionFromReEntry(_lifetime, "IsAFileTemplateValidationRule", () => result = CheckTemplateExists(value)); action.Invoke(); return(result); }
public void DumpDebug(ISolution solution) { var rx = TestingRegEx; solution.GetAllCodeProjects().ForEach( p => ResharperHelper.AppendLineToOutputWindow(solution.Locks, "\tProject Namespace:" + p.GetDefaultNamespace() + (rx.IsMatch(p.GetDefaultNamespace() ?? "") ? " matches " : " does not match ") + rx)); }
public void DumpDebug(ISolution solution) { Regex testNameSpaceRegEx = this.TestNameSpaceRegEx; foreach (IProject project in solution.GetAllCodeProjects()) { string projectDefaultNameSpace = project.GetDefaultNamespace(); bool matchesTestNameSpace = testNameSpaceRegEx.IsMatch(projectDefaultNameSpace ?? ""); string matchResult = matchesTestNameSpace ? " matches " : " does not match "; ResharperHelper.AppendLineToOutputWindow(solution.Locks, $"\tProject Namespace:{projectDefaultNameSpace}{matchResult}{testNameSpaceRegEx}"); } }
private IEnumerable <IClrDeclaredElement> FindReferencesWithinAssociatedAssembly(IDataContext context, ISolution solution, ITextControl textControl, IClrTypeName clrTypeClassName, IEnumerable <TestCopProjectItem> targetProjects) { if (clrTypeClassName == null) { ResharperHelper.AppendLineToOutputWindow(solution.Locks, "FindReferencesWithinAssociatedAssembly() - clrTypeClassName was null"); return(new List <IClrDeclaredElement>()); } IPsiServices services = solution.GetPsiServices(); ISearchDomain searchDomain; if (this.Settings.FindAnyUsageInTestAssembly) { searchDomain = PsiShared.GetComponent <SearchDomainFactory>().CreateSearchDomain( targetProjects.SelectMany(proj => proj.Project.GetAllProjectFiles().Select(p => p.GetPsiModule()))); } else { // look for similar named files that also have references to this code List <ProjectFileFinder.Match> items = new List <ProjectFileFinder.Match>(); foreach (TestCopProjectItem projectItem in targetProjects) { projectItem.Project.Accept(new ProjectFileFinder(items, projectItem.FilePattern)); } searchDomain = PsiShared.GetComponent <SearchDomainFactory>() .CreateSearchDomain(items.Select(p => p.ProjectFile.ToSourceFile())); } ISymbolScope declarationsCache = solution.GetPsiServices().Symbols .GetSymbolScope(LibrarySymbolScope.NONE, false); //, currentProject.GetResolveContext()); ITypeElement declaredElement = declarationsCache.GetTypeElementByCLRName(clrTypeClassName); IReference[] findReferences = services.Finder.FindReferences(declaredElement, searchDomain, new ProgressIndicator(textControl.Lifetime)); List <IClassDeclaration> findReferencesWithinAssociatedAssembly = findReferences.Select(p => p.GetTreeNode().GetContainingNode <IClassDeclaration>(true)).ToList(); return(findReferencesWithinAssociatedAssembly .Select(p => p.DeclaredElement).ToList() .Select(p => p as IClrDeclaredElement).ToList()); }
public TestCopProjectItem(IProject project, ProjectItemTypeEnum projectItemType, string subNameSpace, IList <Tuple <string, bool> > subDirectoryElements, IEnumerable <FilePatternMatcher> filePatterns) { FilePattern = filePatterns.ToArray(); Project = project; SubNamespace = subNameSpace.RemoveLeading("."); var subNameSpaceAccordingToDirectoryElements = subDirectoryElements.Where(i => i.Item2).Select(i => i.Item1).Join(@"."); if (subNameSpaceAccordingToDirectoryElements != SubNamespace) { ResharperHelper.AppendLineToOutputWindow(project.Locks, "Error calculating sub namepsace '{0}'<>'{1}'".FormatEx(subNameSpaceAccordingToDirectoryElements, SubNamespace)); } this._subDirectoryElements = subDirectoryElements; ProjectItemType = projectItemType; }
private void FileTemplateSelectFromList(object sender, System.Windows.Input.MouseButtonEventArgs e) { Template template = null; if (_solution == null) { ResharperHelper.AppendLineToOutputWindow("Unable to identify current solution."); DisplayLoadProjectTip(); return; } var project = _solution.GetAllCodeProjects().FirstOrDefault(); if (project == null) { ResharperHelper.AppendLineToOutputWindow("Unable to identify a code project."); DisplayLoadProjectTip(); return; } var scope = _scopeManager.EnumerateRealScopePoints(new TemplateAcceptanceContext(new ProjectFolderWithLocation(project))); scope = scope.Distinct().Where(s => s is InLanguageSpecificProject).ToList(); using ( var templateDialog = new TemplateChooserDialog(_lifetime, FileTemplatesManager.Instance.QuickListSupports, scope, project.ToDataContext(), TemplateApplicability.File)) { if (templateDialog.ShowDialog(_application.MainWindow.GetActiveWindow()) != DialogResult.OK) { return; } template = templateDialog.Template; } if (template != null) { ((TextBox)sender).Text = template.Description; } }
private static IDeclaredElement FindTypeInFile(ISolution solution, string testFile, int typeSequenceInFile) { var projectFile = solution.GetAllProjects() .SelectMany(p => p.GetAllProjectFiles()).SingleOrDefault(p => p.GetPresentableProjectPath() == testFile); if (projectFile == null) { solution.GetAllProjects().SelectMany(p => p.GetAllProjectFiles()).ForEach(p => Debug.WriteLine(p.GetPresentableProjectPath())); throw new Exception("Whilst configuring test I didn't find project item: " + testFile); } var document = DocumentManager.GetInstance(solution).GetOrCreateDocument(projectFile); var findFirstTypeInFile = ResharperHelper.FindDeclaredElementInFile(solution, document, typeSequenceInFile); return(findFirstTypeInFile); }
private void SingleTestClassAndNamespaceTextChanged(object sender, TextChangedEventArgs e) { TextBlock outcomeTexBox = SingleTestRegExOutcome; Regex regEx; tbSingleTestSuffixGuidanceOne.Text = $"The configuration below defines that the namespace of test classes must match the RegEx '{this.SingleTestNamespaceRegExTextBox.Text}'. " + $"Use brackets to extract the associated code project namespace. The replace string '{this.SingleTestNamespaceToAssemblyRegExReplaceTextBox.Text}' " + $"will be used to identify the code project namespace and the replace string '{this.SingleTestNamespaceToAssemblySubNameSpaceRegExReplaceTextBox.Text}' " + "to build the sub namespace within the code project. \n \n"; tbSingleTestSuffixGuidanceTwo.Text = "The configuration below defines the sections(s) of the code class namespace that will map to sub-namespace within the test project by extracting " + $"'{this.SingleTestCodeNamespaceToTestRegExReplaceTextBox.Text}' from the RegEx '{this.SingleTestCodeNamespaceRegExTextBox.Text}' when it is applied " + "to code files namespace.\n \n"; try { outcomeTexBox.Text = ""; regEx = new Regex(SingleTestNamespaceRegExTextBox.Text); } catch (Exception) { return; } if (regEx.GetGroupNames().Length < 2) { regExOutcome.Text = "RegEx must contain at least one regex group ()."; return; } if (_solution != null) { ResharperHelper.ProtectActionFromReEntry(_lifetime, "TestCopOptionsPage", () => { List <IProject> testProjects = _solution.GetAllCodeProjects() .Select(p => p).Where(p => regEx.IsMatch((p.GetDefaultNamespace() ?? "NS2") + ".NS1")).ToList(); outcomeTexBox.Text = testProjects.Any() ? "" : "Warning: the regex does not match the namespace of any loaded projects."; }).Invoke(); } }
private void FileTemplateSelectFromList(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (_solution == null) { ResharperHelper.AppendLineToOutputWindow(_solution?.Locks, "Unable to identify current solution."); DisplayLoadProjectTip(); return; } IProject project = _solution.GetAllCodeProjects().FirstOrDefault(); if (project == null) { ResharperHelper.AppendLineToOutputWindow(_solution.Locks, "Unable to identify a code project."); DisplayLoadProjectTip(); return; } this._templatesUiHelper.ChooseTemplate(this._settings.ToImplementation(), this._fileTemplatesManager.QuickListSupports, TemplateApplicability.File, template => { ((TextBox)sender).Text = template.Description; }); }
private static string GetNameOfAssociateCodeProject(IProject testProject) { var testNamePattern = Settings.TestProjectNameToCodeProjectNameRegEx; string replaceText = Settings.TestProjectNameToCodeProjectNameRegExReplace; string currentProjectName = testProject.Name; if (string.IsNullOrEmpty(currentProjectName)) { return(""); } string result; if (RegexReplace(testNamePattern, replaceText, currentProjectName, out result)) { return(result); } ResharperHelper.AppendLineToOutputWindow("ERROR: Regex pattern matching failed to extract group - check your regex replace string of " + replaceText); throw new ApplicationException("Unexpected internal error -regex error in testcop - {0} - {1}".FormatEx(testNamePattern, replaceText)); }
public void PerformOneTimeInitialization() { ResharperHelper.ForceKeyboardBindings(_locks); }
public override IList <TestCopProjectItem> GetAssociatedProject(IProject currentProject, string className, string currentTypeNamespace, IList <Tuple <string, bool> > subDirectoryElements) { var settings = Settings; const string warningMessage = "Not Supported: More than one code project has a default namespace of "; var filePatterns = AssociatedFileNames(Settings, className); if (currentProject.IsTestProject()) { // <MyCorp.App.Tests>.API.ClassA --> <MyCorp.App.API>.ClassA string nameSpaceOfAssociateProject; RegexReplace(settings.SingleTestRegexTestToAssembly , settings.SingleTestRegexTestToAssemblyProjectReplace, currentTypeNamespace, out nameSpaceOfAssociateProject); string subNameSpace; RegexReplace(settings.SingleTestRegexTestToAssembly , settings.SingleTestRegexTestToAssemblyProjectSubNamespaceReplace, currentTypeNamespace, out subNameSpace); var matchedCodeProjects = currentProject.GetSolution().GetNonTestProjects().Where( p => p.GetDefaultNamespace() == nameSpaceOfAssociateProject).ToList(); if (matchedCodeProjects.Count() > 1) { ResharperHelper.AppendLineToOutputWindow(warningMessage + nameSpaceOfAssociateProject); } if (matchedCodeProjects.Count == 0) { ResharperHelper.AppendLineToOutputWindow("Didn't find project with namespace of: " + nameSpaceOfAssociateProject + " to match " + currentTypeNamespace); } var subDirectoryElementsWithOutExtraFolderForNS = new List <Tuple <string, bool> >(subDirectoryElements); if (subDirectoryElementsWithOutExtraFolderForNS.Count > 0) { subDirectoryElementsWithOutExtraFolderForNS.RemoveAt(0); } return(matchedCodeProjects.Select(p => new TestCopProjectItem(p, TestCopProjectItem.ProjectItemTypeEnum.Code, subNameSpace, subDirectoryElementsWithOutExtraFolderForNS, filePatterns)).ToList()); } // <MyCorp.App.API>.ClassA --> <MyCorp.App.Tests>.API.ClassA string subNameSpaceOfTest; RegexReplace(settings.SingleTestRegexCodeToTestAssembly , settings.SingleTestRegexCodeToTestReplace, currentTypeNamespace, out subNameSpaceOfTest); var matchedTestProjects = currentProject.GetSolution().GetTestProjects().ToList(); if (matchedTestProjects.Count > 1) { ResharperHelper.AppendLineToOutputWindow("Not Supported: Expected only one test project for all code projects to use"); } var subDirectoryElementsWithExtraFolderForNS = AddMissingDirectoryElementsInNamespace(subDirectoryElements, subNameSpaceOfTest); return(matchedTestProjects.Select(p => new TestCopProjectItem(p, TestCopProjectItem.ProjectItemTypeEnum.Tests, subNameSpaceOfTest, subDirectoryElementsWithExtraFolderForNS, filePatterns)).Take(1).ToList()); }
public IEnumerable <FileRename> GetFileRenames(IDeclaredElement declaredElement, string newName) { if (!Settings.SupportRenameRefactor) { yield break; } var typeElement = declaredElement as ITypeElement; var clrDeclaredElement = declaredElement as IClrDeclaredElement; if (clrDeclaredElement == null) { yield break; } var psiModule = clrDeclaredElement.Module as IProjectPsiModule; if (psiModule == null) { yield break; } if (typeElement != null)//only support renaming of 'types' { var classNameBeingRenamed = declaredElement.ShortName; var project = psiModule.Project; var solution = project.GetSolution(); if (!project.IsTestProject()) { IList <TestCopProjectItem> targetProjects = new List <TestCopProjectItem>(); foreach (var sourceFile in declaredElement.GetSourceFiles()) { var projectFile = sourceFile.ToProjectFile(); targetProjects.AddRange(project.GetAssociatedProjects(projectFile, classNameBeingRenamed)); } //var targetProjects = project.GetAssociatedProjects(projectFiles); if (targetProjects.IsNullOrEmpty()) { yield break; } //now look for expected file names that are also in correct locations foreach (var targetProject in targetProjects) { var projectTestFilesWithMatchingName = new List <ProjectFileFinder.Match>(); targetProject.Project.Accept(new ProjectFileFinder(projectTestFilesWithMatchingName, targetProject.FilePattern)); foreach (var projectFileMatch in projectTestFilesWithMatchingName) { string expectedNameSpace = projectFileMatch.ProjectFile.CalculateExpectedNamespace(projectFileMatch.ProjectFile.GetPrimaryPsiFile().Language); if (expectedNameSpace == targetProject.FullNamespace()) { string currentName = projectFileMatch.ProjectFile.Location.NameWithoutExtension; var newTestClassName = newName + currentName.Substring(classNameBeingRenamed.Length); ResharperHelper.AppendLineToOutputWindow(project.Locks, "Renaming {0} to {1}".FormatEx(projectFileMatch.ProjectFile.Location.FullPath, newTestClassName)); if (projectFileMatch.ProjectFile.Location.NameWithoutExtension == newTestClassName) { ResharperHelper.AppendLineToOutputWindow(project.Locks, "# skip as same name"); continue; } //TODO EditorManager.GetInstance(solution).OpenProjectFile(projectFileMatch.ProjectFile, new OpenFileOptions(false)); EditorManager.GetInstance(solution).OpenProjectFileAsync(projectFileMatch.ProjectFile, new OpenFileOptions(false)); //need to ensure class within file is renamed tooo yield return (new FileRename(psiModule.GetPsiServices(), projectFileMatch.ProjectFile, newTestClassName)); } } } } } }
void IExecutableAction.Execute(IDataContext context, DelegateExecute nextExecute) { ITextControl textControl = context.GetData(TextControlDataConstants.TEXT_CONTROL); if (textControl == null) { MessageBox.ShowError("Text control unavailable."); return; } ISolution solution = context.GetData(JetBrains.ProjectModel.DataContext.ProjectModelDataConstants.SOLUTION); if (solution == null) { return; } IClrTypeName clrTypeClassName = ResharperHelper.GetClassNameAppropriateToLocation(solution, textControl); if (clrTypeClassName == null) { return; } var typeDeclaration = ResharperHelper.FindFirstCharpTypeDeclarationInDocument(solution, textControl.Document); if (typeDeclaration == null) { return; } var currentProject = context.GetData(JetBrains.ProjectModel.DataContext.ProjectModelDataConstants.Project); if (currentProject == null) { ResharperHelper.AppendLineToOutputWindow("Internal Error: No current project"); return; } var targetProjects = currentProject.GetAssociatedProjects(textControl.ToProjectFile(solution)); if (targetProjects.IsEmpty()) { ResharperHelper.AppendLineToOutputWindow("Unable to locate associated assembly - check project namespaces and testcop Regex"); //ProjectMappingHelper.GetProjectMappingHeper().DumpDebug(solution); return; } var settings = solution.GetPsiServices().SettingsStore .BindToContextTransient(ContextRange.Smart(textControl.ToDataContext())) .GetKey <TestFileAnalysisSettings>(SettingsOptimization.OptimizeDefault); var baseFileName = ResharperHelper.GetBaseFileName(context, solution); bool isTestFile = baseFileName.EndsWith(settings.TestClassSuffixes()); if (isTestFile != currentProject.IsTestProject()) { ResharperHelper.AppendLineToOutputWindow( string.Format("Don't know how to navigate with '{0}' within project '{1}'. It is a {2} file within a {3} project" , baseFileName, currentProject.Name, isTestFile ? "test" : "code", currentProject.IsTestProject() ? "test" : "code")); return; } var elementsFoundInTarget = new List <IClrDeclaredElement>(); var elementsFoundInSolution = new List <IClrDeclaredElement>(); foreach (var singleTargetProject in targetProjects) { foreach (var patternMatcher in singleTargetProject.FilePattern) { //FindByClassName elementsFoundInSolution.AddRangeIfMissing(ResharperHelper.FindClass(solution, patternMatcher.RegEx.ToString()), _declElementMatcher); elementsFoundInTarget.AddRangeIfMissing(ResharperHelper.FindClass(solution, patternMatcher.RegEx.ToString(), new List <IProject>() { singleTargetProject.Project }), _declElementMatcher); if (!isTestFile) { //Find via filename (for when we switch to test files) var otherMatches = ResharperHelper.FindFirstTypeWithinCodeFiles(solution, patternMatcher.RegEx, singleTargetProject.Project); elementsFoundInTarget.AddRangeIfMissing(otherMatches, _declElementMatcher); } } } if (!isTestFile) { var references = FindReferencesWithinAssociatedAssembly(context, solution, textControl, clrTypeClassName, targetProjects); elementsFoundInTarget.AddRangeIfMissing(references, _declElementMatcher); } JumpToTestMenuHelper.PromptToOpenOrCreateClassFiles(_menuDisplayer, textControl.Lifetime, context, solution , currentProject, clrTypeClassName, targetProjects , elementsFoundInTarget, elementsFoundInSolution); }
private void CheckClassnameInFileNameActuallyExistsAndCreateWarningIfNot(ICSharpTypeDeclaration thisDeclaration) { if (thisDeclaration.IsAbstract) { return; } var currentFileName = CurrentSourceFile.GetLocation().NameWithoutExtension; var appropriateTestClassSuffixes = TestCopSettingsManager.Instance.Settings.GetAppropriateTestClassSuffixes(currentFileName); foreach (var testClassSuffix in appropriateTestClassSuffixes) { var className = currentFileName.Split(new[] { '.' }, 2)[0].RemoveTrailing(testClassSuffix); var declaredElements = ResharperHelper.FindClass(Solution, className); var currentProject = thisDeclaration.GetProject(); var currentDeclarationNamespace = thisDeclaration.OwnerNamespaceDeclaration != null ? thisDeclaration.OwnerNamespaceDeclaration.DeclaredName : ""; var associatedProjects = currentProject.GetAssociatedProjects(CurrentSourceFile.ToProjectFile()); if (associatedProjects == null || associatedProjects.Count == 0) { var highlight = new TestFileNameWarning( "Project for this test assembly was not found - check namespace of projects", thisDeclaration); AddHighlighting(thisDeclaration.GetNameDocumentRange(), highlight); return; } var filteredDeclaredElements = new List <IClrDeclaredElement>(declaredElements); ResharperHelper.RemoveElementsNotInProjects(filteredDeclaredElements, associatedProjects.Select(p => p.Project).ToList()); if (filteredDeclaredElements.Count == 0) { string message = string.Format( "The file name begins with {0} but no matching class exists in associated project", className); foreach (var declaredElement in declaredElements) { var cls = declaredElement as TypeElement; if (cls != null) { message += string.Format("\nHas it moved to {0}.{1} ?", cls.OwnerNamespaceDeclaration(), cls.GetClrName()); } } var highlight = new TestFileNameWarning(message, thisDeclaration); AddHighlighting(thisDeclaration.GetNameDocumentRange(), highlight); return; } if (Settings.CheckTestNamespaces) { CheckClassNamespaceOfTestMatchesClassUnderTest(thisDeclaration, declaredElements); } } }
private void CheckClassNamespaceOfTestMatchesClassUnderTest(ICSharpTypeDeclaration thisDeclaration, List <IClrDeclaredElement> declaredElements) { var thisProject = thisDeclaration.GetProject(); if (thisProject == null) { return; } var associatedProject = thisProject.GetAssociatedProjects(CurrentSourceFile.ToProjectFile()).FirstOrDefault(); if (associatedProject == null) { return; } ResharperHelper.RemoveElementsNotInProjects(declaredElements, new [] { associatedProject.Project }); var thisProjectsDefaultNamespace = thisProject.GetDefaultNamespace(); if (string.IsNullOrEmpty(thisProjectsDefaultNamespace)) { return; } var associatedProjectsDefaultNameSpace = associatedProject.Project.GetDefaultNamespace(); if (string.IsNullOrEmpty(associatedProjectsDefaultNameSpace)) { return; } //var nsToBeFoundShouldBe = associatedProject.Project.GetDefaultNamespace()+associatedProject.SubNamespace; var nsToBeFoundShouldBe = associatedProject.FullNamespace(); //Lookup the namespaces of the declaredElements we've found that possibly match this test IList <string> foundNameSpaces = new List <string>(); foreach (var declaredTestElement in declaredElements) { var cls = declaredTestElement as TypeElement; if (cls == null) { continue; } var ns = cls.OwnerNamespaceDeclaration(); if (nsToBeFoundShouldBe == ns) { return;//found a match ! } foundNameSpaces.Add(ns); } foreach (var ns in foundNameSpaces) { if (ns.StartsWith(associatedProjectsDefaultNameSpace)) { //TODO: Review this can be probably be replaced with associatedProject method calls var targetsubNameSpace = ns.Substring(associatedProjectsDefaultNameSpace.Length).TrimStart(new[] { '.' }); string suggestedNameSpace = thisProjectsDefaultNamespace.AppendIfNotNull(".", targetsubNameSpace); var targetFolder = thisProject.Location.Combine(targetsubNameSpace.Replace(".", @"\")); var highlight = new TestFileNameSpaceWarning(CurrentSourceFile.ToProjectFile(), thisDeclaration, suggestedNameSpace , thisProject, targetFolder); AddHighlighting(thisDeclaration.GetNameDocumentRange(), highlight); } } }