示例#1
0
        private static Task <Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, XmlElementSyntax node, CancellationToken cancellationToken)
        {
            var typeDeclaration   = node.FirstAncestorOrSelf <BaseTypeDeclarationSyntax>();
            var declarationSyntax = node.FirstAncestorOrSelf <BaseMethodDeclarationSyntax>();

            var standardText = GenerateStandardText(document, declarationSyntax, typeDeclaration, cancellationToken);

            string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp);

            string trailingString = string.Empty;

            var newContent = RemoveMalformattedStandardText(node.Content, standardText[0], standardText[1], ref trailingString);

            if (newContent.Count == 1 && newContent[0] is XmlTextSyntax xmlText)
            {
                if (string.IsNullOrWhiteSpace(xmlText.ToString()))
                {
                    newContent = default;
                }
            }

            var list = BuildStandardTextSyntaxList(typeDeclaration, newLineText, standardText[0], standardText[1] + trailingString);

            newContent = newContent.InsertRange(0, list);

            newContent = RemoveTrailingEmptyLines(newContent);

            var newNode = node.WithContent(newContent).AdjustDocumentationCommentNewLineTrivia();

            var newRoot = root.ReplaceNode(node, newNode);

            var newDocument = document.WithSyntaxRoot(newRoot);

            return(Task.FromResult(newDocument));
        }
示例#2
0
        protected override void HandleInlineCodeElement(ref SyntaxNodeAnalysisContext context, XmlElementSyntax xmlElement)
        {
            // This rule will only apply if the content is a single XmlTextSyntax containing a single
            // XmlTextLiteralToken token
            if (xmlElement.Content.Count != 1)
            {
                return;
            }

            if (!(xmlElement.Content[0] is XmlTextSyntax xmlText))
            {
                return;
            }

            if (xmlText.TextTokens.Count != 1)
            {
                return;
            }

            var semanticModel    = context.SemanticModel;
            var documentedSymbol = semanticModel.GetDeclaredSymbol(xmlElement.FirstAncestorOrSelf <SyntaxNode>(SyntaxNodeExtensionsEx.IsSymbolDeclaration), context.CancellationToken);

            if (!documentedSymbol.HasAnyParameter(xmlText.TextTokens[0].ValueText, StringComparer.Ordinal))
            {
                return;
            }

            context.ReportDiagnostic(Diagnostic.Create(Descriptor, xmlElement.GetLocation()));
        }
        private static Task <Document> GetTransformedDocument(Document document, SyntaxNode root, XmlElementSyntax node)
        {
            var classDeclaration  = node.FirstAncestorOrSelf <ClassDeclarationSyntax>();
            var declarationSyntax = node.FirstAncestorOrSelf <BaseMethodDeclarationSyntax>();

            ImmutableArray <string> standardText;

            if (declarationSyntax is ConstructorDeclarationSyntax)
            {
                if (declarationSyntax.Modifiers.Any(SyntaxKind.StaticKeyword))
                {
                    standardText = SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.StaticConstructorStandardText;
                }
                else if (declarationSyntax.Modifiers.Any(SyntaxKind.PrivateKeyword))
                {
                    // Prefer to insert the "non-private" wording, even though both are considered acceptable by the
                    // diagnostic. https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/413
                    standardText = SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.NonPrivateConstructorStandardText;
                }
                else
                {
                    standardText = SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.NonPrivateConstructorStandardText;
                }
            }
            else if (declarationSyntax is DestructorDeclarationSyntax)
            {
                standardText = SA1643DestructorSummaryDocumentationMustBeginWithStandardText.DestructorStandardText;
            }
            else
            {
                throw new InvalidOperationException("XmlElementSyntax has invalid method as its parent");
            }

            var list = BuildStandardText(classDeclaration.Identifier, classDeclaration.TypeParameterList, standardText[0], standardText[1]);

            var newContent = node.Content.InsertRange(0, list);
            var newNode    = node.WithContent(newContent);

            var newRoot = root.ReplaceNode(node, newNode);

            var newDocument = document.WithSyntaxRoot(newRoot);

            return(Task.FromResult(newDocument));
        }
示例#4
0
        protected override void HandleInlineCodeElement(ref SyntaxNodeAnalysisContext context, XmlElementSyntax xmlElement)
        {
            // Currently this rule will only apply if the content is a single XmlTextSyntax containing a single
            // XmlTextLiteralToken token
            if (xmlElement.Content.Count != 1)
            {
                return;
            }

            if (!(xmlElement.Content[0] is XmlTextSyntax xmlText))
            {
                return;
            }

            if (xmlText.TextTokens.Count != 1)
            {
                return;
            }

            var semanticModel    = context.SemanticModel;
            var documentedSymbol = semanticModel.GetDeclaredSymbol(xmlElement.FirstAncestorOrSelf <SyntaxNode>(SyntaxNodeExtensionsEx.IsSymbolDeclaration), context.CancellationToken);
            var name             = xmlText.TextTokens[0].ValueText;

            for (var currentSymbol = documentedSymbol; currentSymbol != null; currentSymbol = currentSymbol?.ContainingSymbol)
            {
                switch (currentSymbol.Kind)
                {
                case SymbolKind.NamedType:
                    var namedType       = (INamedTypeSymbol)currentSymbol;
                    var matchingMembers = namedType.GetMembers(name);
                    if (matchingMembers.Length != 1)
                    {
                        return;
                    }

                    if (matchingMembers[0].Kind == SymbolKind.Property ||
                        matchingMembers[0].Kind == SymbolKind.Field ||
                        matchingMembers[0].Kind == SymbolKind.Event)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(Descriptor, xmlElement.GetLocation()));
                    }

                    return;

                case SymbolKind.Namespace:
                case SymbolKind.NetModule:
                    return;

                default:
                    continue;
                }
            }
        }
        private static Task<Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, XmlElementSyntax node)
        {
            var typeDeclaration = node.FirstAncestorOrSelf<BaseTypeDeclarationSyntax>();
            var declarationSyntax = node.FirstAncestorOrSelf<BaseMethodDeclarationSyntax>();
            bool isStruct = typeDeclaration.IsKind(SyntaxKind.StructDeclaration);

            TypeParameterListSyntax typeParameterList;
            ClassDeclarationSyntax classDeclaration = typeDeclaration as ClassDeclarationSyntax;
            if (classDeclaration != null)
            {
                typeParameterList = classDeclaration.TypeParameterList;
            }
            else
            {
                typeParameterList = (typeDeclaration as StructDeclarationSyntax)?.TypeParameterList;
            }

            ImmutableArray<string> standardText;
            if (declarationSyntax is ConstructorDeclarationSyntax)
            {
                if (declarationSyntax.Modifiers.Any(SyntaxKind.StaticKeyword))
                {
                    if (isStruct)
                    {
                        standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.StaticConstructorStandardText, " struct.");
                    }
                    else
                    {
                        standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.StaticConstructorStandardText, " class.");
                    }
                }
                else
                {
                    // Prefer to insert the "non-private" wording for all constructors, even though both are considered
                    // acceptable for private constructors by the diagnostic.
                    // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/413
                    if (isStruct)
                    {
                        standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.NonPrivateConstructorStandardText, " struct.");
                    }
                    else
                    {
                        standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.NonPrivateConstructorStandardText, " class.");
                    }
                }
            }
            else if (declarationSyntax is DestructorDeclarationSyntax)
            {
                standardText = SA1643DestructorSummaryDocumentationMustBeginWithStandardText.DestructorStandardText;
            }
            else
            {
                throw new InvalidOperationException("XmlElementSyntax has invalid method as its parent");
            }

            string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp);
            var list = BuildStandardText(typeDeclaration.Identifier, typeParameterList, newLineText, standardText[0], standardText[1]);

            var newContent = node.Content.InsertRange(0, list);
            var newNode = node.WithContent(newContent).AdjustDocumentationCommentNewLineTrivia();

            var newRoot = root.ReplaceNode(node, newNode);

            var newDocument = document.WithSyntaxRoot(newRoot);

            return Task.FromResult(newDocument);
        }
        private static Task <Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, XmlElementSyntax node)
        {
            var  typeDeclaration   = node.FirstAncestorOrSelf <BaseTypeDeclarationSyntax>();
            var  declarationSyntax = node.FirstAncestorOrSelf <BaseMethodDeclarationSyntax>();
            bool isStruct          = typeDeclaration.IsKind(SyntaxKind.StructDeclaration);

            TypeParameterListSyntax typeParameterList;
            ClassDeclarationSyntax  classDeclaration = typeDeclaration as ClassDeclarationSyntax;

            if (classDeclaration != null)
            {
                typeParameterList = classDeclaration.TypeParameterList;
            }
            else
            {
                typeParameterList = (typeDeclaration as StructDeclarationSyntax)?.TypeParameterList;
            }

            ImmutableArray <string> standardText;

            if (declarationSyntax is ConstructorDeclarationSyntax)
            {
                if (declarationSyntax.Modifiers.Any(SyntaxKind.StaticKeyword))
                {
                    if (isStruct)
                    {
                        standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.StaticConstructorStandardText, " struct.");
                    }
                    else
                    {
                        standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.StaticConstructorStandardText, " class.");
                    }
                }
                else
                {
                    // Prefer to insert the "non-private" wording for all constructors, even though both are considered
                    // acceptable for private constructors by the diagnostic.
                    // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/413
                    if (isStruct)
                    {
                        standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.NonPrivateConstructorStandardText, " struct.");
                    }
                    else
                    {
                        standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.NonPrivateConstructorStandardText, " class.");
                    }
                }
            }
            else if (declarationSyntax is DestructorDeclarationSyntax)
            {
                standardText = SA1643DestructorSummaryDocumentationMustBeginWithStandardText.DestructorStandardText;
            }
            else
            {
                throw new InvalidOperationException("XmlElementSyntax has invalid method as its parent");
            }

            var list = BuildStandardText(typeDeclaration.Identifier, typeParameterList, standardText[0], standardText[1]);

            var newContent = node.Content.InsertRange(0, list);
            var newNode    = node.WithContent(newContent);

            var newRoot = root.ReplaceNode(node, newNode);

            var newDocument = document.WithSyntaxRoot(newRoot);

            return(Task.FromResult(newDocument));
        }
        private static Task <Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, XmlElementSyntax node, CancellationToken cancellationToken)
        {
            var  typeDeclaration   = node.FirstAncestorOrSelf <BaseTypeDeclarationSyntax>();
            var  declarationSyntax = node.FirstAncestorOrSelf <BaseMethodDeclarationSyntax>();
            bool isStruct          = typeDeclaration.IsKind(SyntaxKind.StructDeclaration);
            var  settings          = document.Project.AnalyzerOptions.GetStyleCopSettings(cancellationToken);
            var  culture           = new CultureInfo(settings.DocumentationRules.DocumentationCulture);
            var  resourceManager   = DocumentationResources.ResourceManager;

            TypeParameterListSyntax typeParameterList;
            ClassDeclarationSyntax  classDeclaration = typeDeclaration as ClassDeclarationSyntax;

            if (classDeclaration != null)
            {
                typeParameterList = classDeclaration.TypeParameterList;
            }
            else
            {
                typeParameterList = (typeDeclaration as StructDeclarationSyntax)?.TypeParameterList;
            }

            ImmutableArray <string> standardText;

            if (declarationSyntax is ConstructorDeclarationSyntax)
            {
                var typeKindText = resourceManager.GetString(isStruct ? nameof(DocumentationResources.TypeTextStruct) : nameof(DocumentationResources.TypeTextClass), culture);
                if (declarationSyntax.Modifiers.Any(SyntaxKind.StaticKeyword))
                {
                    standardText = ImmutableArray.Create(
                        string.Format(resourceManager.GetString(nameof(DocumentationResources.StaticConstructorStandardTextFirstPart), culture), typeKindText),
                        string.Format(resourceManager.GetString(nameof(DocumentationResources.StaticConstructorStandardTextSecondPart), culture), typeKindText));
                }
                else
                {
                    // Prefer to insert the "non-private" wording for all constructors, even though both are considered
                    // acceptable for private constructors by the diagnostic.
                    // https://github.com/brunocunhasilva/StyleCopAnalyzers/issues/413
                    standardText = ImmutableArray.Create(
                        string.Format(resourceManager.GetString(nameof(DocumentationResources.NonPrivateConstructorStandardTextFirstPart), culture), typeKindText),
                        string.Format(resourceManager.GetString(nameof(DocumentationResources.NonPrivateConstructorStandardTextSecondPart), culture), typeKindText));
                }
            }
            else if (declarationSyntax is DestructorDeclarationSyntax)
            {
                standardText =
                    ImmutableArray.Create(
                        resourceManager.GetString(nameof(DocumentationResources.DestructorStandardTextFirstPart), culture),
                        resourceManager.GetString(nameof(DocumentationResources.DestructorStandardTextSecondPart), culture));
            }
            else
            {
                throw new InvalidOperationException("XmlElementSyntax has invalid method as its parent");
            }

            string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp);

            string trailingString = string.Empty;

            var newContent = RemoveMalformattedStandardText(node.Content, typeDeclaration.Identifier, standardText[0], standardText[1], ref trailingString);

            var list = BuildStandardText(typeDeclaration.Identifier, typeParameterList, newLineText, standardText[0], standardText[1] + trailingString);

            newContent = newContent.InsertRange(0, list);
            var newNode = node.WithContent(newContent).AdjustDocumentationCommentNewLineTrivia();

            var newRoot = root.ReplaceNode(node, newNode);

            var newDocument = document.WithSyntaxRoot(newRoot);

            return(Task.FromResult(newDocument));
        }