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));
                }
            }
예제 #2
0
        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));
                }
            }
        }
예제 #4
0
        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);
        }