public static void HandleSyntaxTree(SyntaxTreeAnalysisContext context, StyleCopSettings settings) { var syntaxRoot = context.Tree.GetRoot(context.CancellationToken); var firstTypeDeclaration = GetFirstTypeDeclaration(syntaxRoot); if (firstTypeDeclaration == null) { return; } if (firstTypeDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword)) { return; } string suffix; var fileName = FileNameHelpers.GetFileNameAndSuffix(context.Tree.FilePath, out suffix); var expectedFileName = FileNameHelpers.GetConventionalFileName(firstTypeDeclaration, settings.DocumentationRules.FileNamingConvention); if (string.Compare(fileName, expectedFileName, StringComparison.OrdinalIgnoreCase) != 0) { if (settings.DocumentationRules.FileNamingConvention == FileNamingConvention.StyleCop && string.Compare(fileName, FileNameHelpers.GetSimpleFileName(firstTypeDeclaration), StringComparison.OrdinalIgnoreCase) == 0) { return; } var properties = ImmutableDictionary.Create <string, string>() .Add(ExpectedFileNameKey, expectedFileName + suffix); context.ReportDiagnostic(Diagnostic.Create(Descriptor, firstTypeDeclaration.Identifier.GetLocation(), properties)); } }
private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context, StyleCopSettings settings) { var syntaxRoot = context.Tree.GetRoot(context.CancellationToken); var typeNodes = GetTopLevelTypeDeclarations(syntaxRoot, settings); string suffix; var fileName = FileNameHelpers.GetFileNameAndSuffix(context.Tree.FilePath, out suffix); var preferredTypeNode = typeNodes.FirstOrDefault(n => FileNameHelpers.GetConventionalFileName(n, settings.DocumentationRules.FileNamingConvention) == fileName) ?? typeNodes.FirstOrDefault(); if (preferredTypeNode == null) { return; } var foundTypeName = NamedTypeHelpers.GetNameOrIdentifier(preferredTypeNode); var isPartialType = NamedTypeHelpers.IsPartialDeclaration(preferredTypeNode); foreach (var typeNode in typeNodes) { if (typeNode == preferredTypeNode || (isPartialType && foundTypeName == NamedTypeHelpers.GetNameOrIdentifier(typeNode))) { continue; } var location = NamedTypeHelpers.GetNameOrIdentifierLocation(typeNode); if (location != null) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, location)); } } }
private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context, StyleCopSettings settings) { var syntaxRoot = context.Tree.GetRoot(context.CancellationToken); var descentNodes = syntaxRoot.DescendantNodes(descendIntoChildren: node => node != null && !node.IsKind(SyntaxKind.ClassDeclaration)); var classNodes = from descentNode in descentNodes where descentNode.IsKind(SyntaxKind.ClassDeclaration) select descentNode as ClassDeclarationSyntax; string suffix; var fileName = FileNameHelpers.GetFileNameAndSuffix(context.Tree.FilePath, out suffix); var preferredClassNode = classNodes.FirstOrDefault(n => FileNameHelpers.GetConventionalFileName(n, settings.DocumentationRules.FileNamingConvention) == fileName) ?? classNodes.FirstOrDefault(); if (preferredClassNode == null) { return; } string foundClassName = null; bool isPartialClass = false; foundClassName = preferredClassNode.Identifier.Text; isPartialClass = preferredClassNode.Modifiers.Any(SyntaxKind.PartialKeyword); foreach (var classNode in classNodes) { if (classNode == preferredClassNode || (isPartialClass && foundClassName == classNode.Identifier.Text)) { continue; } var location = NamedTypeHelpers.GetNameOrIdentifierLocation(classNode); if (location != null) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, location)); } } }
private static async Task <Solution> GetTransformedSolutionAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxNode node = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true); if (!(node is MemberDeclarationSyntax memberDeclarationSyntax)) { return(document.Project.Solution); } DocumentId extractedDocumentId = DocumentId.CreateNewId(document.Project.Id); string suffix; FileNameHelpers.GetFileNameAndSuffix(document.Name, out suffix); var settings = document.Project.AnalyzerOptions.GetStyleCopSettings(root.SyntaxTree, cancellationToken); string extractedDocumentName = FileNameHelpers.GetConventionalFileName(memberDeclarationSyntax, settings.DocumentationRules.FileNamingConvention) + suffix; List <SyntaxNode> nodesToRemoveFromExtracted = new List <SyntaxNode>(); SyntaxNode previous = node; for (SyntaxNode current = node.Parent; current != null; previous = current, current = current.Parent) { foreach (SyntaxNode child in current.ChildNodes()) { if (child == previous) { continue; } switch (child.Kind()) { case SyntaxKind.NamespaceDeclaration: case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.DelegateDeclaration: nodesToRemoveFromExtracted.Add(child); break; default: break; } } } // Add the new file SyntaxNode extractedDocumentNode = root.RemoveNodes(nodesToRemoveFromExtracted, SyntaxRemoveOptions.KeepUnbalancedDirectives); Solution updatedSolution = document.Project.Solution.AddDocument(extractedDocumentId, extractedDocumentName, extractedDocumentNode, document.Folders); // Make sure to also add the file to linked projects foreach (var linkedDocumentId in document.GetLinkedDocumentIds()) { DocumentId linkedExtractedDocumentId = DocumentId.CreateNewId(linkedDocumentId.ProjectId); updatedSolution = updatedSolution.AddDocument(linkedExtractedDocumentId, extractedDocumentName, extractedDocumentNode, document.Folders); } // Remove the type from its original location updatedSolution = updatedSolution.WithDocumentSyntaxRoot(document.Id, root.RemoveNode(node, SyntaxRemoveOptions.KeepUnbalancedDirectives)); return(updatedSolution); }