Skip to content

Commit

Permalink
Added uGUI_Text.SetText("", true) to LocalizationAnalyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
Jannify committed Oct 10, 2023
1 parent d3b0fea commit 72bd72a
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 1 deletion.
57 changes: 56 additions & 1 deletion Nitrox.Analyzers/Diagnostics/LocalizationAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ public sealed class LocalizationAnalyzer : DiagnosticAnalyzer

private const string NITROX_LOCALIZATION_PREFIX = "Nitrox_";
private static readonly string relativePathFromSolutionDirToEnglishLanguageFile = Path.Combine("Nitrox.Assets.Subnautica", "LanguageFiles", "en.json");
private static readonly Regex localizationParseRegex = new(@"^\s*""([^""]+)""\s*:\s*""([^""]+)""", RegexOptions.Compiled | RegexOptions.Multiline);
private static readonly Regex localizationParseRegex = new("""
^\s*"([^"]+)"\s*:\s*"([^"]+)"
""", RegexOptions.Multiline);

private static readonly DiagnosticDescriptor invalidLocalizationKeyRule = new(INVALID_LOCALIZATION_KEY_DIAGNOSTIC_ID,
"Tests localization usages are valid",
Expand Down Expand Up @@ -56,6 +58,7 @@ public override void Initialize(AnalysisContext context)
if (LocalizationHelper.Load(projectDir))
{
startContext.RegisterSyntaxNodeAction(c => AnalyzeStringNode(c, languageGetMethodSymbol), SyntaxKind.StringLiteralExpression);
startContext.RegisterSyntaxNodeAction(AnalyzeSetTextStringNode, SyntaxKind.InvocationExpression);
}
});
}
Expand Down Expand Up @@ -95,6 +98,58 @@ private void AnalyzeStringNode(SyntaxNodeAnalysisContext context, IMethodSymbol
context.ReportDiagnostic(Diagnostic.Create(invalidLocalizationKeyRule, context.Node.GetLocation(), stringValue, LocalizationHelper.FileName));
}


/// <summary>
/// Analyzes string literals in code that are passed as argument to 'Language.main.Get'.
/// </summary>
private void AnalyzeSetTextStringNode(SyntaxNodeAnalysisContext context)
{
InvocationExpressionSyntax expression = (InvocationExpressionSyntax)context.Node;
if (expression.ChildNodes().FirstOrDefault(n => n is MemberAccessExpressionSyntax) is not MemberAccessExpressionSyntax memberAccessExpression)
{
return;
}
// Performance: check SetText first to not call SemanticModel lookup for every invocation expression.
IdentifierNameSyntax funcName = memberAccessExpression.DescendantNodes().OfType<IdentifierNameSyntax>().LastOrDefault();
if (funcName?.Identifier.ValueText != "SetText")
{
return;
}
if (context.SemanticModel.GetSymbolInfo(expression).Symbol?.ContainingType.Name != "uGUI_Text")
{
return;
}

// "translate" is by default false
if (expression.ArgumentList.Arguments.Count != 2)
{
return;
}
// Only interesting if "translate" != false
SyntaxNode secondArgumentNode = expression.ArgumentList.Arguments.ElementAtOrDefault(1)?.ChildNodes().FirstOrDefault();
if (secondArgumentNode is LiteralExpressionSyntax literalSecond && literalSecond.IsKind(SyntaxKind.FalseLiteralExpression))
{
return;
}
SyntaxNode firstArgumentNode = expression.ArgumentList.Arguments.ElementAtOrDefault(0)?.ChildNodes().FirstOrDefault();
if (firstArgumentNode is not LiteralExpressionSyntax literalFirst)
{
return;
}

// Ignore language call for non-nitrox keys.
string stringValue = literalFirst.Token.ValueText;
if (!stringValue.StartsWith(NITROX_LOCALIZATION_PREFIX, StringComparison.OrdinalIgnoreCase))
{
return;
}
if (LocalizationHelper.ContainsKey(stringValue))
{
return;
}
context.ReportDiagnostic(Diagnostic.Create(invalidLocalizationKeyRule, context.Node.GetLocation(), stringValue, LocalizationHelper.FileName));
}

/// <summary>
/// Wrapper API for synchronized access to the English localization file.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions Nitrox.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=cinematics/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Coroutine/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Deconstructable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=escapepod/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Exosuit/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FMOD/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FMODUWE/@EntryIndexedValue">True</s:Boolean>
Expand Down
1 change: 1 addition & 0 deletions NitroxPatcher/Patches/Dynamic/EscapePod_Start_Patch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using HarmonyLib;
using NitroxModel.Helper;
using UnityEngine;
// ReSharper disable UseUtf8StringLiteral

namespace NitroxPatcher.Patches.Dynamic;

Expand Down

0 comments on commit 72bd72a

Please sign in to comment.