public override async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var diagnostic = context.Diagnostics.FirstOrDefault(); if (diagnostic == null) { return; } var diagnosticSpan = diagnostic.Location.SourceSpan; // Find the type declaration identified by the diagnostic. var node = root.FindNode(diagnosticSpan, getInnermostNodeForTie: true); if (!(node is LiteralExpressionSyntax literal)) { return; } var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken); var compilation = semanticModel.Compilation; if (WellKnownTypes.TranslationCatalog(compilation) != null) { RegisterCodeFix(context, IdentifierName("TranslationCatalog"), root, literal); } if (WellKnownTypes.GettextCatalog(compilation) != null) { RegisterCodeFix(context, IdentifierName("GettextCatalog"), root, literal); } if (WellKnownTypes.AddinLocalizer(compilation) != null) { var memberAccess = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("AddinManager"), IdentifierName("CurrentLocalizer")); RegisterCodeFix(context, memberAccess, root, literal); } if (WellKnownTypes.MonoUnixCatalog(compilation) != null) { RegisterCodeFix(context, IdentifierName("Catalog"), root, literal); } }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { // false positive list: // ComponentModelLocalization:40 // // Limit search to compilations which reference the specific localizers. var compilation = compilationContext.Compilation; var translationCatalogType = WellKnownTypes.TranslationCatalog(compilation); var gettextType = WellKnownTypes.GettextCatalog(compilation); var addinsLocalizerType = WellKnownTypes.AddinLocalizer(compilation); var addinsLocalizerInterface = WellKnownTypes.IAddinLocalizer(compilation); var unixCatalog = WellKnownTypes.MonoUnixCatalog(compilation); if (gettextType == null && translationCatalogType == null && addinsLocalizerType == null && addinsLocalizerInterface == null && unixCatalog == null) { return; } compilationContext.RegisterOperationAction(operationContext => { // if we're in a catalog context, do not flag var symbol = operationContext.ContainingSymbol; if (symbol.Name == "GetString" || symbol.Name == "GetPluralString") { if (symbol.GetContainingTypeOrThis().IsCatalogType(gettextType, translationCatalogType, unixCatalog, addinsLocalizerType, addinsLocalizerInterface)) { return; } } var invocation = (IInvocationOperation)operationContext.Operation; var targetMethod = invocation.TargetMethod; if (targetMethod == null || (targetMethod.Name != "GetString" && targetMethod.Name != "GetStringPlural")) { return; } var containingType = targetMethod.ContainingType; if (!containingType.IsCatalogType(gettextType, translationCatalogType, unixCatalog, addinsLocalizerType, addinsLocalizerInterface)) { return; } if (invocation.Arguments.Length < 1) { return; } var phrase = invocation.Arguments[0]; if (phrase.Parameter.Type.SpecialType != SpecialType.System_String) { return; } if (phrase.Value.IsLiteralOperation()) { return; } operationContext.ReportDiagnostic(Diagnostic.Create(descriptor, phrase.Syntax.GetLocation())); }, OperationKind.Invocation); }); }