mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-05 22:29:40 +00:00
Fixed and guarded the I18N key collection against missing keys (#936)
This commit is contained in:
1 parent
415ed35422
commit
99089f853e
11 files changed
+164
-34
No files matched your search
@@ -14,4 +14,5 @@
|
||||
MWAIS0008 | Naming | Error | LocalConstantsAnalyzer
|
||||
MWAIS0009 | Usage | Error | StaticServiceProviderCacheAnalyzer
|
||||
MWAIS0010 | Usage | Error | CanonicalJsonConfigurationAnalyzer
|
||||
MWAIS0011 | Usage | Error | CanonicalJsonShapeAnalyzer
|
||||
MWAIS0011 | Usage | Error | CanonicalJsonShapeAnalyzer
|
||||
MWAIS0012 | Usage | Error | DirectI18NGetTextAnalyzer
|
||||
@@ -13,4 +13,5 @@ public static class Identifier
|
||||
public const string STATIC_SERVICE_PROVIDER_CACHE_ANALYZER = $"{Tools.ID_PREFIX}0009";
|
||||
public const string CANONICAL_JSON_CONFIGURATION_ANALYZER = $"{Tools.ID_PREFIX}0010";
|
||||
public const string CANONICAL_JSON_SHAPE_ANALYZER = $"{Tools.ID_PREFIX}0011";
|
||||
public const string DIRECT_I18N_GET_TEXT_ANALYZER = $"{Tools.ID_PREFIX}0012";
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
using Microsoft.CodeAnalysis.Operations;
|
||||
|
||||
namespace SourceCodeRules.UsageAnalyzers;
|
||||
|
||||
#pragma warning disable RS1038
|
||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||
#pragma warning restore RS1038
|
||||
public sealed class DirectI18NGetTextAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
private const string DIAGNOSTIC_ID = Identifier.DIRECT_I18N_GET_TEXT_ANALYZER;
|
||||
|
||||
private const string TITLE = "Direct translation lookup is not allowed";
|
||||
|
||||
private const string MESSAGE_FORMAT = "Call GetText only from a T or TB wrapper whose first string parameter is forwarded as the fallback text";
|
||||
|
||||
private const string DESCRIPTION = "Translation calls must use collector-compatible T or TB wrappers so that every fallback text is included in the generated I18N resources.";
|
||||
|
||||
private const string CATEGORY = "Usage";
|
||||
|
||||
private static readonly DiagnosticDescriptor RULE = new(DIAGNOSTIC_ID, TITLE, MESSAGE_FORMAT, CATEGORY, DiagnosticSeverity.Error, isEnabledByDefault: true, description: DESCRIPTION);
|
||||
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [RULE];
|
||||
|
||||
public override void Initialize(AnalysisContext context)
|
||||
{
|
||||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
|
||||
context.EnableConcurrentExecution();
|
||||
context.RegisterSyntaxNodeAction(AnalyzeInvocation, SyntaxKind.InvocationExpression);
|
||||
}
|
||||
|
||||
private static void AnalyzeInvocation(SyntaxNodeAnalysisContext context)
|
||||
{
|
||||
var invocation = (InvocationExpressionSyntax)context.Node;
|
||||
if (context.SemanticModel.GetSymbolInfo(invocation).Symbol is not IMethodSymbol method)
|
||||
return;
|
||||
|
||||
var targetMethod = method.ReducedFrom ?? method;
|
||||
if (targetMethod.Name != "GetText" || targetMethod.ContainingType.Name != "ILangExtensions" || targetMethod.ContainingNamespace.ToDisplayString() != "AIStudio.Tools.PluginSystem")
|
||||
return;
|
||||
|
||||
if (context.SemanticModel.GetOperation(invocation) is IInvocationOperation operation
|
||||
&& IsCollectorCompatibleWrapper(context.ContainingSymbol as IMethodSymbol, operation))
|
||||
return;
|
||||
|
||||
context.ReportDiagnostic(Diagnostic.Create(RULE, invocation.GetLocation()));
|
||||
}
|
||||
|
||||
private static bool IsCollectorCompatibleWrapper(IMethodSymbol? containingMethod, IInvocationOperation invocation)
|
||||
{
|
||||
if (containingMethod?.Name is not ("T" or "TB")
|
||||
|| containingMethod.ReturnType.SpecialType != SpecialType.System_String
|
||||
|| containingMethod.Parameters.Length == 0
|
||||
|| containingMethod.Parameters[0].Type.SpecialType != SpecialType.System_String)
|
||||
return false;
|
||||
|
||||
var fallbackArgument = invocation.Arguments.FirstOrDefault(argument => argument.Parameter?.Name == "fallbackEN");
|
||||
return fallbackArgument?.Value is IParameterReferenceOperation parameterReference
|
||||
&& SymbolEqualityComparer.Default.Equals(parameterReference.Parameter, containingMethod.Parameters[0]);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user