diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.md
index facf822421c6..fd1fcef90923 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.md
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.md
@@ -2154,6 +2154,18 @@ Unawaited tasks that use 'IDisposable' instances may use those instances long af
|CodeFix|False|
---
+## [CA2026](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2026): Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+|Item|Value|
+|-|-|
+|Category|Reliability|
+|Enabled|True|
+|Severity|Info|
+|CodeFix|True|
+---
+
## [CA2100](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2100): Review SQL queries for security vulnerabilities
SQL queries that directly use user input can be vulnerable to SQL injection attacks. Review this SQL query for potential vulnerabilities, and consider using a parameterized SQL query.
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.sarif b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.sarif
index a3e0dd7859aa..f36c59791cd4 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.sarif
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.sarif
@@ -3850,6 +3850,26 @@
]
}
},
+ "CA2026": {
+ "id": "CA2026",
+ "shortDescription": "Prefer JsonElement.Parse over JsonDocument.Parse().RootElement",
+ "fullDescription": "JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.",
+ "defaultLevel": "note",
+ "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2026",
+ "properties": {
+ "category": "Reliability",
+ "isEnabledByDefault": true,
+ "typeName": "PreferJsonElementParse",
+ "languages": [
+ "C#",
+ "Visual Basic"
+ ],
+ "tags": [
+ "Telemetry",
+ "EnabledRuleInAggressiveMode"
+ ]
+ }
+ },
"CA2100": {
"id": "CA2100",
"shortDescription": "Review SQL queries for security vulnerabilities",
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md
index 0ecf6597797e..589e86fc4126 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md
@@ -10,3 +10,4 @@ CA1875 | Performance | Info | UseRegexMembers, [Documentation](https://learn.mic
CA2023 | Reliability | Warning | LoggerMessageDefineAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2023)
CA2024 | Reliability | Warning | DoNotUseEndOfStreamInAsyncMethods, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2024)
CA2025 | Reliability | Disabled | DoNotPassDisposablesIntoUnawaitedTasksAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2025)
+CA2026 | Reliability | Info | PreferJsonElementParse, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2026)
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx
index 55948fcbc88d..bacbfc1fe9cb 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx
@@ -2054,6 +2054,18 @@ Widening and user defined conversions are not supported with generic types.
Use '{0}.{1}'
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+ Use 'JsonElement.Parse'
+
Using concrete types avoids virtual or interface call overhead and enables inlining.
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Runtime/PreferJsonElementParse.Fixer.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Runtime/PreferJsonElementParse.Fixer.cs
new file mode 100644
index 000000000000..7dddc3acbc5a
--- /dev/null
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Runtime/PreferJsonElementParse.Fixer.cs
@@ -0,0 +1,78 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
+
+using System.Collections.Immutable;
+using System.Composition;
+using System.Linq;
+using System.Threading.Tasks;
+using Analyzer.Utilities;
+using Analyzer.Utilities.Extensions;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.Editing;
+using Microsoft.CodeAnalysis.Operations;
+
+namespace Microsoft.NetCore.Analyzers.Runtime
+{
+ ///
+ /// Fixer for .
+ ///
+ [ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic), Shared]
+ public sealed class PreferJsonElementParseFixer : CodeFixProvider
+ {
+ public sealed override ImmutableArray FixableDiagnosticIds { get; } =
+ ImmutableArray.Create(PreferJsonElementParse.RuleId);
+
+ public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;
+
+ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
+ {
+ Document doc = context.Document;
+ SemanticModel model = await doc.GetRequiredSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
+ SyntaxNode root = await doc.GetRequiredSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
+
+ if (root.FindNode(context.Span, getInnermostNodeForTie: true) is not SyntaxNode node ||
+ model.GetOperation(node, context.CancellationToken) is not IPropertyReferenceOperation propertyReference ||
+ propertyReference.Property.Name != "RootElement" ||
+ propertyReference.Instance is not IInvocationOperation invocation ||
+ invocation.TargetMethod.Name != "Parse")
+ {
+ return;
+ }
+
+ string title = MicrosoftNetCoreAnalyzersResources.PreferJsonElementParseFix;
+ context.RegisterCodeFix(
+ CodeAction.Create(
+ title,
+ createChangedDocument: async ct =>
+ {
+ DocumentEditor editor = await DocumentEditor.CreateAsync(doc, ct).ConfigureAwait(false);
+ SyntaxGenerator generator = editor.Generator;
+
+ // Get the JsonElement type
+ INamedTypeSymbol? jsonElementType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemTextJsonJsonElement);
+ if (jsonElementType == null)
+ {
+ return doc;
+ }
+
+ // Create the replacement: JsonElement.Parse(...)
+ // We need to use the same arguments that were passed to JsonDocument.Parse
+ var arguments = invocation.Arguments.Select(arg => arg.Syntax).ToArray();
+
+ SyntaxNode memberAccess = generator.MemberAccessExpression(
+ generator.TypeExpressionForStaticMemberAccess(jsonElementType),
+ "Parse");
+
+ SyntaxNode replacement = generator.InvocationExpression(memberAccess, arguments);
+
+ // Replace the entire property reference (JsonDocument.Parse(...).RootElement) with JsonElement.Parse(...)
+ editor.ReplaceNode(propertyReference.Syntax, replacement.WithTriviaFrom(propertyReference.Syntax));
+
+ return editor.GetChangedDocument();
+ },
+ equivalenceKey: title),
+ context.Diagnostics);
+ }
+ }
+}
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Runtime/PreferJsonElementParse.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Runtime/PreferJsonElementParse.cs
new file mode 100644
index 000000000000..2e509f70dfda
--- /dev/null
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Runtime/PreferJsonElementParse.cs
@@ -0,0 +1,118 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
+
+using System.Collections.Immutable;
+using System.Linq;
+using Analyzer.Utilities;
+using Analyzer.Utilities.Extensions;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Operations;
+
+namespace Microsoft.NetCore.Analyzers.Runtime
+{
+ using static MicrosoftNetCoreAnalyzersResources;
+
+ ///
+ /// CA2026: Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ ///
+ [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
+ public sealed class PreferJsonElementParse : DiagnosticAnalyzer
+ {
+ internal const string RuleId = "CA2026";
+
+ internal static readonly DiagnosticDescriptor Rule = DiagnosticDescriptorHelper.Create(
+ RuleId,
+ CreateLocalizableResourceString(nameof(PreferJsonElementParseTitle)),
+ CreateLocalizableResourceString(nameof(PreferJsonElementParseMessage)),
+ DiagnosticCategory.Reliability,
+ RuleLevel.IdeSuggestion,
+ CreateLocalizableResourceString(nameof(PreferJsonElementParseDescription)),
+ isPortedFxCopRule: false,
+ isDataflowRule: false);
+
+ public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule);
+
+ public override void Initialize(AnalysisContext context)
+ {
+ context.EnableConcurrentExecution();
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+
+ context.RegisterCompilationStartAction(context =>
+ {
+ // Get the JsonDocument and JsonElement types
+ INamedTypeSymbol? jsonDocumentType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemTextJsonJsonDocument);
+ INamedTypeSymbol? jsonElementType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemTextJsonJsonElement);
+
+ if (jsonDocumentType is null || jsonElementType is null)
+ {
+ return;
+ }
+
+ // Get all JsonElement.Parse overloads for matching
+ var jsonElementParseOverloads = jsonElementType.GetMembers("Parse")
+ .OfType()
+ .Where(m => m.IsStatic)
+ .ToImmutableArray();
+
+ // Check if JsonElement.Parse exists
+ if (jsonElementParseOverloads.IsEmpty ||
+ !jsonDocumentType.GetMembers("Parse").Any(m => m is IMethodSymbol { IsStatic: true }))
+ {
+ return;
+ }
+
+ // Get the RootElement property
+ IPropertySymbol? rootElementProperty = jsonDocumentType.GetMembers("RootElement")
+ .OfType()
+ .FirstOrDefault();
+
+ if (rootElementProperty is null)
+ {
+ return;
+ }
+
+ context.RegisterOperationAction(context =>
+ {
+ var propertyReference = (IPropertyReferenceOperation)context.Operation;
+
+ // Check if this is accessing the RootElement property and the instance is a direct call to JsonDocument.Parse
+ if (!SymbolEqualityComparer.Default.Equals(propertyReference.Property, rootElementProperty) ||
+ propertyReference.Instance is not IInvocationOperation invocation ||
+ !SymbolEqualityComparer.Default.Equals(invocation.TargetMethod.ContainingType, jsonDocumentType) ||
+ invocation.TargetMethod.Name != "Parse")
+ {
+ return;
+ }
+
+ // Now we have the pattern: JsonDocument.Parse(...).RootElement
+ // Check if there's a matching JsonElement.Parse overload with the same parameter types
+ var jsonDocumentParseMethod = invocation.TargetMethod;
+
+ foreach (var elementParseOverload in jsonElementParseOverloads)
+ {
+ if (elementParseOverload.Parameters.Length != jsonDocumentParseMethod.Parameters.Length)
+ {
+ continue;
+ }
+
+ bool parametersMatch = true;
+ for (int i = 0; i < elementParseOverload.Parameters.Length; i++)
+ {
+ if (!SymbolEqualityComparer.Default.Equals(elementParseOverload.Parameters[i].Type, jsonDocumentParseMethod.Parameters[i].Type))
+ {
+ parametersMatch = false;
+ break;
+ }
+ }
+
+ if (parametersMatch)
+ {
+ context.ReportDiagnostic(propertyReference.CreateDiagnostic(Rule));
+ break;
+ }
+ }
+ }, OperationKind.PropertyReference);
+ });
+ }
+ }
+}
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf
index d5f92baf02e5..547cfec47e45 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf
@@ -2238,6 +2238,26 @@ Rozšíření a uživatelem definované převody se u obecných typů nepodporuj
Upřednostňovat IsEmpty před Count
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.Upřednostňujte použití vlastnosti IsEmpty, Count nebo Length podle toho, která je k dispozici, namísto volání metody Enumerable.Any(). Záměr je jasnější a je výkonnější než použití rozšiřující metody Enumerable.Any().
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf
index f63f006d064d..a13fa704ba8f 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf
@@ -2238,6 +2238,26 @@ Erweiterungen und benutzerdefinierte Konvertierungen werden bei generischen Type
Ziehen Sie "IsEmpty" gegenüber "Count" vor
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.Verwenden Sie lieber die Eigenschaften „IsEmpty“, „Count“ oder „Length“, sofern verfügbar, statt „Enumerable.Any()“ aufzurufen. Die Absicht ist klarer und das Ausführungsverhalten besser als bei Verwendung der Erweiterungsmethode „Enumerable.Any()“.
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf
index a03a7a0fa4d0..1c86fe791114 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf
@@ -2238,6 +2238,26 @@ La ampliación y las conversiones definidas por el usuario no se admiten con tip
Elegir IsEmpty en vez de Count
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.Es preferible usar las propiedades "IsEmpty", "Count" o "Length", si hay alguna disponible, en lugar de llamar a "Enumerable.Any()". La intención es más clara y tiene un mejor rendimiento que usar el método de extensión "Enumerable.Any()".
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf
index 40c160bb5b5f..36c5534b8962 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf
@@ -2238,6 +2238,26 @@ Les conversions étendues et définies par l’utilisateur ne sont pas prises en
Préférer IsEmpty à Count
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.Préférez utiliser les propriétés 'IsEmpty', 'Count' ou 'Length' selon la disponibilité, plutôt que d’appeler 'Enumerable.Any()'. L’intention est plus claire et plus performante que l’utilisation de la méthode d’extension 'Enumerable.Any()'.
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf
index 924a482d9f5d..6c3d97692a3c 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf
@@ -2238,6 +2238,26 @@ L'ampliamento e le conversioni definite dall'utente non sono supportate con tipi
Preferire IsEmpty a Count
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.Preferire l’uso delle proprietà 'IsEmpty', 'Count' o 'Length' se disponibili, anziché chiamare 'Enumerable.Any()'. La finalità è più chiara ed è più efficiente rispetto all'uso del metodo di estensione 'Enumerable.Any()'.
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf
index 6c3fbfeccd9a..8c4aa8a20ea1 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf
@@ -2238,6 +2238,26 @@ Enumerable.OfType<T> で使用されるジェネリック型チェック (
Count より IsEmpty を優先する
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.'Enumerable.Any()' を呼び出すのではなく、'IsEmpty'、'Count'、または 'Length' のいずれか使用可能なプロパティの使用を優先してください。この方が、'Enumerable.Any()' 拡張メソッドを使用するよりも意図が明確で、パフォーマンスが向上します。
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf
index f0706403c0d4..47929d1c21f5 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf
@@ -2238,6 +2238,26 @@ Enumerable.OfType<T>에서 사용하는 제네릭 형식 검사(C# 'is'
Count 대신 IsEmpty 사용
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.'Enumerable.Any()'를 호출하는 것보다 사용 가능한 'IsEmpty', 'Count' 또는 'Length' 속성을 사용하는 것이 좋습니다. 의도가 더 명확하고 'Enumerable.Any()' 확장 방법을 사용하는 것보다 더 성능이 좋습니다.
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf
index 51f4dee3e919..f8c701db54b3 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf
@@ -2238,6 +2238,26 @@ Konwersje poszerzane i zdefiniowane przez użytkownika nie są obsługiwane w pr
Preferuj właściwość IsEmpty przed Count
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.Preferuj używanie właściwości „IsEmpty”, „Count” lub „Length” w zależności od dostępności, zamiast wywoływać metodę „Enumerable.Any()”. Intencja jest bardziej przejrzysta i wydajniejsza niż użycie metody rozszerzenia „Enumerable.Any()”.
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf
index cb9dea8edaf1..71cde1d01b0c 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf
@@ -2238,6 +2238,26 @@ As ampliação e conversões definidas pelo usuário não são compatíveis com
Preferir IsEmpty em vez de Count
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.Prefira usar as propriedades 'IsEmpty', 'Count' ou 'Length', conforme disponível, em vez de chamar 'Enumerable.Any()'. A intenção é mais clara e tem mais desempenho do que usar o método de extensão 'Enumerable.Any()'.
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf
index 57538a5cb231..355273e1bf08 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf
@@ -2238,6 +2238,26 @@ Widening and user defined conversions are not supported with generic types.Старайтесь использовать "IsEmpty" вместо "Count"
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.Старайтесь использовать свойства 'IsEmpty', 'Count' или 'Length' в зависимости от доступности вместо вызова 'Enumerable.Any()'. Намерение является более четким и более эффективным по сравнению с использованием метода расширения 'Enumerable.Any()'.
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf
index de2ea9f502e1..33786bf42bc7 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf
@@ -2238,6 +2238,26 @@ Genel türlerde genişletme ve kullanıcı tanımlı dönüştürmeler desteklen
Count yerine IsEmpty tercih edin
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.'Enumerable.Any()' metodunu çağırmak yerine hangisi mevcutsa 'IsEmpty', 'Count' veya 'Length' özelliklerinden birini kullanmayı tercih edin. Amaç daha kolay anlaşılır ve 'Enumerable.Any()' genişletme metoduna göre daha yüksek performans sunar.
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf
index 68f722d64e4f..c9ff6d540e03 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf
@@ -2238,6 +2238,26 @@ Enumerable.OfType<T> 使用的泛型类型检查(C# 'is' operator/IL 'isin
最好使用 "IsEmpty" (而不是 "Count")
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.首选使用可用的 'IsEmpty'、'Count' 或 'Length' 属性,而不是调用 'Enumerable.Any()'。意向更清晰,其性能高于使用 'Enumerable.Any() 扩展方法。
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf
index 43db515c0d4b..96185b9b1822 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf
@@ -2238,6 +2238,26 @@ Enumerable.OfType<T> 使用的一般型別檢查 (C# 'is' operator/IL 'isi
建議使用 IsEmpty,而不要使用 Count
+
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+ JsonDocument implements IDisposable and needs to be properly disposed. When only the RootElement is needed, prefer JsonElement.Parse which doesn't require disposal.
+
+
+
+ Use 'JsonElement.Parse'
+ Use 'JsonElement.Parse'
+
+
+
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+ Use 'JsonElement.Parse' instead of 'JsonDocument.Parse(...).RootElement' to avoid resource leaks
+
+
+
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+ Prefer JsonElement.Parse over JsonDocument.Parse().RootElement
+
+ Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method.偏好使用 'IsEmpty'、'Count' 或 'Length' 屬性 (以可用者為准),而不是呼叫 'Enumerable.Any()'。意圖更清楚,而且比使用 'Enumerable.Any()' 擴充方法更具效能。
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt
index 84d171e834bd..14da2a1ba4bd 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt
@@ -18,7 +18,7 @@ Usage: CA1801, CA1806, CA1816, CA2200-CA2209, CA2211-CA2265
Naming: CA1700-CA1727
Interoperability: CA1400-CA1422
Maintainability: CA1500-CA1515
-Reliability: CA9998-CA9999, CA2000-CA2025
+Reliability: CA9998-CA9999, CA2000-CA2026
Documentation: CA1200-CA1200
# Microsoft CodeAnalysis API rules
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/WellKnownTypeNames.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/WellKnownTypeNames.cs
index a733c059885b..af724317d84f 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/WellKnownTypeNames.cs
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/WellKnownTypeNames.cs
@@ -438,6 +438,8 @@ internal static class WellKnownTypeNames
public const string SystemSystemException = "System.SystemException";
public const string SystemTextCompositeFormat = "System.Text.CompositeFormat";
public const string SystemTextEncoding = "System.Text.Encoding";
+ public const string SystemTextJsonJsonDocument = "System.Text.Json.JsonDocument";
+ public const string SystemTextJsonJsonElement = "System.Text.Json.JsonElement";
public const string SystemTextJsonJsonSerializerOptions = "System.Text.Json.JsonSerializerOptions";
public const string SystemTextJsonJsonSerializer = "System.Text.Json.JsonSerializer";
public const string SystemTextRegularExpressionsGroup = "System.Text.RegularExpressions.Group";
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Runtime/PreferJsonElementParseTests.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Runtime/PreferJsonElementParseTests.cs
new file mode 100644
index 000000000000..aed9241165a0
--- /dev/null
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Runtime/PreferJsonElementParseTests.cs
@@ -0,0 +1,661 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
+
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.Testing;
+using Xunit;
+using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
+ Microsoft.NetCore.Analyzers.Runtime.PreferJsonElementParse,
+ Microsoft.NetCore.Analyzers.Runtime.PreferJsonElementParseFixer>;
+
+namespace Microsoft.NetCore.Analyzers.Runtime.UnitTests
+{
+ public class PreferJsonElementParseTests
+ {
+ [Fact]
+ public async Task NoDiagnostic_WhenJsonElementParseNotAvailable()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement { }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ JsonElement element = JsonDocument.Parse("json").RootElement;
+ }
+ }
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(source);
+ }
+
+ [Fact]
+ public async Task Diagnostic_WhenUsingJsonDocumentParseRootElement()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ JsonElement element = [|JsonDocument.Parse("json").RootElement|];
+ }
+ }
+ """;
+ var fixedSource = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ JsonElement element = JsonElement.Parse("json");
+ }
+ }
+ """;
+ await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+ }
+
+ [Fact]
+ public async Task Diagnostic_WhenUsingJsonDocumentParseRootElement_WithMultipleArguments()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json, JsonDocumentOptions options) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json, JsonDocumentOptions options) => default;
+ }
+
+ public struct JsonDocumentOptions { }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ JsonElement element = [|JsonDocument.Parse("json", default).RootElement|];
+ }
+ }
+ """;
+ var fixedSource = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json, JsonDocumentOptions options) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json, JsonDocumentOptions options) => default;
+ }
+
+ public struct JsonDocumentOptions { }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ JsonElement element = JsonElement.Parse("json", default);
+ }
+ }
+ """;
+ await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+ }
+
+ [Fact]
+ public async Task NoDiagnostic_WhenJsonDocumentProperlyDisposed_UsingStatement()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ using (var doc = JsonDocument.Parse("json"))
+ {
+ JsonElement element = doc.RootElement;
+ }
+ }
+ }
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(source);
+ }
+
+ [Fact]
+ public async Task NoDiagnostic_WhenJsonDocumentProperlyDisposed_UsingDeclaration()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ using var doc = JsonDocument.Parse("json");
+ JsonElement element = doc.RootElement;
+ }
+ }
+ """;
+ await new VerifyCS.Test
+ {
+ TestCode = source,
+ LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp8
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task Diagnostic_InlineAccess_DirectAssignment()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ void M(string json)
+ {
+ var element = [|JsonDocument.Parse(json).RootElement|];
+ }
+ }
+ """;
+ var fixedSource = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ void M(string json)
+ {
+ var element = JsonElement.Parse(json);
+ }
+ }
+ """;
+ await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+ }
+
+ [Fact]
+ public async Task Diagnostic_ReturnStatement()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ JsonElement M(string json)
+ {
+ return [|JsonDocument.Parse(json).RootElement|];
+ }
+ }
+ """;
+ var fixedSource = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ JsonElement M(string json)
+ {
+ return JsonElement.Parse(json);
+ }
+ }
+ """;
+ await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+ }
+
+ [Fact]
+ public async Task Diagnostic_ExpressionBodiedMember()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ JsonElement M(string json) => [|JsonDocument.Parse(json).RootElement|];
+ }
+ """;
+ var fixedSource = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ JsonElement M(string json) => JsonElement.Parse(json);
+ }
+ """;
+ await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+ }
+
+ [Fact]
+ public async Task NoDiagnostic_WhenJsonElementParseHasNoMatchingOverload()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json, JsonDocumentOptions options) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ // JsonElement.Parse only has single string parameter, not the overload with options
+ public static JsonElement Parse(string json) => default;
+ }
+
+ public struct JsonDocumentOptions { }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ // This should NOT produce a diagnostic because JsonElement.Parse doesn't have an overload with JsonDocumentOptions
+ JsonElement element = JsonDocument.Parse("json", default(JsonDocumentOptions)).RootElement;
+ }
+ }
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(source);
+ }
+
+ [Fact]
+ public async Task Diagnostic_WhenChainedWithOtherOperations()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ public JsonValueKind ValueKind => default;
+ }
+
+ public enum JsonValueKind { }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ // Should produce diagnostic even when chained with property access
+ var kind = [|JsonDocument.Parse("json").RootElement|].ValueKind;
+ }
+ }
+ """;
+ var fixedSource = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ public JsonValueKind ValueKind => default;
+ }
+
+ public enum JsonValueKind { }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ // Should produce diagnostic even when chained with property access
+ var kind = JsonElement.Parse("json").ValueKind;
+ }
+ }
+ """;
+ await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+ }
+
+ [Fact]
+ public async Task NoDiagnostic_WhenRootElementAccessedViaVariable()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ // Not the pattern we're looking for - JsonDocument is stored in a variable
+ var doc = JsonDocument.Parse("json");
+ JsonElement element = doc.RootElement;
+ }
+ }
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(source);
+ }
+
+ [Fact]
+ public async Task Diagnostic_MultipleParametersWithMatchingOverload()
+ {
+ var source = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json, JsonDocumentOptions options) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json, JsonDocumentOptions options) => default;
+ }
+
+ public struct JsonDocumentOptions { }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ JsonElement element = [|JsonDocument.Parse("json", default).RootElement|];
+ }
+ }
+ """;
+ var fixedSource = """
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json, JsonDocumentOptions options) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json, JsonDocumentOptions options) => default;
+ }
+
+ public struct JsonDocumentOptions { }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ JsonElement element = JsonElement.Parse("json", default);
+ }
+ }
+ """;
+ await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+ }
+
+ [Fact]
+ public async Task Diagnostic_InLambdaExpression()
+ {
+ var source = """
+ using System;
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ Func parser = json => [|JsonDocument.Parse(json).RootElement|];
+ }
+ }
+ """;
+ var fixedSource = """
+ using System;
+ using System.Text.Json;
+
+ namespace System.Text.Json
+ {
+ public sealed class JsonDocument : System.IDisposable
+ {
+ public static JsonDocument Parse(string json) => null;
+ public JsonElement RootElement => default;
+ public void Dispose() { }
+ }
+
+ public struct JsonElement
+ {
+ public static JsonElement Parse(string json) => default;
+ }
+ }
+
+ class Test
+ {
+ void M()
+ {
+ Func parser = json => JsonElement.Parse(json);
+ }
+ }
+ """;
+ await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+ }
+ }
+}