/// <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); } } }
/// <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 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))) })); } } } }
private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.Node is AttributeSyntax attribute) { if (context.SemanticModel.TryGetNamedType(attribute, KnownSymbols.DependsOnAttribute, context.CancellationToken, out _) && TryFindStringArgument(attribute, 0, "name", out var argument, out var expression, out string text)) { if (TryFindPropertyRecursive(context.ContainingSymbol.ContainingType, text, out var property)) { if (expression.IsKind(SyntaxKind.StringLiteralExpression)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0150UseNameofInsteadOfLiteral, expression.GetLocation(), ImmutableDictionary <string, string> .Empty.Add(nameof(IdentifierNameSyntax), property.Name), property.Name)); } else if (!argument.Expression.IsNameof()) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0151UseNameofInsteadOfConstant, expression.GetLocation(), ImmutableDictionary <string, string> .Empty.Add(nameof(IdentifierNameSyntax), property.Name), property.Name)); } } else { context.ReportDiagnostic(Diagnostic.Create(Descriptors.WPF0008DependsOnTarget, expression.GetLocation())); } } else if (context.SemanticModel.TryGetNamedType(attribute, KnownSymbols.XmlnsDefinitionAttribute, context.CancellationToken, out _) && TryFindStringArgument(attribute, 1, KnownSymbols.XmlnsDefinitionAttribute.ClrNamespaceArgumentName, out _, out expression, out text) && !TryFindNamespaceRecursive(text, out _)) { context.ReportDiagnostic(Diagnostic.Create(Descriptors.WPF0051XmlnsDefinitionMustMapExistingNamespace, expression.GetLocation(), expression)); } else if (context.SemanticModel.TryGetNamedType(attribute, KnownSymbols.MarkupExtensionReturnTypeAttribute, context.CancellationToken, out _) && context.ContainingSymbol is ITypeSymbol containingType && !containingType.IsAbstract && containingType.IsAssignableTo(KnownSymbols.MarkupExtension, context.Compilation) && attribute.TryFirstAncestor <ClassDeclarationSyntax>(out var classDeclaration) && MarkupExtension.TryGetReturnType(classDeclaration, context.SemanticModel, context.CancellationToken, out var returnType) && returnType != KnownSymbols.Object && TryFindTypeArgument(attribute, 0, "returnType", out expression, out var argumentType) && !returnType.IsAssignableTo(argumentType, context.Compilation)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0081MarkupExtensionReturnTypeMustUseCorrectType, expression.GetLocation(), properties: ImmutableDictionary <string, string> .Empty.Add(nameof(ITypeSymbol), returnType.ToMinimalDisplayString(context.SemanticModel, context.Node.SpanStart)), returnType)); }
private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.Node is AttributeSyntax attribute) { if (Attribute.IsType(attribute, KnownSymbol.XmlnsDefinitionAttribute, context.SemanticModel, context.CancellationToken) && Attribute.TryFindArgument(attribute, 1, KnownSymbol.XmlnsDefinitionAttribute.ClrNamespaceArgumentName, out var arg) && context.SemanticModel.TryGetConstantValue(arg.Expression, context.CancellationToken, out string @namespace) && context.Compilation.GetSymbolsWithName(x => !string.IsNullOrEmpty(x) && @namespace.EndsWith(x), SymbolFilter.Namespace) .All(x => x.ToMinimalDisplayString(context.SemanticModel, 0) != @namespace)) { context.ReportDiagnostic(Diagnostic.Create(WPF0051XmlnsDefinitionMustMapExistingNamespace.Descriptor, arg.GetLocation(), arg)); } else if (Attribute.IsType(attribute, KnownSymbol.MarkupExtensionReturnTypeAttribute, context.SemanticModel, context.CancellationToken) && context.ContainingSymbol is ITypeSymbol containingType && !containingType.IsAbstract && containingType.IsAssignableTo(KnownSymbol.MarkupExtension, context.Compilation) && attribute.TryFirstAncestor <ClassDeclarationSyntax>(out var classDeclaration) && MarkupExtension.TryGetReturnType(classDeclaration, context.SemanticModel, context.CancellationToken, out var returnType) && returnType != KnownSymbol.Object && Attribute.TryFindArgument(attribute, 0, "returnType", out arg) && arg.Expression is TypeOfExpressionSyntax typeOf && context.SemanticModel.TryGetType(typeOf.Type, context.CancellationToken, out var argType) && !ReferenceEquals(argType, returnType)) { context.ReportDiagnostic(Diagnostic.Create(WPF0081MarkupExtensionReturnTypeMustUseCorrectType.Descriptor, arg.GetLocation(), returnType)); } else if (Attribute.IsType(attribute, KnownSymbol.ConstructorArgumentAttribute, context.SemanticModel, context.CancellationToken) && ConstructorArgument.TryGetArgumentName(attribute, out var argument, out var argumentName) && attribute.TryFirstAncestor <PropertyDeclarationSyntax>(out var propertyDeclaration) && context.SemanticModel.TryGetSymbol(propertyDeclaration, context.CancellationToken, out var property) && ConstructorArgument.TryGetParameterName(property, context.SemanticModel, context.CancellationToken, out var parameterName) && argumentName != parameterName) { context.ReportDiagnostic( Diagnostic.Create( WPF0082ConstructorArgument.Descriptor, argument.GetLocation(), ImmutableDictionary.CreateRange(new[] { new KeyValuePair <string, string>(nameof(ConstructorArgument), parameterName) }), parameterName)); }