/// <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 MemberDeclarationSyntax member) && diagnostic.AdditionalLocations.TrySingle(out var additionalLocation) && syntaxRoot.FindNode(additionalLocation.SourceSpan)?.FirstAncestorOrSelf <MemberDeclarationSyntax>() is MemberDeclarationSyntax other && member.SharesAncestor(other, out ClassDeclarationSyntax type)) { context.RegisterCodeFix( $"Move", (e, _) => e.ReplaceNode( type, x => { if (x.Members.IndexOf(m => m.IsEquivalentTo(member)) is var fromIndex && fromIndex >= 0 && x.Members.IndexOf(m => m.IsEquivalentTo(other)) is var toIndex && toIndex < fromIndex) { return(x.WithMembers(x.Members.RemoveAt(fromIndex).Insert(toIndex, member.WithLeadingElasticLineFeed().WithTrailingLineFeed()))); } return(x); }),
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(nameof(TypeSyntax), out var typesText) && syntaxRoot.TryFindNodeOrAncestor(diagnostic, out InvocationExpressionSyntax invocation) && invocation.Expression is MemberAccessExpressionSyntax) { context.RegisterCodeFix( $"Call MakeGenericMethod({typesText}).", (editor, _) => editor.ReplaceNode( invocation, x => { var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression; return(x.WithExpression(memberAccess.WithExpression(SyntaxFactory.ParseExpression($"{memberAccess.Expression.ToFullString()}.MakeGenericMethod({typesText})")))); }), nameof(CallMakeGenericMethodFix), diagnostic); } } }
protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNodeOrAncestor <ClassDeclarationSyntax>(diagnostic, out var classDeclaration)) { if (ValueConverter.TryGetConversionTypes(classDeclaration, semanticModel, context.CancellationToken, out var sourceType, out var targetType)) { context.RegisterCodeFix( $"Add [ValueConversion(typeof({sourceType}), typeof({targetType}))].", (e, _) => AddAttribute(e, classDeclaration, sourceType, targetType), $"Add [ValueConversion(typeof({sourceType}), typeof({targetType}))].", diagnostic); } else { context.RegisterCodeFix( $"Add [ValueConversion(typeof({sourceType?.ToString() ?? "TYPE"}), typeof({targetType?.ToString() ?? "TYPE"}))].", (e, _) => AddAttribute(e, classDeclaration, sourceType, targetType), $"Add [ValueConversion(typeof({sourceType?.ToString() ?? "TYPE"}), typeof({targetType?.ToString() ?? "TYPE"}))].", diagnostic); } } }
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.FindNode(diagnostic.Location.SourceSpan, findInsideTrivia: false, getInnermostNodeForTie: true) is LiteralExpressionSyntax literal && diagnostic.Properties.TryGetValue(nameof(SyntaxKind.StringLiteralExpression), out var text)) { context.RegisterCodeFix( $"Use fully qualified name: {text}.", (editor, _) => editor.ReplaceNode( literal, x => x.WithToken(SyntaxFactory.Literal(text))), nameof(UseFullyQualifiedFix), diagnostic); } if (syntaxRoot.FindNode(diagnostic.Location.SourceSpan, findInsideTrivia: false, getInnermostNodeForTie: true) is IdentifierNameSyntax identifierName && diagnostic.Properties.TryGetValue(nameof(SimpleNameSyntax), out var name)) { context.RegisterCodeFix( $"Use fully qualified name: {name}.", (editor, _) => editor.ReplaceNode( identifierName, x => x.WithIdentifier(SyntaxFactory.Identifier(name))), nameof(UseFullyQualifiedFix), diagnostic); } } }
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>(); switch (argument?.Expression) { case LiteralExpressionSyntax literal when literal.IsKind(SyntaxKind.StringLiteralExpression) && diagnostic.Properties.TryGetValue(nameof(MemberAccessExpressionSyntax), out var member): context.RegisterCodeFix( "Use nameof.", (editor, _) => editor.ReplaceNode( literal, (x, g) => SyntaxFactory.ParseExpression($"nameof({member}.{literal.Token.ValueText})")), "Use nameof.", diagnostic); break; case MemberAccessExpressionSyntax memberAccess: context.RegisterCodeFix( "Use nameof.", (editor, _) => editor.ReplaceNode( memberAccess, (x, g) => SyntaxFactory.ParseExpression($"nameof({memberAccess})")), "Use nameof.", diagnostic); break; } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await 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)) { continue; } if (syntaxRoot.FindNode(diagnostic.Location.SourceSpan).TryFirstAncestorOrSelf <MethodDeclarationSyntax>(out var methodDeclaration) && semanticModel.TryGetSymbol(methodDeclaration, context.CancellationToken, out var method) && method.Parameters.TrySingle(out var parameter)) { context.RegisterCodeFix( $"Add [AttachedPropertyBrowsableForTypeAttribute(typeof({parameter.Type})))].", (e, _) => AddAttribute(e, methodDeclaration, parameter.Type), this.GetType().FullName, diagnostic); } } }
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.FindToken(diagnostic.Location.SourceSpan.Start) is SyntaxToken token) { if (token.IsKind(SyntaxKind.PrivateKeyword)) { context.RegisterCodeFix( $"Change to: protected.", (editor, _) => editor.ReplaceToken( token, SyntaxFactory.Token(SyntaxKind.ProtectedKeyword)), nameof(MakeProtectedFix), diagnostic); } else if (token.IsKind(SyntaxKind.IdentifierToken) && token.Parent is MethodDeclarationSyntax methodDeclaration) { context.RegisterCodeFix( $"Make protected.", (editor, _) => editor.ReplaceNode( methodDeclaration, methodDeclaration.WithModifiers(methodDeclaration.Modifiers.Insert(0, SyntaxFactory.Token(SyntaxKind.ProtectedKeyword)))), nameof(MakeProtectedFix), diagnostic); } } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await 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)) { continue; } if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out MemberDeclarationSyntax member) && semanticModel.TryGetSymbol(member, context.CancellationToken, out ISymbol symbol) && BackingFieldOrProperty.TryCreateForDependencyProperty(symbol, out var fieldOrProperty) && DependencyProperty.TryGetRegisteredName(fieldOrProperty, semanticModel, context.CancellationToken, out var name)) { context.RegisterCodeFix( "Add standard documentation.", (editor, _) => editor.ReplaceNode(member, x => x.WithDocumentationText($"/// <summary>Identifies the <see cref=\"{name}\"/> dependency property.</summary>")), this.GetType(), diagnostic); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await 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)) { continue; } var argument = syntaxRoot.FindNode(diagnostic.Location.SourceSpan) .FirstAncestorOrSelf <AttributeArgumentSyntax>(); var attribute = argument.FirstAncestor <AttributeSyntax>(); if (MarkupExtension.TryGetReturnType(attribute.FirstAncestor <ClassDeclarationSyntax>(), semanticModel, context.CancellationToken, out var returnType)) { context.RegisterCodeFix( $"Change type to {returnType}.", (e, _) => FixType(e, argument, returnType), this.GetType(), diagnostic); } } }
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 InvocationExpressionSyntax? setValue) && TryGetName(setValue, out var identifierName)) { context.RegisterCodeFix( setValue.ToString().Replace("SetValue", "SetCurrentValue"), (editor, _) => editor.ReplaceNode( identifierName, x => x.WithIdentifier(SyntaxFactory.Identifier("SetCurrentValue")).WithTriviaFrom(x)), nameof(UseSetCurrentValueFix), diagnostic); } else if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out AssignmentExpressionSyntax? assignment) && TryCreatePath(assignment, out var path) && diagnostic.Properties.TryGetValue(nameof(BackingFieldOrProperty), out var backingFieldOrProperty)) { var expressionString = $"{path}SetCurrentValue({backingFieldOrProperty}, {Cast(assignment)}{assignment.Right})"; context.RegisterCodeFix( expressionString, (editor, _) => editor.ReplaceNode( assignment, x => SyntaxFactory.ParseExpression(expressionString).WithTriviaFrom(x)), nameof(UseSetCurrentValueFix), diagnostic); }
protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out InvocationExpressionSyntax? invocation) && diagnostic.Properties.TryGetValue(nameof(DependencyPropertyKeyType), out var keyName)) { context.RegisterCodeFix( invocation.ToString(), (e, _) => e.ReplaceNode(invocation.Expression, x => SetValue(x)) .ReplaceNode(invocation.ArgumentList.Arguments[0].Expression, x => PropertyKey(x)), this.GetType().FullName, diagnostic); ExpressionSyntax PropertyKey(ExpressionSyntax old) { return(old switch { IdentifierNameSyntax id => id.WithIdentifier(SyntaxFactory.Identifier(keyName)), MemberAccessExpressionSyntax { Name : IdentifierNameSyntax id } ma => ma.WithName(id.WithIdentifier(SyntaxFactory.Identifier(keyName))), _ => old, }); }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNodeOrAncestor <ClassDeclarationSyntax>(diagnostic, out var classDeclaration)) { if (diagnostic.Properties.TryGetValue(nameof(AttributeListSyntax), out var attribute)) { context.RegisterCodeFix( $"Add {attribute}.", (e, _) => { e.ReplaceNode( classDeclaration, classDeclaration.WithAttributeLists( classDeclaration.AttributeLists.Add( ParseAttributeList(attribute)))); }, "[TemplatePart]", diagnostic); } } } }
protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out ClassDeclarationSyntax? classDeclaration) && MarkupExtension.TryGetReturnType(classDeclaration, semanticModel, context.CancellationToken, out var returnType)) { context.RegisterCodeFix( "Add MarkupExtensionReturnTypeAttribute.", (e, _) => AddAttribute(e), "Add MarkupExtensionReturnTypeAttribute.", diagnostic); void AddAttribute(DocumentEditor editor) { editor.AddAttribute( classDeclaration, editor.Generator.AddAttributeArguments( Attribute, new[] { editor.Generator.AttributeArgument(editor.Generator.TypeOfExpression(editor.Generator.TypeExpression(returnType))) })); } } } }
/// <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 AssignmentExpressionSyntax? assignment) && diagnostic.AdditionalLocations.TrySingle(out var additionalLocation) && syntaxRoot.FindNode(additionalLocation.SourceSpan) is ExpressionSyntax fieldAccess) { context.RegisterCodeFix( "Set backing field.", (e, cancellationToken) => e.ReplaceNode( assignment.Left, (x, _) => Qualify(fieldAccess).WithTriviaFrom(x)), nameof(SetBackingFieldFix), diagnostic); ExpressionSyntax Qualify(ExpressionSyntax expression) { if (expression is IdentifierNameSyntax identifierName && (Scope.HasParameter(assignment, identifierName.Identifier.ValueText) || Scope.HasLocal(assignment, identifierName.Identifier.ValueText))) { return(InpcFactory.SymbolAccess(identifierName.Identifier.ValueText, CodeStyleResult.Yes)); } return(expression); } } } }
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(nameof(ITypeSymbol.ContainingType), out var typeName)) { if (syntaxRoot.TryFindNode(diagnostic, out TypeSyntax type)) { context.RegisterCodeFix( $"Use containing type: {typeName}.", (editor, _) => editor.ReplaceNode( type, x => SyntaxFactory.ParseTypeName(typeName) .WithTriviaFrom(x)), nameof(UseContainingTypeFix), diagnostic); } else if (syntaxRoot.TryFindNode(diagnostic, out MemberAccessExpressionSyntax memberAccess) && memberAccess.Expression is ExpressionSyntax expression) { context.RegisterCodeFix( $"Use containing type: {typeName}.", (editor, _) => editor.ReplaceNode( expression, x => SyntaxFactory.ParseExpression($"typeof({typeName})").WithTriviaFrom(x)), nameof(UseContainingTypeFix), diagnostic); } } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await 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)) { continue; } var classDeclaration = syntaxRoot.FindNode(diagnostic.Location.SourceSpan) .FirstAncestorOrSelf <ClassDeclarationSyntax>(); if (classDeclaration != null && MarkupExtension.TryGetReturnType(classDeclaration, semanticModel, context.CancellationToken, out var returnType)) { context.RegisterCodeFix( "Add MarkupExtensionReturnTypeAttribute.", (e, _) => AddAttribute(e, classDeclaration, returnType), "Add MarkupExtensionReturnTypeAttribute.", diagnostic); } } }
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(nameof(TypeSyntax), out var typeText) && syntaxRoot.TryFindNode(diagnostic, out TypeSyntax typeSyntax) && typeSyntax.Parent is PropertyDeclarationSyntax property && property.TryGetGetter(out var getter)) { context.RegisterCodeFix( $"Change to: {typeText}.", (editor, _) => editor.ReplaceNode( typeSyntax, x => SyntaxFactory.ParseTypeName(typeText).WithTriviaFrom(x)) .ReplaceNode( getter, x => WithCast(x, typeText)), nameof(UseRegisteredTypeFix), diagnostic); } } }
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); switch (node) { case AssignmentExpressionSyntax { Left: { } left } assignment: context.RegisterCodeFix( "Dispose before re-assigning.", (editor, cancellationToken) => DisposeBefore(editor, left, assignment, cancellationToken), "Dispose before re-assigning.", diagnostic); break; case ArgumentSyntax { Expression: { } expression } argument: context.RegisterCodeFix( "Dispose before re-assigning.", (editor, cancellationToken) => DisposeBefore(editor, expression, argument, cancellationToken), "Dispose before re-assigning.", diagnostic); break; } } }
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.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true) is LiteralExpressionSyntax literal && literal.IsKind(SyntaxKind.StringLiteralExpression) && TryGetNameAndArity(literal, out var typeName, out var arity)) { foreach (var assembly in new[] { semanticModel.Compilation.Assembly }.Concat(semanticModel.Compilation.Assembly.Modules.SelectMany(x => x.ReferencedAssemblySymbols))) { foreach (var type in GetTypes(assembly.GlobalNamespace, typeName, arity)) { context.RegisterCodeFix( $"Use: {type}.", (editor, _) => editor.ReplaceNode( literal, x => x.WithToken(SyntaxFactory.Literal(type.QualifiedMetadataName()))), nameof(SuggestTypeFix), diagnostic); } } } } }
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( "Add OnPropertyChanged()", (editor, cancellationToken) => editor.AddOnPropertyChangedMethodAsync( classDeclaration, editor.SemanticModel.GetNullableContext(classDeclaration.SpanStart).AnnotationsEnabled(), cancellationToken), "Add OnPropertyChanged()", diagnostic); if (!classDeclaration.Modifiers.Any(SyntaxKind.AbstractKeyword) && !classDeclaration.Modifiers.Any(SyntaxKind.StaticKeyword)) { var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); if (ShouldSeal(classDeclaration, semanticModel, context.CancellationToken)) { context.RegisterCodeFix( "Seal class.", (editor, _) => editor.Seal(classDeclaration), "Seal class.", diagnostic); } } } } }
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(nameof(TypeSyntax), out var typeString)) { if (syntaxRoot.TryFindNode(diagnostic, out TypeSyntax typeSyntax)) { context.RegisterCodeFix( $"Cast to {typeString}.", (editor, _) => editor.ReplaceNode( typeSyntax, x => SyntaxFactory.ParseTypeName(typeString)), nameof(CastReturnValueFix), diagnostic); } else if (syntaxRoot.TryFindNode(diagnostic, out InvocationExpressionSyntax invocation)) { context.RegisterCodeFix( $"Cast to {typeString}.", (editor, _) => editor.ReplaceNode( invocation, x => SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName(typeString), x)), nameof(CastReturnValueFix), diagnostic); } } } }
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 InvocationExpressionSyntax? invocation) && IdentifierName() is { } identifier) { context.RegisterCodeFix( "Use SetValue", e => e.ReplaceNode( identifier, x => x.WithIdentifier(SyntaxFactory.Identifier("SetValue"))), "Use SetValue", diagnostic); } IdentifierNameSyntax?IdentifierName() { return(invocation !.Expression switch { IdentifierNameSyntax identifierName => identifierName, MemberAccessExpressionSyntax { Name : IdentifierNameSyntax identifierName } => identifierName,
protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out TypeOfExpressionSyntax? typeofExpression) && typeofExpression.TryFirstAncestor(out TypeDeclarationSyntax? typeDeclaration) && semanticModel.TryGetSymbol(typeDeclaration, context.CancellationToken, out var containingType)) { var containingTypeName = containingType.ToMinimalDisplayString(semanticModel, typeofExpression.SpanStart, SymbolDisplayFormat.MinimallyQualifiedFormat); context.RegisterCodeFix( $"Use containing type: {containingTypeName}.", (editor, _) => editor.ReplaceNode( typeofExpression, x => x.WithType(SyntaxFactory.ParseTypeName(containingTypeName))), "Use containing type.", diagnostic); } } }
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 InvocationExpressionSyntax invocation) && invocation.ArgumentList is ArgumentListSyntax argumentList && argumentList.Arguments.TrySingle(out var arg) && IsAssignableFromAnalyzer.IsInstanceGetType(arg.Expression, semanticModel, context.CancellationToken, out var instance)) { context.RegisterCodeFix( $"Change to: IsInstanceOfType().", (editor, _) => editor.ReplaceNode( invocation.Expression, x => { var memberAccess = (MemberAccessExpressionSyntax)x; return(memberAccess.WithName(memberAccess.Name.WithIdentifier(SyntaxFactory.Identifier("IsInstanceOfType")))); }) .ReplaceNode( arg.Expression, x => instance.WithTriviaFrom(x)), nameof(UseIsInstanceOfTypeFix), 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 ArgumentSyntax? argument) && argument.Expression is LiteralExpressionSyntax literal && semanticModel.LookupSymbols(argument.SpanStart, name: literal.Token.ValueText).TryFirst(out var member)) { context.RegisterCodeFix( "Use nameof", async(editor, cancellationToken) => { var replacement = await editor.SymbolAccessAsync(member, literal, cancellationToken) .ConfigureAwait(false); _ = editor.ReplaceNode( literal, x => InpcFactory.Nameof(replacement).WithTriviaFrom(x)); }, nameof(UseNameofFix), diagnostic); } } }
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 (IsSupportedDiagnostic(diagnostic) && syntaxRoot.TryFindNodeOrAncestor(diagnostic, out TypeDeclarationSyntax? typeDeclaration)) { if (diagnostic.Id == Descriptors.IDISP009IsIDisposable.Id) { context.RegisterCodeFix( "Add IDisposable interface", (editor, cancellationToken) => editor.AddInterfaceType(typeDeclaration, IDisposableFactory.SystemIDisposable), "add interface", diagnostic); } else if (typeDeclaration is StructDeclarationSyntax structDeclaration) { context.RegisterCodeFix( "Implement IDisposable.", (editor, _) => editor.AddMethod(structDeclaration, MethodFactory.Dispose()), "Struct", diagnostic); } else if (typeDeclaration is ClassDeclarationSyntax classDeclaration && semanticModel.TryGetNamedType(classDeclaration, context.CancellationToken, out var type)) { if (Disposable.IsAssignableFrom(type, semanticModel.Compilation) && type.TryFindFirstMethodRecursive("Dispose", x => x.IsVirtual, out var baseDispose)) { context.RegisterCodeFix( $"override {baseDispose}", (editor, cancellationToken) => OverrideDisposeAsync(editor, cancellationToken), "override", diagnostic); async Task OverrideDisposeAsync(DocumentEditor editor, CancellationToken cancellationToken) { var disposed = await editor.AddFieldAsync( classDeclaration, "disposed", Accessibility.Private, DeclarationModifiers.None, SyntaxFactory.ParseTypeName("bool"), cancellationToken).ConfigureAwait(false); _ = editor.AddMethod(classDeclaration, MethodFactory.OverrideDispose(disposed, baseDispose !)) .AddThrowIfDisposed(classDeclaration, disposed, cancellationToken); } } else if (CanImplement()) { switch (type) { case { IsSealed: true } :
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await 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)) { continue; } var argument = syntaxRoot.FindNode(diagnostic.Location.SourceSpan) .FirstAncestorOrSelf <AttributeArgumentSyntax>(); var attribute = argument.FirstAncestor <AttributeSyntax>(); if (ValueConverter.TryGetConversionTypes( attribute.FirstAncestor <ClassDeclarationSyntax>(), semanticModel, context.CancellationToken, out var sourceType, out var targetType)) { context.RegisterCodeFix( $"Change to [ValueConversion(typeof({sourceType}), typeof({targetType}))].", (e, _) => FixArgument(e, attribute, sourceType, targetType), $"Change to [ValueConversion(typeof({sourceType}), typeof({targetType}))].", diagnostic); } } }
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 InvocationExpressionSyntax invocation) && invocation.ArgumentList is ArgumentListSyntax argumentList) { if (argumentList.Arguments.Count == 1) { context.RegisterCodeFix( "Throw on error.", (e, cancellationToken) => e.ReplaceNode( argumentList, x => x.AddArguments(SyntaxFactory.Argument(SyntaxFactory.NameColon("throwOnError"), SyntaxFactory.Token(SyntaxKind.None), SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression)))), "Throw on error.", diagnostic); } else if (argumentList.Arguments.Count == 2 && argumentList.Arguments.TrySingle(x => x.Expression.IsKind(SyntaxKind.FalseLiteralExpression), out var argument)) { context.RegisterCodeFix( "Throw on error.", (e, cancellationToken) => e.ReplaceNode( argument.Expression, x => SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression).WithTriviaFrom(x)), "Throw on error.", diagnostic); } } } }
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(nameof(TypeSyntax), out var typeText)) { if (syntaxRoot.TryFindNode(diagnostic, out TypeSyntax typeSyntax) && typeSyntax.Parent is TypeOfExpressionSyntax) { context.RegisterCodeFix( $"Change to: {typeText}.", (editor, _) => editor.ReplaceNode( typeSyntax, x => SyntaxFactory.ParseTypeName(typeText) .WithTriviaFrom(x)), nameof(UseParameterTypeFix), diagnostic); } else if (syntaxRoot.TryFindNode(diagnostic, out ExpressionSyntax expression)) { context.RegisterCodeFix( $"Change to: typeof({typeText}).", (editor, _) => editor.ReplaceNode( expression, x => SyntaxFactory.ParseExpression($"typeof({typeText})") .WithTriviaFrom(x)), nameof(UseParameterTypeFix), diagnostic); } } } }
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 ExpressionSyntax? expression) && semanticModel.TryGetSymbol(expression, context.CancellationToken, out var symbol) && diagnostic.AdditionalLocations.TrySingle(out var valueLocation) && syntaxRoot.FindNode(valueLocation.SourceSpan) is ExpressionSyntax value && expression.TryFirstAncestor(out BlockSyntax? block)) { context.RegisterCodeFix( $"Copy to local.", (editor, _) => { var identifierName = SyntaxFactory.IdentifierName(symbol.Name.ToFirstCharLower()); editor.ReplaceNode( expression, identifierName); editor.InsertBefore( block.Statements[0], editor.Generator.LocalDeclarationStatement(identifierName.Identifier.ValueText, value)); }, nameof(CopyToLocalFix), diagnostic); } } }