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)); }
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)); }
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)); }