/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (diagnostic.Properties.TryGetValue("Name", out var name)) { if (syntaxRoot.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true) is MemberAccessExpressionSyntax memberAccess) { context.RegisterCodeFix( "Prefer parameter.", (editor, _) => editor.ReplaceNode( memberAccess, SyntaxFactory.IdentifierName(name) .WithLeadingTriviaFrom(memberAccess)), "Prefer parameter.", diagnostic); } else if (syntaxRoot.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true) is IdentifierNameSyntax identifierName) { context.RegisterCodeFix( "Prefer parameter.", (editor, _) => editor.ReplaceNode( identifierName, identifierName.WithIdentifier(SyntaxFactory.Identifier(name)) .WithLeadingTriviaFrom(identifierName)), "Prefer parameter.", diagnostic); } } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan); if (node is IdentifierNameSyntax identifierName) { context.RegisterCodeFix( "Throw if null.", (editor, _) => editor.ReplaceNode( node, SyntaxFactory.ParseExpression($"{identifierName.Identifier.ValueText} ?? throw new System.ArgumentNullException(nameof({identifierName.Identifier.ValueText}))").WithSimplifiedNames()), this.GetType(), diagnostic); } else if (node is ParameterSyntax parameter) { var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); var method = parameter.FirstAncestor <BaseMethodDeclarationSyntax>(); if (method != null) { using (var walker = AssignmentWalker.Create(method, Search.TopLevel, semanticModel, context.CancellationToken)) { if (TryFirstAssignedWith(parameter, walker.Assignments, out var assignedValue)) { context.RegisterCodeFix( "Throw if null on first assignment.", (editor, _) => editor.ReplaceNode( assignedValue, SyntaxFactory.ParseExpression($"{assignedValue.Identifier.ValueText} ?? throw new System.ArgumentNullException(nameof({assignedValue.Identifier.ValueText}))").WithSimplifiedNames()), this.GetType(), diagnostic); } else if (method.Body != null) { context.RegisterCodeFix( "Add null check.", (editor, _) => editor.ReplaceNode( method.Body, method.Body.InsertNodesBefore( method.Body.Statements[0], new[] { IfNullThrow(parameter.Identifier.ValueText) })), this.GetType(), diagnostic); } } } } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan); if (node is IdentifierNameSyntax identifierName) { context.RegisterCodeFix( "Throw if null.", (editor, _) => editor.ReplaceNode( node, SyntaxFactory.ParseExpression($"{identifierName.Identifier.ValueText} ?? throw new System.ArgumentNullException(nameof({identifierName.Identifier.ValueText}))").WithSimplifiedNames()), this.GetType(), diagnostic); } else if (node is ParameterSyntax parameter) { var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); if (parameter.Parent is ParameterListSyntax parameterList && parameterList.Parent is BaseMethodDeclarationSyntax methodDeclaration) { using (var walker = AssignmentExecutionWalker.Borrow(methodDeclaration, Scope.Member, semanticModel, context.CancellationToken)) { if (TryFirstAssignedWith(parameter, walker.Assignments, out var assignedValue)) { context.RegisterCodeFix( "Throw if null on first assignment.", (editor, _) => editor.ReplaceNode( assignedValue, SyntaxFactory.ParseExpression($"{assignedValue.Identifier.ValueText} ?? throw new System.ArgumentNullException(nameof({assignedValue.Identifier.ValueText}))").WithSimplifiedNames()), this.GetType(), diagnostic); } else if (methodDeclaration.Body is BlockSyntax block) { context.RegisterCodeFix( "Add null check.", (editor, _) => editor.ReplaceNode( block, x => WithNullCheck(x, parameter)), this.GetType(), diagnostic); } } } } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { var token = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start); if (string.IsNullOrEmpty(token.ValueText) || token.IsMissing) { continue; } var syntaxNode = syntaxRoot.FindNode(diagnostic.Location.SourceSpan); if (diagnostic.Id == Descriptors.GU0021CalculatedPropertyAllocates.Id) { if (syntaxNode is ObjectCreationExpressionSyntax objectCreation) { var arguments = objectCreation.ArgumentList.Arguments; var hasMutable = IsAnyArgumentMutable(semanticModel, context.CancellationToken, arguments) || IsAnyInitializerMutable(semanticModel, context.CancellationToken, objectCreation.Initializer); var property = syntaxNode.FirstAncestorOrSelf <PropertyDeclarationSyntax>(); if (TryGetConstructor(property, out var ctor)) { context.RegisterCodeFix( "Use get-only" + (hasMutable ? " UNSAFE" : string.Empty), (editor, cancellationToken) => ApplyInitializeInCtorFix(editor, ctor, property, objectCreation), this.GetType().FullName + "UNSAFE", diagnostic); } } } else if (diagnostic.Id == Descriptors.GU0022UseGetOnly.Id) { var setter = syntaxNode.FirstAncestorOrSelf <AccessorDeclarationSyntax>(); if (setter != null) { context.RegisterCodeFix( "Use get-only", (editor, _) => ApplyRemoveSetterFix(editor, setter), this.GetType(), diagnostic); } } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { var token = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start); if (string.IsNullOrEmpty(token.ValueText) || token.IsMissing) { continue; } var arguments = (ArgumentListSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan); if (HasAnyNamedArgument(arguments)) { continue; } var method = semanticModel.GetSymbolSafe(arguments.Parent, context.CancellationToken) as IMethodSymbol; if (method == null) { continue; } context.RegisterCodeFix( "Name arguments", (editor, _) => ApplyFix(editor, method, arguments), this.GetType(), diagnostic); } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { var token = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start); if (string.IsNullOrEmpty(token.ValueText) || token.IsMissing) { continue; } if (diagnostic.Id == Descriptors.GU0001NameArguments.Id && syntaxRoot.TryFindNode <ArgumentListSyntax>(diagnostic, out var arguments) && !HasAnyNamedArgument(arguments) && semanticModel.TryGetSymbol(arguments.Parent, context.CancellationToken, out IMethodSymbol method)) { context.RegisterCodeFix( "Name arguments", (editor, _) => ApplyFix(editor, method, arguments, 0), this.GetType(), diagnostic); } else if (diagnostic.Id == Descriptors.GU0009UseNamedParametersForBooleans.Id && syntaxRoot.TryFindNode <ArgumentSyntax>(diagnostic, out var boolArgument) && boolArgument.Parent is ArgumentListSyntax argumentList && !HasAnyNamedArgument(argumentList) && semanticModel.TryGetSymbol(argumentList.Parent, context.CancellationToken, out method)) { context.RegisterCodeFix( "Name arguments", (editor, _) => ApplyFix(editor, method, argumentList, argumentList.Arguments.IndexOf(boolArgument)), this.GetType(), diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { var token = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start); if (string.IsNullOrEmpty(token.ValueText) || token.IsMissing) { continue; } if (syntaxRoot.TryFindNodeOrAncestor <EventFieldDeclarationSyntax>(diagnostic, out var eventField)) { context.RegisterCodeFix( "Add [field:NonSerialized].", (editor, _) => editor.ReplaceNode( eventField, x => x.AddAttributeLists(NonSerializedWithTargetSpecifier) .WithLeadingTriviaFrom(x)), nameof(NonSerializedFix), diagnostic); continue; } if (syntaxRoot.TryFindNodeOrAncestor <FieldDeclarationSyntax>(diagnostic, out var field)) { context.RegisterCodeFix( "Add [NonSerialized].", (editor, _) => editor.ReplaceNode( field, x => x.AddAttributeLists(NonSerialized) .WithLeadingTriviaFrom(x)), nameof(NonSerializedFix), diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { var token = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start); if (string.IsNullOrEmpty(token.ValueText) || token.IsMissing) { continue; } if (diagnostic.Id == Descriptors.GU0002NamedArgumentPositionMatches.Id) { var arguments = (ArgumentListSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan); if (!HasWhitespaceTriviaOnly(arguments)) { continue; } context.RegisterCodeFix( "Move arguments to match parameter positions.", (editor, cancellationToken) => ApplyFixGU0002(editor, arguments, cancellationToken), this.GetType(), diagnostic); } if (diagnostic.Id == Descriptors.GU0005ExceptionArgumentsPositions.Id) { var argument = (ArgumentSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan); context.RegisterCodeFix( "Move name argument to match parameter positions.", (editor, cancellationToken) => ApplyFixGU0005(editor, argument, cancellationToken), this.GetType(), diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNode(diagnostic, out ParameterListSyntax parameterList) && TryFindTestAttribute(parameterList.Parent as MethodDeclarationSyntax, semanticModel, context.CancellationToken, out var attribute) && TryGetParameters(attribute, semanticModel, context.CancellationToken, out var parameters)) { context.RegisterCodeFix( "Update parameters", (editor, c) => editor.ReplaceNode( parameterList, x => x.WithParameters(parameters)), nameof(TestMethodParametersFix), diagnostic); } else if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out attribute) && attribute.TryFirstAncestor(out MethodDeclarationSyntax method) && TryGetParameters(attribute, semanticModel, context.CancellationToken, out parameters)) { context.RegisterCodeFix( "Update parameters", (editor, c) => editor.ReplaceNode( method.ParameterList, x => x.WithParameters(parameters)), nameof(TestMethodParametersFix), diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNodeOrAncestor <BasePropertyDeclarationSyntax>(diagnostic, out var property)) { context.RegisterCodeFix( "Sort property.", (editor, _) => Move(editor, property), "Sort property.", diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNodeOrAncestor <IdentifierNameSyntax>(diagnostic, out var identifierName)) { context.RegisterCodeFix( "Use lambda.", (editor, cancellationToken) => UseLambda(editor, identifierName, cancellationToken), "Use lambda.", diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out ClassDeclarationSyntax classDeclaration)) { context.RegisterCodeFix( "Make sealed.", (editor, _) => editor.MakeSealed(classDeclaration), "Make sealed.", diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNode(diagnostic, out ExpressionSyntax node) && diagnostic.Properties.TryGetValue(nameof(INamedTypeSymbol), out var typeName) && diagnostic.Properties.TryGetValue(nameof(Inject.Injectable), out var injectable)) { context.RegisterCodeFix( $"Inject {(injectable == nameof(Inject.Injectable.Safe) ? injectable.ToLower() : injectable.ToUpper())}.", (editor, cancellationToken) => Fix(editor, cancellationToken, node, typeName), nameof(InjectFix), diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out MethodDeclarationSyntax methodDeclaration)) { context.RegisterCodeFix( "Make Static.", (editor, _) => editor.ReplaceNode( methodDeclaration, x => x.WithModifiers(methodDeclaration.Modifiers.Add(SyntaxFactory.Token(SyntaxKind.StaticKeyword)))), "Make Static.", diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { var argument = syntaxRoot.FindNode(diagnostic.Location.SourceSpan) .FirstAncestorOrSelf <ArgumentSyntax>(); if (argument != null && diagnostic.Properties.TryGetValue("Name", out var name)) { context.RegisterCodeFix( "Use correct parameter name.", (editor, _) => editor.ReplaceNode( argument.Expression, SyntaxFactory.ParseExpression($"nameof({name})")), this.GetType(), diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNode(diagnostic, out ArgumentSyntax argument) && diagnostic.Properties.TryGetValue(nameof(IdentifierNameSyntax), out var name)) { context.RegisterCodeFix( $"Use nameof({name}).", (editor, _) => editor.ReplaceNode( argument.Expression, x => CreateNode(x).WithTriviaFrom(x)), this.GetType(), diagnostic); ExpressionSyntax CreateNode(ExpressionSyntax old) { switch (old) { case LiteralExpressionSyntax literal when literal.IsKind(SyntaxKind.StringLiteralExpression): return(SyntaxFactory.ParseExpression($"nameof({name})")); case IdentifierNameSyntax identifierName when identifierName.Parent is ArgumentSyntax candidate && candidate.Parent is ArgumentListSyntax argumentList && argumentList.Parent is InvocationExpressionSyntax invocation && invocation.IsNameOf(): return(identifierName.WithIdentifier(SyntaxFactory.Identifier(name))); default: throw new InvalidOperationException("Failed updating parameter name."); } } } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { var token = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start); if (string.IsNullOrEmpty(token.ValueText) || token.IsMissing) { continue; } if (syntaxRoot.FindNode(diagnostic.Location.SourceSpan) is ArgumentSyntax argument && argument.Expression is LiteralExpressionSyntax literal) { context.RegisterCodeFix( "Use nameof", (editor, cancellationToken) => ApplyFix(editor, argument, literal.Token.ValueText, cancellationToken), this.GetType(), diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out BaseMethodDeclarationSyntax methodDeclaration)) { if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out ParameterSyntax parameter) && methodDeclaration.TryGetDocumentationComment(out var docs)) { if (StandardDocs.TryGet(parameter, out var text)) { context.RegisterCodeFix( "Generate standard xml documentation for parameter.", (editor, _) => editor.ReplaceNode( docs, x => x.WithParamText(parameter.Identifier.ValueText, text)), text, diagnostic); } else if (parameter.Type is PredefinedTypeSyntax) { context.RegisterCodeFix( "Generate useless xml documentation for parameter.", (editor, _) => editor.ReplaceNode( docs, x => x.WithParamText(parameter.Identifier.ValueText, string.Empty)), nameof(UselessDocsFix), diagnostic); } else { context.RegisterCodeFix( "Generate useless xml documentation for parameter.", (editor, _) => editor.ReplaceNode( docs, x => x.WithParamText(parameter.Identifier.ValueText, $"The <see cref=\"{parameter.Type.ToString().Replace("<", "{").Replace(">", "}")}\"/>.")), nameof(UselessDocsFix), diagnostic); } } else if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out TypeParameterSyntax typeParameter) && methodDeclaration.TryGetDocumentationComment(out docs)) { if (TryGetTypeParameterText(methodDeclaration, typeParameter, semanticModel, context.CancellationToken, out var text)) { context.RegisterCodeFix( "Generate useless xml documentation for type parameter.", (editor, _) => editor.ReplaceNode( docs, x => x.WithTypeParamText(typeParameter.Identifier.ValueText, text)), nameof(UselessDocsFix), diagnostic); } else { context.RegisterCodeFix( "Generate empty xml documentation for type parameter.", (editor, _) => editor.ReplaceNode( docs, x => x.WithTypeParamText(typeParameter.Identifier.ValueText, string.Empty)), nameof(UselessDocsFix), diagnostic); } } else if (syntaxRoot.FindNode(diagnostic.Location.SourceSpan, findInsideTrivia: true, getInnermostNodeForTie: true) is XmlElementSyntax element && element.TryGetNameAttribute(out var name) && methodDeclaration.TryFindParameter(name.Identifier?.Identifier.ValueText, out parameter)) { if (StandardDocs.TryGet(parameter, out var text)) { context.RegisterCodeFix( "Generate standard xml documentation for parameter.", (editor, _) => editor.ReplaceNode( element, x => WithText(x, text)), text, diagnostic); } else { context.RegisterCodeFix( "Generate useless xml documentation for parameter.", (editor, _) => editor.ReplaceNode( element, x => WithText(x, $"The <see cref=\"{parameter.Type.ToString().Replace("<", "{").Replace(">", "}")}\"/>.")), nameof(UselessDocsFix), diagnostic); } } } } }