/*
* Copyright (c) 2026 Proton AG
*
* This file is part of ProtonVPN.
*
* ProtonVPN is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonVPN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonVPN. If not, see .
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace ProtonVPN.Client.Localization.Tests.Helpers;
public static partial class SourceKeyScanner
{
[GeneratedRegex(@"_?[Ll]ocalizer\s*\.\s*Get(?:Format|Plural(?:Format)?)?\s*\(\s*""([^""]+)""")]
private static partial Regex CsLocalizerPattern();
[GeneratedRegex(@"Localizer\.Get(?:Format|Plural(?:Format)?)?\('([^']+)'")]
private static partial Regex XamlLocalizerPattern();
[GeneratedRegex(@"""([A-Z][A-Za-z0-9_]+)""")]
private static partial Regex CsStringLiteralPattern();
[GeneratedRegex(@"'([A-Z][A-Za-z0-9_]+)'")]
private static partial Regex XamlStringLiteralPattern();
public static HashSet CollectReferencedKeys(string sourceRoot, HashSet definedKeys)
{
HashSet keys = new();
HashSet pluralBaseKeys = PluralKeyHelper.GetPluralBaseKeys(definedKeys);
foreach (string file in Directory.EnumerateFiles(sourceRoot, "*.cs", SearchOption.AllDirectories)
.Where(path => !IsIgnoredPath(path)))
{
string content = File.ReadAllText(file);
ExtractMatches(content, CsLocalizerPattern(), keys);
ExtractDefinedLiterals(content, CsStringLiteralPattern(), definedKeys, pluralBaseKeys, keys);
}
foreach (string file in Directory.EnumerateFiles(sourceRoot, "*.xaml", SearchOption.AllDirectories)
.Where(path => !IsIgnoredPath(path)))
{
string content = File.ReadAllText(file);
ExtractMatches(content, XamlLocalizerPattern(), keys);
ExtractDefinedLiterals(content, XamlStringLiteralPattern(), definedKeys, pluralBaseKeys, keys);
}
return keys;
}
private static void ExtractMatches(string content, Regex pattern, HashSet keys)
{
foreach (Match match in pattern.Matches(content))
{
keys.Add(match.Groups[1].Value);
}
}
private static void ExtractDefinedLiterals(
string content,
Regex pattern,
HashSet definedKeys,
HashSet pluralBaseKeys,
HashSet keys)
{
foreach (Match match in pattern.Matches(content))
{
string literal = match.Groups[1].Value;
if (definedKeys.Contains(literal) || pluralBaseKeys.Contains(literal))
{
keys.Add(literal);
}
}
}
private static bool IsIgnoredPath(string path)
{
return path.Contains(Path.DirectorySeparatorChar + "obj" + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase);
}
}