From 6241bceb497040f48e79e74a287304fcbb59e221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Tue, 28 Apr 2020 14:04:04 +0200 Subject: [PATCH] First version of resx analyzer --- .../Core/AnalyzerReleases.Unshipped.md | 1 + .../Core/DefineResourceEntryCorrectly.cs | 96 +++++++++++ .../Core/RoslynDiagnosticIds.cs | 1 + .../RoslynDiagnosticsAnalyzersResources.resx | 9 ++ ...RoslynDiagnosticsAnalyzersResources.cs.xlf | 15 ++ ...RoslynDiagnosticsAnalyzersResources.de.xlf | 15 ++ ...RoslynDiagnosticsAnalyzersResources.es.xlf | 15 ++ ...RoslynDiagnosticsAnalyzersResources.fr.xlf | 15 ++ ...RoslynDiagnosticsAnalyzersResources.it.xlf | 15 ++ ...RoslynDiagnosticsAnalyzersResources.ja.xlf | 15 ++ ...RoslynDiagnosticsAnalyzersResources.ko.xlf | 15 ++ ...RoslynDiagnosticsAnalyzersResources.pl.xlf | 15 ++ ...lynDiagnosticsAnalyzersResources.pt-BR.xlf | 15 ++ ...RoslynDiagnosticsAnalyzersResources.ru.xlf | 15 ++ ...RoslynDiagnosticsAnalyzersResources.tr.xlf | 15 ++ ...nDiagnosticsAnalyzersResources.zh-Hans.xlf | 15 ++ ...nDiagnosticsAnalyzersResources.zh-Hant.xlf | 15 ++ .../DefineResourceEntryCorrectlyTests.cs | 152 ++++++++++++++++++ 18 files changed, 454 insertions(+) create mode 100644 src/Roslyn.Diagnostics.Analyzers/Core/DefineResourceEntryCorrectly.cs create mode 100644 src/Roslyn.Diagnostics.Analyzers/UnitTests/DefineResourceEntryCorrectlyTests.cs diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/AnalyzerReleases.Unshipped.md b/src/Roslyn.Diagnostics.Analyzers/Core/AnalyzerReleases.Unshipped.md index fe33ef6cc7..84acd0ac2e 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/AnalyzerReleases.Unshipped.md +++ b/src/Roslyn.Diagnostics.Analyzers/Core/AnalyzerReleases.Unshipped.md @@ -6,6 +6,7 @@ RS0042 | RoslynDiagnosticsReliability | Warning | DoNotCopyValue RS0043 | RoslynDiagnosticsMaintainability | Warning | DoNotCallGetTestAccessor RS0044 | RoslynDiagnosticsMaintainability | Hidden | CreateTestAccessor RS0045 | RoslynDiagnosticsMaintainability | Hidden | ExposeMemberForTesting +RS0047 | RoslynDiagnosticsDesign | Info | DefineResourceEntryCorrectly ### Changed Rules Rule ID | New Category | New Severity | Old Category | Old Severity | Notes diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/DefineResourceEntryCorrectly.cs b/src/Roslyn.Diagnostics.Analyzers/Core/DefineResourceEntryCorrectly.cs new file mode 100644 index 0000000000..1a68199819 --- /dev/null +++ b/src/Roslyn.Diagnostics.Analyzers/Core/DefineResourceEntryCorrectly.cs @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Immutable; +using System.IO; +using System.Text.RegularExpressions; +using System.Xml; +using Analyzer.Utilities; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Text; + +namespace Roslyn.Diagnostics.Analyzers +{ + [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] + public sealed class DefineResourceEntryCorrectly : DiagnosticAnalyzer + { + private static readonly LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(RoslynDiagnosticsAnalyzersResources.DefineResourceEntryCorrectlyTitle), RoslynDiagnosticsAnalyzersResources.ResourceManager, typeof(RoslynDiagnosticsAnalyzersResources)); + private static readonly LocalizableString s_localizableMessage = new LocalizableResourceString(nameof(RoslynDiagnosticsAnalyzersResources.DefineResourceEntryCorrectlyMessage), RoslynDiagnosticsAnalyzersResources.ResourceManager, typeof(RoslynDiagnosticsAnalyzersResources)); + private static readonly LocalizableString s_localizableDescription = new LocalizableResourceString(nameof(RoslynDiagnosticsAnalyzersResources.DefineResourceEntryCorrectlyDescription), RoslynDiagnosticsAnalyzersResources.ResourceManager, typeof(RoslynDiagnosticsAnalyzersResources)); + + internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor( + RoslynDiagnosticIds.DefineResourceEntryCorrectlyRuleId, + s_localizableTitle, + s_localizableMessage, + DiagnosticCategory.RoslynDiagnosticsDesign, + DiagnosticSeverity.Info, + isEnabledByDefault: true, + description: s_localizableDescription, + helpLinkUri: null, + customTags: WellKnownDiagnosticTags.Telemetry); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + + private static readonly Regex s_dataNameRegex = new Regex("(.*?)", RegexOptions.Compiled); + private const StringComparison s_ResxContentStringComparison = StringComparison.Ordinal; + + public override void Initialize(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + + context.RegisterCompilationAction(context => + { + foreach (var file in context.Options.AdditionalFiles) + { + context.CancellationToken.ThrowIfCancellationRequested(); + + var fileExtension = Path.GetExtension(file.Path); + if (!fileExtension.Equals(".resx", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + var isDescription = false; + var sourceText = file.GetText(context.CancellationToken); + foreach (var line in sourceText.Lines) + { + var text = line.ToString().Trim(); + + var match = s_dataNameRegex.Match(text); + if (match.Success) + { + isDescription = match.Groups[1].Value.EndsWith("Description", s_ResxContentStringComparison); + continue; + } + + match = s_valueRegex.Match(text); + if (match.Success) + { + var endsWithPeriod = match.Groups[1].Value.EndsWith(".", s_ResxContentStringComparison); + + if (endsWithPeriod && !isDescription) + { + var linePositionSpan = sourceText.Lines.GetLinePositionSpan(line.Span); + var location = Location.Create(file.Path, line.Span, linePositionSpan); + context.ReportDiagnostic(Diagnostic.Create(Rule, location)); + } + else if (isDescription && !endsWithPeriod) + { + var linePositionSpan = sourceText.Lines.GetLinePositionSpan(line.Span); + var location = Location.Create(file.Path, line.Span, linePositionSpan); + context.ReportDiagnostic(Diagnostic.Create(Rule, location)); + } + else + { + // do nothing + } + } + } + } + }); + } + } +} diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/RoslynDiagnosticIds.cs b/src/Roslyn.Diagnostics.Analyzers/Core/RoslynDiagnosticIds.cs index 9231f66152..b07ad801e6 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/RoslynDiagnosticIds.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/RoslynDiagnosticIds.cs @@ -49,5 +49,6 @@ internal static class RoslynDiagnosticIds public const string DoNotCallGetTestAccessorRuleId = "RS0043"; public const string CreateTestAccessorRuleId = "RS0044"; public const string ExposeMemberForTestingRuleId = "RS0045"; + public const string DefineResourceEntryCorrectlyRuleId = "RS0047"; } } diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/RoslynDiagnosticsAnalyzersResources.resx b/src/Roslyn.Diagnostics.Analyzers/Core/RoslynDiagnosticsAnalyzersResources.resx index 05f21cbd43..83ad4f68a2 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/RoslynDiagnosticsAnalyzersResources.resx +++ b/src/Roslyn.Diagnostics.Analyzers/Core/RoslynDiagnosticsAnalyzersResources.resx @@ -339,4 +339,13 @@ Expose member for testing + + Define resource entry correctly. + + + Define resource entry correctly + + + Define resource entry correctly + \ No newline at end of file diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.cs.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.cs.xlf index e6fbea6a5e..b895f82b39 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.cs.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.cs.xlf @@ -32,6 +32,21 @@ Typy, které se dají nastavit jako výchozí, by měly mít pole, která se tak dají nastavit taky + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor() je pomocná metoda vyhrazená pro testování. Produkční kód tento člen nesmí volat. diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.de.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.de.xlf index 71c8b7da4a..fe7c3ee9d6 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.de.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.de.xlf @@ -32,6 +32,21 @@ Auf den Standard festlegbare Typen müssen auf den Standard festlegbare Felder aufweisen. + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor() ist eine für Tests reservierte Hilfsmethode. Der Produktionscode darf diesen Member nicht aufrufen. diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.es.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.es.xlf index 6cd20759f8..9020816a82 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.es.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.es.xlf @@ -32,6 +32,21 @@ Los tipos defaultable deben tener campos defaultable + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor() es un método auxiliar reservado para las pruebas. El código de producción no debe llamar a este miembro. diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.fr.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.fr.xlf index 1a9118524f..8ccb9f3acb 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.fr.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.fr.xlf @@ -32,6 +32,21 @@ Les types par défaut doivent avoir des champs par défaut + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor() est une méthode d'assistance réservée aux tests. Le code de production ne doit pas appeler ce membre. diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.it.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.it.xlf index e3126052d8..fbe802399f 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.it.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.it.xlf @@ -32,6 +32,21 @@ I tipi defaultable devono avere campi defaultable + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor() è un metodo helper riservato per il test. IL codice di produzione non deve chiamare questo membro. diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ja.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ja.xlf index f7b29573a0..53f0017d87 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ja.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ja.xlf @@ -32,6 +32,21 @@ 既定に設定可能な型には、既定に設定可能なフィールドが必要です + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor () は、テスト用に予約されているヘルパー メソッドです。運用コードでこのメンバーを呼び出さないでください。 diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ko.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ko.xlf index 5b8a46d07d..0c7057f449 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ko.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ko.xlf @@ -32,6 +32,21 @@ 기본값 설정 가능 형식에는 기본값 설정 가능 필드가 있어야 함 + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor()는 테스트용으로 예약된 도우미 메서드입니다. 프로덕션 코드는 이 멤버를 호출해서는 안 됩니다. diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.pl.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.pl.xlf index a60e0bc994..6220b53b83 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.pl.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.pl.xlf @@ -32,6 +32,21 @@ Typy dopuszczające wartość domyślną powinny mieć pola z wartościami domyślnymi + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor() to metoda pomocnicza zarezerwowana do testowania. Kod produkcyjny nie może wywoływać tego elementu członkowskiego. diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.pt-BR.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.pt-BR.xlf index 64af67fa28..d1ecdf5431 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.pt-BR.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.pt-BR.xlf @@ -32,6 +32,21 @@ Os tipos usados como padrão devem ter campos usados como padrão + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor() é um método auxiliar reservado para testes. O código de produção não deve chamar este membro. diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ru.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ru.xlf index 6a5bc0e602..079d23d380 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ru.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.ru.xlf @@ -32,6 +32,21 @@ Типы, допускающие значения по умолчанию, должны иметь соответствующие поля + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor() — это вспомогательный метод, используемый только для тестирования. Не вызывайте этот метод из рабочего кода. diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.tr.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.tr.xlf index b9924e8581..066d235d5b 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.tr.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.tr.xlf @@ -32,6 +32,21 @@ Varsayılan değer atanabilir türler varsayılan değer atanabilir alanlara sahip olmalıdır + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor(), test için ayrılmış bir yardımcı metottur. Üretim kodu bu üyeyi çağırmamalıdır. diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.zh-Hans.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.zh-Hans.xlf index 46cb04afd0..3d6d273f49 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.zh-Hans.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.zh-Hans.xlf @@ -32,6 +32,21 @@ 可默认类型应具有可默认字段。 + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor() 是保留以用于测试的 helper 方法。生产代码不能调用此成员。 diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.zh-Hant.xlf b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.zh-Hant.xlf index 5ce255db00..23f702a794 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.zh-Hant.xlf +++ b/src/Roslyn.Diagnostics.Analyzers/Core/xlf/RoslynDiagnosticsAnalyzersResources.zh-Hant.xlf @@ -32,6 +32,21 @@ 可設定預設值的類型應要有可設定預設值的欄位 + + Define resource entry correctly. + Define resource entry correctly. + + + + Define resource entry correctly + Define resource entry correctly + + + + Define resource entry correctly + Define resource entry correctly + + 'GetTestAccessor()' is a helper method reserved for testing. Production code must not call this member. GetTestAccessor() 是留待測試用的協助程式方法。實際執行程式碼不可呼叫此成員。 diff --git a/src/Roslyn.Diagnostics.Analyzers/UnitTests/DefineResourceEntryCorrectlyTests.cs b/src/Roslyn.Diagnostics.Analyzers/UnitTests/DefineResourceEntryCorrectlyTests.cs new file mode 100644 index 0000000000..69ee645876 --- /dev/null +++ b/src/Roslyn.Diagnostics.Analyzers/UnitTests/DefineResourceEntryCorrectlyTests.cs @@ -0,0 +1,152 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Xunit; +using VerifyCS = Test.Utilities.CSharpSecurityCodeFixVerifier< + Roslyn.Diagnostics.Analyzers.DefineResourceEntryCorrectly, + Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; +using VerifyVB = Test.Utilities.VisualBasicSecurityCodeFixVerifier< + Roslyn.Diagnostics.Analyzers.DefineResourceEntryCorrectly, + Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; + +namespace Roslyn.Diagnostics.Analyzers.UnitTests +{ + public class DefineResourceEntryCorrectlyTests + { + [Fact] + public async Task DescriptionResourceEntryValueEndsWithPeriod_NoDiagnostic() + { + const string resxContent = +@" + + + Do something. + +"; + + await new VerifyCS.Test + { + TestState = + { + AdditionalFiles = { ("Strings.resx", resxContent), }, + Sources = { "", }, + } + }.RunAsync(); + + await new VerifyVB.Test + { + TestState = + { + AdditionalFiles = { ("Strings.resx", resxContent), }, + Sources = { "", }, + } + }.RunAsync(); + } + + [Fact] + public async Task DescriptionResourceEntryValueDoesNotEndWithPeriod_Diagnostic() + { + const string resxContent = +@" + + + Do something + +"; + + await new VerifyCS.Test + { + TestState = + { + AdditionalFiles = { ("Strings.resx", resxContent), }, + Sources = { "", }, + ExpectedDiagnostics = + { + VerifyCS.Diagnostic().WithLocation("Strings.resx", 4, 1), + }, + } + }.RunAsync(); + + await new VerifyVB.Test + { + TestState = + { + AdditionalFiles = { ("Strings.resx", resxContent), }, + Sources = { "", }, + ExpectedDiagnostics = + { + VerifyVB.Diagnostic().WithLocation("Strings.resx", 4, 1), + }, + } + }.RunAsync(); + } + + [Fact] + public async Task NotDescriptionResourceEntryValueDoesNotEndWithPeriod_NoDiagnostic() + { + const string resxContent = +@" + + + Do something + +"; + + await new VerifyCS.Test + { + TestState = + { + AdditionalFiles = { ("Strings.resx", resxContent), }, + Sources = { "", }, + } + }.RunAsync(); + + await new VerifyVB.Test + { + TestState = + { + AdditionalFiles = { ("Strings.resx", resxContent), }, + Sources = { "", }, + } + }.RunAsync(); + } + + [Fact] + public async Task NotDescriptionResourceEntryValueEndsWithPeriod_Diagnostic() + { + const string resxContent = +@" + + + Do something. + +"; + + await new VerifyCS.Test + { + TestState = + { + AdditionalFiles = { ("Strings.resx", resxContent), }, + Sources = { "", }, + ExpectedDiagnostics = + { + VerifyCS.Diagnostic().WithLocation("Strings.resx", 4, 1), + }, + } + }.RunAsync(); + + await new VerifyVB.Test + { + TestState = + { + AdditionalFiles = { ("Strings.resx", resxContent), }, + Sources = { "", }, + ExpectedDiagnostics = + { + VerifyVB.Diagnostic().WithLocation("Strings.resx", 4, 1), + }, + } + }.RunAsync(); + } + } +}