From d32c498d1dc61128a493986de374d48fcb18a3cd Mon Sep 17 00:00:00 2001 From: Martin Taillefer Date: Mon, 17 Jul 2023 05:16:24 -0700 Subject: [PATCH] Add experimental diagnostics ids --- Directory.Build.targets | 5 +- eng/MSBuild/Shared.props | 2 +- .../CallAnalysis/CallAnalyzer.Handlers.cs | 22 - .../Common/CallAnalysis/CallAnalyzer.cs | 3 - .../Common/CallAnalysis/StringFormat.cs | 74 -- .../Common/DiagDescriptors.cs | 56 +- .../FixAllProviders/ISequentialFixer.cs | 12 - .../SequentialFixAllCodeAction.cs | 99 --- .../SequentialFixAllProvider.cs | 92 --- .../Common/OptimizeArraysAnalyzer.cs | 144 ---- .../Common/Resources.Designer.cs | 135 ---- .../Common/Resources.resx | 45 -- .../Common/StringFormatFixer.cs | 178 ----- .../UsingExcessiveDictionaryLookupAnalyzer.cs | 321 --------- .../UsingExcessiveDictionaryLookupFixer.cs | 241 ------- .../Common/UsingExcessiveSetLookupAnalyzer.cs | 225 ------ .../Common/UsingExcessiveSetLookupFixer.cs | 95 --- .../Common/UsingExperimentalApiAnalyzer.cs | 50 -- .../Common/Utilities/SymbolExtensions.cs | 105 --- .../Utilities/SyntaxEditorExtensions.cs | 34 - ...Extensions.ExtraAnalyzers.Roslyn3.8.csproj | 1 - .../Logging/LoggingOptions.cs | 5 +- .../RequestHeadersLogEnricherOptions.cs | 3 +- .../Tracing/HttpTracingExtensions.cs | 5 +- .../Tracing/HttpTracingOptions.cs | 3 +- .../IAsyncLocalContext.cs | 3 +- .../Classification/DataClassification.cs | 3 +- .../Redaction/Redactor.cs | 3 +- ...althChecksExtensions.TelemetryPublisher.cs | 5 +- .../TelemetryHealthCheckPublisherOptions.cs | 3 +- .../ResourceMonitoringOptions.cs | 3 +- .../Windows/WindowsCountersOptions.cs | 4 +- .../Windows/WindowsUtilizationExtensions.cs | 7 +- .../HostingFakesExtensions.cs | 3 +- .../AutoClientAttribute.cs | 3 +- .../AutoClientException.cs | 3 +- .../AutoClientHttpError.cs | 3 +- .../AutoClientOptions.cs | 3 +- .../BodyAttribute.cs | 3 +- .../BodyContentType.cs | 3 +- .../HeaderAttribute.cs | 3 +- .../Methods/DeleteAttribute.cs | 3 +- .../Methods/GetAttribute.cs | 3 +- .../Methods/HeadAttribute.cs | 3 +- .../Methods/OptionsAttribute.cs | 3 +- .../Methods/PatchAttribute.cs | 3 +- .../Methods/PostAttribute.cs | 3 +- .../Methods/PutAttribute.cs | 3 +- .../QueryAttribute.cs | 3 +- .../RequestNameAttribute.cs | 3 +- .../StaticHeaderAttribute.cs | 3 +- .../FaultInjection/ContextExtensions.cs | 3 +- .../HttpClientFaultInjectionExtensions.cs | 5 +- ...StandardHedgingHandlerBuilderExtensions.cs | 3 +- ...ndardResilienceBuilderBuilderExtensions.cs | 3 +- .../RoutingStrategyBuilderExtensions.cs | 5 +- .../Logging/LoggingOptions.cs | 3 +- .../Metering/HttpClientMeteringExtensions.cs | 5 +- .../Metering/HttpMeteringHandler.cs | 3 +- .../Metering/HttpRequestResultType.cs | 3 +- .../Tracing/HttpClientTracingExtensions.cs | 5 +- .../Tracing/HttpClientTracingOptions.cs | 3 +- .../Tracing/IHttpClientTraceEnricher.netfx.cs | 3 +- .../Tracing/IHttpPathRedactor.cs | 3 +- .../DependencyInjectionPoolOptions.cs | 3 +- .../ObjectPoolServiceCollectionExtensions.cs | 3 +- .../FaultInjectionExtensions.cs | 3 +- .../FaultInjectionOptionsBuilder.cs | 3 +- .../FaultInjection/IChaosPolicyFactory.cs | 3 +- .../Options/ChaosPolicyOptionsGroup.cs | 3 +- .../Options/CustomResultPolicyOptions.cs | 5 +- .../FaultPolicyWeightAssignmentsOptions.cs | 3 +- .../Resilience/ResilienceContextExtensions.cs | 3 +- .../ResilienceServiceCollectionExtensions.cs | 3 +- .../Http/TelemetryConstants.cs | 5 +- .../Logging/LogMethodAttribute.cs | 3 +- .../Metering/MeterT.cs | 5 +- .../Metering/MeteringExtensions.cs | 3 +- .../Metering/CollectedMeasurement.cs | 3 +- .../Metering/MeasurementExtensions.cs | 3 +- .../Metering/MetricCollector.cs | 3 +- .../Logging/LoggerProvider.cs | 3 +- .../Logging/LoggingOptions.cs | 3 +- .../EventCountersCollectorOptions.cs | 3 +- .../Metering/MeteringOptions.cs | 3 +- .../Metering/OTelMeteringExtensions.cs | 9 +- .../Telemetry.Internal/IHttpRouteFormatter.cs | 5 +- .../Telemetry/TelemetryExtensions.cs | 5 +- .../Tracing/TracingEnricherExtensions.cs | 5 +- .../FakeTimeProvider.cs | 9 +- ...osoft.Extensions.TimeProvider.Testing.json | 14 +- .../Model/DatabaseOptions.cs | 3 +- src/Shared/DiagnosticIds/Experiments.cs | 31 + src/Shared/Shared.csproj | 2 +- src/Shared/WarningDefinitions.cs | 11 - .../Common/CallAnalysis/StringFormatTests.cs | 82 --- .../Common/OptimizeArraysAnalyzerTests.cs | 66 -- ...gExcessiveDictionaryLookupAnalyzerTests.cs | 442 ------------ ...singExcessiveDictionaryLookupFixerTests.cs | 674 ------------------ .../UsingExcessiveSetLookupAnalyzerTests.cs | 591 --------------- .../UsingExperimentalApiAnalyzerTest.cs | 112 --- .../Common/UsingStringFormatterFixerTests.cs | 418 ----------- .../ApiLifecycle/ApiLifecycleAnalyzerTest.cs | 18 +- 103 files changed, 213 insertions(+), 4440 deletions(-) delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/StringFormat.cs delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/ISequentialFixer.cs delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/SequentialFixAllCodeAction.cs delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/SequentialFixAllProvider.cs delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/OptimizeArraysAnalyzer.cs delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/StringFormatFixer.cs delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupAnalyzer.cs delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupFixer.cs delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupAnalyzer.cs delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupFixer.cs delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExperimentalApiAnalyzer.cs delete mode 100644 src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Utilities/SyntaxEditorExtensions.cs create mode 100644 src/Shared/DiagnosticIds/Experiments.cs delete mode 100644 src/Shared/WarningDefinitions.cs delete mode 100644 test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/StringFormatTests.cs delete mode 100644 test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/OptimizeArraysAnalyzerTests.cs delete mode 100644 test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupAnalyzerTests.cs delete mode 100644 test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupFixerTests.cs delete mode 100644 test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupAnalyzerTests.cs delete mode 100644 test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExperimentalApiAnalyzerTest.cs delete mode 100644 test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingStringFormatterFixerTests.cs diff --git a/Directory.Build.targets b/Directory.Build.targets index 2dadfc1f5dd..b0149b09bf2 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -35,9 +35,8 @@ $(NoWarn);AD0001 - - $(NoWarn);R9A029 - + + $(NoWarn);EXTEXP0001;EXTEXP0002;EXTEXP0003;EXTEXP0004;EXTEXP0005;EXTEXP0006;EXTEXP0007;EXTEXP0008;EXTEXP0009;EXTEXP0010;EXTEXP0011 $(NoWarn);NU5104 diff --git a/eng/MSBuild/Shared.props b/eng/MSBuild/Shared.props index 688497594f3..04e3f3a09cc 100644 --- a/eng/MSBuild/Shared.props +++ b/eng/MSBuild/Shared.props @@ -1,6 +1,6 @@ - + diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/CallAnalyzer.Handlers.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/CallAnalyzer.Handlers.cs index 7766ad39d09..48cff34d5bd 100644 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/CallAnalyzer.Handlers.cs +++ b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/CallAnalyzer.Handlers.cs @@ -108,27 +108,5 @@ public void HandlePropertyReference(OperationAnalysisContext context) } } } - - public void HandleThrow(OperationAnalysisContext context) - { - var op = (IThrowOperation)context.Operation; - - if (op.Exception is IConversionOperation convOp) - { - if (convOp.Operand is IObjectCreationOperation creationOp) - { - if (creationOp.Type != null) - { - if (_state.ExceptionTypes.TryGetValue(creationOp.Type, out var handlers)) - { - foreach (var handler in handlers) - { - handler(context, op); - } - } - } - } - } - } } } diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/CallAnalyzer.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/CallAnalyzer.cs index 2eceb23502c..cb86bbfc892 100644 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/CallAnalyzer.cs +++ b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/CallAnalyzer.cs @@ -17,7 +17,6 @@ public sealed partial class CallAnalyzer : DiagnosticAnalyzer DiagDescriptors.StartsEndsWith, DiagDescriptors.LegacyLogging, DiagDescriptors.StaticTime, - DiagDescriptors.StringFormat, DiagDescriptors.EnumStrings, DiagDescriptors.ValueTuple, DiagDescriptors.Arrays, @@ -41,7 +40,6 @@ public override void Initialize(AnalysisContext context) _ = new StartsEndsWith(reg); _ = new StaticTime(reg); _ = new ValueTuple(reg); - _ = new StringFormat(reg); _ = new LegacyCollection(reg); _ = new Split(reg); @@ -49,7 +47,6 @@ public override void Initialize(AnalysisContext context) compilationStartContext.RegisterOperationAction(handlers.HandleInvocation, OperationKind.Invocation); compilationStartContext.RegisterOperationAction(handlers.HandleObjectCreation, OperationKind.ObjectCreation); compilationStartContext.RegisterOperationAction(handlers.HandlePropertyReference, OperationKind.PropertyReference); - compilationStartContext.RegisterOperationAction(handlers.HandleThrow, OperationKind.Throw); }); } } diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/StringFormat.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/StringFormat.cs deleted file mode 100644 index c2c9085b3c1..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/StringFormat.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Operations; - -namespace Microsoft.Extensions.ExtraAnalyzers.CallAnalysis; - -/// -/// Recommends using composite text formatting functionality. -/// -internal sealed class StringFormat -{ - public StringFormat(CallAnalyzer.Registrar reg) - { - if (reg.Compilation.GetTypeByMetadataName("System.Text.CompositeFormat") == null) - { - // composite formatting not available - return; - } - - foreach (var method in reg.Compilation.GetSpecialType(SpecialType.System_String).GetMembers("Format").OfType()) - { - reg.RegisterMethod(method, Handle); - } - - var type = reg.Compilation.GetTypeByMetadataName("System.Text.StringBuilder"); - if (type != null) - { - foreach (var method in type.GetMembers("AppendFormat").OfType()) - { - reg.RegisterMethod(method, Handle); - } - } - - static void Handle(OperationAnalysisContext context, IInvocationOperation op) - { - var format = GetFormatArgument(op); - if (format.ChildNodes().First().IsKind(SyntaxKind.StringLiteralExpression)) - { - var properties = new Dictionary(); - if (op.TargetMethod.Name == "Format") - { - properties.Add("StringFormat", null); - } - - var diagnostic = Diagnostic.Create(DiagDescriptors.StringFormat, op.Syntax.GetLocation(), properties.ToImmutableDictionary()); - context.ReportDiagnostic(diagnostic); - } - - static SyntaxNode GetFormatArgument(IInvocationOperation invocation) - { - var sm = invocation.SemanticModel!; - var arguments = invocation.Arguments; - var typeInfo = sm.GetTypeInfo(arguments[0].Syntax.ChildNodes().First()); - - // This check is needed to identify exactly which argument of string.Format is the format argument - // The format might be passed as first or second argument - // if there are more than 1 arguments and first argument is IFormatProvider then format is second argument otherwise it is first - if (arguments.Length > 1 && typeInfo.Type != null && typeInfo.Type.AllInterfaces.Any(i => i.MetadataName == "IFormatProvider")) - { - return arguments[1].Syntax; - } - - return arguments[0].Syntax; - } - } - } -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/DiagDescriptors.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/DiagDescriptors.cs index 5b59ed9393d..05693ffc75e 100644 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/DiagDescriptors.cs +++ b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/DiagDescriptors.cs @@ -49,37 +49,7 @@ internal static class DiagDescriptors helpLinkUri: "https://TODO/r9a000", isEnabledByDefault: true); - // R9A001..R9A017 are retired - - public static DiagnosticDescriptor StringFormat { get; } = new( - id: "R9A018", - messageFormat: Resources.StringFormatMessage, - title: Resources.StringFormatTitle, - category: Performance, - description: Resources.StringFormatDescription, - defaultSeverity: DiagnosticSeverity.Warning, - helpLinkUri: "https://TODO/r9a018", - isEnabledByDefault: true); - - public static DiagnosticDescriptor UsingExcessiveDictionaryLookup { get; } = new( - id: "R9A019", - messageFormat: Resources.UsingExcessiveDictionaryLookupMessage, - title: Resources.UsingExcessiveDictionaryLookupTitle, - category: Performance, - description: Resources.UsingExcessiveDictionaryLookupDescription, - defaultSeverity: DiagnosticSeverity.Warning, - helpLinkUri: "https://TODO/r9a019", - isEnabledByDefault: true); - - public static DiagnosticDescriptor UsingExcessiveSetLookup { get; } = new( - id: "R9A020", - messageFormat: Resources.UsingExcessiveSetLookupMessage, - title: Resources.UsingExcessiveSetLookupTitle, - category: Performance, - description: Resources.UsingExcessiveSetLookupDescription, - defaultSeverity: DiagnosticSeverity.Warning, - helpLinkUri: "https://TODO/r9a020", - isEnabledByDefault: true); + // R9A001..R9A020 are retired public static DiagnosticDescriptor UsingToStringInLoggers { get; } = new( id: "R9A021", @@ -101,17 +71,7 @@ internal static class DiagDescriptors helpLinkUri: "https://TODO/r9a022", isEnabledByDefault: true); - // R9A023..R9A028 retired - - public static DiagnosticDescriptor UsingExperimentalApi { get; } = new( - id: "R9A029", - messageFormat: Resources.UsingExperimentalApiMessage, - title: Resources.UsingExperimentalApiTitle, - category: Reliability, - description: Resources.UsingExperimentalApiDescription, - defaultSeverity: DiagnosticSeverity.Warning, - helpLinkUri: "https://TODO/r9a029", - isEnabledByDefault: true); + // R9A023..R9A029 retired public static DiagnosticDescriptor StartsEndsWith { get; } = new( id: "R9A030", @@ -189,17 +149,7 @@ internal static class DiagDescriptors helpLinkUri: "https://TODO/r9a043", isEnabledByDefault: true); - public static DiagnosticDescriptor MakeArrayStatic { get; } = new( - id: "R9A044", - messageFormat: Resources.MakeArrayStaticMessage, - title: Resources.MakeArrayStaticTitle, - category: Performance, - description: Resources.MakeArrayStaticDescription, - defaultSeverity: DiagnosticSeverity.Warning, - helpLinkUri: "https://TODO/r9a044", - isEnabledByDefault: true); - - // R9A045..R9A055 retired + // R9A044..R9A055 retired public static DiagnosticDescriptor AsyncCallInsideUsingBlock { get; } = new( id: "R9A056", diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/ISequentialFixer.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/ISequentialFixer.cs deleted file mode 100644 index f458a34227c..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/ISequentialFixer.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.CodeAnalysis; - -namespace Microsoft.Extensions.ExtraAnalyzers.FixAllProviders; - -public interface ISequentialFixer -{ - public SyntaxNode GetFixableSyntaxNodeFromDiagnostic(SyntaxNode documentRoot, Diagnostic diagnostic); - public SyntaxNode ApplyDiagnosticFixToSyntaxNode(SyntaxNode nodeToFix, Diagnostic diagnostic); -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/SequentialFixAllCodeAction.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/SequentialFixAllCodeAction.cs deleted file mode 100644 index b51863ed6d7..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/SequentialFixAllCodeAction.cs +++ /dev/null @@ -1,99 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; - -namespace Microsoft.Extensions.ExtraAnalyzers.FixAllProviders; - -public sealed class SequentialFixAllCodeAction : CodeAction -{ - public override string Title { get; } - - public SequentialFixAllCodeAction( - string fixAllTitle, - FixAllContext context, - ConcurrentDictionary> diagsToFixGroupedByDocId, - ImmutableArray inScopeDocumentIds) - { - Title = fixAllTitle; - _context = context; - _sequentialFixer = (context.CodeFixProvider as ISequentialFixer)!; - _diagsToFixGroupedByDocId = diagsToFixGroupedByDocId; - _solution = context.Solution; - _inScopeDocumentIds = inScopeDocumentIds; - } - - protected override async Task GetChangedSolutionAsync(CancellationToken cancellationToken) - { - do - { - // Apply CodeFix for all in scope documents and update solution with changed documents - var fixDiagTasks = _diagsToFixGroupedByDocId.Select(diagsInDoc => - { - var docId = diagsInDoc.Key; - return ApplyDiagnosticFixesAndGetDocumentRootAsync(docId) - .ContinueWith(completeFixDiagTask => - { - lock (_solution) - { - _solution = _solution.WithDocumentSyntaxRoot(docId, completeFixDiagTask.Result); - } - }, TaskScheduler.Default); - }); - await Task.WhenAll(fixDiagTasks).ConfigureAwait(continueOnCapturedContext: false); - - // Clear the internal map of document grouped diagnostics - _diagsToFixGroupedByDocId.Clear(); - - // Recompute diagnostics from all in scope documents - var recomputeDiagTasks = _inScopeDocumentIds.Select(docId => - { - var document = _solution.GetDocument(docId); - return _context - .GetDocumentDiagnosticsAsync(document!) - .ContinueWith(completeRecomputeTask => - { - var newDiagnostics = completeRecomputeTask.Result; - if (newDiagnostics.Any()) - { - _ = _diagsToFixGroupedByDocId.TryAdd(docId, newDiagnostics); - } - }, TaskScheduler.Default); - }); - await Task.WhenAll(recomputeDiagTasks).ConfigureAwait(continueOnCapturedContext: false); - } - while (!_diagsToFixGroupedByDocId.IsEmpty); - - return _solution; - } - - private readonly FixAllContext _context; - private readonly ISequentialFixer _sequentialFixer; - private readonly ConcurrentDictionary> _diagsToFixGroupedByDocId; - private Solution _solution; - private ImmutableArray _inScopeDocumentIds; - - private async Task ApplyDiagnosticFixesAndGetDocumentRootAsync(DocumentId docIdToFix) - { - var document = _solution.GetDocument(docIdToFix); - var docRoot = await document!.GetSyntaxRootAsync().ConfigureAwait(continueOnCapturedContext: false); - var diagnostics = _diagsToFixGroupedByDocId[docIdToFix]; - var nodeToDiagsMap = new Dictionary(); - - foreach (var d in diagnostics) - { - nodeToDiagsMap.Add(_sequentialFixer.GetFixableSyntaxNodeFromDiagnostic(docRoot!, d), d); - } - - return docRoot!.ReplaceNodes(nodeToDiagsMap.Keys.ToArray(), - (oldNode, _) => _sequentialFixer.ApplyDiagnosticFixToSyntaxNode(oldNode, nodeToDiagsMap[oldNode])); - } -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/SequentialFixAllProvider.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/SequentialFixAllProvider.cs deleted file mode 100644 index b6eaf013da0..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/FixAllProviders/SequentialFixAllProvider.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Concurrent; -using System.Collections.Immutable; -using System.Globalization; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; - -namespace Microsoft.Extensions.ExtraAnalyzers.FixAllProviders; - -public sealed class SequentialFixAllProvider : FixAllProvider -{ - public const string DocumentScopeStr = "document"; - public const string ProjectScopeStr = "project"; - - public static SequentialFixAllProvider GetInstance(ISequentialFixer _) => _instance; - - public override async Task GetFixAsync(FixAllContext fixAllContext) - { - (var fixAllTitle, var documentsToFix) = GetFixAllTitleAndDocumentsToFix(fixAllContext); - ConcurrentDictionary> diagsToFixGroupedByDocId = new(); - - var computeDiagTasks = documentsToFix.Select(docId => - fixAllContext.GetDocumentDiagnosticsAsync(fixAllContext.Solution.GetDocument(docId)!) - .ContinueWith((completeComputeDiagsTask) => - { - var diagsToFixInDocument = completeComputeDiagsTask.Result; - if (diagsToFixInDocument.Any()) - { - _ = diagsToFixGroupedByDocId.TryAdd(docId, diagsToFixInDocument); - } - }, TaskScheduler.Default)); - - await Task.WhenAll(computeDiagTasks).ConfigureAwait(continueOnCapturedContext: false); - - return new SequentialFixAllCodeAction( - fixAllTitle, - fixAllContext, - diagsToFixGroupedByDocId, - documentsToFix); - } - - private static readonly SequentialFixAllProvider _instance = new(); - - internal static ImmutableArray GetAllDocumentsInSolution(Solution solution) - { - var allDocsInSolution = ImmutableArray.Empty; - - foreach (var project in solution.Projects) - { - allDocsInSolution = allDocsInSolution.AddRange(project!.Documents.Select(d => d.Id)); - } - - return allDocsInSolution; - } - - internal static (string fixAllTitle, ImmutableArray documentsToFix) GetFixAllTitleAndDocumentsToFix(FixAllContext context) - { - var fixAllTitle = string.Empty; - var documentsToFix = ImmutableArray.Empty; - - switch (context.Scope) - { - case FixAllScope.Document: - fixAllTitle = string.Format( - CultureInfo.InvariantCulture, - Resources.SequentialFixAllFormat, - DocumentScopeStr, - context.Document!.Name); - documentsToFix = ImmutableArray.Create(context.Document!.Id); - break; - case FixAllScope.Project: - fixAllTitle = string.Format( - CultureInfo.InvariantCulture, - Resources.SequentialFixAllFormat, - ProjectScopeStr, - context.Project!.Name); - documentsToFix = context.Project.Documents.Select(d => d.Id).ToImmutableArray(); - break; - case FixAllScope.Solution: - fixAllTitle = Resources.SequentialFixAllInSolution; - documentsToFix = GetAllDocumentsInSolution(context.Solution); - break; - } - - return (fixAllTitle, documentsToFix); - } -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/OptimizeArraysAnalyzer.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/OptimizeArraysAnalyzer.cs deleted file mode 100644 index a0338d00df0..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/OptimizeArraysAnalyzer.cs +++ /dev/null @@ -1,144 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Operations; - -namespace Microsoft.Extensions.ExtraAnalyzers; - -/// -/// C# analyzer that recommends using Array.Empty, or making arrays of literals into static readonly fields. -/// -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public sealed class OptimizeArraysAnalyzer : DiagnosticAnalyzer -{ - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(DiagDescriptors.MakeArrayStatic); - - public override void Initialize(AnalysisContext context) - { - context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); - context.EnableConcurrentExecution(); - - context.RegisterOperationAction(operationAnalysisContext => - { - var arrayCreation = (IArrayCreationOperation)operationAnalysisContext.Operation; - - if (arrayCreation.Syntax.AncestorsAndSelf().Any(x => x.IsKind(SyntaxKind.Attribute))) - { - return; - } - - var initializer = arrayCreation.Initializer; - var target = arrayCreation.Parent; - var type = ((IArrayTypeSymbol?)arrayCreation.Type)?.ElementType; - - var empty = initializer?.ElementValues.Length == 0; -#pragma warning disable S1067 // Expressions should not be too complex - if (initializer == null - && arrayCreation.DimensionSizes.Length == 1 - && arrayCreation.DimensionSizes[0] is ILiteralOperation lit - && lit.ConstantValue.HasValue - && lit.ConstantValue.Value is 0) - { - empty = true; - } -#pragma warning restore S1067 // Expressions should not be too complex - - if (empty) - { - // empty arrays, handled by CA1825 - return; - } - - if (initializer == null) - { - return; - } - - foreach (var value in initializer.ElementValues) - { - if (value.Kind == OperationKind.Literal) - { - continue; - } - - if (value.Kind == OperationKind.FieldReference) - { - var fieldRef = (IFieldReferenceOperation)value; - if (fieldRef.ConstantValue.HasValue) - { - continue; - } - } - - return; - } - - // found a candidate array initialization... - - if (target != null) - { - if (InitializesStaticFieldOrProp(target)) - { - return; - } - } - - var diagnostic = Diagnostic.Create(DiagDescriptors.MakeArrayStatic, arrayCreation.Syntax.GetLocation()); - operationAnalysisContext.ReportDiagnostic(diagnostic); - }, OperationKind.ArrayCreation); - } - - private static bool InitializesStaticFieldOrProp(IOperation op) - { - // if this array allocation is done to initialize a static field or property, then don't report it - switch (op.Kind) - { - case OperationKind.FieldInitializer: - { - var fieldRef = (IFieldInitializerOperation)op; - foreach (var field in fieldRef.InitializedFields) - { - if (field.IsStatic) - { - return true; - } - } - - break; - } - - case OperationKind.PropertyInitializer: - { - var propRef = (IPropertyInitializerOperation)op; - foreach (var prop in propRef.InitializedProperties) - { - if (prop.IsStatic) - { - return true; - } - } - - break; - } - - case OperationKind.Conversion: - case OperationKind.Argument: - case OperationKind.Invocation: - { - if (op.Parent != null) - { - return InitializesStaticFieldOrProp(op.Parent); - } - - break; - } - } - - return false; - } -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Resources.Designer.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Resources.Designer.cs index 5151ed0abb5..12ea8d95178 100644 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Resources.Designer.cs +++ b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Resources.Designer.cs @@ -312,33 +312,6 @@ internal static string LegacyLoggingTitle { } } - /// - /// Looks up a localized string similar to Arrays of literal values should generally be assigned to static fields in order to avoid creating them redundantly over time. - /// - internal static string MakeArrayStaticDescription { - get { - return ResourceManager.GetString("MakeArrayStaticDescription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Assign array of literal values to a static field for improved performance. - /// - internal static string MakeArrayStaticMessage { - get { - return ResourceManager.GetString("MakeArrayStaticMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Assign array of literal values to a static field for improved performance. - /// - internal static string MakeArrayStaticTitle { - get { - return ResourceManager.GetString("MakeArrayStaticTitle", resourceCulture); - } - } - /// /// Looks up a localized string similar to Making an executable's types internal enables dead code analysis along with other potential optimizations. /// @@ -474,114 +447,6 @@ internal static string StaticTimeTitle { } } - /// - /// Looks up a localized string similar to Identifies uses of 'String.Format' and 'StringBuilder.AppendFormat'. - /// - internal static string StringFormatDescription { - get { - return ResourceManager.GetString("StringFormatDescription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Use 'System.Text.CompositeFormat' instead of 'string.Format' for improved performance. - /// - internal static string StringFormatMessage { - get { - return ResourceManager.GetString("StringFormatMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Use 'System.Text.CompositeFormat' instead of 'string.Format' for improved performance. - /// - internal static string StringFormatTitle { - get { - return ResourceManager.GetString("StringFormatTitle", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Encourages optimal use of dictionary lookup. - /// - internal static string UsingExcessiveDictionaryLookupDescription { - get { - return ResourceManager.GetString("UsingExcessiveDictionaryLookupDescription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Remove excessive dictionary lookups. - /// - internal static string UsingExcessiveDictionaryLookupMessage { - get { - return ResourceManager.GetString("UsingExcessiveDictionaryLookupMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Remove unnecessary dictionary lookups. - /// - internal static string UsingExcessiveDictionaryLookupTitle { - get { - return ResourceManager.GetString("UsingExcessiveDictionaryLookupTitle", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Encourages optimal use of set lookup. - /// - internal static string UsingExcessiveSetLookupDescription { - get { - return ResourceManager.GetString("UsingExcessiveSetLookupDescription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Remove excessive set lookups. - /// - internal static string UsingExcessiveSetLookupMessage { - get { - return ResourceManager.GetString("UsingExcessiveSetLookupMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Remove unnecessary set lookups. - /// - internal static string UsingExcessiveSetLookupTitle { - get { - return ResourceManager.GetString("UsingExcessiveSetLookupTitle", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Indicates that code is depending on an experimental API. - /// - internal static string UsingExperimentalApiDescription { - get { - return ResourceManager.GetString("UsingExperimentalApiDescription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to '{0}' is experimental and is subject to change without notice. - /// - internal static string UsingExperimentalApiMessage { - get { - return ResourceManager.GetString("UsingExperimentalApiMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Using experimental API. - /// - internal static string UsingExperimentalApiTitle { - get { - return ResourceManager.GetString("UsingExperimentalApiTitle", resourceCulture); - } - } - /// /// Looks up a localized string similar to Identifies calls to the 'ToString' method as arguments to a logging method. /// diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Resources.resx b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Resources.resx index ec270b81cb6..3a3d7e91220 100644 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Resources.resx +++ b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Resources.resx @@ -129,33 +129,6 @@ Use source generated logging methods for improved performance - - Identifies uses of 'String.Format' and 'StringBuilder.AppendFormat' - - - Use 'System.Text.CompositeFormat' instead of 'string.Format' for improved performance - - - Use 'System.Text.CompositeFormat' instead of 'string.Format' for improved performance - - - Encourages optimal use of dictionary lookup - - - Remove excessive dictionary lookups - - - Remove unnecessary dictionary lookups - - - Encourages optimal use of set lookup - - - Remove excessive set lookups - - - Remove unnecessary set lookups - Identifies calls to the 'ToString' method as arguments to a logging method @@ -180,15 +153,6 @@ Apply code fix for all issues in current solution - - Indicates that code is depending on an experimental API - - - Using experimental API - - - '{0}' is experimental and is subject to change without notice - When checking for a single character, prefer the character overloads of 'String.StartsWith' and 'String.EndsWith' for improved performance @@ -255,15 +219,6 @@ Use 'System.MemoryExtensions.Split' for improved performance - - Arrays of literal values should generally be assigned to static fields in order to avoid creating them redundantly over time - - - Assign array of literal values to a static field for improved performance - - - Assign array of literal values to a static field for improved performance - When skipping the await keyword for asynchronous operations inside a using block, then a disposable object could be disposed before the asynchronous invocation finishes. This might result in incorrect behavior and very often ends with a runtime exception notifying that the code is trying to operate on a disposed object. diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/StringFormatFixer.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/StringFormatFixer.cs deleted file mode 100644 index 85c4b1e707b..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/StringFormatFixer.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.Extensions.ExtraAnalyzers.Utilities; - -namespace Microsoft.Extensions.ExtraAnalyzers; - -/// -/// Replace string.Format usage with System.Text.CompositeFormat. -/// -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(StringFormatFixer))] -[Shared] -public sealed class StringFormatFixer : CodeFixProvider -{ - private const string TargetClass = "CompositeFormat"; - private const string TargetMethod = "Format"; - private const string VariableName = "_sf"; - private const int ArgumentsToSkip = 2; - private static readonly IdentifierNameSyntax _textNamespace = SyntaxFactory.IdentifierName("System.Text"); - - /// - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagDescriptors.StringFormat.Id); - - /// - public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - - /// - public override Task RegisterCodeFixesAsync(CodeFixContext context) - { - var diagnostics = context.Diagnostics.First(); - context.RegisterCodeFix( - CodeAction.Create( - title: Resources.StringFormatTitle, - createChangedDocument: cancellationToken => ApplyFixAsync(context.Document, diagnostics.Location, diagnostics.Properties, cancellationToken), - equivalenceKey: nameof(Resources.StringFormatTitle)), - context.Diagnostics); - - return Task.CompletedTask; - } - - private static async Task ApplyFixAsync(Document document, Location diagnosticLocation, IReadOnlyDictionary properties, CancellationToken cancellationToken) - { - var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); - if (editor.OriginalRoot.FindNode(diagnosticLocation.SourceSpan) is InvocationExpressionSyntax expression) - { - var classDeclaration = GetTypeDeclaration(expression); - if (classDeclaration != null) - { - var (format, argList) = GetFormatAndArguments(editor, expression); - var formatKind = format.ChildNodes().First().Kind(); - - if (formatKind is SyntaxKind.StringLiteralExpression) - { - var (identifier, field) = GetFieldDeclaration(editor, classDeclaration, format); - var invocation = properties.ContainsKey("StringFormat") - ? CreateInvocationExpression(editor, identifier, argList.Arguments, expression) - : GetStringBuilderExpression(editor, identifier, argList.Arguments, expression); - ApplyChanges(editor, expression, invocation, classDeclaration, field); - } - } - } - - return editor.GetChangedDocument(); - } - - private static TypeDeclarationSyntax? GetTypeDeclaration(SyntaxNode node) - { - return node.FirstAncestorOrSelf(n => n.IsKind(SyntaxKind.ClassDeclaration) || n.IsKind(SyntaxKind.StructDeclaration)); - } - - private static (string identifier, FieldDeclarationSyntax? field) GetFieldDeclaration(SyntaxEditor editor, SyntaxNode classDeclaration, SyntaxNode format) - { - var members = classDeclaration.DescendantNodes().OfType(); - int numberOfMembers = 1; - - var strExp = format.ToString(); - - var arguments = SyntaxFactory.Argument(SyntaxFactory.ParseExpression(strExp)); - HashSet fields = new HashSet(); - - foreach (var member in members) - { - var fieldName = member.DescendantNodes().OfType().First().Identifier.ToString(); - _ = fields.Add(fieldName); - - if (member.Declaration.Type.ToString() == "CompositeFormat") - { - if (member.DescendantNodes().OfType().First().ArgumentList!.Arguments.First().ToString() == strExp) - { - return (member.DescendantNodes().OfType().First().Identifier.ToString(), null); - } - - numberOfMembers++; - } - } - - string variableName; - do - { - variableName = $"{VariableName}{numberOfMembers}"; - numberOfMembers++; - } - while (!IsFieldNameAvailable(fields, variableName)); - - return (variableName, editor.Generator.FieldDeclaration( - variableName, - SyntaxFactory.ParseTypeName(TargetClass), - Accessibility.Private, - DeclarationModifiers.Static | DeclarationModifiers.ReadOnly, - SyntaxFactory.ObjectCreationExpression( - SyntaxFactory.Token(SyntaxKind.NewKeyword), - SyntaxFactory.IdentifierName(TargetClass), - SyntaxFactory.ArgumentList().AddArguments(arguments), - null)) as FieldDeclarationSyntax); - } - - private static bool IsFieldNameAvailable(ICollection fields, string field) - { - return !fields.Contains(field); - } - - private static (ArgumentSyntax argument, ArgumentListSyntax argumentList) GetFormatAndArguments(DocumentEditor editor, InvocationExpressionSyntax invocation) - { - var arguments = invocation.ArgumentList.Arguments; - var first = arguments[0]; - var typeInfo = editor.SemanticModel.GetTypeInfo(first.ChildNodes().First()); - SeparatedSyntaxList separatedList; - if (arguments.Count > 1 && typeInfo.Type!.AllInterfaces.Any(i => i.MetadataName == "IFormatProvider")) - { - separatedList = SyntaxFactory.SingletonSeparatedList(first).AddRange(arguments.Skip(ArgumentsToSkip)); - return (arguments[1], SyntaxFactory.ArgumentList(separatedList)); - } - - var nullArgument = SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)); - separatedList = SyntaxFactory.SingletonSeparatedList(nullArgument).AddRange(arguments.Skip(1)); - return (first, SyntaxFactory.ArgumentList(separatedList)); - } - - private static SyntaxNode CreateInvocationExpression(SyntaxEditor editor, string identifierName, IEnumerable arguments, SyntaxNode invocation) - { - var gen = editor.Generator; - var identifier = gen.IdentifierName(identifierName); - var memberAccessExpression = gen.MemberAccessExpression(identifier, TargetMethod); - return gen.InvocationExpression(memberAccessExpression, arguments).WithTriviaFrom(invocation); - } - - private static void ApplyChanges(SyntaxEditor editor, SyntaxNode oldInvocation, SyntaxNode newInvocation, SyntaxNode classDeclaration, SyntaxNode? field) - { - if (field != null) - { - editor.AddMember(classDeclaration, field); - } - - editor.ReplaceNode(oldInvocation, newInvocation); - editor.TryAddUsingDirective(_textNamespace); - } - - private static SyntaxNode GetStringBuilderExpression(SyntaxEditor editor, string identifierName, IEnumerable arguments, InvocationExpressionSyntax invocation) - { - var gen = editor.Generator; - var identifier = gen.IdentifierName(identifierName); - var memberAccessExpression = gen.Argument(identifier); - var list = SyntaxFactory.SingletonSeparatedList(memberAccessExpression).AddRange(arguments); - return invocation.WithArgumentList(SyntaxFactory.ArgumentList(list)); - } -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupAnalyzer.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupAnalyzer.cs deleted file mode 100644 index 473cd86b2b0..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupAnalyzer.cs +++ /dev/null @@ -1,321 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -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.Extensions.ExtraAnalyzers.Utilities; - -namespace Microsoft.Extensions.ExtraAnalyzers; - -/// -/// C# analyzer that finds excessive dictionary lookups. -/// -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public sealed class UsingExcessiveDictionaryLookupAnalyzer : DiagnosticAnalyzer -{ - private static readonly HashSet _containsKeyMethodFullNames = new(StringComparer.Ordinal) - { - "System.Collections.Generic.IDictionary.ContainsKey(TKey)", - "System.Collections.Generic.Dictionary.ContainsKey(TKey)", - "System.Collections.Generic.IReadOnlyDictionary.ContainsKey(TKey)" - }; - - private static readonly HashSet _addMethodFullNames = new(StringComparer.Ordinal) - { - "System.Collections.Generic.IDictionary.Add(TKey, TValue)", - "System.Collections.Generic.IDictionary.TryAdd(TKey, TValue)", - "System.Collections.Generic.Dictionary.TryAdd(TKey, TValue)", - "System.Collections.Generic.Dictionary.Add(TKey, TValue)" - }; - - private static readonly HashSet _otherMethodsFullNamesToCheck = new(_addMethodFullNames, StringComparer.Ordinal) - { - "System.Collections.Generic.IDictionary.Remove(TKey, out TValue)", - "System.Collections.Generic.IDictionary.Remove(TKey)", - "System.Collections.Generic.IDictionary.TryGetValue(TKey, out TValue)", - "System.Collections.Generic.Dictionary.Remove(TKey, out TValue)", - "System.Collections.Generic.Dictionary.Remove(TKey)", - "System.Collections.Generic.Dictionary.TryGetValue(TKey, out TValue)", - "System.Collections.Generic.IReadOnlyDictionary.TryGetValue(TKey, out TValue)" - }; - - /// - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(DiagDescriptors.UsingExcessiveDictionaryLookup); - - /// - public override void Initialize(AnalysisContext context) - { - context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); - context.EnableConcurrentExecution(); - - context.RegisterSyntaxNodeAction(syntaxNodeContext => - { - var ifStatement = (IfStatementSyntax)syntaxNodeContext.Node; - var invocationExpression = GetInvocationExpression(ifStatement.Condition)!; - if (!invocationExpression.NodeHasSpecifiedMethod(syntaxNodeContext.SemanticModel, _containsKeyMethodFullNames)) - { - return; - } - - string? expectedDictionaryIdentifierNameText = - invocationExpression.Expression is MemberAccessExpressionSyntax memberAccessExpression && - memberAccessExpression.Expression is IdentifierNameSyntax identifierNameSyntax - ? identifierNameSyntax.Identifier.Text - : null; - - if (expectedDictionaryIdentifierNameText == null) - { - return; - } - - var expectedContainsMethodArgument = invocationExpression.ArgumentList.Arguments[0]; - if (expectedContainsMethodArgument!.DescendantNodesAndSelf().Any(w => w is InvocationExpressionSyntax)) - { - return; - } - - var expectedContainsMethodArgumentText = expectedContainsMethodArgument!.GetText().ToString(); - - if (ifStatement.Else != null) - { - string? valueAddedToDictionaryInElse = ProcessStatementSyntaxAndGetAssignedValue( - ifStatement.Else.Statement, - syntaxNodeContext.SemanticModel, - expectedDictionaryIdentifierNameText, - expectedContainsMethodArgumentText); - - if (!string.IsNullOrEmpty(valueAddedToDictionaryInElse) && - valueAddedToDictionaryInElse!.Equals( - ProcessStatementSyntaxAndGetAssignedValue( - ifStatement.Statement, - syntaxNodeContext.SemanticModel, - expectedDictionaryIdentifierNameText, - expectedContainsMethodArgumentText), - StringComparison.OrdinalIgnoreCase)) - { - CreateDiagnosticAndReport(invocationExpression.GetLocation(), syntaxNodeContext); - } - - return; - } - - bool isDictionaryUsedInIfBody = ifStatement.Statement.DescendantNodes() - .Any(w => w is IdentifierNameSyntax id && id.Identifier.Text == expectedDictionaryIdentifierNameText); - - if (isDictionaryUsedInIfBody) - { - if (ifStatement.Statement is BlockSyntax block) - { - if (block.Statements.Count > 1) - { - CheckMultilineBlockAndReportDiagnostic( - block, - syntaxNodeContext, - expectedDictionaryIdentifierNameText, - expectedContainsMethodArgumentText, - invocationExpression.GetLocation()); - } - else - { - CheckSingleLineBlockAndReportDiagnostic( - block.Statements[0], - syntaxNodeContext, - expectedDictionaryIdentifierNameText, - expectedContainsMethodArgumentText, - invocationExpression.GetLocation()); - } - } - else - { - CheckSingleLineBlockAndReportDiagnostic( - ifStatement.Statement, - syntaxNodeContext, - expectedDictionaryIdentifierNameText, - expectedContainsMethodArgumentText, - invocationExpression.GetLocation()); - } - } - else if (ifStatement.Parent is BlockSyntax parentBlock) - { - var next = parentBlock.Statements.SkipWhile(w => w != ifStatement).Skip(1).FirstOrDefault(); - CheckSingleLineBlockAndReportDiagnostic( - next, - syntaxNodeContext, - expectedDictionaryIdentifierNameText, - expectedContainsMethodArgumentText, - null); - } - }, SyntaxKind.IfStatement); - } - - private static string? ProcessStatementSyntaxAndGetAssignedValue( - StatementSyntax statement, - SemanticModel semanticModel, - string expectedDictionaryIdentifierName, - string expectedContainsMethodArgumentText) - { - if (statement is BlockSyntax block) - { - if (block.Statements.Count == 1 && block.Statements[0] is ExpressionStatementSyntax expressionStatement) - { - return ProcessExpressionStatementSyntaxAndGetAssignedValue(expressionStatement, semanticModel, expectedDictionaryIdentifierName, expectedContainsMethodArgumentText); - } - } - else if (statement is ExpressionStatementSyntax expressionStatement) - { - return ProcessExpressionStatementSyntaxAndGetAssignedValue(expressionStatement, semanticModel, expectedDictionaryIdentifierName, expectedContainsMethodArgumentText); - } - - return null; - } - - private static string? ProcessExpressionStatementSyntaxAndGetAssignedValue( - ExpressionStatementSyntax expressionStatement, - SemanticModel semanticModel, - string expectedDictionaryIdentifierName, - string expectedContainsMethodArgumentText) - { - if (expressionStatement.Expression.NodeHasSpecifiedMethod(semanticModel, _addMethodFullNames)) - { - var foundInvocation = (InvocationExpressionSyntax)expressionStatement.Expression; - if (CheckIndentifierNameAndFirstArgument( - (foundInvocation.Expression as MemberAccessExpressionSyntax)!.Expression, - foundInvocation.ArgumentList, - expectedDictionaryIdentifierName, - expectedContainsMethodArgumentText)) - { - return foundInvocation.ArgumentList.Arguments[1].Expression.GetText().ToString(); - } - } - - if (expressionStatement.Expression is AssignmentExpressionSyntax assignmentExpression) - { - if (assignmentExpression.Left is ElementAccessExpressionSyntax elementAccessExpr && - CheckIndentifierNameAndFirstArgument( - elementAccessExpr.Expression, - elementAccessExpr.ArgumentList, - expectedDictionaryIdentifierName, - expectedContainsMethodArgumentText)) - { - return assignmentExpression.Right.GetText().ToString(); - } - } - - return null; - } - - private static void CheckMultilineBlockAndReportDiagnostic( - SyntaxNode block, - SyntaxNodeAnalysisContext syntaxNodeContext, - string expectedDictionaryIdentifierNameText, - string expectedContainsMethodArgumentText, - Location invocationExpressionLocation) - { - var dictionaryItemAccessExpressions = - block - .DescendantNodes() - .Where(w => w is ElementAccessExpressionSyntax elementAccessExpr && - CheckIndentifierNameAndFirstArgument( - elementAccessExpr.Expression, - elementAccessExpr.ArgumentList, - expectedDictionaryIdentifierNameText, - expectedContainsMethodArgumentText)); - - bool isInefficientDictionaryUsageFound = dictionaryItemAccessExpressions.Any( - w => - { - var isRightPartOfAssignmentExpression = w.Parent is AssignmentExpressionSyntax a && a.Right == w; - var isRightPartOfEqualsValueClause = w.Parent is EqualsValueClauseSyntax e && e.Value == w; - var isUsedAsArgument = w.Parent is ArgumentSyntax arg && arg.Expression == w; - - return isRightPartOfAssignmentExpression || isRightPartOfEqualsValueClause || isUsedAsArgument; - }); - - if (isInefficientDictionaryUsageFound) - { - CreateDiagnosticAndReport(invocationExpressionLocation, syntaxNodeContext); - } - } - - private static InvocationExpressionSyntax? GetInvocationExpression(ExpressionSyntax expression) - { - if (expression is PrefixUnaryExpressionSyntax logicalExpr && logicalExpr.IsKind(SyntaxKind.LogicalNotExpression)) - { - return logicalExpr.Operand as InvocationExpressionSyntax; - } - - return expression as InvocationExpressionSyntax; - } - - private static bool CheckIndentifierNameAndFirstArgument(ExpressionSyntax expression, BaseArgumentListSyntax argumentListSyntax, string expectedIndetifierName, string expectedFirstArgument) - { - return expression.IdentifierNameEquals(expectedIndetifierName) && - argumentListSyntax.Arguments[0].GetText().ToString() == expectedFirstArgument; - } - - private static void CheckSingleLineBlockAndReportDiagnostic( - StatementSyntax statementSyntax, - SyntaxNodeAnalysisContext syntaxNodeContext, - string expectedDictionaryIdentifierName, - string expectedContainsMethodArgumentText, - Location? locationToReport) - { - if (statementSyntax is ExpressionStatementSyntax expressionStatement) - { - if (CheckSingleLineBlock(expressionStatement.Expression, syntaxNodeContext.SemanticModel, expectedDictionaryIdentifierName, expectedContainsMethodArgumentText)) - { - CreateDiagnosticAndReport(locationToReport ?? expressionStatement.Expression.GetLocation(), syntaxNodeContext); - return; - } - - if (expressionStatement.Expression is AssignmentExpressionSyntax assignmentExpression) - { - if (assignmentExpression.Left is ElementAccessExpressionSyntax elementAccessExpr && - CheckIndentifierNameAndFirstArgument(elementAccessExpr.Expression, elementAccessExpr.ArgumentList, expectedDictionaryIdentifierName, expectedContainsMethodArgumentText)) - { - CreateDiagnosticAndReport(locationToReport ?? assignmentExpression.Left.GetLocation(), syntaxNodeContext); - return; - } - - bool shouldReport = assignmentExpression.Right is ElementAccessExpressionSyntax rightElementAccessExpr && - CheckIndentifierNameAndFirstArgument( - rightElementAccessExpr.Expression, - rightElementAccessExpr.ArgumentList, - expectedDictionaryIdentifierName, - expectedContainsMethodArgumentText); - if (shouldReport || CheckSingleLineBlock(assignmentExpression.Right, syntaxNodeContext.SemanticModel, expectedDictionaryIdentifierName, expectedContainsMethodArgumentText)) - { - CreateDiagnosticAndReport(locationToReport ?? assignmentExpression.Right.GetLocation(), syntaxNodeContext); - } - } - } - } - - private static void CreateDiagnosticAndReport(Location locationToReport, SyntaxNodeAnalysisContext syntaxNodeContext) - { - var diagnostic = Diagnostic.Create(DiagDescriptors.UsingExcessiveDictionaryLookup, locationToReport); - syntaxNodeContext.ReportDiagnostic(diagnostic); - } - - private static bool CheckSingleLineBlock( - SyntaxNode node, - SemanticModel semanticModel, - string expectedDictionaryIdentifierName, - string expectedContainsMethodArgumentText) - { - if (node.NodeHasSpecifiedMethod(semanticModel, _otherMethodsFullNamesToCheck)) - { - var foundInvocation = (InvocationExpressionSyntax)node; - var memberAccessExpression = foundInvocation.Expression as MemberAccessExpressionSyntax; - return CheckIndentifierNameAndFirstArgument(memberAccessExpression!.Expression, foundInvocation.ArgumentList, expectedDictionaryIdentifierName, expectedContainsMethodArgumentText); - } - - return false; - } -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupFixer.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupFixer.cs deleted file mode 100644 index 9ad135434a9..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupFixer.cs +++ /dev/null @@ -1,241 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.Formatting; -using Microsoft.Extensions.ExtraAnalyzers.Utilities; - -namespace Microsoft.Extensions.ExtraAnalyzers; - -/// -/// Removes excessive dictionary lookups. -/// -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(UsingExcessiveDictionaryLookupFixer))] -[Shared] -public sealed class UsingExcessiveDictionaryLookupFixer : CodeFixProvider -{ - private const string ContainsKeyMethodName = "ContainsKey"; - private static readonly SimpleNameSyntax _tryGetValueMethod = (SimpleNameSyntax)SyntaxFactory.ParseName("TryGetValue"); - private static readonly SimpleNameSyntax _tryAddMethod = (SimpleNameSyntax)SyntaxFactory.ParseName("TryAdd"); - private static readonly HashSet _removeAndTryGetMethodFullNames = new() - { - "System.Collections.Generic.IDictionary.Remove(TKey, out TValue)", - "System.Collections.Generic.IDictionary.Remove(TKey)", - "System.Collections.Generic.Dictionary.Remove(TKey)", - "System.Collections.Generic.Dictionary.Remove(TKey, out TValue)", - "System.Collections.Generic.IDictionary.TryGetValue(TKey, out TValue)", - "System.Collections.Generic.Dictionary.TryGetValue(TKey, out TValue)", - "System.Collections.Generic.IReadOnlyDictionary.TryGetValue(TKey, out TValue)" - }; - - private static readonly HashSet _methodsFullNamesToBeHanled = new(_removeAndTryGetMethodFullNames) - { - "System.Collections.Generic.IDictionary.Add(TKey, TValue)", - "System.Collections.Generic.IDictionary.TryAdd(TKey, TValue)", - "System.Collections.Generic.Dictionary.TryAdd(TKey, TValue)", - "System.Collections.Generic.Dictionary.Add(TKey, TValue)" - }; - - /// - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagDescriptors.UsingExcessiveDictionaryLookup.Id); - - /// - public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - - /// - public override Task RegisterCodeFixesAsync(CodeFixContext context) - { - context.RegisterCodeFix( - CodeAction.Create( - title: Resources.UsingExcessiveDictionaryLookupTitle, - createChangedDocument: cancellationToken => ApplyFixAsync(context.Document, context.Diagnostics.First().Location, cancellationToken), - equivalenceKey: nameof(Resources.UsingExcessiveDictionaryLookupTitle)), - context.Diagnostics); - - return Task.CompletedTask; - } - - private static async Task ApplyFixAsync(Document document, Location diagnosticLocation, CancellationToken cancellationToken) - { - var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); - - var invocationExpression = editor.OriginalRoot.FindNode(diagnosticLocation.SourceSpan) as InvocationExpressionSyntax; - var memberAccessExpression = invocationExpression?.Expression as MemberAccessExpressionSyntax; - if (memberAccessExpression == null || memberAccessExpression.Name.GetText().ToString() != ContainsKeyMethodName) - { - return document; - } - - var expectedDictionaryIdentifier = (IdentifierNameSyntax)memberAccessExpression.Expression; - - var expectedKeyArgument = invocationExpression!.ArgumentList.Arguments[0]; - var ifStatementSyntax = (IfStatementSyntax)invocationExpression.GetFirstAncestorOfSyntaxKind(SyntaxKind.IfStatement)!; - - if (ifStatementSyntax.Else != null) - { - var separatedList = SyntaxFactory.SeparatedList(new[] { expectedKeyArgument }); - var bracketedArgumentList = SyntaxFactory.BracketedArgumentList(SyntaxFactory.ParseToken("["), separatedList, SyntaxFactory.ParseToken("]")); - var elementAccessExpression = SyntaxFactory.ElementAccessExpression(expectedDictionaryIdentifier, bracketedArgumentList); - - var expressionStatementSyntax = (ExpressionStatementSyntax)(ifStatementSyntax.Else.Statement is BlockSyntax blockInsideElse - ? blockInsideElse.Statements[0] - : ifStatementSyntax.Else.Statement); - - var assignedValue = expressionStatementSyntax.Expression is InvocationExpressionSyntax inv - ? inv.ArgumentList.Arguments[1].Expression - : ((AssignmentExpressionSyntax)expressionStatementSyntax.Expression).Right; - - var simpleAssignmentExpression = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, elementAccessExpression, assignedValue); - - return CreateExpressionStatementAndReplaceOldNode(simpleAssignmentExpression, ifStatementSyntax, editor); - } - - var expectedDictionaryIdentifierNameText = expectedDictionaryIdentifier.Identifier.Text; - var expectedKeyText = expectedKeyArgument.GetText().ToString(); - if (ifStatementSyntax.Statement is BlockSyntax block) - { - if (block.Statements.Count > 1) - { - return ProcessIfWithMultilineBody(editor, ifStatementSyntax, invocationExpression, expectedDictionaryIdentifierNameText, expectedKeyText); - } - - return ProcessIfWithSingleLineBody(editor, ifStatementSyntax, invocationExpression, expectedDictionaryIdentifierNameText, block.Statements[0]); - } - - return ProcessIfWithSingleLineBody(editor, ifStatementSyntax, invocationExpression, expectedDictionaryIdentifierNameText, ifStatementSyntax.Statement); - } - - private static Document ProcessIfWithMultilineBody( - DocumentEditor editor, - IfStatementSyntax ifStatement, - InvocationExpressionSyntax invocationExpression, - string dictionaryName, - string expectedKeyText) - { - // replaces ContainsKey by TryGetValue - var newInvocationExpression = CreateTryGetValueInvocationExpression(invocationExpression); - var newIfStatement = ifStatement.ReplaceNode(invocationExpression, newInvocationExpression); - - // replaces dictionary item access expressions by 'retrievedValue' in 'if' body - var dictionaryItemAccessExpressionsToReplace = - newIfStatement.Statement - .DescendantNodes() - .Where(w => w is ElementAccessExpressionSyntax elementAccessExpr && - CheckIndentifierNameAndFirstArgument( - elementAccessExpr.Expression, - elementAccessExpr.ArgumentList, - dictionaryName, - expectedKeyText)); - - var newIdentifierName = SyntaxFactory.IdentifierName("retrievedValue"); - newIfStatement = newIfStatement.ReplaceNodes(dictionaryItemAccessExpressionsToReplace, (_, _) => newIdentifierName); - editor.ReplaceNode(ifStatement, newIfStatement); - - return editor.GetChangedDocument(); - } - - private static Document CreateExpressionStatementAndReplaceOldNode(ExpressionSyntax newExpressionSyntax, SyntaxNode oldSyntaxNode, DocumentEditor editor) - { - var newExpression = SyntaxFactory.ExpressionStatement(newExpressionSyntax, SyntaxFactory.ParseToken(";")).WithTriviaFrom(oldSyntaxNode); - editor.ReplaceNode(oldSyntaxNode, newExpression); - return editor.GetChangedDocument(); - } - - private static Document ProcessIfWithSingleLineBody( - DocumentEditor editor, - SyntaxNode ifStatement, - InvocationExpressionSyntax invocationExpression, - string dictionaryName, - StatementSyntax statementSyntax) - { - ExpressionSyntax expression = ((ExpressionStatementSyntax)statementSyntax).Expression; - - if (expression is AssignmentExpressionSyntax assignmentExpression) - { - if (assignmentExpression!.Left is ElementAccessExpressionSyntax elementAccessExpr && - elementAccessExpr.Expression.IdentifierNameEquals(dictionaryName)) - { - // replaces if with ContainsKey by TryAdd - ExpressionSyntax newExpr = ((MemberAccessExpressionSyntax)invocationExpression.Expression) - .WithName(_tryAddMethod).WithAdditionalAnnotations(Formatter.Annotation); - - var newArguments = invocationExpression.ArgumentList.AddArguments(SyntaxFactory.Argument(assignmentExpression.Right)); - var newInvocationExpr = invocationExpression.WithExpression(newExpr).WithArgumentList(newArguments); - - return CreateExpressionStatementAndReplaceOldNode(newInvocationExpr, ifStatement, editor); - } - - if (assignmentExpression!.Right is ElementAccessExpressionSyntax elementAccessExprRight && - elementAccessExprRight.Expression.IdentifierNameEquals(dictionaryName)) - { - // replaces if with ContainsKey by TryGetValue - var newTryGetValueInvocationExpr = CreateTryGetValueInvocationExpression(invocationExpression); - - editor.ReplaceNode(invocationExpression, newTryGetValueInvocationExpr); - - var identifierName = SyntaxFactory.IdentifierName("retrievedValue"); - editor.ReplaceNode(assignmentExpression.Right, identifierName); - return editor.GetChangedDocument(); - } - - return CreateExpressionStatementAndReplaceOldNode(assignmentExpression, ifStatement, editor); - } - - var removeOrAddOrTryGetSyntaxNode = expression - .DescendantNodesAndSelf() - .First(w => w.NodeHasSpecifiedMethod(editor.SemanticModel, _methodsFullNamesToBeHanled)); - - return CheckInvocation(removeOrAddOrTryGetSyntaxNode, editor, ifStatement); - } - - private static Document CheckInvocation( - SyntaxNode node, - DocumentEditor editor, - SyntaxNode ifStatement) - { - if (node.NodeHasSpecifiedMethod(editor.SemanticModel, _removeAndTryGetMethodFullNames)) - { - // replaces "if" containing "ContainsKey" with "Remove" or "TryGetValue" - return CreateExpressionStatementAndReplaceOldNode((InvocationExpressionSyntax)node, ifStatement, editor); - } - - // replaces "if" containing "ContainsKey" with "TryAdd" - var foundInvocation = (InvocationExpressionSyntax)node; - ExpressionSyntax newExpr = ((MemberAccessExpressionSyntax)foundInvocation.Expression) - .WithName(_tryAddMethod).WithAdditionalAnnotations(Formatter.Annotation); - var newInvocationExpr = foundInvocation.WithExpression(newExpr); - - return CreateExpressionStatementAndReplaceOldNode(newInvocationExpr, ifStatement, editor); - } - - private static InvocationExpressionSyntax CreateTryGetValueInvocationExpression(InvocationExpressionSyntax oldInvocation) - { - ExpressionSyntax newExpr = ((MemberAccessExpressionSyntax)oldInvocation.Expression) - .WithName(_tryGetValueMethod).WithAdditionalAnnotations(Formatter.Annotation); - - var newArgument = SyntaxFactory.DeclarationExpression( - SyntaxFactory.IdentifierName(SyntaxFactory.ParseToken("var")).WithTrailingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.Whitespace(" "))), - SyntaxFactory.SingleVariableDesignation(SyntaxFactory.ParseToken("retrievedValue"))); - - var newArguments = oldInvocation.ArgumentList.AddArguments(SyntaxFactory.Argument(null, SyntaxFactory.ParseToken("out"), newArgument)); - - return oldInvocation.WithExpression(newExpr).WithArgumentList(newArguments); - } - - private static bool CheckIndentifierNameAndFirstArgument(ExpressionSyntax expression, BaseArgumentListSyntax argumentListSyntax, string expectedIndetifierName, string expectedFirstArgument) - { - return expression.IdentifierNameEquals(expectedIndetifierName) && - argumentListSyntax.Arguments[0].GetText().ToString() == expectedFirstArgument; - } -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupAnalyzer.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupAnalyzer.cs deleted file mode 100644 index 3771e199b5b..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupAnalyzer.cs +++ /dev/null @@ -1,225 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -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.Extensions.ExtraAnalyzers.Utilities; - -namespace Microsoft.Extensions.ExtraAnalyzers; - -/// -/// C# analyzer that finds excessive set lookups. -/// -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public sealed class UsingExcessiveSetLookupAnalyzer : DiagnosticAnalyzer -{ - private const string SetCollectionFullName = "System.Collections.Generic.ISet"; - private static readonly HashSet _collectionContainsMethodFullName = new(StringComparer.Ordinal) - { - "System.Collections.Generic.ICollection.Contains(T)" - }; - - private static readonly HashSet _containsMethodFullNames = new(StringComparer.Ordinal) - { - "System.Collections.Generic.SortedSet.Contains(T)", - "System.Collections.Generic.HashSet.Contains(T)", - "System.Collections.Immutable.ImmutableHashSet.Contains(T)", - "System.Collections.Immutable.ImmutableSortedSet.Contains(T)", - "System.Collections.Immutable.ImmutableHashSet.Builder.Contains(T)", - "System.Collections.Immutable.ImmutableSortedSet.Builder.Contains(T)" - }; - - private static readonly HashSet _methodsReturningBool = new(StringComparer.Ordinal) - { - "System.Collections.Generic.SortedSet.Remove(T)", - "System.Collections.Generic.HashSet.Remove(T)", - "System.Collections.Generic.ICollection.Remove(T)", - "System.Collections.Immutable.ImmutableHashSet.Builder.Remove(T)", - "System.Collections.Immutable.ImmutableSortedSet.Builder.Remove(T)", - - "System.Collections.Generic.SortedSet.TryGetValue(T, out T)", - "System.Collections.Generic.HashSet.TryGetValue(T, out T)", - "System.Collections.Immutable.ImmutableHashSet.TryGetValue(T, out T)", - "System.Collections.Immutable.ImmutableSortedSet.TryGetValue(T, out T)", - - "System.Collections.Generic.SortedSet.Add(T)", - "System.Collections.Generic.HashSet.Add(T)", - "System.Collections.Generic.ISet.Add(T)", - "System.Collections.Immutable.ImmutableHashSet.Builder.Add(T)", - "System.Collections.Immutable.ImmutableSortedSet.Builder.Add(T)" - }; - - private static readonly HashSet _otherMethodsFullNamesToCheck = new(_methodsReturningBool, StringComparer.Ordinal) - { - "System.Collections.Immutable.ImmutableHashSet.Remove(T)", - "System.Collections.Immutable.ImmutableSortedSet.Remove(T)", - "System.Collections.Immutable.ImmutableHashSet.Add(T)", - "System.Collections.Immutable.ImmutableSortedSet.Add(T)", - }; - - /// - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(DiagDescriptors.UsingExcessiveSetLookup); - - /// - public override void Initialize(AnalysisContext context) - { - _ = context ?? throw new ArgumentNullException(nameof(context)); - - context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); - context.EnableConcurrentExecution(); - - context.RegisterSyntaxNodeAction(syntaxNodeContext => - { - var ifStatement = (IfStatementSyntax)syntaxNodeContext.Node; - if (ifStatement.Else != null) - { - return; - } - - var invocationExpression = GetInvocationExpression(ifStatement.Condition)!; - if (!invocationExpression.NodeHasSpecifiedMethod(syntaxNodeContext.SemanticModel, _containsMethodFullNames) - && !(invocationExpression.NodeHasSpecifiedMethod(syntaxNodeContext.SemanticModel, _collectionContainsMethodFullName) - && NodeHasSpecifiedType(invocationExpression, syntaxNodeContext.SemanticModel))) - { - return; - } - - string? expectedSetIdentifierNameText = - invocationExpression.Expression is MemberAccessExpressionSyntax memberAccessExpression && - memberAccessExpression.Expression is IdentifierNameSyntax identifierNameSyntax - ? identifierNameSyntax.Identifier.Text - : null; - - if (expectedSetIdentifierNameText == null) - { - return; - } - - var expectedContainsMethodArgument = invocationExpression.ArgumentList.Arguments[0]; - if (expectedContainsMethodArgument!.DescendantNodesAndSelf().Any(w => w is InvocationExpressionSyntax)) - { - return; - } - - var expectedContainsMethodArgumentText = expectedContainsMethodArgument!.GetText().ToString(); - - bool isSetUsedInIfBody = ifStatement.Statement.DescendantNodes() - .Any(w => w is IdentifierNameSyntax id && id.Identifier.Text == expectedSetIdentifierNameText); - - if (isSetUsedInIfBody) - { - var lineToCheck = ifStatement.Statement is BlockSyntax block ? block.Statements[0] : ifStatement.Statement; - CheckSingleLineBlockAndReportDiagnostic( - lineToCheck, - syntaxNodeContext, - expectedSetIdentifierNameText, - expectedContainsMethodArgumentText, - invocationExpression.GetLocation()); - } - else if (ifStatement.Parent is BlockSyntax parentBlock) - { - var next = parentBlock.Statements.SkipWhile(w => w != ifStatement).Skip(1).FirstOrDefault(); - CheckSingleLineBlockAndReportDiagnostic( - next, - syntaxNodeContext, - expectedSetIdentifierNameText, - expectedContainsMethodArgumentText, - null, - checkOnlyMethodsReturningBool: true); - } - }, SyntaxKind.IfStatement); - } - - private static bool NodeHasSpecifiedType( - InvocationExpressionSyntax? invocationExpression, - SemanticModel semanticModel) - { - if (invocationExpression != null) - { - var memberAccessExpression = (MemberAccessExpressionSyntax)invocationExpression.Expression; - if (memberAccessExpression!.Expression is IdentifierNameSyntax identifierNameSyntax) - { - var symbol = semanticModel.GetTypeInfo(identifierNameSyntax).Type; - return symbol!.OriginalDefinition!.ToString() == SetCollectionFullName; - } - } - - return false; - } - - private static InvocationExpressionSyntax? GetInvocationExpression(ExpressionSyntax expression) - { - if (expression is PrefixUnaryExpressionSyntax logicalExpr && logicalExpr.IsKind(SyntaxKind.LogicalNotExpression)) - { - return logicalExpr.Operand as InvocationExpressionSyntax; - } - - return expression as InvocationExpressionSyntax; - } - - private static bool CheckIndentifierNameAndFirstArgument(ExpressionSyntax expression, BaseArgumentListSyntax argumentListSyntax, string expectedIndetifierName, string expectedFirstArgument) - { - return expression.IdentifierNameEquals(expectedIndetifierName) && - argumentListSyntax.Arguments[0].GetText().ToString() == expectedFirstArgument; - } - - private static void CheckSingleLineBlockAndReportDiagnostic( - StatementSyntax statementSyntax, - SyntaxNodeAnalysisContext syntaxNodeContext, - string expectedSetIdentifierName, - string expectedContainsMethodArgumentText, - Location? locationToReport, - bool checkOnlyMethodsReturningBool = false) - { - if (statementSyntax is ExpressionStatementSyntax expressionStatement) - { - if (expressionStatement.Expression is AssignmentExpressionSyntax assignmentExpression) - { - var invocationExpr = GetInvocationExpression(assignmentExpression.Right); - if (assignmentExpression.Left.IdentifierNameEquals("_") && - CheckSingleLineBlock(invocationExpr, syntaxNodeContext.SemanticModel, expectedSetIdentifierName, expectedContainsMethodArgumentText, _methodsReturningBool)) - { - CreateDiagnosticAndReport(locationToReport ?? invocationExpr!.GetLocation(), syntaxNodeContext); - } - - return; - } - - var invocationExpression = GetInvocationExpression(expressionStatement.Expression); - var methodsToCheck = checkOnlyMethodsReturningBool ? _methodsReturningBool : _otherMethodsFullNamesToCheck; - if (CheckSingleLineBlock(invocationExpression, syntaxNodeContext.SemanticModel, expectedSetIdentifierName, expectedContainsMethodArgumentText, methodsToCheck)) - { - CreateDiagnosticAndReport(locationToReport ?? invocationExpression!.GetLocation(), syntaxNodeContext); - } - } - } - - private static bool CheckSingleLineBlock( - SyntaxNode? node, - SemanticModel semanticModel, - string expectedSetIdentifierName, - string expectedContainsMethodArgumentText, - ICollection methodsToCheck) - { - if (node.NodeHasSpecifiedMethod(semanticModel, methodsToCheck)) - { - var foundInvocation = (InvocationExpressionSyntax)node!; - var memberAccessExpression = (MemberAccessExpressionSyntax)foundInvocation.Expression; - return CheckIndentifierNameAndFirstArgument(memberAccessExpression!.Expression, foundInvocation.ArgumentList, expectedSetIdentifierName, expectedContainsMethodArgumentText); - } - - return false; - } - - private static void CreateDiagnosticAndReport(Location locationToReport, SyntaxNodeAnalysisContext syntaxNodeContext) - { - var diagnostic = Diagnostic.Create(DiagDescriptors.UsingExcessiveSetLookup, locationToReport); - syntaxNodeContext.ReportDiagnostic(diagnostic); - } -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupFixer.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupFixer.cs deleted file mode 100644 index 6f9a32bdd49..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupFixer.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Immutable; -using System.Composition; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.Extensions.ExtraAnalyzers.Utilities; - -namespace Microsoft.Extensions.ExtraAnalyzers; - -/// -/// Removes excessive lookups. -/// -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(UsingExcessiveSetLookupFixer))] -[Shared] -public sealed class UsingExcessiveSetLookupFixer : CodeFixProvider -{ - private const string ContainsMethodName = "Contains"; - private const string AddMethodName = "Add"; - private const string RemoveMethodName = "Remove"; - - /// - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagDescriptors.UsingExcessiveSetLookup.Id); - - /// - public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - - /// - public override Task RegisterCodeFixesAsync(CodeFixContext context) - { - context.RegisterCodeFix( - CodeAction.Create( - title: Resources.UsingExcessiveSetLookupTitle, - createChangedDocument: cancellationToken => ApplyFixAsync(context.Document, context.Diagnostics.First().Location, cancellationToken), - equivalenceKey: nameof(Resources.UsingExcessiveSetLookupTitle)), - context.Diagnostics); - - return Task.CompletedTask; - } - - private static async Task ApplyFixAsync(Document document, Location diagnosticLocation, CancellationToken cancellationToken) - { - var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); - var invocationExpression = (InvocationExpressionSyntax)editor.OriginalRoot.FindNode(diagnosticLocation.SourceSpan); - var memberAccessExpression = (MemberAccessExpressionSyntax)invocationExpression.Expression; - var methodName = memberAccessExpression.Name.GetText().ToString(); - if (methodName == ContainsMethodName) - { - var ifStatementSyntax = (IfStatementSyntax)invocationExpression.GetFirstAncestorOfSyntaxKind(SyntaxKind.IfStatement)!; - - if (ifStatementSyntax.Statement is BlockSyntax block) - { - if (block.Statements.Count > 1) - { - var newInvocation = ((ExpressionStatementSyntax)block.Statements[0]).Expression.WithTriviaFrom(invocationExpression); - editor.ReplaceNode(invocationExpression, newInvocation); - var newBlock = block.WithStatements(block.Statements.RemoveAt(0)); - editor.ReplaceNode(block, newBlock); - } - else - { - editor.ReplaceNode(ifStatementSyntax, block.Statements[0].WithTriviaFrom(ifStatementSyntax)); - } - - return editor.GetChangedDocument(); - } - - editor.ReplaceNode(ifStatementSyntax, ifStatementSyntax.Statement.WithTriviaFrom(ifStatementSyntax)); - return editor.GetChangedDocument(); - } - - if (methodName == AddMethodName || methodName == RemoveMethodName) - { - var nodeToRemove = invocationExpression.GetFirstAncestorOfSyntaxKind(SyntaxKind.ExpressionStatement); - var blockStatements = ((BlockSyntax)nodeToRemove!.Parent!).Statements; - int ifStatementIndex = blockStatements.IndexOf((StatementSyntax)nodeToRemove) - 1; - var ifStatement = (IfStatementSyntax)blockStatements[ifStatementIndex]; - - var newNode = SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, invocationExpression); - editor.ReplaceNode(ifStatement.Condition, newNode); - editor.RemoveNode(nodeToRemove!); - return editor.GetChangedDocument(); - } - - return document; - } -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExperimentalApiAnalyzer.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExperimentalApiAnalyzer.cs deleted file mode 100644 index 33f5d430bee..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExperimentalApiAnalyzer.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Immutable; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.Extensions.ExtraAnalyzers.Utilities; - -namespace Microsoft.Extensions.ExtraAnalyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -internal sealed class UsingExperimentalApiAnalyzer : DiagnosticAnalyzer -{ - public override ImmutableArray SupportedDiagnostics - => ImmutableArray.Create(DiagDescriptors.UsingExperimentalApi); - - public override void Initialize(AnalysisContext context) - { - context.EnableConcurrentExecution(); - context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); - - context.RegisterCompilationStartAction(context => - { - var experimentalAttribute = context.Compilation.GetTypeByMetadataName("System.Diagnostics.CodeAnalysis.ExperimentalAttribute"); - - context.RegisterSyntaxNodeAction(context => - { - var sn = (IdentifierNameSyntax)context.Node; - if (sn.IsVar) - { - return; - } - - var sym = context.SemanticModel.GetSymbolInfo(sn).Symbol; - - if (sym != null - && (sym.Kind is not SymbolKind.Namespace and not SymbolKind.Label and not SymbolKind.Discard) - && sym.IsContaminated(experimentalAttribute)) - { - if (sym.IsExternallyVisible()) - { - context.ReportDiagnostic(Diagnostic.Create(DiagDescriptors.UsingExperimentalApi, sn.GetLocation(), sym)); - } - } - }, SyntaxKind.IdentifierName); - }); - } -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Utilities/SymbolExtensions.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Utilities/SymbolExtensions.cs index 6c1a11e56ae..bc8966ba8cf 100644 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Utilities/SymbolExtensions.cs +++ b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Utilities/SymbolExtensions.cs @@ -77,109 +77,4 @@ public static bool ImplementsPublicInterface(this IMethodSymbol method) return false; } - - /// - /// Checks if a symbol has the queried fully qualified name. - /// - /// The symbol to check. - /// The fully qualified name to check against. - /// True if the symbol has the provided fully qualified name, false otherwise. - public static bool HasFullyQualifiedName(this ISymbol symbol, string fullyQualifiedName) - { - if (symbol is not null) - { - var actualSymbolFullName = symbol.ToDisplayString(); - return actualSymbolFullName.Equals(fullyQualifiedName, System.StringComparison.Ordinal); - } - - return false; - } - - /// - /// Checks if a type has the specified base type. - /// - /// The type being checked. - /// The fully qualified name of the base type to look for. - /// True if the type has the specified base type, false otherwise. - public static bool InheritsFromType(this ITypeSymbol type, string baseTypeFullName) - { - if (type is not null) - { - while (type.BaseType != null) - { - var actualBaseTypeFullName = string.Concat(type.BaseType.ContainingNamespace, ".", type.BaseType.Name); - if (actualBaseTypeFullName.Equals(baseTypeFullName, System.StringComparison.Ordinal)) - { - return true; - } - - type = type.BaseType; - } - } - - return false; - } - - public static bool HasAttribute(this ISymbol sym, INamedTypeSymbol attribute) - { - foreach (var a in sym.GetAttributes()) - { - if (SymbolEqualityComparer.Default.Equals(a.AttributeClass, attribute)) - { - return true; - } - } - - return false; - } - - public static bool IsContaminated(this ISymbol symbol, INamedTypeSymbol? contaminationAttribute) - { - return (contaminationAttribute != null) && IsContaminated(symbol); - - bool IsContaminated(ISymbol symbol) - { - if (symbol.HasAttribute(contaminationAttribute)) - { - // symbol is annotated - return true; - } - - if (symbol.ContainingAssembly != null - && symbol.ContainingAssembly.HasAttribute(contaminationAttribute)) - { - // symbol's assembly is annotated - return true; - } - - var container = symbol.ContainingType; - while (container != null) - { - if (IsContaminated(container)) - { - // symbol's container is annotated - return true; - } - - container = container.ContainingType; - } - - if (symbol is INamedTypeSymbol type) - { - var baseType = type.BaseType; - while (baseType != null) - { - if (IsContaminated(baseType)) - { - // symbol's base type is annotated - return true; - } - - baseType = baseType.BaseType; - } - } - - return false; - } - } } diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Utilities/SyntaxEditorExtensions.cs b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Utilities/SyntaxEditorExtensions.cs deleted file mode 100644 index 10dc369f87c..00000000000 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/Utilities/SyntaxEditorExtensions.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.Formatting; - -namespace Microsoft.Extensions.ExtraAnalyzers.Utilities; - -/// -/// Class contains extensions. -/// -internal static class SyntaxEditorExtensions -{ - /// - /// Tries to add using directive. - /// - /// The syntax editor. - /// The namespace name. - public static void TryAddUsingDirective(this SyntaxEditor editor, NameSyntax namespaceName) - { - if (editor.GetChangedRoot() is CompilationUnitSyntax documentRoot) - { - var anyUsings = documentRoot.Usings.Any(u => u.Name.GetText().ToString().Equals(namespaceName.ToString(), StringComparison.Ordinal)); - var usingDirective = SyntaxFactory.UsingDirective(namespaceName); - documentRoot = anyUsings ? documentRoot : documentRoot.AddUsings(usingDirective).WithAdditionalAnnotations(Formatter.Annotation); - editor.ReplaceNode(editor.OriginalRoot, documentRoot); - } - } -} diff --git a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Microsoft.Extensions.ExtraAnalyzers.Roslyn3.8/Microsoft.Extensions.ExtraAnalyzers.Roslyn3.8.csproj b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Microsoft.Extensions.ExtraAnalyzers.Roslyn3.8/Microsoft.Extensions.ExtraAnalyzers.Roslyn3.8.csproj index 47076388095..46cf686e30a 100644 --- a/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Microsoft.Extensions.ExtraAnalyzers.Roslyn3.8/Microsoft.Extensions.ExtraAnalyzers.Roslyn3.8.csproj +++ b/src/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Microsoft.Extensions.ExtraAnalyzers.Roslyn3.8/Microsoft.Extensions.ExtraAnalyzers.Roslyn3.8.csproj @@ -10,7 +10,6 @@ - diff --git a/src/Libraries/Microsoft.AspNetCore.Telemetry.Middleware/Logging/LoggingOptions.cs b/src/Libraries/Microsoft.AspNetCore.Telemetry.Middleware/Logging/LoggingOptions.cs index 1b8d4484e75..cc1f517e92f 100644 --- a/src/Libraries/Microsoft.AspNetCore.Telemetry.Middleware/Logging/LoggingOptions.cs +++ b/src/Libraries/Microsoft.AspNetCore.Telemetry.Middleware/Logging/LoggingOptions.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Compliance.Classification; using Microsoft.Extensions.Http.Telemetry; using Microsoft.Shared.Data.Validation; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.AspNetCore.Telemetry; @@ -67,7 +68,7 @@ public class LoggingOptions /// /// The default value is . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public HttpRouteParameterRedactionMode RequestPathParameterRedactionMode { get; set; } = DefaultPathParameterRedactionMode; /// @@ -208,7 +209,7 @@ public class LoggingOptions /// }; /// /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] [Required] [SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "Options pattern.")] diff --git a/src/Libraries/Microsoft.AspNetCore.Telemetry/Enrichment.RequestHeaders/RequestHeadersLogEnricherOptions.cs b/src/Libraries/Microsoft.AspNetCore.Telemetry/Enrichment.RequestHeaders/RequestHeadersLogEnricherOptions.cs index 48a9c455637..507737468c1 100644 --- a/src/Libraries/Microsoft.AspNetCore.Telemetry/Enrichment.RequestHeaders/RequestHeadersLogEnricherOptions.cs +++ b/src/Libraries/Microsoft.AspNetCore.Telemetry/Enrichment.RequestHeaders/RequestHeadersLogEnricherOptions.cs @@ -5,6 +5,7 @@ using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Compliance.Classification; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.AspNetCore.Telemetry; @@ -20,7 +21,7 @@ public class RequestHeadersLogEnricherOptions /// Default value is an empty dictionary. /// [Required] - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] #pragma warning disable CA2227 // Collection properties should be read only public IDictionary HeadersDataClasses { get; set; } = new Dictionary(); #pragma warning restore CA2227 // Collection properties should be read only diff --git a/src/Libraries/Microsoft.AspNetCore.Telemetry/Tracing/HttpTracingExtensions.cs b/src/Libraries/Microsoft.AspNetCore.Telemetry/Tracing/HttpTracingExtensions.cs index 479800527cf..4ab7c5aa71e 100644 --- a/src/Libraries/Microsoft.AspNetCore.Telemetry/Tracing/HttpTracingExtensions.cs +++ b/src/Libraries/Microsoft.AspNetCore.Telemetry/Tracing/HttpTracingExtensions.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Options; using Microsoft.Extensions.Options.Validation; using Microsoft.Extensions.Telemetry.Internal; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using OpenTelemetry.Instrumentation.AspNetCore; using OpenTelemetry.Trace; @@ -116,7 +117,7 @@ public static TracerProviderBuilder AddHttpTraceEnricher(this TracerProviderBuil /// The to add this enricher. /// for chaining. /// The argument is . - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static IServiceCollection AddHttpTraceEnricher(this IServiceCollection services) where T : class, IHttpTraceEnricher { @@ -132,7 +133,7 @@ public static IServiceCollection AddHttpTraceEnricher(this IServiceCollection /// Enricher to be added. /// for chaining. /// The argument or is . - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static IServiceCollection AddHttpTraceEnricher(this IServiceCollection services, IHttpTraceEnricher enricher) { _ = Throw.IfNull(services); diff --git a/src/Libraries/Microsoft.AspNetCore.Telemetry/Tracing/HttpTracingOptions.cs b/src/Libraries/Microsoft.AspNetCore.Telemetry/Tracing/HttpTracingOptions.cs index 795304f4961..9f11d2cf47e 100644 --- a/src/Libraries/Microsoft.AspNetCore.Telemetry/Tracing/HttpTracingOptions.cs +++ b/src/Libraries/Microsoft.AspNetCore.Telemetry/Tracing/HttpTracingOptions.cs @@ -7,6 +7,7 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Compliance.Classification; using Microsoft.Extensions.Http.Telemetry; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.AspNetCore.Telemetry; @@ -51,7 +52,7 @@ public class HttpTracingOptions /// /// This property is applicable when the option is enabled. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public HttpRouteParameterRedactionMode RequestPathParameterRedactionMode { get; set; } = DefaultPathParameterRedactionMode; /// diff --git a/src/Libraries/Microsoft.Extensions.AsyncState/IAsyncLocalContext.cs b/src/Libraries/Microsoft.Extensions.AsyncState/IAsyncLocalContext.cs index 84f8113f0e4..0a435267b1d 100644 --- a/src/Libraries/Microsoft.Extensions.AsyncState/IAsyncLocalContext.cs +++ b/src/Libraries/Microsoft.Extensions.AsyncState/IAsyncLocalContext.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.AsyncState; @@ -11,7 +12,7 @@ namespace Microsoft.Extensions.AsyncState; /// /// The type of the asynchronous state. /// This type is intended for internal use. Use instead. -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AsyncState, UrlFormat = Experiments.UrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] #pragma warning disable S4023 // Interfaces should not be empty public interface IAsyncLocalContext : IAsyncContext diff --git a/src/Libraries/Microsoft.Extensions.Compliance.Abstractions/Classification/DataClassification.cs b/src/Libraries/Microsoft.Extensions.Compliance.Abstractions/Classification/DataClassification.cs index 879e1424a21..5b1c29381ab 100644 --- a/src/Libraries/Microsoft.Extensions.Compliance.Abstractions/Classification/DataClassification.cs +++ b/src/Libraries/Microsoft.Extensions.Compliance.Abstractions/Classification/DataClassification.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Compliance.Classification; @@ -153,6 +154,6 @@ public static DataClassification Combine(DataClassification left, DataClassifica /// Gets a string representation of this object. /// /// A string representing the object. - [Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] + [Experimental(diagnosticId: Experiments.Compliance, UrlFormat = Experiments.UrlFormat)] public override string ToString() => $"{TaxonomyName}:{Value:x}"; } diff --git a/src/Libraries/Microsoft.Extensions.Compliance.Abstractions/Redaction/Redactor.cs b/src/Libraries/Microsoft.Extensions.Compliance.Abstractions/Redaction/Redactor.cs index d98511bc331..2bd257d06e4 100644 --- a/src/Libraries/Microsoft.Extensions.Compliance.Abstractions/Redaction/Redactor.cs +++ b/src/Libraries/Microsoft.Extensions.Compliance.Abstractions/Redaction/Redactor.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; +using Microsoft.Shared.DiagnosticIds; #if !NETCOREAPP3_1_OR_GREATER using System.Buffers; @@ -199,7 +200,7 @@ public int Redact(T value, Span destination, string? format = null, IFo /// if the destination buffer was large enough, otherwise . [SkipLocalsInit] [SuppressMessage("Minor Code Smell", "S3247:Duplicate casts should not be made", Justification = "Avoid pattern matching to improve jitted code")] - [Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] + [Experimental(diagnosticId: Experiments.Compliance, UrlFormat = Experiments.UrlFormat)] public bool TryRedact(T value, Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider = null) { #if NET6_0_OR_GREATER diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/CommonHealthChecksExtensions.TelemetryPublisher.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/CommonHealthChecksExtensions.TelemetryPublisher.cs index 8b11352cc8e..8f4d5ce9412 100644 --- a/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/CommonHealthChecksExtensions.TelemetryPublisher.cs +++ b/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/CommonHealthChecksExtensions.TelemetryPublisher.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Telemetry.Metering; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Diagnostics.HealthChecks; @@ -30,7 +31,7 @@ public static IServiceCollection AddTelemetryHealthCheckPublisher(this IServiceC /// Configuration for . /// The value of . /// or is . - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.HealthChecks, UrlFormat = Experiments.UrlFormat)] public static IServiceCollection AddTelemetryHealthCheckPublisher(this IServiceCollection services, IConfigurationSection section) => Throw.IfNull(services) .Configure(Throw.IfNull(section)) @@ -44,7 +45,7 @@ public static IServiceCollection AddTelemetryHealthCheckPublisher(this IServiceC /// Configuration for . /// The value of . /// or is . - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.HealthChecks, UrlFormat = Experiments.UrlFormat)] public static IServiceCollection AddTelemetryHealthCheckPublisher(this IServiceCollection services, Action configure) => Throw.IfNull(services) .Configure(Throw.IfNull(configure)) diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/TelemetryHealthCheckPublisherOptions.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/TelemetryHealthCheckPublisherOptions.cs index e8d358c322a..a6c9ef49b90 100644 --- a/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/TelemetryHealthCheckPublisherOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.Common/TelemetryHealthCheckPublisherOptions.cs @@ -2,13 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Diagnostics.HealthChecks; /// /// Options for the telemetry health check publisher. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.HealthChecks, UrlFormat = Experiments.UrlFormat)] public class TelemetryHealthCheckPublisherOptions { /// diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ResourceMonitoringOptions.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ResourceMonitoringOptions.cs index 8e2c81b3eb8..77ca5b7f77b 100644 --- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ResourceMonitoringOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ResourceMonitoringOptions.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using Microsoft.Shared.Data.Validation; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring; @@ -50,7 +51,7 @@ public class ResourceMonitoringOptions /// The value needs to be less than or equal to the . /// Most importantly, this period is used to calculate instances pushed to publishers. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.ResourceMonitoring, UrlFormat = Experiments.UrlFormat)] [TimeSpan(MinimumSamplingWindow, MaximumSamplingWindow)] public TimeSpan CalculationPeriod { get; set; } = DefaultCollectionWindow; } diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsCountersOptions.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsCountersOptions.cs index 143038d129b..6c666b0729a 100644 --- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsCountersOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsCountersOptions.cs @@ -6,13 +6,14 @@ using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using Microsoft.Shared.Data.Validation; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring; /// /// Options for WindowsCounters. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.ResourceMonitoring, UrlFormat = Experiments.UrlFormat)] public class WindowsCountersOptions { internal const int MinimumCachingInterval = 100; @@ -33,7 +34,6 @@ public class WindowsCountersOptions /// /// The default value is 5 seconds. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] [TimeSpan(MinimumCachingInterval, MaximumCachingInterval)] public TimeSpan CachingInterval { get; set; } = DefaultCachingInterval; } diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsUtilizationExtensions.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsUtilizationExtensions.cs index 24b2181c9c2..9410d89c546 100644 --- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsUtilizationExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsUtilizationExtensions.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Options; using Microsoft.Extensions.Options.Validation; using Microsoft.Extensions.Telemetry.Metering; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring; @@ -65,7 +66,7 @@ public static IResourceMonitorBuilder AddWindowsPerfCounterPublisher(this IResou /// The value of . /// is . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.ResourceMonitoring, UrlFormat = Experiments.UrlFormat)] public static IResourceMonitorBuilder AddWindowsCounters(this IResourceMonitorBuilder builder) { _ = Throw.IfNull(builder); @@ -93,7 +94,7 @@ public static IResourceMonitorBuilder AddWindowsCounters(this IResourceMonitorBu /// The value of . /// is . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.ResourceMonitoring, UrlFormat = Experiments.UrlFormat)] public static IResourceMonitorBuilder AddWindowsCounters(this IResourceMonitorBuilder builder, IConfigurationSection section) { _ = Throw.IfNull(builder); @@ -123,7 +124,7 @@ public static IResourceMonitorBuilder AddWindowsCounters(this IResourceMonitorBu /// The value of . /// is . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.ResourceMonitoring, UrlFormat = Experiments.UrlFormat)] public static IResourceMonitorBuilder AddWindowsCounters(this IResourceMonitorBuilder builder, Action configure) { _ = Throw.IfNull(builder); diff --git a/src/Libraries/Microsoft.Extensions.Hosting.Testing/HostingFakesExtensions.cs b/src/Libraries/Microsoft.Extensions.Hosting.Testing/HostingFakesExtensions.cs index dd7f30caa0d..cf5e7d48555 100644 --- a/src/Libraries/Microsoft.Extensions.Hosting.Testing/HostingFakesExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Hosting.Testing/HostingFakesExtensions.cs @@ -12,6 +12,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting.Testing.Internal; using Microsoft.Extensions.Telemetry.Testing.Logging; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Hosting.Testing; @@ -19,7 +20,7 @@ namespace Microsoft.Extensions.Hosting.Testing; /// /// Extension methods supporting host unit testing scenarios. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Hosting, UrlFormat = Experiments.UrlFormat)] public static class HostingFakesExtensions { /// diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientAttribute.cs index 991d8dc86c7..3653eb0c0af 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientAttribute.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Net.Http; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -27,7 +28,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Interface)] [Conditional("CODE_GENERATION_ATTRIBUTES")] public sealed class AutoClientAttribute : Attribute diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientException.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientException.cs index fcf66278270..67dcf2636b5 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientException.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientException.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Http.AutoClient; @@ -27,7 +28,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// /// [SuppressMessage("Design", "CA1032:Implement standard exception constructors", Justification = "Not applicable to this exception")] -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] public class AutoClientException : Exception { /// diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientHttpError.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientHttpError.cs index 5fa83d55f6d..4011f38658e 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientHttpError.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientHttpError.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Primitives; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Http.AutoClient; @@ -19,7 +20,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// When a REST API client fails, it will throw a . /// This exception contains a instance that holds details like content, headers and status code. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] public class AutoClientHttpError { /// diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientOptions.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientOptions.cs index 9d2396b9d9f..4e656e5e87a 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/AutoClientOptions.cs @@ -4,6 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.Text.Json; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -21,7 +22,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// }); /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] public class AutoClientOptions { /// diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/BodyAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/BodyAttribute.cs index e42f95bc907..9032de48d02 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/BodyAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/BodyAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -24,7 +25,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Parameter)] [Conditional("CODE_GENERATION_ATTRIBUTES")] public sealed class BodyAttribute : Attribute diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/BodyContentType.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/BodyContentType.cs index f0db4db2d67..70e24c5c7db 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/BodyContentType.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/BodyContentType.cs @@ -2,13 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; /// /// Defines the types of encoding possible for request bodies. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] public enum BodyContentType { /// diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/HeaderAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/HeaderAttribute.cs index 870ec80600a..67ed984b32d 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/HeaderAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/HeaderAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -23,7 +24,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Parameter)] [Conditional("CODE_GENERATION_ATTRIBUTES")] public sealed class HeaderAttribute : Attribute diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/DeleteAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/DeleteAttribute.cs index e7121e9089d..f722271035d 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/DeleteAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/DeleteAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Net.Http; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -29,7 +30,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Method)] public sealed class DeleteAttribute : Attribute { diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/GetAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/GetAttribute.cs index 83d21e01cd6..dd0117aa22f 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/GetAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/GetAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Net.Http; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -29,7 +30,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Method)] public sealed class GetAttribute : Attribute { diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/HeadAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/HeadAttribute.cs index 57f24addaec..4fd6b3050d4 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/HeadAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/HeadAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Net.Http; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -29,7 +30,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Method)] public sealed class HeadAttribute : Attribute { diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/OptionsAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/OptionsAttribute.cs index 9d000a6dd98..a9f2f00ce53 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/OptionsAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/OptionsAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Net.Http; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -29,7 +30,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Method)] public sealed class OptionsAttribute : Attribute { diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PatchAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PatchAttribute.cs index d3388371ca2..5e1472cebca 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PatchAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PatchAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Net.Http; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -29,7 +30,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Method)] public sealed class PatchAttribute : Attribute { diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PostAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PostAttribute.cs index c88d022a988..c83f7be2bd2 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PostAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PostAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Net.Http; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -29,7 +30,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Method)] public sealed class PostAttribute : Attribute { diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PutAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PutAttribute.cs index db4e5c3eecb..58d69ef720d 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PutAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/Methods/PutAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Net.Http; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -29,7 +30,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Method)] public sealed class PutAttribute : Attribute { diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/QueryAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/QueryAttribute.cs index b41741594e7..3069e273a41 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/QueryAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/QueryAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -23,7 +24,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Parameter)] [Conditional("CODE_GENERATION_ATTRIBUTES")] public sealed class QueryAttribute : Attribute diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/RequestNameAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/RequestNameAttribute.cs index 36334e48012..fc50dab9aef 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/RequestNameAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/RequestNameAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -26,7 +27,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Method)] [Conditional("CODE_GENERATION_ATTRIBUTES")] public sealed class RequestNameAttribute : Attribute diff --git a/src/Libraries/Microsoft.Extensions.Http.AutoClient/StaticHeaderAttribute.cs b/src/Libraries/Microsoft.Extensions.Http.AutoClient/StaticHeaderAttribute.cs index 3414c852343..8e08ddaf5e0 100644 --- a/src/Libraries/Microsoft.Extensions.Http.AutoClient/StaticHeaderAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Http.AutoClient/StaticHeaderAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.AutoClient; @@ -27,7 +28,7 @@ namespace Microsoft.Extensions.Http.AutoClient; /// } /// /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.AutoClient, UrlFormat = Experiments.UrlFormat)] [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Method, AllowMultiple = true)] [Conditional("CODE_GENERATION_ATTRIBUTES")] public sealed class StaticHeaderAttribute : Attribute diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/FaultInjection/ContextExtensions.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/FaultInjection/ContextExtensions.cs index a2d6fce2463..81c344ab1be 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Resilience/FaultInjection/ContextExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/FaultInjection/ContextExtensions.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.Net.Http; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using Polly; @@ -11,7 +12,7 @@ namespace Microsoft.Extensions.Http.Resilience.FaultInjection; /// /// Provides extension methods for . /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public static class ContextExtensions { private const string CallingRequestMessage = "CallingRequestMessage"; diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/FaultInjection/HttpClientFaultInjectionExtensions.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/FaultInjection/HttpClientFaultInjectionExtensions.cs index 79384677e04..d8c6eab11b8 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Resilience/FaultInjection/HttpClientFaultInjectionExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/FaultInjection/HttpClientFaultInjectionExtensions.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Http.Resilience.FaultInjection.Internal; using Microsoft.Extensions.Options; using Microsoft.Extensions.Resilience.FaultInjection; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using Polly; @@ -147,7 +148,7 @@ public static IHttpClientBuilder AddFaultInjectionPolicyHandler(this IHttpClient /// /// The so that additional calls can be chained. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public static IHttpClientBuilder AddWeightedFaultInjectionPolicyHandlers(this IHttpClientBuilder httpClientBuilder, Action weightAssignmentsConfig) { @@ -176,7 +177,7 @@ public static IHttpClientBuilder AddWeightedFaultInjectionPolicyHandlers(this IH /// /// The so that additional calls can be chained. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] [DynamicDependency( DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor, typeof(FaultPolicyWeightAssignmentsOptions))] diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/Hedging/StandardHedgingHandlerBuilderExtensions.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/Hedging/StandardHedgingHandlerBuilderExtensions.cs index 482134c966e..45590188236 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Resilience/Hedging/StandardHedgingHandlerBuilderExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/Hedging/StandardHedgingHandlerBuilderExtensions.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Http.Resilience.Internal; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Http.Resilience; @@ -61,7 +62,7 @@ public static IStandardHedgingHandlerBuilder Configure(this IStandardHedgingHand /// The strategy builder. /// The configure method. /// The same builder instance. - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public static IStandardHedgingHandlerBuilder Configure(this IStandardHedgingHandlerBuilder builder, Action configure) { _ = Throw.IfNull(builder); diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/HttpStandardResilienceBuilderBuilderExtensions.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/HttpStandardResilienceBuilderBuilderExtensions.cs index cea0f55d811..e1605362d1b 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/HttpStandardResilienceBuilderBuilderExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/HttpStandardResilienceBuilderBuilderExtensions.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Http.Resilience.Internal; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Http.Resilience; @@ -62,7 +63,7 @@ public static IHttpStandardResilienceStrategyBuilder Configure(this IHttpStandar /// The configure method. /// The same builder instance. #pragma warning disable S3872 // Parameter names should not duplicate the names of their methods - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public static IHttpStandardResilienceStrategyBuilder Configure(this IHttpStandardResilienceStrategyBuilder builder, Action configure) #pragma warning restore S3872 // Parameter names should not duplicate the names of their methods { diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/RoutingStrategyBuilderExtensions.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/RoutingStrategyBuilderExtensions.cs index 3af3821ca72..f8eaf3f554c 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/RoutingStrategyBuilderExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/RoutingStrategyBuilderExtensions.cs @@ -12,6 +12,7 @@ using Microsoft.Extensions.Http.Resilience.Routing.Internal.WeightedGroups; using Microsoft.Extensions.Options; using Microsoft.Extensions.Options.Validation; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Http.Resilience; @@ -65,7 +66,7 @@ public static IRoutingStrategyBuilder ConfigureOrderedGroups(this IRoutingStrate /// /// The same routing builder instance. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public static IRoutingStrategyBuilder ConfigureOrderedGroups(this IRoutingStrategyBuilder builder, Action configure) { _ = Throw.IfNull(builder); @@ -119,7 +120,7 @@ public static IRoutingStrategyBuilder ConfigureWeightedGroups(this IRoutingStrat /// /// The same routing builder instance. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public static IRoutingStrategyBuilder ConfigureWeightedGroups(this IRoutingStrategyBuilder builder, Action configure) { _ = Throw.IfNull(builder); diff --git a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Logging/LoggingOptions.cs b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Logging/LoggingOptions.cs index dde659ecf0e..4bb97be2ac0 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Logging/LoggingOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Logging/LoggingOptions.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Compliance.Classification; using Microsoft.Extensions.Http.Telemetry; using Microsoft.Shared.Data.Validation; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.Telemetry.Logging; @@ -134,7 +135,7 @@ public class LoggingOptions /// /// The default value is . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public HttpRouteParameterRedactionMode RequestPathParameterRedactionMode { get; set; } = DefaultPathParameterRedactionMode; /// diff --git a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpClientMeteringExtensions.cs b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpClientMeteringExtensions.cs index 5bfe9a45cb5..53beea6b9e1 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpClientMeteringExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpClientMeteringExtensions.cs @@ -13,6 +13,9 @@ using Microsoft.Extensions.Telemetry.Metering; using Microsoft.Shared.Collections; using Microsoft.Shared.Diagnostics; +#if !NETFRAMEWORK +using Microsoft.Shared.DiagnosticIds; +#endif namespace Microsoft.Extensions.Http.Telemetry.Metering; @@ -34,7 +37,7 @@ public static class HttpClientMeteringExtensions /// /// instance for chaining. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static IServiceCollection AddHttpClientMeteringForAllHttpClients(this IServiceCollection services) { _ = Throw.IfNull(services); diff --git a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpMeteringHandler.cs b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpMeteringHandler.cs index c91c0ea162a..d2cd3747888 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpMeteringHandler.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpMeteringHandler.cs @@ -16,6 +16,7 @@ using Microsoft.Extensions.Telemetry; using Microsoft.Extensions.Telemetry.Internal; using Microsoft.Extensions.Telemetry.Metering; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using Microsoft.Shared.Pools; @@ -49,7 +50,7 @@ public class HttpMeteringHandler : DelegatingHandler /// /// The meter. /// Enumerable of outgoing request metric enrichers. - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public HttpMeteringHandler( Meter meter, IEnumerable enrichers) diff --git a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpRequestResultType.cs b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpRequestResultType.cs index c93429ec899..f2ccaab80c8 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpRequestResultType.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Metering/HttpRequestResultType.cs @@ -3,13 +3,14 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.EnumStrings; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.Telemetry.Metering; /// /// Statuses for classifying http request result. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] [EnumStrings] public enum HttpRequestResultType { diff --git a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/HttpClientTracingExtensions.cs b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/HttpClientTracingExtensions.cs index 5d0a2a297b0..21bc7c0ae90 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/HttpClientTracingExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/HttpClientTracingExtensions.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Options; using Microsoft.Extensions.Options.Validation; using Microsoft.Extensions.Telemetry.Internal; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using OpenTelemetry.Instrumentation.Http; using OpenTelemetry.Trace; @@ -82,7 +83,7 @@ public static TracerProviderBuilder AddHttpClientTracing(this TracerProviderBuil /// The to add this enricher to. /// for chaining. /// The argument is . - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static IServiceCollection AddHttpClientTraceEnricher(this IServiceCollection services) where T : class, IHttpClientTraceEnricher { @@ -98,7 +99,7 @@ public static IServiceCollection AddHttpClientTraceEnricher(this IServiceColl /// Enricher to be added. /// for chaining. /// The argument or is . - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static IServiceCollection AddHttpClientTraceEnricher(this IServiceCollection services, IHttpClientTraceEnricher enricher) { _ = Throw.IfNull(services); diff --git a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/HttpClientTracingOptions.cs b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/HttpClientTracingOptions.cs index 8833ee5cb55..401bf767c70 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/HttpClientTracingOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/HttpClientTracingOptions.cs @@ -7,6 +7,7 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Compliance.Classification; using Microsoft.Extensions.Http.Telemetry; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.Telemetry.Tracing; @@ -23,7 +24,7 @@ public class HttpClientTracingOptions /// /// The default value is . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public HttpRouteParameterRedactionMode RequestPathParameterRedactionMode { get; set; } = DefaultPathParameterRedactionMode; /// diff --git a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/IHttpClientTraceEnricher.netfx.cs b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/IHttpClientTraceEnricher.netfx.cs index dde431b28ff..f32a1b30a90 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/IHttpClientTraceEnricher.netfx.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/IHttpClientTraceEnricher.netfx.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Net; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.Telemetry.Tracing; @@ -23,7 +24,7 @@ public interface IHttpClientTraceEnricher /// /// If your enricher fetches some information from or to enrich HTTP traces, then make sure to check it for . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] void Enrich(Activity activity, HttpWebRequest? webRequest, HttpWebResponse? webResponse); } diff --git a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/IHttpPathRedactor.cs b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/IHttpPathRedactor.cs index 42beec0a000..c69371c3789 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/IHttpPathRedactor.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Telemetry/Tracing/IHttpPathRedactor.cs @@ -4,13 +4,14 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Compliance.Classification; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.Telemetry.Tracing; /// /// Interface for implementing a redaction mechanism for outgoing HTTP request paths. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public interface IHttpPathRedactor { /// diff --git a/src/Libraries/Microsoft.Extensions.ObjectPool.DependencyInjection/DependencyInjectionPoolOptions.cs b/src/Libraries/Microsoft.Extensions.ObjectPool.DependencyInjection/DependencyInjectionPoolOptions.cs index 2569ccb4ba3..440e3194cee 100644 --- a/src/Libraries/Microsoft.Extensions.ObjectPool.DependencyInjection/DependencyInjectionPoolOptions.cs +++ b/src/Libraries/Microsoft.Extensions.ObjectPool.DependencyInjection/DependencyInjectionPoolOptions.cs @@ -2,13 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.ObjectPool; /// /// Contains configuration for pools. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.ObjectPool, UrlFormat = Experiments.UrlFormat)] public sealed class DependencyInjectionPoolOptions { internal const int DefaultCapacity = 1024; diff --git a/src/Libraries/Microsoft.Extensions.ObjectPool.DependencyInjection/ObjectPoolServiceCollectionExtensions.cs b/src/Libraries/Microsoft.Extensions.ObjectPool.DependencyInjection/ObjectPoolServiceCollectionExtensions.cs index 0fb5894b606..8b1cd045916 100644 --- a/src/Libraries/Microsoft.Extensions.ObjectPool.DependencyInjection/ObjectPoolServiceCollectionExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.ObjectPool.DependencyInjection/ObjectPoolServiceCollectionExtensions.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.ObjectPool; using Microsoft.Extensions.Options; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.ObjectPool; @@ -15,7 +16,7 @@ namespace Microsoft.Extensions.ObjectPool; /// /// Extension methods for adding to DI container. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.ObjectPool, UrlFormat = Experiments.UrlFormat)] public static class ObjectPoolServiceCollectionExtensions { /// diff --git a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/FaultInjectionExtensions.cs b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/FaultInjectionExtensions.cs index 9eb6eaf6812..d6648d5b2df 100644 --- a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/FaultInjectionExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/FaultInjectionExtensions.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Telemetry.Metering; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using Polly; @@ -125,7 +126,7 @@ public static Context WithFaultInjection(this Context context, string groupName) /// /// Any argument is . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public static Context WithFaultInjection(this Context context, FaultPolicyWeightAssignmentsOptions weightAssignments) { _ = Throw.IfNull(context); diff --git a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/FaultInjectionOptionsBuilder.cs b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/FaultInjectionOptionsBuilder.cs index c839db73056..90fbe7048b9 100644 --- a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/FaultInjectionOptionsBuilder.cs +++ b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/FaultInjectionOptionsBuilder.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options.Validation; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Resilience.FaultInjection; @@ -126,7 +127,7 @@ public FaultInjectionOptionsBuilder AddException(string key, Exception exception /// /// is an empty string or . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public FaultInjectionOptionsBuilder AddCustomResult(string key, object customResult) { _ = Throw.IfNull(customResult); diff --git a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/IChaosPolicyFactory.cs b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/IChaosPolicyFactory.cs index da707ba38ef..f11d9c15a32 100644 --- a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/IChaosPolicyFactory.cs +++ b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/IChaosPolicyFactory.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; using Polly; using Polly.Contrib.Simmy.Latency; using Polly.Contrib.Simmy.Outcomes; @@ -40,6 +41,6 @@ public interface IChaosPolicyFactory /// /// The type of value policies created by this method will inject. /// A custom result policy, an instance of . - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public AsyncInjectOutcomePolicy CreateCustomResultPolicy(); } diff --git a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/ChaosPolicyOptionsGroup.cs b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/ChaosPolicyOptionsGroup.cs index 15f734e1d93..018ab350786 100644 --- a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/ChaosPolicyOptionsGroup.cs +++ b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/ChaosPolicyOptionsGroup.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Options; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Resilience.FaultInjection; @@ -42,6 +43,6 @@ public class ChaosPolicyOptionsGroup /// Gets or sets the custom result policy options of the chaos policy options group. /// [ValidateObjectMembers] - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public CustomResultPolicyOptions? CustomResultPolicyOptions { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/CustomResultPolicyOptions.cs b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/CustomResultPolicyOptions.cs index 58e9d7c2527..19aacb93159 100644 --- a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/CustomResultPolicyOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/CustomResultPolicyOptions.cs @@ -3,13 +3,14 @@ using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Resilience.FaultInjection; /// /// Custom Result chaos policy options definition. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public class CustomResultPolicyOptions : ChaosPolicyOptionsBase { /// @@ -20,7 +21,7 @@ public class CustomResultPolicyOptions : ChaosPolicyOptionsBase /// from . /// Default is set to . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] [Required] public string CustomResultKey { get; set; } = string.Empty; } diff --git a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/FaultPolicyWeightAssignmentsOptions.cs b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/FaultPolicyWeightAssignmentsOptions.cs index e83c75d9eea..4a2d51dcb45 100644 --- a/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/FaultPolicyWeightAssignmentsOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Resilience/FaultInjection/Options/FaultPolicyWeightAssignmentsOptions.cs @@ -3,13 +3,14 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Resilience.FaultInjection; /// /// Class to contain fault-injection policy weight assignments. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public class FaultPolicyWeightAssignmentsOptions { /// diff --git a/src/Libraries/Microsoft.Extensions.Resilience/Resilience/ResilienceContextExtensions.cs b/src/Libraries/Microsoft.Extensions.Resilience/Resilience/ResilienceContextExtensions.cs index 87a43d693f1..dee6b90172b 100644 --- a/src/Libraries/Microsoft.Extensions.Resilience/Resilience/ResilienceContextExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Resilience/Resilience/ResilienceContextExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Http.Telemetry; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using Polly; @@ -12,7 +13,7 @@ namespace Microsoft.Extensions.Resilience.Resilience; /// /// Extensions for . /// -[Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] +[Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public static class ResilienceContextExtensions { private static readonly ResiliencePropertyKey _requestMetadataKey = new(TelemetryConstants.RequestMetadataKey); diff --git a/src/Libraries/Microsoft.Extensions.Resilience/Resilience/ResilienceServiceCollectionExtensions.cs b/src/Libraries/Microsoft.Extensions.Resilience/Resilience/ResilienceServiceCollectionExtensions.cs index a89b4d0be32..6b497996830 100644 --- a/src/Libraries/Microsoft.Extensions.Resilience/Resilience/ResilienceServiceCollectionExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Resilience/Resilience/ResilienceServiceCollectionExtensions.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Http.Telemetry; using Microsoft.Extensions.Options; using Microsoft.Extensions.Resilience.Resilience.Internal; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using Polly.Extensions.Telemetry; @@ -17,7 +18,7 @@ namespace Microsoft.Extensions.Resilience; /// /// Extension class for the Service Collection DI container. /// -[Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] +[Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)] public static class ResilienceServiceCollectionExtensions { /// diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Http/TelemetryConstants.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Http/TelemetryConstants.cs index 9905266f05b..4878852d451 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Http/TelemetryConstants.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Http/TelemetryConstants.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Http.Telemetry; @@ -28,12 +29,12 @@ public static class TelemetryConstants /// /// Header for client application name, sent on an outgoing http call. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public const string ClientApplicationNameHeader = "X-ClientApplication"; /// /// Header for server application name, sent on a http request. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public const string ServerApplicationNameHeader = "X-ServerApplication"; } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Logging/LogMethodAttribute.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Logging/LogMethodAttribute.cs index 19ad568e435..8b1131676ed 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Logging/LogMethodAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Logging/LogMethodAttribute.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Logging; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Telemetry.Logging; @@ -266,7 +267,7 @@ public LogMethodAttribute(int eventId) /// } /// /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public LogMethodAttribute() { EventId = 0; diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metering/MeterT.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metering/MeterT.cs index 8326cb378ca..62a1701cbdc 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metering/MeterT.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metering/MeterT.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Metrics; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Telemetry.Metering; @@ -12,13 +13,13 @@ namespace Microsoft.Extensions.Telemetry.Metering; /// A meter class where the meter name is derived from the specified type name. /// /// The type whose name is used as the meter name. -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public class Meter : Meter { /// /// Initializes a new instance of the class. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public Meter() : base(typeof(TMeterName).FullName!) { diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metering/MeteringExtensions.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metering/MeteringExtensions.cs index b4a44b1048a..f499671f33c 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metering/MeteringExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metering/MeteringExtensions.cs @@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Telemetry.Metering; @@ -17,7 +18,7 @@ public static class MeteringExtensions /// /// The dependency injection container to register metering into. /// The value of . - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static IServiceCollection RegisterMetering(this IServiceCollection services) { services.TryAdd(ServiceDescriptor.Singleton(typeof(Meter<>), typeof(Meter<>))); diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/CollectedMeasurement.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/CollectedMeasurement.cs index 36d486d4d39..2719b5e33ad 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/CollectedMeasurement.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/CollectedMeasurement.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Telemetry.Testing.Metering; @@ -14,7 +15,7 @@ namespace Microsoft.Extensions.Telemetry.Testing.Metering; /// Represents a single measurement performed by an instrument. /// /// The type of metric measurement value. -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] [DebuggerDisplay("{DebuggerToString(),nq}")] public sealed class CollectedMeasurement where T : struct diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/MeasurementExtensions.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/MeasurementExtensions.cs index 1178dd4899a..1f7e5876550 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/MeasurementExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/MeasurementExtensions.cs @@ -5,13 +5,14 @@ using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Metrics; using System.Linq; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Telemetry.Testing.Metering; /// /// Extensions to simplify working with lists of measurements. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static class MeasurementExtensions { /// diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/MetricCollector.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/MetricCollector.cs index 012653476c4..9e34bc64eb6 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/MetricCollector.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Testing/Metering/MetricCollector.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Telemetry.Testing.Metering; @@ -17,7 +18,7 @@ namespace Microsoft.Extensions.Telemetry.Testing.Metering; /// Collects the measurements published from an or . /// /// The type of metric data being recorded. -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] [DebuggerDisplay("{_measurements.Count} measurements")] public sealed class MetricCollector : IDisposable where T : struct diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Logging/LoggerProvider.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Logging/LoggerProvider.cs index 54d44e9f1c6..234345eb20d 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Logging/LoggerProvider.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Logging/LoggerProvider.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Options; using Microsoft.Extensions.Telemetry.Enrichment; using Microsoft.Extensions.Telemetry.Internal; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using OpenTelemetry; using OpenTelemetry.Logs; @@ -19,7 +20,7 @@ namespace Microsoft.Extensions.Telemetry.Logging; /// OpenTelemetry Logger provider class. /// [ProviderAlias("R9")] -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public sealed class LoggerProvider : BaseProvider, ILoggerProvider, ISupportExternalScope { private const int ProcessorShutdownGracePeriodInMs = 5000; diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Logging/LoggingOptions.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Logging/LoggingOptions.cs index d717b176710..81212a68c96 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Logging/LoggingOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Logging/LoggingOptions.cs @@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Telemetry.Logging; @@ -59,7 +60,7 @@ public class LoggingOptions /// /// When set to a value less than 2 KB or greater than 32 KB, an exception will be thrown. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] [Range(MinDefinedStackTraceLength, MaxDefinedStackTraceLength, ErrorMessage = "Maximum stack trace length should be between 2kb and 32kb")] public int MaxStackTraceLength { get; set; } = DefaultStackTraceLength; } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Metering.Collectors.EventCounters/EventCountersCollectorOptions.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Metering.Collectors.EventCounters/EventCountersCollectorOptions.cs index cfc1c2e6cbb..65c5bced7d2 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Metering.Collectors.EventCounters/EventCountersCollectorOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Metering.Collectors.EventCounters/EventCountersCollectorOptions.cs @@ -6,6 +6,7 @@ using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using Microsoft.Shared.Data.Validation; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Telemetry.Metering; @@ -60,6 +61,6 @@ public class EventCountersCollectorOptions /// EventSource: "Microsoft-AspNetCore-Server-Kestrel", Counters: /// - "connection-queue-length", "request-queue-length". /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public bool IncludeRecommendedDefault { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Metering/MeteringOptions.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Metering/MeteringOptions.cs index 2853844ced7..cdc5305d3fb 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Metering/MeteringOptions.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Metering/MeteringOptions.cs @@ -3,13 +3,14 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Telemetry.Metering; /// /// Options for configuring metering. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public class MeteringOptions { /// diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Metering/OTelMeteringExtensions.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Metering/OTelMeteringExtensions.cs index 7ffafd48ffc..816f5aee719 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Metering/OTelMeteringExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Metering/OTelMeteringExtensions.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using OpenTelemetry.Metrics; @@ -14,7 +15,7 @@ namespace Microsoft.Extensions.Telemetry.Metering; /// /// Metering extensions for OpenTelemetry based metrics. /// -[Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] +[Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static class OTelMeteringExtensions { /// @@ -22,7 +23,7 @@ public static class OTelMeteringExtensions /// /// instance. /// Returns for chaining. - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static MeterProviderBuilder AddMetering( this MeterProviderBuilder builder) { @@ -35,7 +36,7 @@ public static MeterProviderBuilder AddMetering( /// instance. /// Configuration section that contains . /// Returns for chaining. - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static MeterProviderBuilder AddMetering( this MeterProviderBuilder builder, IConfigurationSection configurationSection) @@ -52,7 +53,7 @@ public static MeterProviderBuilder AddMetering( /// instance. /// The configuration delegate. /// Returns for chaining. - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static MeterProviderBuilder AddMetering( this MeterProviderBuilder builder, Action configure) diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Telemetry.Internal/IHttpRouteFormatter.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Telemetry.Internal/IHttpRouteFormatter.cs index 4ceaaf9ee54..8913a370e70 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Telemetry.Internal/IHttpRouteFormatter.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Telemetry.Internal/IHttpRouteFormatter.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Compliance.Classification; using Microsoft.Extensions.Http.Telemetry; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Telemetry.Internal; @@ -21,7 +22,7 @@ internal interface IHttpRouteFormatter /// Strategy to decide how parameters are redacted. /// Dictionary of parameters with their data classification that needs to be redacted. /// Returns formatted path with sensitive parameter values redacted. - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] string Format(string httpRoute, string httpPath, HttpRouteParameterRedactionMode redactionMode, IReadOnlyDictionary parametersToRedact); /// @@ -32,6 +33,6 @@ internal interface IHttpRouteFormatter /// Strategy to decide how parameters are redacted. /// Dictionary of parameters with their data classification that needs to be redacted. /// Returns formatted path with sensitive parameter values redacted. - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] string Format(in ParsedRouteSegments routeSegments, string httpPath, HttpRouteParameterRedactionMode redactionMode, IReadOnlyDictionary parametersToRedact); } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Telemetry/TelemetryExtensions.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Telemetry/TelemetryExtensions.cs index c825c6397bc..5c4445e86e7 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Telemetry/TelemetryExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Telemetry/TelemetryExtensions.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Http.Telemetry; using Microsoft.Extensions.Telemetry.Internal; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Telemetry; @@ -25,7 +26,7 @@ public static class TelemetryExtensions /// /// object. /// Metadata for the request. - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static void SetRequestMetadata(this HttpWebRequest request, RequestMetadata metadata) { _ = Throw.IfNull(request); @@ -58,7 +59,7 @@ public static void SetRequestMetadata(this HttpRequestMessage request, RequestMe /// /// object. /// Request metadata. - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static RequestMetadata? GetRequestMetadata(this HttpWebRequest request) { _ = Throw.IfNull(request); diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Tracing/TracingEnricherExtensions.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Tracing/TracingEnricherExtensions.cs index aeca5ff9f39..5b67804ed6e 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Tracing/TracingEnricherExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Tracing/TracingEnricherExtensions.cs @@ -6,6 +6,7 @@ using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Telemetry.Enrichment; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using OpenTelemetry.Trace; @@ -53,7 +54,7 @@ public static TracerProviderBuilder AddTraceEnricher(this TracerProviderBuilder /// The to add this enricher to. /// The so that additional calls can be chained. /// The argument is . - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static IServiceCollection AddTraceEnricher(this IServiceCollection services) where T : class, ITraceEnricher { @@ -71,7 +72,7 @@ public static IServiceCollection AddTraceEnricher(this IServiceCollection ser /// Enricher to be added. /// The so that additional calls can be chained. /// The argument or is . - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.Telemetry, UrlFormat = Experiments.UrlFormat)] public static IServiceCollection AddTraceEnricher(this IServiceCollection services, ITraceEnricher enricher) { _ = Throw.IfNull(services); diff --git a/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/FakeTimeProvider.cs b/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/FakeTimeProvider.cs index 07819603cad..2ba12002d19 100644 --- a/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/FakeTimeProvider.cs +++ b/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/FakeTimeProvider.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.Threading; using Microsoft.Extensions.Time.Testing; +using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Time.Testing; @@ -15,6 +16,7 @@ namespace Microsoft.Extensions.Time.Testing; /// /// A synthetic time provider used to enable deterministic behavior in tests. /// +[Experimental(diagnosticId: Experiments.TimeProvider, UrlFormat = Experiments.UrlFormat)] public class FakeTimeProvider : TimeProvider { internal readonly HashSet Waiters = new(); @@ -30,7 +32,6 @@ public class FakeTimeProvider : TimeProvider /// This creates a provider whose time is initially set to midnight January 1st 2000. /// The provider is set to not automatically advance time each time it is read. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] public FakeTimeProvider() { Start = _now; @@ -43,7 +44,6 @@ public FakeTimeProvider() /// /// The provider is set to not automatically advance time each time it is read. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] public FakeTimeProvider(DateTimeOffset startDateTime) { _ = Throw.IfLessThan(startDateTime.Ticks, 0); @@ -55,7 +55,6 @@ public FakeTimeProvider(DateTimeOffset startDateTime) /// /// Gets the starting date and time for this provider. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] public DateTimeOffset Start { get; } /// @@ -64,7 +63,6 @@ public FakeTimeProvider(DateTimeOffset startDateTime) /// /// This defaults to . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] public TimeSpan AutoAdvanceAmount { get => _autoAdvanceAmount; @@ -94,7 +92,6 @@ public override DateTimeOffset GetUtcNow() /// Sets the date and time in the UTC time zone. /// /// The date and time in the UTC time zone. - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] public void SetUtcNow(DateTimeOffset value) { lock (Waiters) @@ -120,7 +117,6 @@ public void SetUtcNow(DateTimeOffset value) /// marches forward automatically in hardware, for the fake time provider the application is responsible for /// doing this explicitly by calling this method. /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] public void Advance(TimeSpan delta) { _ = Throw.IfLessThan(delta.Ticks, 0); @@ -155,7 +151,6 @@ public override long GetTimestamp() /// Sets the local time zone. /// /// The local time zone. - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] public void SetLocalTimeZone(TimeZoneInfo localTimeZone) => _localTimeZone = localTimeZone; /// diff --git a/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/Microsoft.Extensions.TimeProvider.Testing.json b/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/Microsoft.Extensions.TimeProvider.Testing.json index 0be704bca9c..f5720815fcf 100644 --- a/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/Microsoft.Extensions.TimeProvider.Testing.json +++ b/src/Libraries/Microsoft.Extensions.TimeProvider.Testing/Microsoft.Extensions.TimeProvider.Testing.json @@ -3,7 +3,7 @@ "Types": [ { "Type": "class Microsoft.Extensions.Time.Testing.FakeTimeProvider : System.TimeProvider", - "Stage": "Stable", + "Stage": "Experimental", "Methods": [ { "Member": "Microsoft.Extensions.Time.Testing.FakeTimeProvider.FakeTimeProvider();", @@ -19,15 +19,15 @@ }, { "Member": "override System.Threading.ITimer Microsoft.Extensions.Time.Testing.FakeTimeProvider.CreateTimer(System.Threading.TimerCallback callback, object? state, System.TimeSpan dueTime, System.TimeSpan period);", - "Stage": "Stable" + "Stage": "Experimental" }, { "Member": "override long Microsoft.Extensions.Time.Testing.FakeTimeProvider.GetTimestamp();", - "Stage": "Stable" + "Stage": "Experimental" }, { "Member": "override System.DateTimeOffset Microsoft.Extensions.Time.Testing.FakeTimeProvider.GetUtcNow();", - "Stage": "Stable" + "Stage": "Experimental" }, { "Member": "void Microsoft.Extensions.Time.Testing.FakeTimeProvider.SetLocalTimeZone(System.TimeZoneInfo localTimeZone);", @@ -39,7 +39,7 @@ }, { "Member": "override string Microsoft.Extensions.Time.Testing.FakeTimeProvider.ToString();", - "Stage": "Stable" + "Stage": "Experimental" } ], "Properties": [ @@ -49,7 +49,7 @@ }, { "Member": "override System.TimeZoneInfo Microsoft.Extensions.Time.Testing.FakeTimeProvider.LocalTimeZone { get; }", - "Stage": "Stable" + "Stage": "Experimental" }, { "Member": "System.DateTimeOffset Microsoft.Extensions.Time.Testing.FakeTimeProvider.Start { get; }", @@ -57,7 +57,7 @@ }, { "Member": "override long Microsoft.Extensions.Time.Testing.FakeTimeProvider.TimestampFrequency { get; }", - "Stage": "Stable" + "Stage": "Experimental" } ] } diff --git a/src/Libraries/System.Cloud.DocumentDb.Abstractions/Model/DatabaseOptions.cs b/src/Libraries/System.Cloud.DocumentDb.Abstractions/Model/DatabaseOptions.cs index 39bb7f959d3..45ccec94663 100644 --- a/src/Libraries/System.Cloud.DocumentDb.Abstractions/Model/DatabaseOptions.cs +++ b/src/Libraries/System.Cloud.DocumentDb.Abstractions/Model/DatabaseOptions.cs @@ -7,6 +7,7 @@ using System.Diagnostics.CodeAnalysis; using System.Text.Json; using Microsoft.Shared.Data.Validation; +using Microsoft.Shared.DiagnosticIds; namespace System.Cloud.DocumentDb; @@ -97,7 +98,7 @@ public class DatabaseOptions /// When enabled, System.Text.Json based serialization will be configured with /// settings defined in . /// - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: Experiments.DocumentDb, UrlFormat = Experiments.UrlFormat)] public bool OverrideSerialization { get; set; } = true; /// diff --git a/src/Shared/DiagnosticIds/Experiments.cs b/src/Shared/DiagnosticIds/Experiments.cs new file mode 100644 index 00000000000..23fe1774660 --- /dev/null +++ b/src/Shared/DiagnosticIds/Experiments.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#pragma warning disable CA1716 +namespace Microsoft.Shared.DiagnosticIds; +#pragma warning restore CA1716 + +/// +/// Experiments supported by this repo. +/// +/// +/// When adding a new experiment, add a corresponding suppression to the root Directory.Build.targets file. +/// +internal static class Experiments +{ +#pragma warning disable S1075 // URIs should not be hardcoded + internal const string UrlFormat = "https://aka.ms/dotnet-extensions-warnings/{0}"; +#pragma warning restore S1075 // URIs should not be hardcoded + + internal const string Resilience = "EXTEXP0001"; + internal const string Compliance = "EXTEXP0002"; + internal const string Telemetry = "EXTEXP0003"; + internal const string TimeProvider = "EXTEXP0004"; + internal const string AutoClient = "EXTEXP0005"; + internal const string AsyncState = "EXTEXP0006"; + internal const string HealthChecks = "EXTEXP0007"; + internal const string ResourceMonitoring = "EXTEXP0008"; + internal const string Hosting = "EXTEXP0009"; + internal const string ObjectPool = "EXTEXP0010"; + internal const string DocumentDb = "EXTEXP0011"; +} diff --git a/src/Shared/Shared.csproj b/src/Shared/Shared.csproj index 5418ee99e8e..4e241163eb4 100644 --- a/src/Shared/Shared.csproj +++ b/src/Shared/Shared.csproj @@ -42,6 +42,6 @@ - + diff --git a/src/Shared/WarningDefinitions.cs b/src/Shared/WarningDefinitions.cs deleted file mode 100644 index e91963c3e8f..00000000000 --- a/src/Shared/WarningDefinitions.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Diagnostics.CodeAnalysis; - -#pragma warning disable S1075 // URIs should not be hardcoded -internal static class WarningDefinitions -{ - internal const string SharedUrlFormat = "https://aka.ms/dotnet-extensions-warnings/{0}"; -} -#pragma warning restore S1075 // URIs should not be hardcoded diff --git a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/StringFormatTests.cs b/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/StringFormatTests.cs deleted file mode 100644 index d6aa2aefe79..00000000000 --- a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/CallAnalysis/StringFormatTests.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Threading.Tasks; -using Microsoft.Extensions.ExtraAnalyzers.Test; -using Xunit; - -namespace Microsoft.Extensions.ExtraAnalyzers.CallAnalysis.Test; - -public static class StringFormatTests -{ - [Fact] - public static async Task ShouldFindWarning() - { - const int ExpectedNumberOfWarnings = 7; // update number of expected warnings - - const string Source = @" - #pragma warning disable CS8767 - - using System; - using System.Text; - - namespace Example - { - public class TestClass - { - private static string GetFormat() - { - return ""format""; - } - - public static void Test() - { - /*0+*/string.Format(""test"")/*-0*/; - /*1+*/String.Format(""test"")/*-1*/; - /*2+*/System.String.Format(""test"")/*-2*/; - var format = GetFormat(); - string.Format(format); - /*3+*/string.Format(""test"", 1, 2)/*-3*/; - StringBuilder sb = new StringBuilder(); - /*4+*/sb.AppendFormat(""test"", 1, 2)/*-4*/; - var textString = /*5+*/string.Format(""test"", 1, 2)/*-5*/; - sb.AppendFormat(textString, 1, 2); - string.Format(null, ""test""); - - F f = new F(); - /*6+*/string.Format(f, ""test"")/*-6*/; - - } - } - - interface I - { - public string i(); - } - - public class F : IFormatProvider, I - { - public object GetFormat(Type formatType) - { - return this; - } - - public string i() - { - return ""test""; - } - } - }"; - - var d = await RoslynTestUtils.RunAnalyzer( - new CallAnalyzer(), - null, - new[] { Source }).ConfigureAwait(false); - - Assert.Equal(ExpectedNumberOfWarnings, d.Count); - for (int i = 0; i < d.Count; i++) - { - Source.AssertDiagnostic(i, DiagDescriptors.StringFormat, d[i]); - } - } -} diff --git a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/OptimizeArraysAnalyzerTests.cs b/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/OptimizeArraysAnalyzerTests.cs deleted file mode 100644 index 72267e6d12c..00000000000 --- a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/OptimizeArraysAnalyzerTests.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Reflection; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Extensions.ExtraAnalyzers.Test; - -public static class OptimizeArraysAnalyzerTests -{ - [Fact] - public static async Task MakeArrayStatic() - { - const string Source = """ - using System.Collections.Generic; - using System.Collections.Immutable; - - namespace Example - { - public enum Color { Red, Green, Blue } - - public class Test - { - private readonly int[] _nums = /*0+*/new[] { 1, 2, 3 }/*-0*/; - private readonly Color[] _colors = /*1+*/new[] { Color.Red, Color.Green, Color.Blue }/*-1*/; - private readonly string[] _strings = /*2+*/new[] { "One", "Two", "Three" }/*-2*/; - - public void Method(string[] stuff) { } - - public void Method2() - { - var a = /*3+*/new[] { 1, 2, 3 }/*-3*/; - Method(/*4+*/new[] { "One", "Two", "Three" }/*-4*/); - } - - public string[] Prop { get; } = /*5+*/new[] { "One", "Two", "Three" }/*-5*/; - - public static int HowMany(string[] strings) - { - return strings.Length; - } - - private static readonly int[] _staticNums = new[] { 1, 2, 3 }; - private static readonly int _numStrings = HowMany(new[] { "One", "Two", "Three" }); - public static int NumStrings { get; } = HowMany(new[] { "One", "Two", "Three" }); - public static ImmutableArray Immutable { get; } = ImmutableArray.Create(new[] { "One", "Two", "Three" }); - public static IEnumerable All { get; } = new[] { "One", "Two", "Three" }; - } - } - """; - - var d = await RoslynTestUtils.RunAnalyzer( - new OptimizeArraysAnalyzer(), - new[] { Assembly.GetAssembly(typeof(ImmutableArray))! }, - new[] { Source }).ConfigureAwait(false); - - Assert.Equal(6, d.Count); - for (int i = 0; i < d.Count; i++) - { - Source.AssertDiagnostic(i, DiagDescriptors.MakeArrayStatic, d[i]); - } - } -} diff --git a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupAnalyzerTests.cs b/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupAnalyzerTests.cs deleted file mode 100644 index 6e848189073..00000000000 --- a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupAnalyzerTests.cs +++ /dev/null @@ -1,442 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Extensions.ExtraAnalyzers.Test; - -public class UsingExcessiveDictionaryLookupAnalyzerTests -{ - private static IEnumerable References => new[] - { - Assembly.GetAssembly(typeof(IDictionary<,>))!, - Assembly.GetAssembly(typeof(IEnumerable))!, - Assembly.GetAssembly(typeof(CollectionExtensions))! - }; - - public static IEnumerable AnalyzerData => new List - { - new object[] - { - 2, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - string key = ""key""; - var flag = false; - if (/*0+*/dictionary.ContainsKey(key)/*-0*/) - flag = dictionary.TryAdd(key, ""val""); - - if (/*1+*/dictionary.ContainsKey(key)/*-1*/) - _ = dictionary.Remove(key); - - if (!flag) - dictionary.Add(key, ""val""); - } - } - }" - }, - new object[] - { - 7, - @"using System; - using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - int b = 6; - - if (/*0+*/dictionary.ContainsKey(""key"")/*-0*/) - { - b = 7; - var value = dictionary[""key""]; - b = 5; - } - - string value2 = ""123""; - if (/*1+*/dictionary.ContainsKey(""key"")/*-1*/) - { - b = 6; - value2 = dictionary[""key""]; - b = 5; - } - - if (!/*2+*/dictionary.ContainsKey(""key"")/*-2*/) - { - dictionary.Add(""key"", ""val""); - } - - if (!/*3+*/dictionary.ContainsKey(""key"")/*-3*/) - { - dictionary[""key""] = ""newval""; - } - - if (/*4+*/dictionary.ContainsKey(""key"")/*-4*/) - { - dictionary.TryAdd(""key"", ""val""); - } - - if (/*5+*/dictionary.ContainsKey(""key"")/*-5*/) - { - dictionary.Remove(""key""); - } - - if (/*6+*/dictionary.ContainsKey(""key"")/*-6*/) - { - b = 7; - if (string.IsNullOrEmpty(dictionary[""key""])) - { - throw new Exception(""Error""); - } - - b = 5; - } - - if (!dictionary.ContainsKey(""key"") && b < 5) - { - dictionary.Add(""key"", ""val""); - } - } - } - }" - }, - new object[] - { - 6, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(IDictionary dictionary) - { - int b = 6; - - if (/*0+*/dictionary.ContainsKey(""key"")/*-0*/) - { - b = 7; - var value = dictionary[""key""]; - b = 5; - } - - string value2 = ""123""; - if (/*1+*/dictionary.ContainsKey(""key"")/*-1*/) - { - b = 6; - value2 = dictionary[""key""]; - b = 5; - } - - if (!/*2+*/dictionary.ContainsKey(""key"")/*-2*/) - { - dictionary.Add(""key"", ""val""); - } - - if (!/*3+*/dictionary.ContainsKey(""key"")/*-3*/) - { - dictionary[""key""] = ""newval""; - } - - if (/*4+*/dictionary.ContainsKey(""key"")/*-4*/) - { - dictionary.Remove(""key""); - } - - if (/*5+*/dictionary.ContainsKey(""key"")/*-5*/) - { - dictionary.TryAdd(""key"", ""val""); - } - - if (!dictionary.ContainsKey(""key"") && b < 5) - { - dictionary.Add(""key"", ""val""); - } - } - } - }" - }, - new object[] - { - 5, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - int b = 6; - string key = ""key""; - if (!/*0+*/dictionary.ContainsKey(key)/*-0*/) - dictionary.Add(key, ""val""); - - if (!/*1+*/dictionary.ContainsKey(key)/*-1*/) - dictionary[key] = ""newval""; - - if (/*2+*/dictionary.ContainsKey(key)/*-2*/) - dictionary.TryAdd(key, ""val""); - - if (/*3+*/dictionary.ContainsKey(key)/*-3*/) - dictionary.Remove(key); - - string value = ""abc""; - if (/*4+*/dictionary.ContainsKey(key)/*-4*/) - value = dictionary[key]; - - if (!dictionary.ContainsKey(key) && b < 5 && value == ""abc"") - dictionary.Add(key, ""val""); - } - } - }" - }, - new object[] - { - 4, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(IDictionary dictionary) - { - int b = 6; - if (!/*0+*/dictionary.ContainsKey(""key"")/*-0*/) - dictionary.Add(""key"", ""val""); - - if (!/*1+*/dictionary.ContainsKey(""key"")/*-1*/) - dictionary[""key""] = ""newval""; - - if (/*2+*/dictionary.ContainsKey(""key"")/*-2*/) - dictionary.Remove(""key""); - - if (/*3+*/dictionary.ContainsKey(""key"")/*-3*/) - dictionary.TryAdd(""key"", ""val""); - - if (!dictionary.ContainsKey(""key"") && b < 5) - dictionary.Add(""key"", ""val""); - } - } - }" - }, - new object[] - { - 0, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - if (!dictionary.ContainsKey(""key"")) - { - dictionary.Add(""key2"", ""val""); - } - } - } - }" - }, - new object[] - { - 0, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - if (!dictionary.ContainsKey(GetKey())) - { - dictionary.Add(GetKey(), ""val""); - } - } - - private string GetKey() - { - return ""someKey""; - } - } - }" - }, - new object[] - { - 0, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public bool DoSomething(Dictionary dictionary) - { - if (dictionary.ContainsKey(""key"")) - { - return GetDictionary().Remove(""key""); - } - - if (GetDictionary().ContainsKey(""key"")) - { - return dictionary.Remove(""key""); - } - - return false; - } - - private Dictionary GetDictionary() - { - return new Dictionary(); - } - } - }" - }, - new object[] - { - 0, - @"using System; - using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(Dictionary dictionary, Dictionary anotherDictionary) - { - if (dictionary.ContainsKey(""key"")) - { - anotherDictionary.Add(""key"", ""val""); - } - - if (dictionary.ContainsKey(""key"")) - anotherDictionary.Add(""key"", ""val""); - - if (dictionary.ContainsKey(""key"")) - { - anotherDictionary[""key""] = ""value""; - } - - string value = ""abc""; - if (dictionary.ContainsKey(""key"")) - value = anotherDictionary[""key""]; - - if (value == ""abc"") - { - throw new Exception(""Error""); - } - } - } - }" - }, - new object[] - { - 0, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - if (dictionary.ContainsKey(""key"")) - { - } - } - } - }" - }, - new object[] - { - 4, - @"using System; - using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - int b = 6; - string value = ""123""; - if (dictionary.ContainsKey(""key"")) - { - b = 7; - } - - value = /*0+*/dictionary[""key""]/*-0*/; - - if (dictionary.ContainsKey(""key"")) - b = 7; - - /*1+*/dictionary.Add(""key"", ""val"")/*-1*/; - - if (dictionary.ContainsKey(""key"")) - b = 7; - - /*2+*/dictionary[""key""]/*-2*/ = ""newval""; - - if (dictionary.ContainsKey(""key"")) - b = 7; - - _ = /*3+*/dictionary.TryAdd(""key"", ""val"")/*-3*/; - - if (dictionary.ContainsKey(""key"")) - dictionary[""key2""] = ""7""; - - _ = dictionary.TryAdd(""key"", ""val""); - - if (dictionary.ContainsKey(""key"")) - { - b = 7; - } - else - { - b = 9; - } - - _ = dictionary.TryAdd(""key"", ""val""); - - if (b == 6) - { - throw new Exception(""Error""); - } - } - } - }" - } - }; - - [Theory] - [MemberData(nameof(AnalyzerData))] - public async Task ShouldFindWarnings(int expectedNumberOfWarnings, string source) - { - var d = await RoslynTestUtils.RunAnalyzer( - new UsingExcessiveDictionaryLookupAnalyzer(), - References, - new[] { source }).ConfigureAwait(false); - - Assert.Equal(expectedNumberOfWarnings, d.Count); - for (int i = 0; i < d.Count; i++) - { - source.AssertDiagnostic(i, DiagDescriptors.UsingExcessiveDictionaryLookup, d[i]); - } - } -} diff --git a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupFixerTests.cs b/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupFixerTests.cs deleted file mode 100644 index a2e3a7d0a15..00000000000 --- a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveDictionaryLookupFixerTests.cs +++ /dev/null @@ -1,674 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CodeFixes; -using Xunit; - -namespace Microsoft.Extensions.ExtraAnalyzers.Test; - -public class UsingExcessiveDictionaryLookupFixerTests -{ - private static IEnumerable References => new[] - { - Assembly.GetAssembly(typeof(IDictionary<,>))!, - Assembly.GetAssembly(typeof(IEnumerable))!, - Assembly.GetAssembly(typeof(CollectionExtensions))! - }; - - public static IEnumerable FixerData => new List - { - new[] - { -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - int b = 6; - - if (dictionary.ContainsKey(""key"")) - { - b = 7; - var value = dictionary[""key""]; - var anotherValue = dictionary[""key""]; - var anotherValue2 = dictionary[""key2""]; - if (string.IsNullOrEmpty(dictionary[""key""])) - { - throw new Exception(""Error""); - } - - b = 5; - } - - if (dictionary.ContainsKey(""key"")) - { - dictionary.Remove(""key"", out _); - } - - if (dictionary.ContainsKey(""key"")) - { - dictionary.Remove(""key""); - } - - if (!dictionary.ContainsKey(""key"")) - { - dictionary.Add(""key"", ""value""); - } - - if (!dictionary.ContainsKey(""key2"")) - { - dictionary.TryAdd(""key2"", ""value2""); - } - - if (!dictionary.ContainsKey(""key3"")) - { - dictionary[""key3""] = ""value3""; - } - - if (b < 5) - { - throw new Exception(""Error""); - } - } - } -} -", -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - int b = 6; - - if (dictionary.TryGetValue(""key"", out var retrievedValue)) - { - b = 7; - var value = retrievedValue; - var anotherValue = retrievedValue; - var anotherValue2 = dictionary[""key2""]; - if (string.IsNullOrEmpty(retrievedValue)) - { - throw new Exception(""Error""); - } - - b = 5; - } - - dictionary.Remove(""key"", out _); - - dictionary.Remove(""key""); - - dictionary.TryAdd(""key"", ""value""); - - dictionary.TryAdd(""key2"", ""value2""); - - dictionary.TryAdd(""key3"", ""value3""); - - if (b < 5) - { - throw new Exception(""Error""); - } - } - } -} -" - }, - new[] - { -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - string value = ""abc""; - if (dictionary.ContainsKey(""key"")) - value = dictionary[""key""]; - - if (dictionary.ContainsKey(""key"")) - dictionary.Remove(""key"", out _); - - if (dictionary.ContainsKey(""key"")) - dictionary.Remove(""key""); - - if (!dictionary.ContainsKey(""key"")) - dictionary.Add(""key"", ""value""); - - if (!dictionary.ContainsKey(""key2"")) - dictionary.TryAdd(""key2"", ""value2""); - - if (!dictionary.ContainsKey(""key3"")) - dictionary[""key3""] = ""value3""; - - if (dictionary.ContainsKey(""key"")) - dictionary.TryGetValue(""key"", out _); - - if (value == ""abc"") - { - throw new Exception(""Error""); - } - } - } -} -", -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - string value = ""abc""; - if (dictionary.TryGetValue(""key"", out var retrievedValue)) - value = retrievedValue; - - dictionary.Remove(""key"", out _); - - dictionary.Remove(""key""); - - dictionary.TryAdd(""key"", ""value""); - - dictionary.TryAdd(""key2"", ""value2""); - - dictionary.TryAdd(""key3"", ""value3""); - - dictionary.TryGetValue(""key"", out _); - - if (value == ""abc"") - { - throw new Exception(""Error""); - } - } - } -} -" - }, - new[] - { -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(IDictionary dictionary, IDictionary anotherDictionary) - { - int b = 6; - - if (dictionary.ContainsKey(""key"")) - { - b = 7; - var value = dictionary[""key""]; - var anotherValue = dictionary[""key""]; - var anotherValue2 = dictionary[""key2""]; - anotherDictionary[""key""] = dictionary[""key""]; - b = 5; - } - - if (dictionary.ContainsKey(""key"")) - { - dictionary.Remove(""key"", out _); - } - - if (dictionary.ContainsKey(""key"")) - { - dictionary.Remove(""key""); - } - - if (!dictionary.ContainsKey(""key"")) - { - dictionary.Add(""key"", ""value""); - } - - if (!dictionary.ContainsKey(""key2"")) - { - dictionary.TryAdd(""key2"", ""value2""); - } - - if (!dictionary.ContainsKey(""key3"")) - { - dictionary[""key3""] = ""value3""; - } - - if (dictionary.ContainsKey(""key"")) - { - dictionary.TryGetValue(""key"", out _); - } - - if (b < 5) - { - throw new Exception(""Error""); - } - } - } -} -", -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(IDictionary dictionary, IDictionary anotherDictionary) - { - int b = 6; - - if (dictionary.TryGetValue(""key"", out var retrievedValue)) - { - b = 7; - var value = retrievedValue; - var anotherValue = retrievedValue; - var anotherValue2 = dictionary[""key2""]; - anotherDictionary[""key""] = retrievedValue; - b = 5; - } - - dictionary.Remove(""key"", out _); - - dictionary.Remove(""key""); - - dictionary.TryAdd(""key"", ""value""); - - dictionary.TryAdd(""key2"", ""value2""); - - dictionary.TryAdd(""key3"", ""value3""); - - dictionary.TryGetValue(""key"", out _); - - if (b < 5) - { - throw new Exception(""Error""); - } - } - } -} -" - }, - new[] - { -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(IReadOnlyDictionary dictionary) - { - int b = 6; - - if (dictionary.ContainsKey(""key"")) - { - b = 7; - var value = dictionary[""key""]; - var anotherValue = dictionary[""key""]; - var anotherValue2 = dictionary[""key2""]; - b = 5; - } - - if (b < 5) - { - throw new Exception(""Error""); - } - } - } -} -", -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(IReadOnlyDictionary dictionary) - { - int b = 6; - - if (dictionary.TryGetValue(""key"", out var retrievedValue)) - { - b = 7; - var value = retrievedValue; - var anotherValue = retrievedValue; - var anotherValue2 = dictionary[""key2""]; - b = 5; - } - - if (b < 5) - { - throw new Exception(""Error""); - } - } - } -} -" - }, - new[] - { -@"using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(IReadOnlyDictionary dictionary) - { - if (dictionary.ContainsKey(""key"")) - dictionary.TryGetValue(""key"", out _); - } - } -} -", -@"using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(IReadOnlyDictionary dictionary) - { - dictionary.TryGetValue(""key"", out _); - } - } -} -" - }, - new[] - { -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(Dictionary dictionary, Dictionary anotherDictionary) - { - string value = ""abc""; - if (dictionary.ContainsKey(""key"")) - { - dictionary[""key""] = ""value""; - } - else - { - dictionary.Add(""key"", ""value""); - } - - if (!dictionary.ContainsKey(""key"")) - dictionary.Add(""key"", ""value""); - else - dictionary[""key""] = ""value""; - - if (dictionary.ContainsKey(""key"")) - dictionary.Add(""key2"", ""value""); - else - dictionary[""key""] = ""value""; - - if (dictionary.ContainsKey(""key"")) - dictionary.Add(""key"", ""value""); - else - dictionary[""key2""] = ""value""; - - if (dictionary.ContainsKey(""key"")) - dictionary.Add(""key"", ""value""); - else - dictionary[""key""] = ""value2""; - - if (dictionary.ContainsKey(""key"")) - anotherDictionary.Add(""key"", ""value""); - else - anotherDictionary[""key""] = ""value""; - - if (dictionary.ContainsKey(""key"")) - { - dictionary[""key""] = ""value""; - dictionary[""key2""] = ""value""; - } - else - { - dictionary.Add(""key"", ""value""); - } - - if (dictionary.ContainsKey(""key"")) - { - value = dictionary[""key""]; - } - else - { - dictionary.Add(""key"", ""value""); - } - - if (value == ""abc"") - { - throw new Exception(""Error""); - } - } - } -} -", -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(Dictionary dictionary, Dictionary anotherDictionary) - { - string value = ""abc""; - dictionary[""key""] = ""value""; - - dictionary[""key""] = ""value""; - - if (dictionary.ContainsKey(""key"")) - dictionary.Add(""key2"", ""value""); - else - dictionary[""key""] = ""value""; - - if (dictionary.ContainsKey(""key"")) - dictionary.Add(""key"", ""value""); - else - dictionary[""key2""] = ""value""; - - if (dictionary.ContainsKey(""key"")) - dictionary.Add(""key"", ""value""); - else - dictionary[""key""] = ""value2""; - - if (dictionary.ContainsKey(""key"")) - anotherDictionary.Add(""key"", ""value""); - else - anotherDictionary[""key""] = ""value""; - - if (dictionary.ContainsKey(""key"")) - { - dictionary[""key""] = ""value""; - dictionary[""key2""] = ""value""; - } - else - { - dictionary.Add(""key"", ""value""); - } - - if (dictionary.ContainsKey(""key"")) - { - value = dictionary[""key""]; - } - else - { - dictionary.Add(""key"", ""value""); - } - - if (value == ""abc"") - { - throw new Exception(""Error""); - } - } - } -} -" - }, - new[] - { -@"using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - if (dictionary.ContainsKey(""key"")) - _ = dictionary.Remove(""key"", out _); - - if (dictionary.ContainsKey(""key"")) - _ = dictionary.Remove(""key""); - - if (!dictionary.ContainsKey(""key2"")) - _ = dictionary.TryAdd(""key2"", ""value2""); - - if (dictionary.ContainsKey(""key"")) - _ = dictionary.TryGetValue(""key"", out _); - - if (dictionary.ContainsKey(""key"")) - _ = dictionary.TryGetValue(""key"", out _).ToString(); - } - } -} -", -@"using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - _ = dictionary.Remove(""key"", out _); - - _ = dictionary.Remove(""key""); - - _ = dictionary.TryAdd(""key2"", ""value2""); - - _ = dictionary.TryGetValue(""key"", out _); - - if (dictionary.ContainsKey(""key"")) - _ = dictionary.TryGetValue(""key"", out _).ToString(); - } - } -} -" - } - }; - - public static IEnumerable AnotherFixerData => new List - { - new[] - { - @"using System; - using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - int b = 6; - string value = ""123""; - if (dictionary.ContainsKey(""key"")) - { - b = 7; - } - - value = dictionary[""key""]; - if (b == 6) - { - throw new Exception(""Error""); - } - } - } - }" - }, - new[] - { - @"using System; - using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(Dictionary dictionary) - { - int b = 6; - if (dictionary.ContainsKey(""key"")) - b = 7; - - dictionary.Add(""key"", ""val""); - - if (b == 6) - { - throw new Exception(""Error""); - } - } - } - }" - } - }; - - [Theory] - [MemberData(nameof(FixerData))] - public async Task CanFixWarning(string source, string expected) - { - var actual = (await RoslynTestUtils.RunAnalyzerAndFixer( - new UsingExcessiveDictionaryLookupAnalyzer(), - new UsingExcessiveDictionaryLookupFixer(), - References, - new[] { source }).ConfigureAwait(false))[0]; - - Assert.Equal(expected.Replace("\r\n", "\n", StringComparison.Ordinal), actual); - } - - [Theory] - [MemberData(nameof(AnotherFixerData))] - public async Task ShouldNotFixWarning(string source) - { - var actual = (await RoslynTestUtils.RunAnalyzerAndFixer( - new UsingExcessiveDictionaryLookupAnalyzer(), - new UsingExcessiveDictionaryLookupFixer(), - References, - new[] { source }).ConfigureAwait(false))[0]; - - Assert.Equal(source.Replace("\r\n", "\n", StringComparison.Ordinal), actual); - } - - [Fact] - public void CheckFixerPropertiesAreSetCorrectly() - { - var fixer = new UsingExcessiveDictionaryLookupFixer(); - - Assert.Single(fixer.FixableDiagnosticIds); - Assert.Equal(DiagDescriptors.UsingExcessiveDictionaryLookup.Id, fixer.FixableDiagnosticIds[0]); - Assert.Equal(WellKnownFixAllProviders.BatchFixer, fixer.GetFixAllProvider()); - } -} diff --git a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupAnalyzerTests.cs b/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupAnalyzerTests.cs deleted file mode 100644 index 98462e03d8d..00000000000 --- a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExcessiveSetLookupAnalyzerTests.cs +++ /dev/null @@ -1,591 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Reflection; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CodeFixes; -using Xunit; - -namespace Microsoft.Extensions.ExtraAnalyzers.Test; - -public class UsingExcessiveSetLookupAnalyzerTests -{ - private static IEnumerable References => new[] - { - Assembly.GetAssembly(typeof(IDictionary<,>))!, - Assembly.GetAssembly(typeof(ImmutableHashSet<>))!, - Assembly.GetAssembly(typeof(IEnumerable))!, - Assembly.GetAssembly(typeof(CollectionExtensions))!, - Assembly.GetAssembly(typeof(SortedSet<>))!, - }; - - public static IEnumerable FixerData => new List - { - new[] - { -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(SortedSet collection) - { - int b = 6; - - if (collection.Contains(""key"")) - { - collection.TryGetValue(""key"", out _); - b = 5; - } - - if (collection.Contains(""key"")) - { - collection.Remove(""key""); - } - - if (!collection.Contains(""key"")) - { - b = 6; - collection.Add(""key""); - b = 5; - } - - if (!collection.Contains(""key"")) - collection.Add(""key""); - - if (collection.Contains(""key"")) - { - _ = collection.TryGetValue(""key"", out _); - } - - if (b < 5) - { - throw new Exception(""Error""); - } - } - } -}", -@"using System; -using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public void DoSomething(SortedSet collection) - { - int b = 6; - - if (collection.TryGetValue(""key"", out _)) - { - b = 5; - } - - collection.Remove(""key""); - - if (!collection.Contains(""key"")) - { - b = 6; - collection.Add(""key""); - b = 5; - } - - collection.Add(""key""); - - _ = collection.TryGetValue(""key"", out _); - - if (b < 5) - { - throw new Exception(""Error""); - } - } - } -}" - }, - new[] - { -@"using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public int DoSomething(HashSet collection) - { - int b = 6; - if (!collection.Contains(""key"")) - b = 7; - - collection.Add(""key""); - - if (collection.Contains(""key"")) - b = 7; - - _ = collection.Remove(""key""); - - if (collection.Contains(""key"")) - b = 7; - - _ = collection.TryGetValue(""key"", out string _); - return b; - } - } -}", -@"using System.Collections.Generic; - -namespace Example -{ - public class TestClass - { - public int DoSomething(HashSet collection) - { - int b = 6; - if (!collection.Add(""key"")) - b = 7; - if (!collection.Remove(""key"")) - b = 7; - if (collection.Contains(""key"")) - b = 7; - - _ = collection.TryGetValue(""key"", out string _); - return b; - } - } -}" - } - }; - - public static IEnumerable AnalyzerData => new List - { - new object[] - { - 6, - @"using System; - using System.Collections.Generic; - using System.Collections.Immutable; - - namespace Example - { - public class TestClass - { - public void DoSomething(SortedSet collection, ImmutableHashSet anotherCollection) - { - int b = 6; - - if (!/*0+*/collection.Contains(""key"")/*-0*/) - { - collection.Add(""key""); - b = 5; - } - - if (!/*1+*/anotherCollection.Contains(""key"")/*-1*/) - { - anotherCollection.Add(""key""); - } - - if (!collection.Contains(""key"")) - { - b = 6; - collection.Add(""key""); - b = 5; - } - - if (/*2+*/collection.Contains(""key"")/*-2*/) - { - collection.Remove(""key""); - b = 5; - } - - if (/*3+*/anotherCollection.Contains(""key"")/*-3*/) - { - anotherCollection.Remove(""key""); - } - - if (collection.Contains(""key"")) - { - b = 6; - collection.Remove(""key""); - b = 5; - } - - if (/*4+*/collection.Contains(""key"")/*-4*/) - { - collection.TryGetValue(""key"", out _); - b = 5; - } - - if (/*5+*/anotherCollection.Contains(""key"")/*-5*/) - { - anotherCollection.TryGetValue(""key"", out _); - } - - if (collection.Contains(""key"")) - { - b = 6; - collection.TryGetValue(""key"", out _); - b = 5; - } - - if (collection.Contains(""key"")) - { - if (!collection.TryGetValue(""key"", out _)) - { - throw new Exception(""Error""); - } - - b = 5; - } - - if (!collection.Contains(""key"") && b < 5) - { - collection.TryGetValue(""key"", out _); - } - } - } - }" - }, - new object[] - { - 6, - @"using System.Collections.Generic; - using System.Collections.Immutable; - - namespace Example - { - public class TestClass - { - public void DoSomething(HashSet collection, ImmutableSortedSet anotherCollection) - { - int b = 6; - - if (!/*0+*/collection.Contains(""key"")/*-0*/) - _ = collection.Add(""key""); - - if (/*1+*/collection.Contains(""key"")/*-1*/) - _ = !collection.Remove(""key""); - - if (/*2+*/collection.Contains(""key"")/*-2*/) - collection.TryGetValue(""key"", out _); - - if (!/*3+*/anotherCollection.Contains(""key"")/*-3*/) - anotherCollection.Add(""key""); - - if (/*4+*/anotherCollection.Contains(""key"")/*-4*/) - anotherCollection.Remove(""key""); - - if (/*5+*/anotherCollection.Contains(""key"")/*-5*/) - anotherCollection.TryGetValue(""key"", out _); - - bool flag = false; - if (!collection.Contains(""key"")) - flag = collection.Add(""key""); - - if (anotherCollection.Contains(""key"")) - b = 7; - - _ = anotherCollection.Remove(""key""); - - if (collection.Contains(""key"") && b < 5 && flag) - collection.TryGetValue(""key"", out _); - } - } - }" - }, - new object[] - { - 4, - @"using System.Collections.Immutable; - - namespace Example - { - public class TestClass - { - public void DoSomething(ImmutableHashSet.Builder builder, ImmutableSortedSet.Builder anotherBuilder) - { - if (!/*0+*/builder.Contains(1)/*-0*/) - builder.Add(1); - - if (/*1+*/builder.Contains(2)/*-1*/) - builder.Remove(2); - - if (!/*2+*/anotherBuilder.Contains(1)/*-2*/) - anotherBuilder.Add(1); - - if (/*3+*/anotherBuilder.Contains(2)/*-3*/) - anotherBuilder.Remove(2); - } - } - }" - }, - new object[] - { - 0, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(HashSet collection) - { - if (!collection.Contains(""key"")) - { - collection.Add(""key2""); - } - } - } - }" - }, - new object[] - { - 0, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(ICollection collection) - { - if (!collection.Contains(""key"")) - { - collection.Add(""key""); - } - } - } - }" - }, - new object[] - { - 0, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(HashSet collection) - { - if (!collection.Contains(GetKey())) - { - collection.Add(GetKey()); - } - } - - private string GetKey() - { - return ""someKey""; - } - } - }" - }, - new object[] - { - 0, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public bool DoSomething(HashSet collection) - { - if (collection.Contains(""key"")) - { - return GetCollection().Remove(""key""); - } - - if (GetAnotherCollection().Contains(""key"")) - { - return collection.Remove(""key""); - } - - if (GetCollection().Contains(""key"")) - { - return collection.Remove(""key""); - } - - return false; - } - - private HashSet GetCollection() - { - return new HashSet(); - } - - private ICollection GetAnotherCollection() - { - return new HashSet(); - } - } - }" - }, - new object[] - { - 0, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(HashSet collection, HashSet anotherCollection) - { - if (collection.Contains(""key"")) - { - anotherCollection.Add(""key""); - } - - if (collection.Contains(""key"")) - anotherCollection.Add(""key""); - - if (!collection.Contains(""key"")) - { - collection.Add(""key""); - } - else - { - anotherCollection.Add(""key""); - } - } - } - }" - }, - new object[] - { - 0, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(HashSet collection) - { - if (collection.Contains(""key"")) - { - } - } - } - }" - }, - new object[] - { - 2, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public void DoSomething(ISet collection) - { - if (!/*0+*/collection.Contains(""key"")/*-0*/) - collection.Add(""key""); - - if (/*1+*/collection.Contains(""key"")/*-1*/) - collection.Remove(""key""); - } - } - }" - }, - new object[] - { - 2, - @"using System.Collections.Generic; - - namespace Example - { - public class TestClass - { - public int DoSomething(ISet collection, ISet collection2) - { - var b = 6; - if (!collection.Contains(""key"")) - collection.Add(""key2""); - - collection.Add(""key""); - - if (collection.Contains(""key"")) - collection.Add(""key2""); - - _ = collection.Add(""key""); - - if (!collection.Contains(""key"")) - b = 7; - - /*0+*/collection.Add(""key"")/*-0*/; - - if (collection.Contains(""key"")) - b = 7; - - _ = !/*1+*/collection.Add(""key"")/*-1*/; - - if (collection.Contains(""key"")) - b = 7; - - _ = !collection.Add(""key2""); - - if (collection.Contains(""key"")) - b = 7; - - _ = !collection2.Add(""key""); - - return b; - } - } - }" - } - }; - - [Theory] - [MemberData(nameof(FixerData))] - public async Task CanFixWarning(string source, string expected) - { - var actual = (await RoslynTestUtils.RunAnalyzerAndFixer( - new UsingExcessiveSetLookupAnalyzer(), - new UsingExcessiveSetLookupFixer(), - References, - new[] { source }).ConfigureAwait(false))[0]; - - Assert.Equal(expected.Replace("\r\n", "\n", StringComparison.Ordinal), actual); - } - - [Theory] - [MemberData(nameof(AnalyzerData))] - public async Task ShouldFindWarnings(int expectedNumberOfWarnings, string source) - { - var d = await RoslynTestUtils.RunAnalyzer( - new UsingExcessiveSetLookupAnalyzer(), - References, - new[] { source }).ConfigureAwait(false); - - Assert.Equal(expectedNumberOfWarnings, d.Count); - for (int i = 0; i < d.Count; i++) - { - source.AssertDiagnostic(i, DiagDescriptors.UsingExcessiveSetLookup, d[i]); - } - } - - [Fact] - public void CheckExceptionIsThrownWhenNullIsPassedToInitializeCall() - { - var a = new UsingExcessiveSetLookupAnalyzer(); - Assert.Throws(() => a.Initialize(null!)); - } - - [Fact] - public void CheckFixerPropertiesAreSetCorrectly() - { - var fixer = new UsingExcessiveSetLookupFixer(); - - Assert.Single(fixer.FixableDiagnosticIds); - Assert.Equal(DiagDescriptors.UsingExcessiveSetLookup.Id, fixer.FixableDiagnosticIds[0]); - Assert.Equal(WellKnownFixAllProviders.BatchFixer, fixer.GetFixAllProvider()); - } -} diff --git a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExperimentalApiAnalyzerTest.cs b/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExperimentalApiAnalyzerTest.cs deleted file mode 100644 index 3e2771f0a7e..00000000000 --- a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingExperimentalApiAnalyzerTest.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Extensions.ExtraAnalyzers.Test; - -public static class UsingExperimentalApiAnalyzerTest -{ - [Theory] - [MemberData(nameof(TestData))] - public static async Task Common(string source) - { - var d = await RoslynTestUtils.RunAnalyzer( - new UsingExperimentalApiAnalyzer(), - null, - new[] - { - source, - }).ConfigureAwait(false); - - var expectedCount = source.CountSpans(); - Assert.Equal(expectedCount, d.Count); - - for (int i = 0; i < d.Count; i++) - { - source.AssertDiagnostic(i, DiagDescriptors.UsingExperimentalApi, d[i]); - } - } - - public static IEnumerable TestData => new List - { - new[] - { - @" - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - - public class TestClass : /*0+*/ExpClass/*-0*/ - { - /*1+*/ExpClass/*-1*/? _f0; - - public TestClass() - { - _f0 = new /*2+*/ExpClass/*-2*/(); - var l0 = new /*3+*/ExpClass/*-3*/(); - /*4+*/ExpClass/*-4*/ l1 = new /*5+*/ExpClass/*-5*/(); - } - - public /*6+*/ExpClass/*-6*/? P0 { get; set; } - public /*7+*/ExpClass/*-7*/? M0(/*8+*/ExpClass/*-8*/ ec) => null; - - public void Test() - { - _ = typeof(/*9+*/ExpClass/*-9*/); - _ = nameof(/*10+*/ExpClass/*-10*/); - _ = new List(); - } - } - - [Experimental(diagnosticId: ""TBD"", UrlFormat = ""TBD"")] - public class ExpClass - { - } - " - }, - - new[] - { - @" - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - - #pragma warning disable R9A029 - [assembly: Experimental(diagnosticId: ""TBD"", UrlFormat = ""TBD"")] - #pragma warning restore R9A029 - - public class TestClass : /*0+*/ExpClass/*-0*/ - { - /*1+*/ExpClass/*-1*/? _f0; - - public TestClass() - { - _f0 = new /*2+*/ExpClass/*-2*/(); - var l0 = new /*3+*/ExpClass/*-3*/(); - /*4+*/ExpClass/*-4*/ l1 = new /*5+*/ExpClass/*-5*/(); - } - - public /*6+*/ExpClass/*-6*/? P0 { get; set; } - public /*7+*/ExpClass/*-7*/? M0(/*8+*/ExpClass/*-8*/ ec) => null; - - public void Test() - { - _ = typeof(/*9+*/ExpClass/*-9*/); - _ = nameof(/*10+*/ExpClass/*-10*/); - _ = new List(); - } - } - - public class ExpClass - { - void Foo() - { - _ = new /*12+*/TestClass/*-12*/(); - } - } - " - }, - }; -} diff --git a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingStringFormatterFixerTests.cs b/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingStringFormatterFixerTests.cs deleted file mode 100644 index 6c4be2fe69f..00000000000 --- a/test/Analyzers/Microsoft.Extensions.ExtraAnalyzers/Common/UsingStringFormatterFixerTests.cs +++ /dev/null @@ -1,418 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.Extensions.ExtraAnalyzers.CallAnalysis; -using Xunit; - -namespace Microsoft.Extensions.ExtraAnalyzers.Test; - -public class UsingStringFormatterFixerTests -{ - private static IEnumerable References => new[] - { - Assembly.GetAssembly(typeof(CompositeFormat))!, - }; - - [Theory] - [MemberData(nameof(FixerData))] - public async Task CanFixWarning(string original, string expected) - { - var actual = (await RoslynTestUtils.RunAnalyzerAndFixer( - new CallAnalyzer(), - new StringFormatFixer(), - References, - new[] { original }).ConfigureAwait(false))[0]; - - Assert.Equal(expected.Replace("\r\n", "\n", StringComparison.Ordinal), actual); - } - - [Fact] - public void UtilityMethods() - { - var f = new StringFormatFixer(); - Assert.Single(f.FixableDiagnosticIds); - Assert.Equal(DiagDescriptors.StringFormat.Id, f.FixableDiagnosticIds[0]); - Assert.Equal(WellKnownFixAllProviders.BatchFixer, f.GetFixAllProvider()); - } - - public static IEnumerable FixerData => new List - { - new object[] - { -@"namespace Example -{ - public class TestClass - { - public static void Test() - { - string.Format(""Hello {0}"", ""World""); - } - } -}", -@"using System.Text; - -namespace Example -{ - public class TestClass - { - public static void Test() - { - _sf1.Format(null, ""World""); - } - - private static readonly CompositeFormat _sf1 = new CompositeFormat(""Hello {0}""); - } -}" - }, - new object[] - { -@"namespace Example -{ - public class TestClass - { - public static void Test() - { - string.Format(""Hello {0}"", ""test""); - string.Format(""Hello {0}"", ""World""); - string.Format(""Hello World {0}"", ""test""); - } - } -}", -@"using System.Text; - -namespace Example -{ - public class TestClass - { - public static void Test() - { - _sf1.Format(null, ""test""); - _sf1.Format(null, ""World""); - _sf2.Format(null, ""test""); - } - - private static readonly CompositeFormat _sf1 = new CompositeFormat(""Hello {0}""); - private static readonly CompositeFormat _sf2 = new CompositeFormat(""Hello World {0}""); - } -}" - }, - new object[] - { -@"using System.Globalization; - -namespace Example -{ - public class TestClass - { - public static void Test() - { - string.Format(CultureInfo.InvariantCulture, ""Hello {0}"", ""test""); - var formatter = CultureInfo.InvariantCulture; - string.Format(formatter, ""Hello world {0}"", ""test 123""); - } - } -}", -@"using System.Globalization; -using System.Text; - -namespace Example -{ - public class TestClass - { - public static void Test() - { - _sf1.Format(CultureInfo.InvariantCulture, ""test""); - var formatter = CultureInfo.InvariantCulture; - _sf2.Format(formatter, ""test 123""); - } - - private static readonly CompositeFormat _sf1 = new CompositeFormat(""Hello {0}""); - private static readonly CompositeFormat _sf2 = new CompositeFormat(""Hello world {0}""); - } -}" - }, - new object[] - { -@"using System.Globalization; - -namespace Example -{ - public class TestClass - { - public static string GetFormat() - { - return ""format""; - } - public static void Test() - { - var formatter = CultureInfo.InvariantCulture; - var format = GetFormat(); - string.Format(formatter, format, ""test 123""); - string.Format(""test"", 123); - } - } -}", -@"using System.Globalization; -using System.Text; - -namespace Example -{ - public class TestClass - { - public static string GetFormat() - { - return ""format""; - } - public static void Test() - { - var formatter = CultureInfo.InvariantCulture; - var format = GetFormat(); - string.Format(formatter, format, ""test 123""); - _sf1.Format(null, 123); - } - - private static readonly CompositeFormat _sf1 = new CompositeFormat(""test""); - } -}" - }, - new object[] - { -@"namespace Example -{ - public class TestClass - { - public static void Test() - { - string.Format(""Hello {0}"", ""World""); - } - public static string _sf1 = ""test""; - } -}", -@"using System.Text; - -namespace Example -{ - public class TestClass - { - public static void Test() - { - _sf2.Format(null, ""World""); - } - public static string _sf1 = ""test""; - private static readonly CompositeFormat _sf2 = new CompositeFormat(""Hello {0}""); - } -}" - }, - new object[] - { -@"using System.Text; - -namespace Example -{ - public class TestClass - { - public static void Test() - { - StringBuilder sb = new StringBuilder(); - sb.AppendFormat(""Hello {0}"", ""World""); - } - } -}", -@"using System.Text; - -namespace Example -{ - public class TestClass - { - public static void Test() - { - StringBuilder sb = new StringBuilder(); - sb.AppendFormat(_sf1, null, ""World""); - } - - private static readonly CompositeFormat _sf1 = new CompositeFormat(""Hello {0}""); - } -}" - }, - new object[] - { -@"using System.Text; -using System.Globalization; - -namespace Example -{ - public class TestClass - { - public static void Test() - { - StringBuilder sb = new StringBuilder(); - sb.AppendFormat(CultureInfo.InvariantCulture, ""Hello {0}"", ""World""); - } - } -}", -@"using System.Text; -using System.Globalization; - -namespace Example -{ - public class TestClass - { - public static void Test() - { - StringBuilder sb = new StringBuilder(); - sb.AppendFormat(_sf1, CultureInfo.InvariantCulture, ""World""); - } - - private static readonly CompositeFormat _sf1 = new CompositeFormat(""Hello {0}""); - } -}" - }, - new object[] - { -@"namespace Example -{ - public struct TestClass - { - public static void Test() - { - string.Format(""Hello {0}"", ""World""); - } - } -}", -@"using System.Text; - -namespace Example -{ - public struct TestClass - { - public static void Test() - { - _sf1.Format(null, ""World""); - } - - private static readonly CompositeFormat _sf1 = new CompositeFormat(""Hello {0}""); - } -}" - }, - new object[] - { -@"using System.Text; - -namespace Example -{ - public struct TestClass - { - public static void Test() - { - string.Format(""Hello {0}"", ""World""); - } - - private static readonly CompositeFormat _sf = new CompositeFormat(""Hello {0}""); - } -}", -@"using System.Text; - -namespace Example -{ - public struct TestClass - { - public static void Test() - { - _sf.Format(null, ""World""); - } - - private static readonly CompositeFormat _sf = new CompositeFormat(""Hello {0}""); - } -}" - }, - new object[] - { -@"using System.Globalization; -using System.Text; - -namespace Example -{ - public struct TestClass - { - public static void Test() - { - string.Format(CultureInfo.InvariantCulture, ""Hello 1 {0}"", ""World""); - } - - private static readonly CompositeFormat _sf1 = new CompositeFormat(""Hello {0}""); - } -}", -@"using System.Globalization; -using System.Text; - -namespace Example -{ - public struct TestClass - { - public static void Test() - { - _sf2.Format(CultureInfo.InvariantCulture, ""World""); - } - - private static readonly CompositeFormat _sf1 = new CompositeFormat(""Hello {0}""); - private static readonly CompositeFormat _sf2 = new CompositeFormat(""Hello 1 {0}""); - } -}" - }, - new object[] - { -@"namespace Example -{ - public class TestClass - { - public static void Test() - { - string.Format(null, ""World""); - } - } -}", -@"namespace Example -{ - public class TestClass - { - public static void Test() - { - string.Format(null, ""World""); - } - } -}" - }, - new object[] - { -@"namespace Example -{ - public class TestClass - { - public static void Test() - { - string.Format(""Hello {0}""); - } - } -}", -@"using System.Text; - -namespace Example -{ - public class TestClass - { - public static void Test() - { - _sf1.Format(null); - } - - private static readonly CompositeFormat _sf1 = new CompositeFormat(""Hello {0}""); - } -}" - }, - }; -} diff --git a/test/Analyzers/Microsoft.Extensions.LocalAnalyzers/ApiLifecycle/ApiLifecycleAnalyzerTest.cs b/test/Analyzers/Microsoft.Extensions.LocalAnalyzers/ApiLifecycle/ApiLifecycleAnalyzerTest.cs index 6239d25dd8b..379a0fe65df 100644 --- a/test/Analyzers/Microsoft.Extensions.LocalAnalyzers/ApiLifecycle/ApiLifecycleAnalyzerTest.cs +++ b/test/Analyzers/Microsoft.Extensions.LocalAnalyzers/ApiLifecycle/ApiLifecycleAnalyzerTest.cs @@ -228,7 +228,7 @@ namespace Microsoft.Extensions.Security.Identity; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] public class AdditionalContext2 { protected IReadOnlyDictionary Features { get; } = new Dictionary(); @@ -347,7 +347,7 @@ public sealed class BufferWriter2 : IBufferWriter private T[] _buffer = Array.Empty(); - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] public BufferWriter2() { } public ReadOnlyMemory WrittenMemory => _buffer.AsMemory(0, WrittenCount); @@ -474,7 +474,7 @@ public interface IClassifiedData public DataClass DataClass { get; } } - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] public enum DataClass { @@ -562,10 +562,10 @@ namespace SomePackage; using System.Diagnostics.CodeAnalysis; - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] public static class Test { - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] public static void Load() { // Intentionally left empty. @@ -707,7 +707,7 @@ namespace Microsoft.Extensions.Diagnostics; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] public class WindowsCountersOptions2 { [Required] @@ -728,7 +728,7 @@ namespace Test; using System.Diagnostics.CodeAnalysis; - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] public sealed class BufferWriter { internal const int MaxArrayLength = 0X7FEF_FFFF; // Copy of the internal Array.MaxArrayLength const @@ -751,7 +751,7 @@ namespace Inheritance; using System.Diagnostics.CodeAnalysis; - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] public class BaseType { public virtual int P => 1; @@ -774,7 +774,7 @@ namespace Nested; using System.Diagnostics.CodeAnalysis; - [Experimental(diagnosticId: "TBD", UrlFormat = WarningDefinitions.SharedUrlFormat)] + [Experimental(diagnosticId: "TBD", UrlFormat = "TBD")] public class OuterType { public int ReadValue(string s) => new InnerType().P;