From 77f2de53a902fa34bd57beade0f054e80cbd762f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Sun, 13 Jul 2025 02:06:19 +0000 Subject: [PATCH 01/14] [VMR] Codeflow d3571ef-d3571ef [[ commit created by automation ]] --- .../Program.cs | 23 +++++++++---------- .../Program.cs | 2 +- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index a0660a5fe4844..435c54303a75f 100644 --- a/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -32,8 +32,15 @@ WindowsErrorReporting.SetErrorModeOnWindows(); -var parser = CreateCommandLineParser(); -return await parser.Parse(args).InvokeAsync(CancellationToken.None); +var command = CreateCommand(); +var invocationConfiguration = new InvocationConfiguration() +{ + // By default, System.CommandLine will catch all exceptions, log them to the console, and return a non-zero exit code. + // Unfortunately this makes .NET's crash dump collection environment variables (e.g. 'DOTNET_DbgEnableMiniDump') + // entirely useless as it never detects an actual crash. Disable this behavior so we can collect crash dumps when asked to. + EnableDefaultExceptionHandler = false +}; +return await command.Parse(args).InvokeAsync(invocationConfiguration, CancellationToken.None); static async Task RunAsync(ServerConfiguration serverConfiguration, CancellationToken cancellationToken) { @@ -167,7 +174,7 @@ static async Task RunAsync(ServerConfiguration serverConfiguration, Cancellation } } -static CommandLineConfiguration CreateCommandLineParser() +static RootCommand CreateCommand() { var debugOption = new Option("--debug") { @@ -294,15 +301,7 @@ static CommandLineConfiguration CreateCommandLineParser() return RunAsync(serverConfiguration, cancellationToken); }); - var config = new CommandLineConfiguration(rootCommand) - { - // By default, System.CommandLine will catch all exceptions, log them to the console, and return a non-zero exit code. - // Unfortunately this makes .NET's crash dump collection environment variables (e.g. 'DOTNET_DbgEnableMiniDump') - // entirely useless as it never detects an actual crash. Disable this behavior so we can collect crash dumps when asked to. - EnableDefaultExceptionHandler = false - }; - - return config; + return rootCommand; } static (string clientPipe, string serverPipe) CreateNewPipeNames() diff --git a/src/RoslynAnalyzers/Tools/GenerateDocumentationAndConfigFiles/Program.cs b/src/RoslynAnalyzers/Tools/GenerateDocumentationAndConfigFiles/Program.cs index deae10986e16e..5d31f6a311644 100644 --- a/src/RoslynAnalyzers/Tools/GenerateDocumentationAndConfigFiles/Program.cs +++ b/src/RoslynAnalyzers/Tools/GenerateDocumentationAndConfigFiles/Program.cs @@ -257,7 +257,7 @@ public static Task Main(string[] args) return HandleAsync(commandLineArgs, cancellationToken); }); - return rootCommand.Parse(args).InvokeAsync(CancellationToken.None); + return rootCommand.Parse(args).InvokeAsync(null, CancellationToken.None); } private static async Task HandleAsync(CommandLineArgs args, CancellationToken cancellationToken) From 9c4f3cb1c5f94e0b49d0f5aee10b8c499344c8c5 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Sun, 13 Jul 2025 02:06:20 +0000 Subject: [PATCH 02/14] Update dependencies from https://github.com/dotnet/dotnet build 275021 No dependency updates to commit --- eng/Version.Details.xml | 2 +- global.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a1e403bfb4226..517778df51884 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,6 +1,6 @@ - + diff --git a/global.json b/global.json index 765ae32155ef0..ce037f9a8e772 100644 --- a/global.json +++ b/global.json @@ -16,4 +16,4 @@ "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25259.2", "Microsoft.Build.Traversal": "3.4.0" } -} \ No newline at end of file +} From b5f086c70dc675bd550abc52a48089b163e4d879 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 14 Jul 2025 02:06:06 +0000 Subject: [PATCH 03/14] Update dependencies from https://github.com/dotnet/dotnet build 275039 No dependency updates to commit --- eng/Version.Details.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 517778df51884..9fb7e0a77aef9 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,6 +1,6 @@ - + From c883fa894d10f49a2fca7b0e02ea633e0bb60e2c Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Tue, 15 Jul 2025 02:05:21 +0000 Subject: [PATCH 04/14] Update dependencies from https://github.com/dotnet/dotnet build 275143 No dependency updates to commit --- eng/Version.Details.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9fb7e0a77aef9..2b023b6373691 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,6 +1,6 @@ - + From 20905893cd6f76a25ae53e6f9ec4b80bd6188862 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Wed, 16 Jul 2025 02:05:23 +0000 Subject: [PATCH 05/14] Update dependencies from https://github.com/dotnet/dotnet build 275313 No dependency updates to commit --- eng/Version.Details.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 2b023b6373691..098b6641ac17b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,6 +1,6 @@ - + From e902f73195ec6005ffffdb751c2764aa5dba1694 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Thu, 17 Jul 2025 02:17:07 +0000 Subject: [PATCH 06/14] [VMR] Codeflow c1794aa-c1794aa [[ commit created by automation ]] --- ...saryNullableDirectiveDiagnosticAnalyzer.cs | 23 +- .../NullableImpactingSpanWalker.cs | 4 + .../AddObsoleteAttributeTests.cs | 10 +- .../Tests/FileHeaders/FileHeaderTests.cs | 9 +- .../RemoveUnnecessaryCastTests.cs | 24 + ...RemoveUnnecessaryNullableDirectiveTests.cs | 27 + ...veUnnecessaryAttributeSuppressionsTests.cs | 8 +- .../UpdateLegacySuppressionsTests.cs | 9 +- .../UseImplicitTypeTests.cs | 48 +- .../RemoveUnnecessaryParenthesesTests.vb | 11 +- ...dMissingImportsRefactoringProviderTests.cs | 41 +- .../AddUsing/AbstractAddUsingTests.cs | 14 +- .../CodeActions/AddUsing/AddUsingTests.cs | 13 + ...ateEqualsAndGetHashCodeFromMembersTests.cs | 10 +- .../GenerateType/GenerateTypeTests.cs | 22 + ...berFromPrimaryConstructorParameterTests.cs | 44 + .../CSharpMoveStaticMembersTests.cs | 7 +- ...agnosticProviderBasedUserDiagnosticTest.cs | 47 +- .../Core/InlineRename/InlineRenameSession.cs | 9 +- .../UI/Adornment/RenameFlyoutViewModel.cs | 5 +- .../CaretPreservingEditTransaction.cs | 5 +- ...Presenter.SignatureHelpPresenterSession.cs | 5 +- .../CodeActions/AbstractCodeActionTest.cs | 5 +- .../FindReferencesTests.NamedTypeSymbols.vb | 60 + ...tructorParameterCodeRefactoringProvider.cs | 34 +- .../GenerateComparisonOperatorsTests.cs | 6 +- .../GenerateOverridesWithDialogCodeAction.cs | 5 +- .../AbstractGenerateTypeService.cs | 3 +- .../Portable/QuickInfo/QuickInfoUtilities.cs | 5 +- ...pertyWithMethodsCodeRefactoringProvider.cs | 16 +- .../AbstractCodeActionTest_NoEditor.cs | 5 +- .../ReplacePropertyWithMethodsTests.vb | 21 +- .../ResxGeneratorTests.cs | 1490 ++++++++--------- ...oidAllocationWithArrayEmptyCodeFixTests.cs | 802 ++++----- ...CallSiteImplicitAllocationAnalyzerTests.cs | 293 ++-- .../ConcatenationAllocationAnalyzerTests.cs | 163 +- .../DisplayClassAllocationAnalyzerTests.cs | 236 +-- .../EnumeratorAllocationAnalyzerTests.cs | 245 +-- .../ExplicitAllocationAnalyzerTests.cs | 1322 +++++++-------- .../TypeConversionAllocationAnalyzerTests.cs | 1232 +++++++------- src/Scripting/Core/ScriptBuilder.cs | 5 +- .../InheritanceMarginLogger.cs | 5 +- .../Core/Def/Utilities/TaskItemsEnum.cs | 5 +- .../AnalyzersCommandHandler.cs | 10 +- .../CSharp/CSharpAddMissingUsingsOnPaste.cs | 7 +- .../Finders/AbstractReferenceFinder.cs | 24 +- .../Services/SyntaxFacts/CSharpSyntaxKinds.cs | 2 + .../Simplifiers/CastSimplifier.cs | 2 +- .../TypeStyle/CSharpUseImplicitTypeHelper.cs | 18 +- .../Core/Extensions/SymbolUsageInfo.cs | 28 +- .../Core/Services/SyntaxFacts/ISyntaxKinds.cs | 2 + ...ParenthesizedExpressionSyntaxExtensions.vb | 2 + .../SyntaxFacts/VisualBasicSyntaxKinds.vb | 2 + .../CSharpCodeGenerationHelpers.cs | 5 +- .../CodeGeneration/NamedTypeGenerator.cs | 6 +- .../CodeGeneration/CodeGenerationHelpers.cs | 9 +- 56 files changed, 3379 insertions(+), 3091 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer.cs index d1c1f8c444548..544731492afc0 100644 --- a/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer.cs @@ -19,26 +19,19 @@ namespace Microsoft.CodeAnalysis.RemoveUnnecessaryNullableDirective; [DiagnosticAnalyzer(LanguageNames.CSharp)] -internal sealed class CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer - : AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer +internal sealed class CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer() + : AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer(IDEDiagnosticIds.RemoveUnnecessaryNullableDirectiveDiagnosticId, + EnforceOnBuildValues.RemoveUnnecessaryNullableDirective, + option: null, + fadingOption: null, + new LocalizableResourceString(nameof(CSharpAnalyzersResources.Remove_unnecessary_nullable_directive), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), + new LocalizableResourceString(nameof(CSharpAnalyzersResources.Nullable_directive_is_unnecessary), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources))) { - public CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer() - : base(IDEDiagnosticIds.RemoveUnnecessaryNullableDirectiveDiagnosticId, - EnforceOnBuildValues.RemoveUnnecessaryNullableDirective, - option: null, - fadingOption: null, - new LocalizableResourceString(nameof(CSharpAnalyzersResources.Remove_unnecessary_nullable_directive), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), - new LocalizableResourceString(nameof(CSharpAnalyzersResources.Nullable_directive_is_unnecessary), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources))) - { - } - public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticDocumentAnalysis; protected override void InitializeWorker(AnalysisContext context) - { - context.RegisterCompilationStartAction(AnalyzeCompilation); - } + => context.RegisterCompilationStartAction(AnalyzeCompilation); private void AnalyzeCompilation(CompilationStartAnalysisContext context) { diff --git a/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/NullableImpactingSpanWalker.cs b/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/NullableImpactingSpanWalker.cs index 38622e35bf702..372636faed961 100644 --- a/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/NullableImpactingSpanWalker.cs +++ b/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/NullableImpactingSpanWalker.cs @@ -97,6 +97,10 @@ private static bool IsLanguageRestrictedToNonNullForm(TypeSyntax node) return true; } + // An attribute name cannot itself be nullable. `[CLSCompliant?]` is not a thing. + if (node.IsParentKind(SyntaxKind.Attribute)) + return true; + return false; // If this is Y in X.Y, walk up to X.Y diff --git a/src/Analyzers/CSharp/Tests/AddObsoleteAttribute/AddObsoleteAttributeTests.cs b/src/Analyzers/CSharp/Tests/AddObsoleteAttribute/AddObsoleteAttributeTests.cs index 8d60be340f045..a940ac5dcca60 100644 --- a/src/Analyzers/CSharp/Tests/AddObsoleteAttribute/AddObsoleteAttributeTests.cs +++ b/src/Analyzers/CSharp/Tests/AddObsoleteAttribute/AddObsoleteAttributeTests.cs @@ -3,14 +3,18 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.AddObsoleteAttribute; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Testing; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier< - Microsoft.CodeAnalysis.Testing.EmptyDiagnosticAnalyzer, - Microsoft.CodeAnalysis.CSharp.AddObsoleteAttribute.CSharpAddObsoleteAttributeCodeFixProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.AddObsoleteAttribute; +using VerifyCS = CSharpCodeFixVerifier< + EmptyDiagnosticAnalyzer, + CSharpAddObsoleteAttributeCodeFixProvider>; + [Trait(Traits.Feature, Traits.Features.CodeActionsAddObsoleteAttribute)] public sealed class AddObsoleteAttributeTests { diff --git a/src/Analyzers/CSharp/Tests/FileHeaders/FileHeaderTests.cs b/src/Analyzers/CSharp/Tests/FileHeaders/FileHeaderTests.cs index 4a8b37d756bf5..2bc54c7c094ce 100644 --- a/src/Analyzers/CSharp/Tests/FileHeaders/FileHeaderTests.cs +++ b/src/Analyzers/CSharp/Tests/FileHeaders/FileHeaderTests.cs @@ -3,16 +3,19 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.FileHeaders; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Testing; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.FileHeaders.CSharpFileHeaderDiagnosticAnalyzer, - Microsoft.CodeAnalysis.CSharp.FileHeaders.CSharpFileHeaderCodeFixProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.FileHeaders; +using VerifyCS = CSharpCodeFixVerifier< + CSharpFileHeaderDiagnosticAnalyzer, + CSharpFileHeaderCodeFixProvider>; + public sealed class FileHeaderTests { private const string TestSettings = """ diff --git a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs index 05cb84877df8c..9047d5010c850 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs @@ -13484,4 +13484,28 @@ uint M(bool condition) CodeFixTestBehaviors = CodeFixTestBehaviors.FixOne | CodeFixTestBehaviors.SkipFixAllCheck, DiagnosticSelector = d => d[1], }.RunAsync(); + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/60720")] + public Task TestNullableWithinGeneric() + => new VerifyCS.Test + { + TestCode = """ + #nullable enable + + using System; + using System.Threading.Tasks; + + Task M(string s, Func> func) + { + return string.IsNullOrWhiteSpace(s) + ? Task.FromResult(null) + : (Task)func(s)!; + } + """, + LanguageVersion = LanguageVersion.CSharp13, + TestState = + { + OutputKind = OutputKind.ConsoleApplication, + }, + }.RunAsync(); } diff --git a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveTests.cs index f4ffe53ba2e40..b9656bbb5609d 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveTests.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.RemoveUnnecessaryNullableDirective; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.Analyzers.UnitTests.RemoveUnnecessaryNullableDirective; @@ -62,6 +63,32 @@ enum EnumName } """); + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/65401")] + public Task TestUnnecessaryDisableEnumDeclaration_WithAttribute() + => VerifyCodeFixAsync( + NullableContextOptions.Enable, + """ + [|#nullable disable|] + using System; + + [CLSCompliant(false)] + enum EnumName + { + First, + Second, + } + """, + """ + using System; + + [CLSCompliant(false)] + enum EnumName + { + First, + Second, + } + """); + [Fact] public Task TestUnnecessaryDisableEnumDeclarationWithFileHeader() => VerifyCodeFixAsync( diff --git a/src/Analyzers/CSharp/Tests/RemoveUnnecessarySuppressions/RemoveUnnecessaryAttributeSuppressionsTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnnecessarySuppressions/RemoveUnnecessaryAttributeSuppressionsTests.cs index 47866bc70cace..409cfd9bbe7af 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnnecessarySuppressions/RemoveUnnecessaryAttributeSuppressionsTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnnecessarySuppressions/RemoveUnnecessaryAttributeSuppressionsTests.cs @@ -3,17 +3,19 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.RemoveUnnecessarySuppressions; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.RemoveUnnecessarySuppressions; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.RemoveUnnecessarySuppressions.CSharpRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer, - Microsoft.CodeAnalysis.RemoveUnnecessarySuppressions.RemoveUnnecessaryAttributeSuppressionsCodeFixProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RemoveUnnecessarySuppressions; +using VerifyCS = CSharpCodeFixVerifier< + CSharpRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer, + RemoveUnnecessaryAttributeSuppressionsCodeFixProvider>; + [Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessarySuppressions)] [WorkItem("https://github.com/dotnet/roslyn/issues/44176")] public sealed class RemoveUnnecessaryAttributeSuppressionsTests diff --git a/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs b/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs index f52eaa57550a9..a28518bbe3648 100644 --- a/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs +++ b/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs @@ -3,17 +3,20 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.RemoveUnnecessarySuppressions; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.RemoveUnnecessarySuppressions; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.UpdateLegacySuppressions; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.RemoveUnnecessarySuppressions.CSharpRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer, - Microsoft.CodeAnalysis.UpdateLegacySuppressions.UpdateLegacySuppressionsCodeFixProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UpdateLegacySuppressions; +using VerifyCS = CSharpCodeFixVerifier< + CSharpRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer, + UpdateLegacySuppressionsCodeFixProvider>; + [Trait(Traits.Feature, Traits.Features.CodeActionsUpdateLegacySuppressions)] [WorkItem("https://github.com/dotnet/roslyn/issues/44362")] public sealed class UpdateLegacySuppressionsTests diff --git a/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs b/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs index 818f0e09cd6d1..75db660d4d9d8 100644 --- a/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs +++ b/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs @@ -2097,9 +2097,11 @@ static void M() } """, new TestParameters(options: ImplicitTypeEverywhere())); - [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")] - public Task DoNotSuggestVarOnStackAllocExpressions_SpanType_NestedConditional() - => TestMissingInRegularAndScriptAsync(""" + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/22768")] + [WorkItem("https://github.com/dotnet/roslyn/issues/79337")] + public Task DoSuggestVarOnStackAllocExpressions_SpanType_NestedConditional() + => TestInRegularAndScript1Async(""" using System; namespace System { @@ -2115,11 +2117,29 @@ static void M(bool choice) [|Span|] x = choice ? stackalloc int [10] : stackalloc int [100]; } } + """, """ + using System; + namespace System + { + public readonly ref struct Span + { + unsafe public Span(void* pointer, int length) { } + } + } + class C + { + static void M(bool choice) + { + var x = choice ? stackalloc int [10] : stackalloc int [100]; + } + } """, new TestParameters(options: ImplicitTypeEverywhere())); - [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")] - public Task DoNotSuggestVarOnStackAllocExpressions_SpanType_NestedCast() - => TestMissingInRegularAndScriptAsync(""" + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/22768")] + [WorkItem("https://github.com/dotnet/roslyn/issues/79337")] + public Task DoSuggestVarOnStackAllocExpressions_SpanType_NestedCast() + => TestInRegularAndScript1Async(""" using System; namespace System { @@ -2135,6 +2155,22 @@ static void M() [|Span|] x = (Span)stackalloc int [100]; } } + """, """ + using System; + namespace System + { + public readonly ref struct Span + { + unsafe public Span(void* pointer, int length) { } + } + } + class C + { + static void M() + { + var x = (Span)stackalloc int [100]; + } + } """, new TestParameters(options: ImplicitTypeEverywhere())); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")] diff --git a/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryParenthesesTests.vb b/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryParenthesesTests.vb index 9d66369c48bf2..5b7e600d503b9 100644 --- a/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryParenthesesTests.vb +++ b/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryParenthesesTests.vb @@ -15,7 +15,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.RemoveUnnecessaryP ''' whose current option is set to something other than 'Ignore'. ''' - Partial Public Class RemoveUnnecessaryParenthesesTests + Partial Public NotInheritable Class RemoveUnnecessaryParenthesesTests Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest_NoEditor Private Shared ReadOnly CheckOverflow As CompilationOptions = New VisualBasicCompilationOptions(OutputKind.ConsoleApplication, checkOverflow:=True) @@ -651,7 +651,16 @@ end class" Assert.Equal("[1,2]", diagnostic.Properties.Item(WellKnownDiagnosticTags.Unnecessary)) End Using + End Function + + Public Async Function TestWithNullMemberAccess() As Task + Await TestMissingAsync( +"class C + sub M() + RoundTime($$(d.EndDate - d.StartDate)?.TotalMinutes / 60) + end sub +end class", New TestParameters(options:=RequireArithmeticBinaryParenthesesForClarity)) End Function End Class End Namespace diff --git a/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs b/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs index 335d55a65f3f5..93ceaedbf5734 100644 --- a/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs @@ -2,13 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeRefactorings.AddMissingImports; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; @@ -26,6 +27,12 @@ public sealed class CSharpAddMissingImportsRefactoringProviderTests : AbstractCS protected override CodeRefactoringProvider CreateCodeRefactoringProvider(EditorTestWorkspace workspace, TestParameters parameters) => new CSharpAddMissingImportsRefactoringProvider(); + private static readonly CodeStyleOption2 InsideNamespaceOption = + new(AddImportPlacement.InsideNamespace, NotificationOption2.Error); + + private static readonly CodeStyleOption2 OutsideNamespaceOption = + new(AddImportPlacement.InsideNamespace, NotificationOption2.Error); + protected override void InitializeWorkspace(EditorTestWorkspace workspace, TestParameters parameters) { // Treat the span being tested as the pasted span @@ -46,13 +53,16 @@ protected override void InitializeWorkspace(EditorTestWorkspace workspace, TestP private Task TestInRegularAndScriptAsync( [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string initialMarkup, [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string expectedMarkup, - bool placeSystemNamespaceFirst, bool separateImportDirectiveGroups) + bool placeSystemNamespaceFirst, + bool separateImportDirectiveGroups, + bool placeInsideNamespace = false) { var options = new OptionsCollection(GetLanguage()) { { GenerationOptions.PlaceSystemNamespaceFirst, placeSystemNamespaceFirst }, { GenerationOptions.SeparateImportDirectiveGroups, separateImportDirectiveGroups }, + { CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, placeInsideNamespace ? InsideNamespaceOption : OutsideNamespaceOption }, }; return TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: options); } @@ -353,4 +363,29 @@ class C List list; } """, placeSystemNamespaceFirst: true, separateImportDirectiveGroups: true); + + [WpfTheory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/54842")] + public Task TestWithNamespace(bool placeInsideNamespace) + => TestInRegularAndScriptAsync(""" + namespace N + { + using System; + + class C + { + [|List list;|] + } + } + """, """ + namespace N + { + using System; + using System.Collections.Generic; + + class C + { + List list; + } + } + """, placeSystemNamespaceFirst: true, separateImportDirectiveGroups: true, placeInsideNamespace); } diff --git a/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AbstractAddUsingTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AbstractAddUsingTests.cs index d739fecb85cb5..d6cb4ae26b9c0 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AbstractAddUsingTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AbstractAddUsingTests.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; @@ -18,14 +16,10 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.AddUsing; -public abstract class AbstractAddUsingTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest +public abstract class AbstractAddUsingTests(ITestOutputHelper? logger = null) + : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest(logger) { - protected AbstractAddUsingTests(ITestOutputHelper logger = null) - : base(logger) - { - } - - internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) + internal override (DiagnosticAnalyzer?, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) => (null, new CSharpAddImportCodeFixProvider()); private protected OptionsCollection SeparateGroups => Option(GenerationOptions.SeparateImportDirectiveGroups, true); @@ -36,7 +30,7 @@ internal Task TestAsync( TestHost testHost, int index = 0, CodeActionPriority? priority = null, - OptionsCollection options = null) + OptionsCollection? options = null) => TestInRegularAndScript1Async( initialMarkup, expectedMarkup, diff --git a/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AddUsingTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AddUsingTests.cs index c9ce5e2cdac8c..a9f79963b3c59 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AddUsingTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AddUsingTests.cs @@ -6633,4 +6633,17 @@ class Program """, index: 0, parameters: new TestParameters(testHost: testHost)); + + [Theory, CombinatorialData] + [WorkItem("https://github.com/dotnet/roslyn/issues/72022")] + public Task TestAssemblyLevelAttribute(TestHost testHost) + => TestAsync( + """ + [assembly: [|NeutralResourcesLanguage|]("en")] + """, + """ + using System.Resources; + + [assembly: NeutralResourcesLanguage("en")] + """, testHost); } diff --git a/src/EditorFeatures/CSharpTest/CodeActions/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs index cdb2f66eb1944..d9bd2d2acc41a 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs @@ -20,11 +20,12 @@ using Microsoft.CodeAnalysis.Testing; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeRefactoringVerifier< - Microsoft.CodeAnalysis.GenerateEqualsAndGetHashCodeFromMembers.GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.GenerateEqualsAndGetHashCodeFromMembers; +using VerifyCS = CSharpCodeRefactoringVerifier< + GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider>; + [UseExportProvider] [Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)] public sealed class GenerateEqualsAndGetHashCodeFromMembersTests @@ -69,10 +70,7 @@ private static OptionsCollection PreferExplicitTypeWithInfo() internal static void EnableOption(ImmutableArray options, string id) { var option = options.FirstOrDefault(o => o.Id == id); - if (option != null) - { - option.Value = true; - } + option?.Value = true; } [Fact] diff --git a/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs index ade0311f695ca..d42de6fa6e5d1 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs @@ -5901,4 +5901,26 @@ internal class Test public int B { get; set; } } """, index: 1); + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/49649")] + public Task TestInTopLevelProgram() + => TestInRegularAndScriptAsync( + """ + var student = new [|Student|]("Youssef"); + Console.WriteLine(student.Name); + """, + """ + var student = new Student("Youssef"); + Console.WriteLine(student.Name); + + internal class Student + { + private string v; + + public Student(string v) + { + this.v = v; + } + } + """, index: 1); } diff --git a/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs index 1dd09cc7e77b9..8f3cab891e6c9 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs @@ -1349,6 +1349,50 @@ public partial class Goo """); + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/76565")] + public Task TestCouldInitializeThrowingProperty_ButGeneratePropertyInstead() + => TestInRegularAndScript1Async( + """ + using System; + + class C([||]string s) + { + private string S => throw new NotImplementedException(); + } + """, + """ + using System; + + class C(string s) + { + public string S1 { get; } = s; + + private string S => throw new NotImplementedException(); + } + """, index: 1); + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/76565")] + public Task TestCouldInitializeThrowingProperty_ButGenerateFieldInstead() + => TestInRegularAndScript1Async( + """ + using System; + + class C([||]string s) + { + private string S => throw new NotImplementedException(); + } + """, + """ + using System; + + class C(string s) + { + private readonly string s = s; + + private string S => throw new NotImplementedException(); + } + """, index: 2); + [Fact] public Task TestUpdateCodeToReferenceExistingField1() => TestInRegularAndScript1Async( diff --git a/src/EditorFeatures/CSharpTest/CodeActions/MoveStaticMembers/CSharpMoveStaticMembersTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/MoveStaticMembers/CSharpMoveStaticMembersTests.cs index 10c97ce96b009..d943b9e2b3c7d 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/MoveStaticMembers/CSharpMoveStaticMembersTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/MoveStaticMembers/CSharpMoveStaticMembersTests.cs @@ -4,16 +4,19 @@ using System.Collections.Immutable; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.CodeRefactorings.MoveStaticMembers; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.MoveStaticMembers; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities.MoveStaticMembers; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeRefactoringVerifier< - Microsoft.CodeAnalysis.CSharp.CodeRefactorings.MoveStaticMembers.CSharpMoveStaticMembersRefactoringProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.MoveStaticMembers; +using VerifyCS = CSharpCodeRefactoringVerifier< + CSharpMoveStaticMembersRefactoringProvider>; + [UseExportProvider] [Trait(Traits.Feature, Traits.Features.CodeActionsMoveStaticMembers)] public sealed class CSharpMoveStaticMembersTests diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest.cs b/src/EditorFeatures/CSharpTest/Diagnostics/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest.cs index de315e1a8000d..9ea1e21c7bfcd 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest.cs @@ -2,21 +2,29 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable +#if CODE_STYLE +extern alias CODESTYLE_UTILITIES; +#endif +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Remote.Testing; using Xunit.Abstractions; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; -public abstract partial class AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest : AbstractDiagnosticProviderBasedUserDiagnosticTest -{ - protected AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest(ITestOutputHelper logger) - : base(logger) - { - } +#if CODE_STYLE +using OptionsCollectionAlias = CODESTYLE_UTILITIES::Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.OptionsCollection; +#else +using OptionsCollectionAlias = OptionsCollection; +#endif +public abstract partial class AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest(ITestOutputHelper? logger) + : AbstractDiagnosticProviderBasedUserDiagnosticTest(logger) +{ protected override ParseOptions GetScriptOptions() => Options.Script; protected internal override string GetLanguage() => LanguageNames.CSharp; @@ -151,4 +159,29 @@ public interface IAsyncEnumerator : IAsyncDisposable internal OptionsCollection IgnoreAllParentheses => ParenthesesOptionsProvider.IgnoreAllParentheses; internal OptionsCollection RemoveAllUnnecessaryParentheses => ParenthesesOptionsProvider.RemoveAllUnnecessaryParentheses; internal OptionsCollection RequireAllParenthesesForClarity => ParenthesesOptionsProvider.RequireAllParenthesesForClarity; + + internal new Task TestInRegularAndScript1Async( + [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string initialMarkup, + [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string expectedMarkup, + int index = 0, + TestParameters? parameters = null) + { + return base.TestInRegularAndScript1Async(initialMarkup, expectedMarkup, index, parameters); + } + + internal new Task TestInRegularAndScriptAsync( + [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string initialMarkup, + [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string expectedMarkup, + int index = 0, + CodeActionPriority? priority = null, + CompilationOptions? compilationOptions = null, + OptionsCollectionAlias? options = null, + object? fixProviderData = null, + ParseOptions? parseOptions = null, + string? title = null, + TestHost testHost = TestHost.OutOfProcess) + { + return base.TestInRegularAndScriptAsync( + initialMarkup, expectedMarkup, index, priority, compilationOptions, options, fixProviderData, parseOptions, title, testHost); + } } diff --git a/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs b/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs index c9afd36b6d880..ff3450ab70def 100644 --- a/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs +++ b/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs @@ -753,12 +753,9 @@ public async Task CommitAsync(bool previewChanges, IUIThreadOperationContext edi previewChanges = previewChanges || PreviewChanges; - if (editorOperationContext is not null) - { - // Prevent Editor's typing responsiveness auto canceling the rename operation. - // InlineRenameSession will call IUIThreadOperationExecutor to sets up our own IUIThreadOperationContext - editorOperationContext.TakeOwnership(); - } + // Prevent Editor's typing responsiveness auto canceling the rename operation. + // InlineRenameSession will call IUIThreadOperationExecutor to sets up our own IUIThreadOperationContext + editorOperationContext?.TakeOwnership(); try { diff --git a/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs b/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs index 367eeb23440c8..e5d4ed313e564 100644 --- a/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs +++ b/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs @@ -333,10 +333,7 @@ protected virtual void Dispose(bool disposing) Session.ReplacementsComputed -= OnReplacementsComputed; Session.CommitStateChange -= CommitStateChange; - if (SmartRenameViewModel is not null) - { - SmartRenameViewModel.Dispose(); - } + SmartRenameViewModel?.Dispose(); UnregisterOleComponent(); } diff --git a/src/EditorFeatures/Core/Shared/Utilities/CaretPreservingEditTransaction.cs b/src/EditorFeatures/Core/Shared/Utilities/CaretPreservingEditTransaction.cs index 5bcb2e0203bce..7dfdafeb9d975 100644 --- a/src/EditorFeatures/Core/Shared/Utilities/CaretPreservingEditTransaction.cs +++ b/src/EditorFeatures/Core/Shared/Utilities/CaretPreservingEditTransaction.cs @@ -93,10 +93,7 @@ public IMergeTextUndoTransactionPolicy? MergePolicy set { - if (_transaction != null) - { - _transaction.MergePolicy = value; - } + _transaction?.MergePolicy = value; } } diff --git a/src/EditorFeatures/Core/SignatureHelp/Presentation/SignatureHelpPresenter.SignatureHelpPresenterSession.cs b/src/EditorFeatures/Core/SignatureHelp/Presentation/SignatureHelpPresenter.SignatureHelpPresenterSession.cs index 7dc0a0b51f3f8..4bdd65c15742b 100644 --- a/src/EditorFeatures/Core/SignatureHelp/Presentation/SignatureHelpPresenter.SignatureHelpPresenterSession.cs +++ b/src/EditorFeatures/Core/SignatureHelp/Presentation/SignatureHelpPresenter.SignatureHelpPresenterSession.cs @@ -98,10 +98,7 @@ public void PresentItems( Contract.ThrowIfNull(_signatureMap); var defaultValue = _signatureMap.GetValueOrDefault(_selectedItem); - if (_editorSessionOpt != null) - { - _editorSessionOpt.SelectedSignature = defaultValue; - } + _editorSessionOpt?.SelectedSignature = defaultValue; } finally { diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs index aa5f7030fb9f9..7090b5e0b51a7 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs @@ -166,10 +166,7 @@ internal static void EnableOptions( internal static void EnableOption(ImmutableArray options, string id) { var option = options.FirstOrDefault(o => o.Id == id); - if (option != null) - { - option.Value = true; - } + option?.Value = true; } internal Task TestWithPickMembersDialogAsync( diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb index c6d15c0d97abb..97c02854545a2 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb @@ -254,6 +254,66 @@ class var { } Await TestAPIAndFeature(input, kind, host) End Function + + + Public Async Function TestNamedType_TypeOfOperator_Name(kind As TestKind, host As TestHost) As Task + Dim input = + + + + class {|Definition:Celsius|} + { + public {|Definition:Celsius|}() + { + System.Type t = typeof({|ValueUsageInfo.Name:[|$$Celsius|]|}); + } + } + + + + Await TestAPIAndFeature(input, kind, host) + End Function + + + + Public Async Function TestNamedType_SizeOfOperator_Name(kind As TestKind, host As TestHost) As Task + Dim input = + + + + class {|Definition:Celsius|} + { + public {|Definition:Celsius|}() + { + int t = sizeof({|ValueUsageInfo.Name:[|$$Celsius|]|}); + } + } + + + + Await TestAPIAndFeature(input, kind, host) + End Function + + + + Public Async Function TestNamedType_NameOfOperator_Name(kind As TestKind, host As TestHost) As Task + Dim input = + + + + class {|Definition:Celsius|} + { + public {|Definition:Celsius|}() + { + string t = nameof({|ValueUsageInfo.Name:[|$$Celsius|]|}); + } + } + + + + Await TestAPIAndFeature(input, kind, host) + End Function + Public Async Function TestNamedType_InaccessibleType(kind As TestKind, host As TestHost) As Task diff --git a/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs index c6a60c70f0202..4e02d3fe20834 100644 --- a/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs @@ -20,7 +20,6 @@ using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.InitializeParameter; -using Microsoft.CodeAnalysis.Shared.Collections; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Naming; using Roslyn.Utilities; @@ -73,11 +72,18 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false); var fieldOrProperty = TryFindMatchingUninitializedFieldOrPropertySymbol(); - var refactorings = fieldOrProperty == null - ? HandleNoExistingFieldOrProperty() - : HandleExistingFieldOrProperty(); + using var refactorings = TemporaryArray.Empty; + if (fieldOrProperty != null) + { + // Found a field/property that this parameter should be assigned to. Just offer the simple assignment to it. + refactorings.Add(CreateCodeAction( + string.Format(fieldOrProperty.Kind == SymbolKind.Field ? FeaturesResources.Initialize_field_0 : FeaturesResources.Initialize_property_0, fieldOrProperty.Name), + cancellationToken => AddAssignmentForPrimaryConstructorAsync(document, parameter, fieldOrProperty, cancellationToken))); + } + + AddCreateFieldOrPropertyCodeActions(); - context.RegisterRefactorings(refactorings.ToImmutableArray(), context.Span); + context.RegisterRefactorings(refactorings.ToImmutableAndClear(), context.Span); return; ISymbol? TryFindMatchingUninitializedFieldOrPropertySymbol() @@ -133,15 +139,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte static CodeAction CreateCodeAction(string title, Func> createSolution) => CodeAction.Create(title, createSolution, title); - IEnumerable HandleExistingFieldOrProperty() - { - // Found a field/property that this parameter should be assigned to. Just offer the simple assignment to it. - yield return CreateCodeAction( - string.Format(fieldOrProperty.Kind == SymbolKind.Field ? FeaturesResources.Initialize_field_0 : FeaturesResources.Initialize_property_0, fieldOrProperty.Name), - cancellationToken => AddAssignmentForPrimaryConstructorAsync(document, parameter, fieldOrProperty, cancellationToken)); - } - - IEnumerable HandleNoExistingFieldOrProperty() + void AddCreateFieldOrPropertyCodeActions() { // Didn't find a field/prop that this parameter could be assigned to. Offer to create new one and assign to that. @@ -159,8 +157,8 @@ IEnumerable HandleNoExistingFieldOrProperty() string.Format(FeaturesResources.Create_and_assign_property_0, property.Name), cancellationToken => AddMultipleMembersAsync(document, typeDeclaration, [parameter], [property], cancellationToken)); - yield return siblingFieldOrProperty is IFieldSymbol ? fieldAction : propertyAction; - yield return siblingFieldOrProperty is IFieldSymbol ? propertyAction : fieldAction; + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? fieldAction : propertyAction); + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? propertyAction : fieldAction); var parameters = GetParametersWithoutAssociatedMembers(); if (parameters.Length >= 2) @@ -172,8 +170,8 @@ IEnumerable HandleNoExistingFieldOrProperty() FeaturesResources.Create_and_assign_remaining_as_properties, cancellationToken => AddMultipleMembersAsync(document, typeDeclaration, parameters, parameters.SelectAsArray(CreateProperty), cancellationToken)); - yield return siblingFieldOrProperty is IFieldSymbol ? allFieldsAction : allPropertiesAction; - yield return siblingFieldOrProperty is IFieldSymbol ? allPropertiesAction : allFieldsAction; + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? allFieldsAction : allPropertiesAction); + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? allPropertiesAction : allFieldsAction); } } diff --git a/src/Features/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs b/src/Features/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs index 37992126de4dd..3263b9dcd5040 100644 --- a/src/Features/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs +++ b/src/Features/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs @@ -7,14 +7,16 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; +using Microsoft.CodeAnalysis.GenerateComparisonOperators; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeRefactoringVerifier< - Microsoft.CodeAnalysis.GenerateComparisonOperators.GenerateComparisonOperatorsCodeRefactoringProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.GenerateComparisonOperators; +using VerifyCS = CSharpCodeRefactoringVerifier< + GenerateComparisonOperatorsCodeRefactoringProvider>; + [UseExportProvider] [Trait(Traits.Feature, Traits.Features.CodeActionsGenerateComparisonOperators)] public sealed class GenerateComparisonOperatorsTests diff --git a/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs b/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs index bd8c52909be04..049fbf52bbe4c 100644 --- a/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs +++ b/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs @@ -102,10 +102,7 @@ private sealed class ChangeOptionValueOperation(bool selectedAll) : CodeActionOp public override void Apply(Workspace workspace, CancellationToken cancellationToken) { var service = workspace.Services.GetService(); - if (service != null) - { - service.GenerateOverrides = _selectedAll; - } + service?.GenerateOverrides = _selectedAll; } } } diff --git a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs index 0ebac83ad0f28..2309c81eb50e6 100644 --- a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs +++ b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.PooledObjects; @@ -100,7 +101,7 @@ private ImmutableArray GetActions( State state, CancellationToken cancellationToken) { - using var _ = ArrayBuilder.GetInstance(out var result); + using var result = TemporaryArray.Empty; var generateNewTypeInDialog = false; if (state.NamespaceToGenerateInOpt != null) diff --git a/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs b/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs index bdce9d78b0cae..a2a2490d683aa 100644 --- a/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs +++ b/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs @@ -77,10 +77,7 @@ public static async Task CreateQuickInfoItemAsync( if (groups.TryGetValue(SymbolDescriptionGroups.Documentation, out var docParts) && !docParts.IsDefaultOrEmpty) { AddSection(QuickInfoSectionKinds.DocumentationComments, docParts); - if (onTheFlyDocsInfo != null) - { - onTheFlyDocsInfo.HasComments = true; - } + onTheFlyDocsInfo?.HasComments = true; } if (options.QuickInfoOptions.ShowRemarksInQuickInfo && diff --git a/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs b/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs index ccd8de0608582..53ef252db13b6 100644 --- a/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs @@ -263,13 +263,10 @@ private async Task ReplaceReferencesAsync( editor.ReplaceNode(parent, parent.WithAdditionalAnnotations( ConflictAnnotation.Create(FeaturesResources.Property_referenced_implicitly))); } - else if (syntaxFacts.IsMemberInitializerNamedAssignmentIdentifier(parent)) - { - editor.ReplaceNode(parent, parent.WithAdditionalAnnotations( - ConflictAnnotation.Create(FeaturesResources.Property_reference_cannot_be_updated))); - } - else if (syntaxFacts.IsNameOfSubpattern(parent)) + else if (IsInNonUpdatableLocation(syntaxFacts, parent)) { + // If the property is in a location where it cannot be updated, then just + // replace it with a warning. editor.ReplaceNode(parent, parent.WithAdditionalAnnotations( ConflictAnnotation.Create(FeaturesResources.Property_reference_cannot_be_updated))); } @@ -284,6 +281,13 @@ await service.ReplaceReferenceAsync( } } } + + static bool IsInNonUpdatableLocation(ISyntaxFacts syntaxFacts, SyntaxNode parent) + { + return syntaxFacts.IsMemberInitializerNamedAssignmentIdentifier(parent) || + syntaxFacts.IsNameOfSubpattern(parent) || + syntaxFacts.IsInNamespaceOrTypeContext(parent); + } } private static async Task ReplaceDefinitionsWithMethodsAsync( diff --git a/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionTest_NoEditor.cs b/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionTest_NoEditor.cs index 887450a6e6f1a..12d8bd9c7eb01 100644 --- a/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionTest_NoEditor.cs +++ b/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionTest_NoEditor.cs @@ -174,10 +174,7 @@ internal static void EnableOptions( internal static void EnableOption(ImmutableArray options, string id) { var option = options.FirstOrDefault(o => o.Id == id); - if (option != null) - { - option.Value = true; - } + option?.Value = true; } internal Task TestWithPickMembersDialogAsync( diff --git a/src/Features/VisualBasicTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb b/src/Features/VisualBasicTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb index ba62265f778b2..fe7c9d8b76edf 100644 --- a/src/Features/VisualBasicTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb +++ b/src/Features/VisualBasicTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb @@ -8,7 +8,7 @@ Imports Microsoft.CodeAnalysis.ReplacePropertyWithMethods Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeActions.ReplacePropertyWithMethods - Public Class ReplacePropertyWithMethodsTests + Public NotInheritable Class ReplacePropertyWithMethodsTests Inherits AbstractVisualBasicCodeActionTest_NoEditor Protected Overrides Function CreateCodeRefactoringProvider(workspace As TestWorkspace, parameters As TestParameters) As CodeRefactoringProvider @@ -698,5 +698,24 @@ Class C End Sub End Class") End Function + + + Public Async Function TestPropertyNameReferencedInAsClause() As Task + Await TestInRegularAndScriptAsync( +"class C + property [||]Goo as Goo +end class", +"class C + Private _Goo As Goo + + Public Function GetGoo() As Goo + Return _Goo + End Function + + Public Sub SetGoo(AutoPropertyValue As Goo) + _Goo = AutoPropertyValue + End Sub +end class") + End Function End Class End Namespace diff --git a/src/RoslynAnalyzers/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/ResxGeneratorTests.cs b/src/RoslynAnalyzers/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/ResxGeneratorTests.cs index 7f723ad532d4e..55bea2fa656a9 100644 --- a/src/RoslynAnalyzers/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/ResxGeneratorTests.cs +++ b/src/RoslynAnalyzers/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/ResxGeneratorTests.cs @@ -5,860 +5,860 @@ using System.Threading.Tasks; using Xunit; using CSharpLanguageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion; -using VerifyCS = Microsoft.CodeAnalysis.ResxSourceGenerator.Test.CSharpSourceGeneratorVerifier; -using VerifyVB = Microsoft.CodeAnalysis.ResxSourceGenerator.Test.VisualBasicSourceGeneratorVerifier; -namespace Microsoft.CodeAnalysis.ResxSourceGenerator.Test +namespace Microsoft.CodeAnalysis.ResxSourceGenerator.Test; + +using VerifyCS = CSharpSourceGeneratorVerifier; +using VerifyVB = VisualBasicSourceGeneratorVerifier; + +public sealed class ResxGeneratorTests { - public class ResxGeneratorTests + private const string ResxHeader = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + """; + private const string ResxFooter = """ + + """; + + [Theory] + [InlineData(CSharpLanguageVersion.CSharp5, Skip = "Expression-bodied members are not supported in C# 5")] + [InlineData(CSharpLanguageVersion.CSharp6)] + [InlineData(CSharpLanguageVersion.CSharp7)] + [InlineData(CSharpLanguageVersion.CSharp8)] + [InlineData(CSharpLanguageVersion.CSharp9)] + public async Task SingleString_DefaultCSharpAsync(CSharpLanguageVersion languageVersion) { - private const string ResxHeader = """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - """; - private const string ResxFooter = """ - - """; - - [Theory] - [InlineData(CSharpLanguageVersion.CSharp5, Skip = "Expression-bodied members are not supported in C# 5")] - [InlineData(CSharpLanguageVersion.CSharp6)] - [InlineData(CSharpLanguageVersion.CSharp7)] - [InlineData(CSharpLanguageVersion.CSharp8)] - [InlineData(CSharpLanguageVersion.CSharp9)] - public async Task SingleString_DefaultCSharpAsync(CSharpLanguageVersion languageVersion) + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: languageVersion.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: languageVersion.ToString()) + LanguageVersion = languageVersion, + TestState = { - LanguageVersion = languageVersion, - TestState = - { - Sources = { "" }, - AdditionalFiles = { ("/0/Resources.resx", code) }, - }, - }.AddGeneratedSources().RunAsync(); - } + Sources = { "" }, + AdditionalFiles = { ("/0/Resources.resx", code) }, + }, + }.AddGeneratedSources().RunAsync(); + } - [Fact] - public async Task TwoResourcesSameName_DefaultCSharpAsync() + [Fact] + public async Task TwoResourcesSameName_DefaultCSharpAsync() + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test() { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test() + TestState = { - TestState = + Sources = { "" }, + AdditionalFiles = { - Sources = { "" }, - AdditionalFiles = - { - ("/0/First/Resources.resx", code), - ("/0/Second/Resources.resx", code), - }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - build_property.RootNamespace = TestProject - - [/0/First/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = First/ - - [/0/Second/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = Second/ - """), - }, + ("/0/First/Resources.resx", code), + ("/0/Second/Resources.resx", code), }, - }.AddGeneratedSources().RunAsync(); - } + AnalyzerConfigFiles = + { + ("/.globalconfig", $""" + is_global = true - [Fact] - public async Task TwoResourcesSameName_DefaultVisualBasicAsync() + build_property.RootNamespace = TestProject + + [/0/First/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = First/ + + [/0/Second/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = Second/ + """), + }, + }, + }.AddGeneratedSources().RunAsync(); + } + + [Fact] + public async Task TwoResourcesSameName_DefaultVisualBasicAsync() + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test() { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test() + TestState = { - TestState = + Sources = { "" }, + AdditionalFiles = { - Sources = { "" }, - AdditionalFiles = - { - ("/0/First/Resources.resx", code), - ("/0/Second/Resources.resx", code), - }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - build_property.RootNamespace = TestProject - - [/0/First/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = First/ - - [/0/Second/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = Second/ - """), - }, + ("/0/First/Resources.resx", code), + ("/0/Second/Resources.resx", code), + }, + AnalyzerConfigFiles = + { + ("/.globalconfig", $""" + is_global = true + + build_property.RootNamespace = TestProject + + [/0/First/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = First/ + + [/0/Second/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = Second/ + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Fact] - public async Task SingleString_DefaultVisualBasicAsync() + [Fact] + public async Task SingleString_DefaultVisualBasicAsync() + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test + TestState = { - TestState = - { - AdditionalFiles = { ("/0/Resources.resx", code) }, - }, - }.AddGeneratedSources().RunAsync(); - } + AdditionalFiles = { ("/0/Resources.resx", code) }, + }, + }.AddGeneratedSources().RunAsync(); + } - [Fact] - public async Task SingleString_DisableCodeGenAsync() + [Fact] + public async Task SingleString_DisableCodeGenAsync() + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test + TestState = { - TestState = + Sources = { "" }, + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - Sources = { "" }, - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", """ - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.GenerateSource = false - """), - }, + ("/.globalconfig", """ + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.GenerateSource = false + """), }, - }.RunAsync(); + }, + }.RunAsync(); - await new VerifyVB.Test + await new VerifyVB.Test + { + TestState = { - TestState = + Sources = { "" }, + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - Sources = { "" }, - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", """ - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.GenerateSource = false - """), - }, + ("/.globalconfig", """ + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.GenerateSource = false + """), }, - }.RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_RootNamespaceCSharpAsync(string rootNamespace) + }, + }.RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_RootNamespaceCSharpAsync(string rootNamespace) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: rootNamespace) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: rootNamespace) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - build_property.RootNamespace = {rootNamespace} - """), - }, + ("/.globalconfig", $""" + is_global = true + + build_property.RootNamespace = {rootNamespace} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_RootNamespaceVisualBasicAsync(string rootNamespace) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_RootNamespaceVisualBasicAsync(string rootNamespace) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: rootNamespace) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: rootNamespace) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - build_property.RootNamespace = {rootNamespace} - """), - }, + ("/.globalconfig", $""" + is_global = true + + build_property.RootNamespace = {rootNamespace} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_RelativeDirCSharpAsync(string relativeDir) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_RelativeDirCSharpAsync(string relativeDir) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: relativeDir) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: relativeDir) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = {relativeDir} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = {relativeDir} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_RelativeDirVisualBasicAsync(string relativeDir) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_RelativeDirVisualBasicAsync(string relativeDir) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: relativeDir) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: relativeDir) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = {relativeDir} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = {relativeDir} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_ClassNameCSharpAsync(string className) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_ClassNameCSharpAsync(string className) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: className) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: className) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.ClassName = {className} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.ClassName = {className} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_ClassNameVisualBasicAsync(string className) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_ClassNameVisualBasicAsync(string className) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: className) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: className) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.ClassName = {className} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.ClassName = {className} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_OmitGetResourceStringCSharpAsync(bool omitGetResourceString) - { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - var customGetResourceString = """ - #nullable enable - - namespace TestProject + [Theory] + [CombinatorialData] + public async Task SingleString_OmitGetResourceStringCSharpAsync(bool omitGetResourceString) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + var customGetResourceString = """ + #nullable enable + + namespace TestProject + { + internal static partial class Resources { - internal static partial class Resources - { - internal static string? GetResourceString(string resourceKey, string? defaultValue = null) => throw null!; - } + internal static string? GetResourceString(string resourceKey, string? defaultValue = null) => throw null!; } - """; + } + """; - await new VerifyCS.Test(identifier: omitGetResourceString.ToString()) + await new VerifyCS.Test(identifier: omitGetResourceString.ToString()) + { + TestState = { - TestState = + Sources = { omitGetResourceString ? customGetResourceString : "" }, + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - Sources = { omitGetResourceString ? customGetResourceString : "" }, - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.OmitGetResourceString = {(omitGetResourceString ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.OmitGetResourceString = {(omitGetResourceString ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_OmitGetResourceStringVisualBasicAsync(bool omitGetResourceString) + [Theory] + [CombinatorialData] + public async Task SingleString_OmitGetResourceStringVisualBasicAsync(bool omitGetResourceString) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + var customGetResourceString = """ + Namespace Global.TestProject + Friend Partial Class Resources + Friend Shared Function GetResourceString(resourceKey As String, Optional defaultValue As String = Nothing) + Return "" + End Function + End Class + End Namespace + """; + + await new VerifyVB.Test(identifier: omitGetResourceString.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - var customGetResourceString = """ - Namespace Global.TestProject - Friend Partial Class Resources - Friend Shared Function GetResourceString(resourceKey As String, Optional defaultValue As String = Nothing) - Return "" - End Function - End Class - End Namespace - """; - - await new VerifyVB.Test(identifier: omitGetResourceString.ToString()) + TestState = { - TestState = + Sources = { omitGetResourceString ? customGetResourceString : "" }, + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - Sources = { omitGetResourceString ? customGetResourceString : "" }, - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.OmitGetResourceString = {(omitGetResourceString ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.OmitGetResourceString = {(omitGetResourceString ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_AsConstantsCSharpAsync(bool asConstants) + [Theory] + [CombinatorialData] + public async Task SingleString_AsConstantsCSharpAsync(bool asConstants) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: asConstants.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: asConstants.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.AsConstants = {(asConstants ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.AsConstants = {(asConstants ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_AsConstantsVisualBasicAsync(bool asConstants) + [Theory] + [CombinatorialData] + public async Task SingleString_AsConstantsVisualBasicAsync(bool asConstants) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: asConstants.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: asConstants.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.AsConstants = {(asConstants ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.AsConstants = {(asConstants ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_IncludeDefaultValuesCSharpAsync(bool includeDefaultValues) + [Theory] + [CombinatorialData] + public async Task SingleString_IncludeDefaultValuesCSharpAsync(bool includeDefaultValues) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: includeDefaultValues.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: includeDefaultValues.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.IncludeDefaultValues = {(includeDefaultValues ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.IncludeDefaultValues = {(includeDefaultValues ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_IncludeDefaultValuesVisualBasicAsync(bool includeDefaultValues) + [Theory] + [CombinatorialData] + public async Task SingleString_IncludeDefaultValuesVisualBasicAsync(bool includeDefaultValues) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: includeDefaultValues.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: includeDefaultValues.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.IncludeDefaultValues = {(includeDefaultValues ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.IncludeDefaultValues = {(includeDefaultValues ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [CombinatorialData] - public async Task SingleString_EmitFormatMethodsCSharpAsync( - [CombinatorialValues("0", "x", "replacement")] string placeholder, - bool emitFormatMethods) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [CombinatorialData] + public async Task SingleString_EmitFormatMethodsCSharpAsync( + [CombinatorialValues("0", "x", "replacement")] string placeholder, + bool emitFormatMethods) + { + var code = ResxHeader + + $$""" + + value {{{placeholder}}} + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: $"{placeholder}_{emitFormatMethods}") { - var code = ResxHeader - + $$""" - - value {{{placeholder}}} - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: $"{placeholder}_{emitFormatMethods}") + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.EmitFormatMethods = {(emitFormatMethods ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.EmitFormatMethods = {(emitFormatMethods ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [InlineData(true, Skip = "Not yet supported")] - [InlineData(false)] - public async Task SingleString_EmitFormatMethodsVisualBasicAsync(bool emitFormatMethods) + [Theory] + [InlineData(true, Skip = "Not yet supported")] + [InlineData(false)] + public async Task SingleString_EmitFormatMethodsVisualBasicAsync(bool emitFormatMethods) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: emitFormatMethods.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: emitFormatMethods.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.EmitFormatMethods = {(emitFormatMethods ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.EmitFormatMethods = {(emitFormatMethods ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_PublicCSharpAsync(bool publicResource) + [Theory] + [CombinatorialData] + public async Task SingleString_PublicCSharpAsync(bool publicResource) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: publicResource.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: publicResource.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.Public = {(publicResource ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.Public = {(publicResource ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_PublicVisualBasicAsync(bool publicResource) + [Theory] + [CombinatorialData] + public async Task SingleString_PublicVisualBasicAsync(bool publicResource) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: publicResource.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: publicResource.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.Public = {(publicResource ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.Public = {(publicResource ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("CS1591")] - [InlineData("CS1591, IDE0010")] - [InlineData(" , CS1591, IDE0010 ")] - public async Task SingleString_NoWarnsCSharpAsync(string noWarn) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("CS1591")] + [InlineData("CS1591, IDE0010")] + [InlineData(" , CS1591, IDE0010 ")] + public async Task SingleString_NoWarnsCSharpAsync(string noWarn) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + var id = string.Join("_", noWarn.Replace(" ", "").Split(",", System.StringSplitOptions.TrimEntries | System.StringSplitOptions.RemoveEmptyEntries)); + + await new VerifyCS.Test(identifier: id) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - var id = string.Join("_", noWarn.Replace(" ", "").Split(",", System.StringSplitOptions.TrimEntries | System.StringSplitOptions.RemoveEmptyEntries)); - - await new VerifyCS.Test(identifier: id) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.NoWarn = {noWarn} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.NoWarn = {noWarn} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("CS1591")] - [InlineData("CS1591, IDE0010")] - [InlineData(" , CS1591, IDE0010 ")] - public async Task SingleString_NoWarnsVisualBasicAsync(string noWarn) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("CS1591")] + [InlineData("CS1591, IDE0010")] + [InlineData(" , CS1591, IDE0010 ")] + public async Task SingleString_NoWarnsVisualBasicAsync(string noWarn) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + var id = string.Join("_", noWarn.Replace(" ", "").Split(",", System.StringSplitOptions.TrimEntries | System.StringSplitOptions.RemoveEmptyEntries)); + + await new VerifyVB.Test(identifier: id) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - var id = string.Join("_", noWarn.Replace(" ", "").Split(",", System.StringSplitOptions.TrimEntries | System.StringSplitOptions.RemoveEmptyEntries)); - - await new VerifyVB.Test(identifier: id) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.NoWarn = {noWarn} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.NoWarn = {noWarn} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); } } diff --git a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/AvoidAllocationWithArrayEmptyCodeFixTests.cs b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/AvoidAllocationWithArrayEmptyCodeFixTests.cs index 59a0985f90ba1..8554fb4694795 100644 --- a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/AvoidAllocationWithArrayEmptyCodeFixTests.cs +++ b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/AvoidAllocationWithArrayEmptyCodeFixTests.cs @@ -3,513 +3,515 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.CodeFixes; using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.ExplicitAllocationAnalyzer, - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.CodeFixes.AvoidAllocationWithArrayEmptyCodeFix>; -namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests +namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + ExplicitAllocationAnalyzer, + AvoidAllocationWithArrayEmptyCodeFix>; + +public class AvoidAllocationWithArrayEmptyCodeFixTests { - public class AvoidAllocationWithArrayEmptyCodeFixTests - { - [Theory] - [InlineData("IEnumerable")] - [InlineData("IReadOnlyList")] - [InlineData("IReadOnlyCollection")] - public Task ShouldReplaceEmptyListCreationWithArrayEmptyWithReturnTypeAsync(string type) - => VerifyCS.VerifyCodeFixAsync($$""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + [Theory] + [InlineData("IEnumerable")] + [InlineData("IReadOnlyList")] + [InlineData("IReadOnlyCollection")] + public Task ShouldReplaceEmptyListCreationWithArrayEmptyWithReturnTypeAsync(string type) + => VerifyCS.VerifyCodeFixAsync($$""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public {{type}} DoSomething() { - [PerformanceSensitive("uri")] - public {{type}} DoSomething() - { - return new List(); - } + return new List(); } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 35), $$""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 35), $$""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public {{type}} DoSomething() { - [PerformanceSensitive("uri")] - public {{type}} DoSomething() - { - return Array.Empty(); - } + return Array.Empty(); } } - """); - - [Fact] - public Task ShouldReplaceEmptyListCreationWithArrayEmptyWhenReturnFromMethodArrayAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + + [Fact] + public Task ShouldReplaceEmptyListCreationWithArrayEmptyWhenReturnFromMethodArrayAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public int[] DoSomething() { - [PerformanceSensitive("uri")] - public int[] DoSomething() - { - return new int[0]; - } + return new int[0]; } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 30), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 30), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public int[] DoSomething() { - [PerformanceSensitive("uri")] - public int[] DoSomething() - { - return Array.Empty(); - } + return Array.Empty(); } } - """); - - [Fact] - public Task ShouldReplaceEmptyLisCreationWithArrayEmptyForArrowExpressionAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + + [Fact] + public Task ShouldReplaceEmptyLisCreationWithArrayEmptyForArrowExpressionAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass - { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething => new List(); - } + [PerformanceSensitive("uri")] + public IEnumerable DoSomething => new List(); } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(10, 48, 10, 63), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(10, 48, 10, 63), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass - { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething => Array.Empty(); - } + [PerformanceSensitive("uri")] + public IEnumerable DoSomething => Array.Empty(); } - """); - [Fact] - public Task ShouldReplaceEmptyListCreationWithArrayEmptyForReadonlyPropertyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public Task ShouldReplaceEmptyListCreationWithArrayEmptyForReadonlyPropertyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething { get {return new List();}} + } + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(10, 59, 10, 74), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass + { + [PerformanceSensitive("uri")] + public IEnumerable DoSomething { get {return Array.Empty();}} + } + } + """); + [Fact] + public Task ShouldReplaceEmptyListWithCreationWithPredefinedSizeWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass + { + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething { get {return new List();}} + return new List(10); } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(10, 59, 10, 74), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 37), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething { get {return Array.Empty();}} + return Array.Empty(); } } - """); - [Fact] - public Task ShouldReplaceEmptyListWithCreationWithPredefinedSizeWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public async Task ShouldNotProposeCodeFixWhenNonEmptyListCreatedAsync() + { + var code = """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new List(10); - } + return new List(){1, 2}; } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 37), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; + } + """; - namespace SampleNamespace + await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 41), code); + } + [Fact] + public async Task ShouldNotProposeCodeFixWhenReturnTypeInheritFormEnumerableAsync() + { + var code = """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public List DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return Array.Empty(); - } + return new List(); } } - """); - [Fact] - public async Task ShouldNotProposeCodeFixWhenNonEmptyListCreatedAsync() - { - var code = """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """; + + await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 35), code); + } + [Fact] + public async Task ShouldNotProposeCodeFixWhenForCollectionCreationUsingCopyConstructorAsync() + { + var code = """ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new List(){1, 2}; - } + var innerList = new List(){1, 2}; + return new ReadOnlyCollection(innerList); } } - """; - - await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 41), code); - } - [Fact] - public async Task ShouldNotProposeCodeFixWhenReturnTypeInheritFormEnumerableAsync() - { - var code = """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """; + + await VerifyCS.VerifyCodeFixAsync(code, + [ + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(13, 29, 13, 50), + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(14, 20, 14, 58), + ], code); + } + [Fact] + public Task ShouldReplacEmptyCollectionCreationWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public List DoSomething() - { - return new List(); - } + return new Collection(); } } - """; - - await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 35), code); - } - [Fact] - public async Task ShouldNotProposeCodeFixWhenForCollectionCreationUsingCopyConstructorAsync() - { - var code = """ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(13, 20, 13, 41), """ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - var innerList = new List(){1, 2}; - return new ReadOnlyCollection(innerList); - } + return Array.Empty(); } } - """; - - await VerifyCS.VerifyCodeFixAsync(code, - [ - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(13, 29, 13, 50), - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(14, 20, 14, 58), - ], code); - } - [Fact] - public Task ShouldReplacEmptyCollectionCreationWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public Task ShouldReplaceEmptyArrayCreationWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new Collection(); - } + return new int[0]; } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(13, 20, 13, 41), """ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 30), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return Array.Empty(); - } + return Array.Empty(); } } - """); - [Fact] - public Task ShouldReplaceEmptyArrayCreationWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public async Task ShouldNotProposeCodeFixWhenNonEmptyArrayCreationAsync() + { + var code = """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new int[0]; - } + return new int[]{1, 2}; } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 30), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; + } + """; - namespace SampleNamespace + await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 35), code); + } + [Fact] + public Task ShouldReplaceEmptyArrayCreationWithInitBlockWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return Array.Empty(); - } + return new int[] { }; } } - """); - [Fact] - public async Task ShouldNotProposeCodeFixWhenNonEmptyArrayCreationAsync() - { - var code = """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 33), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new int[]{1, 2}; - } + return Array.Empty(); } } - """; - - await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 35), code); - } - [Fact] - public Task ShouldReplaceEmptyArrayCreationWithInitBlockWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public Task ShouldReplaceListCreationAsMethodInvocationParameterWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new int[] { }; - } + Do(new List()); } - } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 33), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - namespace SampleNamespace - { - class SampleClass + private void Do(IEnumerable a) { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return Array.Empty(); - } + } } - """); - [Fact] - public Task ShouldReplaceListCreationAsMethodInvocationParameterWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 16, 12, 31), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething() { - [PerformanceSensitive("uri")] - public void DoSomething() - { - Do(new List()); - } - - private void Do(IEnumerable a) - { - - } + Do(Array.Empty()); } - } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 16, 12, 31), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - namespace SampleNamespace - { - class SampleClass + private void Do(IEnumerable a) { - [PerformanceSensitive("uri")] - public void DoSomething() - { - Do(Array.Empty()); - } - private void Do(IEnumerable a) - { - - } } } - """); - [Fact] - public Task ShouldReplaceArrayCreationAsMethodInvocationParameterWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public Task ShouldReplaceArrayCreationAsMethodInvocationParameterWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething() { - [PerformanceSensitive("uri")] - public void DoSomething() - { - Do(new int[0]); - } + Do(new int[0]); + } - private void Do(IEnumerable a) - { + private void Do(IEnumerable a) + { - } } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 16, 12, 26), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 16, 12, 26), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething() { - [PerformanceSensitive("uri")] - public void DoSomething() - { - Do(Array.Empty()); - } + Do(Array.Empty()); + } - private void Do(IEnumerable a) - { + private void Do(IEnumerable a) + { - } } } - """); - [Fact] - public Task ShouldReplaceArrayCreationAsDelegateInvocationParameterWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public Task ShouldReplaceArrayCreationAsDelegateInvocationParameterWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething(Action> doSth) { - [PerformanceSensitive("uri")] - public void DoSomething(Action> doSth) - { - doSth(new int[0]); - } + doSth(new int[0]); } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 19, 12, 29), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 19, 12, 29), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething(Action> doSth) { - [PerformanceSensitive("uri")] - public void DoSomething(Action> doSth) - { - doSth(Array.Empty()); - } + doSth(Array.Empty()); } } - """); - } + } + """); } diff --git a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/CallSiteImplicitAllocationAnalyzerTests.cs b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/CallSiteImplicitAllocationAnalyzerTests.cs index bf22e1b99b7bb..5ed9549069443 100644 --- a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/CallSiteImplicitAllocationAnalyzerTests.cs +++ b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/CallSiteImplicitAllocationAnalyzerTests.cs @@ -4,203 +4,204 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.CallSiteImplicitAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -namespace Microsoft.CodeAnalysisPerformanceSensitiveAnalyzers.UnitTests +namespace Microsoft.CodeAnalysisPerformanceSensitiveAnalyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + CallSiteImplicitAllocationAnalyzer, + EmptyCodeFixProvider>; + +public sealed class CallSiteImplicitAllocationAnalyzerTests { - public class CallSiteImplicitAllocationAnalyzerTests - { - [Fact] - public Task CallSiteImplicitAllocation_ParamAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + [Fact] + public Task CallSiteImplicitAllocation_ParamAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Params(); //no allocation, because compiler will implicitly substitute Array.Empty() - Params(1, 2); - Params(new [] { 1, 2}); // explicit, so no warning - ParamsWithObjects(new [] { 1, 2}); // explicit, but converted to objects, so stil la warning?! + Params(); //no allocation, because compiler will implicitly substitute Array.Empty() + Params(1, 2); + Params(new [] { 1, 2}); // explicit, so no warning + ParamsWithObjects(new [] { 1, 2}); // explicit, but converted to objects, so stil la warning?! - // Only 4 args and above use the params overload of String.Format - var test = String.Format("Testing {0}, {1}, {2}, {3}", 1, "blah", 2.0m, 'c'); - } + // Only 4 args and above use the params overload of String.Format + var test = String.Format("Testing {0}, {1}, {2}, {3}", 1, "blah", 2.0m, 'c'); + } - public void Params(params int[] args) - { - } + public void Params(params int[] args) + { + } - public void ParamsWithObjects(params object[] args) - { - } + public void ParamsWithObjects(params object[] args) + { } - """, - // Test0.cs(11,9): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation + } + """, + // Test0.cs(11,9): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(11, 9), + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(11, 9), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(13,9): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation + // Test0.cs(13,9): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(13, 9), + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(13, 9), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(16,20): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation + // Test0.cs(16,20): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(16, 20)); - - [Fact, WorkItem(3272, "https://github.com/dotnet/roslyn-analyzers/issues/3272")] - public Task EmptyParamsWithNetFramework45Async() - => new VerifyCS.Test + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(16, 20)); + + [Fact, WorkItem(3272, "https://github.com/dotnet/roslyn-analyzers/issues/3272")] + public Task EmptyParamsWithNetFramework45Async() + => new VerifyCS.Test + { + ReferenceAssemblies = ReferenceAssemblies.NetFramework.Net45.Default, + TestState = { - ReferenceAssemblies = ReferenceAssemblies.NetFramework.Net45.Default, - TestState = + Sources = { - Sources = + """ + using System; + using Roslyn.Utilities; + + public class MyClass { - """ - using System; - using Roslyn.Utilities; + [PerformanceSensitive("uri")] + public void Testing() + { + Params(); // allocation + } - public class MyClass + public void Params(params int[] args) { - [PerformanceSensitive("uri")] - public void Testing() - { - Params(); // allocation - } - - public void Params(params int[] args) - { - } } - """, - ("PerformanceSensitiveAttribute.cs", VerifyCS.PerformanceSensitiveAttributeSource) - }, - ExpectedDiagnostics = - { + } + """, + ("PerformanceSensitiveAttribute.cs", VerifyCS.PerformanceSensitiveAttributeSource) + }, + ExpectedDiagnostics = + { #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(9, 9), + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(9, 9), #pragma warning restore RS0030 // Do not use banned APIs - }, }, - }.RunAsync(); + }, + }.RunAsync(); - [Fact] - public Task CallSiteImplicitAllocation_NonOverridenMethodOnStructAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task CallSiteImplicitAllocation_NonOverridenMethodOnStructAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var normal = new Normal().GetHashCode(); - var overridden = new OverrideToHashCode().GetHashCode(); - } + var normal = new Normal().GetHashCode(); + var overridden = new OverrideToHashCode().GetHashCode(); } + } - public struct Normal - { - } + public struct Normal + { + } - public struct OverrideToHashCode + public struct OverrideToHashCode + { + public override int GetHashCode() { - public override int GetHashCode() - { - return -1; - } + return -1; } - """, - // Test0.cs(10,22): warning HAA0102: Non-overridden virtual method call on a value type adds a boxing or constrained instruction + } + """, + // Test0.cs(10,22): warning HAA0102: Non-overridden virtual method call on a value type adds a boxing or constrained instruction #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ValueTypeNonOverridenCallRule).WithLocation(9, 22)); + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ValueTypeNonOverridenCallRule).WithLocation(9, 22)); - [Fact] - public Task CallSiteImplicitAllocation_DoNotReportNonOverriddenMethodCallForStaticCallsAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task CallSiteImplicitAllocation_DoNotReportNonOverriddenMethodCallForStaticCallsAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var t = System.Enum.GetUnderlyingType(typeof(System.StringComparison)); - } + var t = System.Enum.GetUnderlyingType(typeof(System.StringComparison)); } - """); + } + """); - [Fact] - public Task CallSiteImplicitAllocation_DoNotReportNonOverriddenMethodCallForNonVirtualCallsAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.IO; - using Roslyn.Utilities; + [Fact] + public Task CallSiteImplicitAllocation_DoNotReportNonOverriddenMethodCallForNonVirtualCallsAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.IO; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - FileAttributes attr = FileAttributes.System; - attr.HasFlag (FileAttributes.Directory); - } + FileAttributes attr = FileAttributes.System; + attr.HasFlag (FileAttributes.Directory); } - """); + } + """); - [Fact] - public Task ParamsIsPrecededByOptionalParametersAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.IO; - using Roslyn.Utilities; + [Fact] + public Task ParamsIsPrecededByOptionalParametersAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.IO; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + void Fun1() { - [PerformanceSensitive("uri")] - void Fun1() - { - Fun2(); - {|#0:Fun2(args: "", i: 5)|}; - } + Fun2(); + {|#0:Fun2(args: "", i: 5)|}; + } - void Fun2(int i = 0, params object[] args) - { - } + void Fun2(int i = 0, params object[] args) + { } - """, - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(0)); + } + """, + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(0)); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Calling_non_overridden_virtual_methods_on_value_typesAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Calling_non_overridden_virtual_methods_on_value_typesAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - enum E { A } + enum E { A } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - E.A.GetHashCode(); - } + E.A.GetHashCode(); } - """, - // Test0.cs(12,9): warning HAA0102: Non-overridden virtual method call on a value type adds a boxing or constrained instruction + } + """, + // Test0.cs(12,9): warning HAA0102: Non-overridden virtual method call on a value type adds a boxing or constrained instruction #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ValueTypeNonOverridenCallRule).WithLocation(11, 9)); - } + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ValueTypeNonOverridenCallRule).WithLocation(11, 9)); } diff --git a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ConcatenationAllocationAnalyzerTests.cs b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ConcatenationAllocationAnalyzerTests.cs index 98e7c045bd135..680e1420ebbcb 100644 --- a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ConcatenationAllocationAnalyzerTests.cs +++ b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ConcatenationAllocationAnalyzerTests.cs @@ -4,110 +4,111 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.ConcatenationAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -namespace Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests +namespace Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + ConcatenationAllocationAnalyzer, + EmptyCodeFixProvider>; + +public sealed class ConcatenationAllocationAnalyzerTests { - public class ConcatenationAllocationAnalyzerTests - { - [Fact] - public Task ConcatenationAllocation_Basic1Async() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task ConcatenationAllocation_Basic1Async() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - string s0 = "hello" + 0.ToString() + "world" + 1.ToString(); - } + string s0 = "hello" + 0.ToString() + "world" + 1.ToString(); } - """); + } + """); - [Fact] - public Task ConcatenationAllocation_Basic2Async() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task ConcatenationAllocation_Basic2Async() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - string s2 = "ohell" + 2.ToString() + "world" + 3.ToString() + 4.ToString(); - } + string s2 = "ohell" + 2.ToString() + "world" + 3.ToString() + 4.ToString(); } - """, - // Test0.cs(9,21): warning HAA0201: Considering using StringBuilder + } + """, + // Test0.cs(9,21): warning HAA0201: Considering using StringBuilder #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ConcatenationAllocationAnalyzer.StringConcatenationAllocationRule).WithLocation(9, 21)); + VerifyCS.Diagnostic(ConcatenationAllocationAnalyzer.StringConcatenationAllocationRule).WithLocation(9, 21)); - [Theory] - [InlineData("string s0 = nameof(System.String) + '-';")] - [InlineData("string s0 = nameof(System.String) + true;")] - [InlineData("string s0 = nameof(System.String) + new System.IntPtr();")] - [InlineData("string s0 = nameof(System.String) + new System.UIntPtr();")] - public Task ConcatenationAllocation_DoNotWarnForOptimizedValueTypesAsync(string statement) - => VerifyCS.VerifyAnalyzerAsync($$""" - using System; - using Roslyn.Utilities; + [Theory] + [InlineData("string s0 = nameof(System.String) + '-';")] + [InlineData("string s0 = nameof(System.String) + true;")] + [InlineData("string s0 = nameof(System.String) + new System.IntPtr();")] + [InlineData("string s0 = nameof(System.String) + new System.UIntPtr();")] + public Task ConcatenationAllocation_DoNotWarnForOptimizedValueTypesAsync(string statement) + => VerifyCS.VerifyAnalyzerAsync($$""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - {{statement}} - } + {{statement}} } - """); + } + """); - [Theory] - [InlineData(@"const string s0 = nameof(System.String) + ""."" + nameof(System.String);")] - [InlineData(@"const string s0 = nameof(System.String) + ""."";")] - [InlineData(@"string s0 = nameof(System.String) + ""."" + nameof(System.String);")] - [InlineData(@"string s0 = nameof(System.String) + ""."";")] - public Task ConcatenationAllocation_DoNotWarnForConstAsync(string statement) - => VerifyCS.VerifyAnalyzerAsync($$""" - using System; - using Roslyn.Utilities; + [Theory] + [InlineData(@"const string s0 = nameof(System.String) + ""."" + nameof(System.String);")] + [InlineData(@"const string s0 = nameof(System.String) + ""."";")] + [InlineData(@"string s0 = nameof(System.String) + ""."" + nameof(System.String);")] + [InlineData(@"string s0 = nameof(System.String) + ""."";")] + public Task ConcatenationAllocation_DoNotWarnForConstAsync(string statement) + => VerifyCS.VerifyAnalyzerAsync($$""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - {{statement}} - } + {{statement}} } - """); + } + """); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Non_constant_value_types_in_CSharp_string_concatenationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Non_constant_value_types_in_CSharp_string_concatenationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - System.DateTime c = System.DateTime.Now; - string s1 = "char value will box" + c; - } + System.DateTime c = System.DateTime.Now; + string s1 = "char value will box" + c; } - """, - // Test0.cs(11,45): warning HAA0202: Value type (System.DateTime) is being boxed to a reference type for a string concatenation. + } + """, + // Test0.cs(11,45): warning HAA0202: Value type (System.DateTime) is being boxed to a reference type for a string concatenation. #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ConcatenationAllocationAnalyzer.ValueTypeToReferenceTypeInAStringConcatenationRule).WithLocation(10, 45).WithArguments("System.DateTime")); - } + VerifyCS.Diagnostic(ConcatenationAllocationAnalyzer.ValueTypeToReferenceTypeInAStringConcatenationRule).WithLocation(10, 45).WithArguments("System.DateTime")); } diff --git a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/DisplayClassAllocationAnalyzerTests.cs b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/DisplayClassAllocationAnalyzerTests.cs index 62f1fae06db9a..8c0f431e85aa6 100644 --- a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/DisplayClassAllocationAnalyzerTests.cs +++ b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/DisplayClassAllocationAnalyzerTests.cs @@ -4,164 +4,166 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; +using Microsoft.CodeAnalysis.Testing; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.DisplayClassAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests +namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + DisplayClassAllocationAnalyzer, + EmptyCodeFixProvider>; + +public sealed class DisplayClassAllocationAnalyzerTests { - public class DisplayClassAllocationAnalyzerTests - { - [Fact] - public Task DisplayClassAllocation_AnonymousMethodExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - class Test + [Fact] + public Task DisplayClassAllocation_AnonymousMethodExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + class Test + { + static void Main() { - static void Main() - { - Action action = CreateAction(5); - } + Action action = CreateAction(5); + } - [PerformanceSensitive("uri")] - static Action CreateAction(T item) + [PerformanceSensitive("uri")] + static Action CreateAction(T item) + { + T test = default(T); + int counter = 0; + return delegate { - T test = default(T); - int counter = 0; - return delegate - { - counter++; - Console.WriteLine("counter={0}", counter); - }; - } + counter++; + Console.WriteLine("counter={0}", counter); + }; } - """, - // Test0.cs(15,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure + } + """, + // Test0.cs(15,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(15, 13), + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(15, 13), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(16,16): warning HAA0303: Considering moving this out of the generic method + // Test0.cs(16,16): warning HAA0303: Considering moving this out of the generic method #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.LambaOrAnonymousMethodInGenericMethodRule).WithLocation(16, 16), + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.LambaOrAnonymousMethodInGenericMethodRule).WithLocation(16, 16), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(16,16): warning HAA0301: Heap allocation of closure Captures: counter + // Test0.cs(16,16): warning HAA0301: Heap allocation of closure Captures: counter #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(16, 16).WithArguments("counter")); + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(16, 16).WithArguments("counter")); - [Fact] - public Task DisplayClassAllocation_SimpleLambdaExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System; - using System.Linq; - using Roslyn.Utilities; + [Fact] + public Task DisplayClassAllocation_SimpleLambdaExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System; + using System.Linq; + using Roslyn.Utilities; - public class Testing + public class Testing + { + [PerformanceSensitive("uri")] + public Testing() { - [PerformanceSensitive("uri")] - public Testing() - { - int[] intData = new[] { 123, 32, 4 }; - int min = 31; - var results = intData.Where(i => i > min).ToList(); - } + int[] intData = new[] { 123, 32, 4 }; + int min = 31; + var results = intData.Where(i => i > min).ToList(); } - """, - // Test0.cs(12,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure + } + """, + // Test0.cs(12,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(12, 13), + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(12, 13), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(13,39): warning HAA0301: Heap allocation of closure Captures: min + // Test0.cs(13,39): warning HAA0301: Heap allocation of closure Captures: min #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(13, 39).WithArguments("min")); + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(13, 39).WithArguments("min")); - [Fact] - public Task DisplayClassAllocation_ParenthesizedLambdaExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System; - using System.Linq; - using Roslyn.Utilities; + [Fact] + public Task DisplayClassAllocation_ParenthesizedLambdaExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System; + using System.Linq; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() + var words = new[] { "aaaa", "bbbb", "cccc", "ddd" }; + var actions = new List(); + foreach (string word in words) // <-- captured closure { - var words = new[] { "aaaa", "bbbb", "cccc", "ddd" }; - var actions = new List(); - foreach (string word in words) // <-- captured closure - { - actions.Add(() => Console.WriteLine(word)); // <-- reason for closure capture - } + actions.Add(() => Console.WriteLine(word)); // <-- reason for closure capture } } - """, - // Test0.cs(13,25): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure + } + """, + // Test0.cs(13,25): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(13, 25), + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(13, 25), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(15,28): warning HAA0301: Heap allocation of closure Captures: word + // Test0.cs(15,28): warning HAA0301: Heap allocation of closure Captures: word #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(15, 28).WithArguments("word")); + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(15, 28).WithArguments("word")); - [Fact] - public Task DisplayClassAllocation_DoNotReportForNonCapturingAnonymousMethodAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task DisplayClassAllocation_DoNotReportForNonCapturingAnonymousMethodAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Sorter(int[] arr) { - [PerformanceSensitive("uri")] - public void Sorter(int[] arr) - { - System.Array.Sort(arr, delegate(int x, int y) { return x - y; }); - } + System.Array.Sort(arr, delegate(int x, int y) { return x - y; }); } - """); + } + """); - [Fact] - public Task DisplayClassAllocation_DoNotReportForNonCapturingLambdaAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task DisplayClassAllocation_DoNotReportForNonCapturingLambdaAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Sorter(int[] arr) { - [PerformanceSensitive("uri")] - public void Sorter(int[] arr) - { - System.Array.Sort(arr, (x, y) => x - y); - } + System.Array.Sort(arr, (x, y) => x - y); } - """); + } + """); - [Fact] - public Task DisplayClassAllocation_ReportForCapturingAnonymousMethodAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task DisplayClassAllocation_ReportForCapturingAnonymousMethodAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Sorter(int[] arr) { - [PerformanceSensitive("uri")] - public void Sorter(int[] arr) - { - int z = 2; - System.Array.Sort(arr, delegate(int x, int y) { return x - z; }); - } + int z = 2; + System.Array.Sort(arr, delegate(int x, int y) { return x - z; }); } - """, - // Test0.cs(9,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure + } + """, + // Test0.cs(9,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(9, 13), + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(9, 13), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(10,32): warning HAA0301: Heap allocation of closure Captures: z + // Test0.cs(10,32): warning HAA0301: Heap allocation of closure Captures: z #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(10, 32).WithArguments("z")); - } + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(10, 32).WithArguments("z")); } diff --git a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/EnumeratorAllocationAnalyzerTests.cs b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/EnumeratorAllocationAnalyzerTests.cs index c79909c88626e..eb8a5092ffa0c 100644 --- a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/EnumeratorAllocationAnalyzerTests.cs +++ b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/EnumeratorAllocationAnalyzerTests.cs @@ -3,152 +3,155 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; +using Microsoft.CodeAnalysis.Testing; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.EnumeratorAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests +namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + EnumeratorAllocationAnalyzer, + EmptyCodeFixProvider>; + +public sealed class EnumeratorAllocationAnalyzerTests { - public class EnumeratorAllocationAnalyzerTests - { - [Fact] - public Task EnumeratorAllocation_BasicAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System; - using System.Linq; - using Roslyn.Utilities; - - public class MyClass + [Fact] + public Task EnumeratorAllocation_BasicAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System; + using System.Linq; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() + int[] intData = new[] { 123, 32, 4 }; + IList iListData = new[] { 123, 32, 4 }; + List listData = new[] { 123, 32, 4 }.ToList(); + + foreach (var i in intData) { - int[] intData = new[] { 123, 32, 4 }; - IList iListData = new[] { 123, 32, 4 }; - List listData = new[] { 123, 32, 4 }.ToList(); - - foreach (var i in intData) - { - Console.WriteLine(i); - } - - foreach (var i in listData) - { - Console.WriteLine(i); - } - - foreach (var i in iListData) // Allocations (line 19) - { - Console.WriteLine(i); - } - - foreach (var i in (IEnumerable)intData) // Allocations (line 24) - { - Console.WriteLine(i); - } + Console.WriteLine(i); + } + + foreach (var i in listData) + { + Console.WriteLine(i); } - } - """, - // Test0.cs(25,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation -#pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic().WithLocation(25, 24), -#pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(30,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation -#pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic().WithLocation(30, 24)); - [Fact] - public Task EnumeratorAllocation_AdvancedAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System; - using Roslyn.Utilities; + foreach (var i in iListData) // Allocations (line 19) + { + Console.WriteLine(i); + } - public class MyClass - { - [PerformanceSensitive("uri")] - public void SomeMethod() + foreach (var i in (IEnumerable)intData) // Allocations (line 24) { - // These next 3 are from the YouTube video - foreach (object a in new[] { 1, 2, 3}) // Allocations 'new [] { 1. 2, 3}' - { - Console.WriteLine(a.ToString()); - } - - IEnumerable fx1 = default(IEnumerable); - foreach (var f in fx1) // Allocations 'in' - { - } - - List fx2 = default(List); - foreach (var f in fx2) // NO Allocations - { - } + Console.WriteLine(i); } } - """, - // Test0.cs(17,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation + } + """, + // Test0.cs(25,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic().WithLocation(17, 24)); - - [Fact] - public Task EnumeratorAllocation_Via_InvocationExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System.Collections; - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyCS.Diagnostic().WithLocation(25, 24), +#pragma warning restore RS0030 // Do not use banned APIs + // Test0.cs(30,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation +#pragma warning disable RS0030 // Do not use banned APIs + VerifyCS.Diagnostic().WithLocation(30, 24)); + + [Fact] + public Task EnumeratorAllocation_AdvancedAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() + // These next 3 are from the YouTube video + foreach (object a in new[] { 1, 2, 3}) // Allocations 'new [] { 1. 2, 3}' { - var enumeratorRaw = GetIEnumerableRaw(); - while (enumeratorRaw.MoveNext()) - { - Console.WriteLine(enumeratorRaw.Current.ToString()); - } - - var enumeratorRawViaIEnumerable = GetIEnumeratorViaIEnumerable(); - while (enumeratorRawViaIEnumerable.MoveNext()) - { - Console.WriteLine(enumeratorRawViaIEnumerable.Current.ToString()); - } + Console.WriteLine(a.ToString()); } - private IEnumerator GetIEnumerableRaw() + IEnumerable fx1 = default(IEnumerable); + foreach (var f in fx1) // Allocations 'in' { - return new[] { 123, 32, 4 }.GetEnumerator(); } - private IEnumerator GetIEnumeratorViaIEnumerable() + List fx2 = default(List); + foreach (var f in fx2) // NO Allocations { - int[] intData = new[] { 123, 32, 4 }; - return (IEnumerator)intData.GetEnumerator(); } } - """, - // Test0.cs(17,43): warning HAA0401: Non-ValueType enumerator may result in a heap allocation + } + """, + // Test0.cs(17,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic().WithLocation(17, 43)); - - [Fact] - public Task EnumeratorAllocation_IterateOverString_NoWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyCS.Diagnostic().WithLocation(17, 24)); + + [Fact] + public Task EnumeratorAllocation_Via_InvocationExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System.Collections; + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() + var enumeratorRaw = GetIEnumerableRaw(); + while (enumeratorRaw.MoveNext()) + { + Console.WriteLine(enumeratorRaw.Current.ToString()); + } + + var enumeratorRawViaIEnumerable = GetIEnumeratorViaIEnumerable(); + while (enumeratorRawViaIEnumerable.MoveNext()) { - foreach (char c in "aaa") { }; + Console.WriteLine(enumeratorRawViaIEnumerable.Current.ToString()); } } - """); - } + + private IEnumerator GetIEnumerableRaw() + { + return new[] { 123, 32, 4 }.GetEnumerator(); + } + + private IEnumerator GetIEnumeratorViaIEnumerable() + { + int[] intData = new[] { 123, 32, 4 }; + return (IEnumerator)intData.GetEnumerator(); + } + } + """, + // Test0.cs(17,43): warning HAA0401: Non-ValueType enumerator may result in a heap allocation +#pragma warning disable RS0030 // Do not use banned APIs + VerifyCS.Diagnostic().WithLocation(17, 43)); + + [Fact] + public Task EnumeratorAllocation_IterateOverString_NoWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() + { + foreach (char c in "aaa") { }; + } + } + """); } diff --git a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ExplicitAllocationAnalyzerTests.cs b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ExplicitAllocationAnalyzerTests.cs index 1879859818011..208e5874c6fa7 100644 --- a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ExplicitAllocationAnalyzerTests.cs +++ b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ExplicitAllocationAnalyzerTests.cs @@ -4,755 +4,757 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; +using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.ExplicitAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -using VerifyVB = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.VisualBasicPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.ExplicitAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; - -namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests -{ - public class ExplicitAllocationAnalyzerTests - { - [Fact] - public Task ExplicitAllocation_ObjectInitializerAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass - { - [PerformanceSensitive("uri")] - public void Testing() - { - var @class = new TestClass { Name = "Bob" }; - } - } - public class TestClass - { - public string Name { get; set; } - } - """, -#pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 22)); - - [Fact] - public Task ExplicitAllocation_ObjectInitializer_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync( - """ - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim instance = New TestClass With {.Name = "Bob"} - End Sub - End Class - - Public Class TestClass - Public Property Name As String - End Class - """, -#pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 24)); +namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests; - [Fact] - public Task ExplicitAllocation_ObjectInitializerStruct_NoWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; +using VerifyCS = CSharpPerformanceCodeFixVerifier< + ExplicitAllocationAnalyzer, + EmptyCodeFixProvider>; +using VerifyVB = VisualBasicPerformanceCodeFixVerifier< + ExplicitAllocationAnalyzer, + EmptyCodeFixProvider>; - public class MyClass +public sealed class ExplicitAllocationAnalyzerTests +{ + [Fact] + public Task ExplicitAllocation_ObjectInitializerAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var @struct = new TestStruct { Name = "Bob" }; - } + var @class = new TestClass { Name = "Bob" }; } + } - public struct TestStruct + public class TestClass + { + public string Name { get; set; } + } + """, +#pragma warning disable RS0030 // Do not use banned APIs + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 22)); + + [Fact] + public Task ExplicitAllocation_ObjectInitializer_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync( + """ + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim instance = New TestClass With {.Name = "Bob"} + End Sub + End Class + + Public Class TestClass + Public Property Name As String + End Class + """, +#pragma warning disable RS0030 // Do not use banned APIs + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 24)); + + [Fact] + public Task ExplicitAllocation_ObjectInitializerStruct_NoWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - public string Name { get; set; } + var @struct = new TestStruct { Name = "Bob" }; } - """); - - [Fact] - public Task ExplicitAllocation_ObjectInitializerStruct_NoWarning_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim instance = New TestClass With {.Name = "Bob"} - End Sub - End Class - - Public Structure TestClass - Public Property Name As String - End Structure - """); - - [Fact] - public Task ExplicitAllocation_ImplicitArrayCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using Roslyn.Utilities; - - public class MyClass + } + + public struct TestStruct + { + public string Name { get; set; } + } + """); + + [Fact] + public Task ExplicitAllocation_ObjectInitializerStruct_NoWarning_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim instance = New TestClass With {.Name = "Bob"} + End Sub + End Class + + Public Structure TestClass + Public Property Name As String + End Structure + """); + + [Fact] + public Task ExplicitAllocation_ImplicitArrayCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - int[] intData = new[] { 123, 32, 4 }; - } + int[] intData = new[] { 123, 32, 4 }; } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(9, 25)); - - [Fact] - public Task ExplicitAllocation_ImplicitArrayCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System.Collections.Generic - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim intData() As Integer = {123, 32, 4} - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(9, 25)); + + [Fact] + public Task ExplicitAllocation_ImplicitArrayCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System.Collections.Generic + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim intData() As Integer = {123, 32, 4} + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(7, 36)); - - [Fact] - public Task ExplicitAllocation_AnonymousObjectCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(7, 36)); + + [Fact] + public Task ExplicitAllocation_AnonymousObjectCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var temp = new { A = 123, Name = "Test", }; - } + var temp = new { A = 123, Name = "Test", }; } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.AnonymousObjectCreationRule).WithLocation(9, 20)); - - [Fact] - public Task ExplicitAllocation_AnonymousObjectCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim temp = New With {Key .B = 123, .Name = "Test"} - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.AnonymousObjectCreationRule).WithLocation(9, 20)); + + [Fact] + public Task ExplicitAllocation_AnonymousObjectCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim temp = New With {Key .B = 123, .Name = "Test"} + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.AnonymousObjectCreationRule).WithLocation(7, 20)); - - [Fact] - public Task ExplicitAllocation_ArrayCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.AnonymousObjectCreationRule).WithLocation(7, 20)); + + [Fact] + public Task ExplicitAllocation_ArrayCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - int[] intData = new int[] { 123, 32, 4 }; - } + int[] intData = new int[] { 123, 32, 4 }; } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(9, 25)); - - [Fact] - public Task ExplicitAllocation_ArrayCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System.Collections.Generic - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim intData = New Integer() {123, 32, 4} - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(9, 25)); + + [Fact] + public Task ExplicitAllocation_ArrayCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System.Collections.Generic + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim intData = New Integer() {123, 32, 4} + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(7, 23)); - - [Fact] - public Task ExplicitAllocation_ObjectCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(7, 23)); + + [Fact] + public Task ExplicitAllocation_ObjectCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var allocation = new String('a', 10); - } + var allocation = new String('a', 10); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 26)); - - [Fact] - public Task ExplicitAllocation_ObjectCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim allocation = New String("a"c, 10) - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 26)); + + [Fact] + public Task ExplicitAllocation_ObjectCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim allocation = New String("a"c, 10) + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 26)); - - [Fact] - public Task ExplicitAllocation_LetClauseAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System.Linq; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 26)); + + [Fact] + public Task ExplicitAllocation_LetClauseAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System.Linq; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - int[] intData = new[] { 123, 32, 4 }; - var result = (from a in intData - let b = a * 3 - select b).ToList(); - } + int[] intData = new[] { 123, 32, 4 }; + var result = (from a in intData + let b = a * 3 + select b).ToList(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(10, 25), + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(10, 25), #pragma warning restore RS0030 // Do not use banned APIs #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.LetCauseRule).WithLocation(12, 23)); - - [Fact] - public Task ExplicitAllocation_LetClause_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System.Collections.Generic - Imports System.Linq - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim intData() As Integer = {123, 32, 4} - Dim result = (From x In intData - Let b = x * 3 - Select b).ToList() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.LetCauseRule).WithLocation(12, 23)); + + [Fact] + public Task ExplicitAllocation_LetClause_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System.Collections.Generic + Imports System.Linq + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim intData() As Integer = {123, 32, 4} + Dim result = (From x In intData + Let b = x * 3 + Select b).ToList() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(8, 36), + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(8, 36), #pragma warning restore RS0030 // Do not use banned APIs #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.LetCauseRule).WithLocation(10, 27)); + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.LetCauseRule).WithLocation(10, 27)); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_to_System_Object_typeAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_to_System_Object_typeAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using Roslyn.Utilities; - public struct S { } + public struct S { } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - object box = new S(); - } + object box = new S(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 22)); - - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_to_System_Object_type_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports Roslyn.Utilities - - Public Structure S - End Structure - - Public Class A - - Public Sub SomeMethod() - Dim box As Object = new S() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 22)); + + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_to_System_Object_type_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports Roslyn.Utilities + + Public Structure S + End Structure + + Public Class A + + Public Sub SomeMethod() + Dim box As Object = new S() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 29)); + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 29)); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_to_System_ValueType_typeAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_to_System_ValueType_typeAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using Roslyn.Utilities; - public struct S { } + public struct S { } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - System.ValueType box = new S(); - } + System.ValueType box = new S(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 32)); - - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_to_System_ValueType_type_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports Roslyn.Utilities - - Public Structure S - End Structure - - Public Class A - - Public Sub SomeMethod() - Dim box As System.ValueType = new S() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 32)); + + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_to_System_ValueType_type_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports Roslyn.Utilities + + Public Structure S + End Structure + + Public Class A + + Public Sub SomeMethod() + Dim box As System.ValueType = new S() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 39)); + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 39)); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_into_interface_referenceAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_into_interface_referenceAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using Roslyn.Utilities; - interface I { } + interface I { } - public struct S : I { } + public struct S : I { } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - I box = new S(); - } + I box = new S(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(12, 17)); - - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_into_interface_reference_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports Roslyn.Utilities - - Interface I - End Interface - - Public Structure S - Implements I - End Structure - - Public Class A - - Public Sub SomeMethod() - Dim box As I = new S() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(12, 17)); + + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_into_interface_reference_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports Roslyn.Utilities + + Interface I + End Interface + + Public Structure S + Implements I + End Structure + + Public Class A + + Public Sub SomeMethod() + Dim box As I = new S() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(13, 24)); + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(13, 24)); - [Fact] - public Task ExplicitAllocation_StructCreation_NoWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task ExplicitAllocation_StructCreation_NoWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public struct S { } + public struct S { } - public class MyClass - { + public class MyClass + { - [PerformanceSensitive("uri")] - public void Testing() - { - var noBox1 = new DateTime(); - S noBox2 = new S(); - } - } - """); - - [Fact] - public Task ExplicitAllocation_StructCreation_NoWarning_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Structure S - End Structure - - Public Class A - - Public Sub Testing() - Dim noBox1 = new DateTime() - Dim noBox2 As S = new S() - End Sub - End Class - """); - - [Fact] - public Task ExplicitAllocation_PrimitiveTypeConversion_NoWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - double x = new int(); - } + var noBox1 = new DateTime(); + S noBox2 = new S(); } - """); - - [Fact] - public Task ExplicitAllocation_PrimitiveTypeConversion_NoWarning_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim x As Double = New Integer() - End Sub - End Class - """); - - [Fact] - public Task ExplicitAllocation_ImplicitValueTypeConversion_NoWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - struct A + } + """); + + [Fact] + public Task ExplicitAllocation_StructCreation_NoWarning_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Structure S + End Structure + + Public Class A + + Public Sub Testing() + Dim noBox1 = new DateTime() + Dim noBox2 As S = new S() + End Sub + End Class + """); + + [Fact] + public Task ExplicitAllocation_PrimitiveTypeConversion_NoWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - public static implicit operator A(B other) - { - return new A(); - } + double x = new int(); } - - struct B + } + """); + + [Fact] + public Task ExplicitAllocation_PrimitiveTypeConversion_NoWarning_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim x As Double = New Integer() + End Sub + End Class + """); + + [Fact] + public Task ExplicitAllocation_ImplicitValueTypeConversion_NoWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + struct A + { + public static implicit operator A(B other) { + return new A(); } + } - public class MyClass + struct B + { + } + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - A a = new B(); - } + A a = new B(); } - """); - - [Fact] - public Task ExplicitAllocation_ImplicitValueTypeConversion_NoWarning_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Structure A - Public Shared Widening Operator CType(other As B) As A - Return New A() - End Operator - End Structure - - Structure B - End Structure - - Public Class C - - Public Sub Testing() - Dim a As A = New B() - End Sub - End Class - """); - - [Fact] - public Task ExplicitAllocation_NoParamsArrayCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using Roslyn.Utilities; - - public class MyClass + } + """); + + [Fact] + public Task ExplicitAllocation_ImplicitValueTypeConversion_NoWarning_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Structure A + Public Shared Widening Operator CType(other As B) As A + Return New A() + End Operator + End Structure + + Structure B + End Structure + + Public Class C + + Public Sub Testing() + Dim a As A = New B() + End Sub + End Class + """); + + [Fact] + public Task ExplicitAllocation_NoParamsArrayCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing(params int[] values) { - [PerformanceSensitive("uri")] - public void Testing(params int[] values) - { - Testing(); - } + Testing(); } - """); - - [Fact] - public Task ExplicitAllocation_NoParamsArrayCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System.Collections.Generic - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(ParamArray values() As Integer) - Testing() - End Sub - End Class - """); - - [Fact] - public Task ExplicitAllocation_ExplicitDelegateCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + } + """); + + [Fact] + public Task ExplicitAllocation_NoParamsArrayCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System.Collections.Generic + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(ParamArray values() As Integer) + Testing() + End Sub + End Class + """); + + [Fact] + public Task ExplicitAllocation_ExplicitDelegateCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing(object sender, EventArgs e) { - [PerformanceSensitive("uri")] - public void Testing(object sender, EventArgs e) - { - var handler = new EventHandler(Testing); - } + var handler = new EventHandler(Testing); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 23)); - - [Fact] - public Task ExplicitAllocation_ExplicitDelegateCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(sender As Object, e As EventArgs) - Dim handler = new EventHandler(AddressOf Testing) - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 23)); + + [Fact] + public Task ExplicitAllocation_ExplicitDelegateCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(sender As Object, e As EventArgs) + Dim handler = new EventHandler(AddressOf Testing) + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 23)); - - [Fact] - public Task ExplicitAllocation_ImplicitDelegateCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 23)); + + [Fact] + public Task ExplicitAllocation_ImplicitDelegateCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing(object sender, EventArgs e) { - [PerformanceSensitive("uri")] - public void Testing(object sender, EventArgs e) - { - EventHandler handler = Testing; - } + EventHandler handler = Testing; } - """); - - [Fact] - public Task ExplicitAllocation_ImplicitDelegateCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(sender As Object, e As EventArgs) - Dim handler As EventHandler = AddressOf Testing - End Sub - End Class - """); - - [Fact] - public Task ExplicitAllocation_ListInitializerCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using Roslyn.Utilities; - - public class MyClass + } + """); + + [Fact] + public Task ExplicitAllocation_ImplicitDelegateCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(sender As Object, e As EventArgs) + Dim handler As EventHandler = AddressOf Testing + End Sub + End Class + """); + + [Fact] + public Task ExplicitAllocation_ListInitializerCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var intData = new List { 3, 4 }; - } + var intData = new List { 3, 4 }; } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 23)); - - [Fact] - public Task ExplicitAllocation_ListInitializerCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System.Collections.Generic - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim intData = New List(Of Integer) From {3, 4} - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 23)); + + [Fact] + public Task ExplicitAllocation_ListInitializerCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System.Collections.Generic + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim intData = New List(Of Integer) From {3, 4} + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 23)); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 23)); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() + where T : class, new() { - [PerformanceSensitive("uri")] - public void Testing() - where T : class, new() - { - var allocation = new T(); - } + var allocation = new T(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 26)); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(Of T As {Class, New})() - Dim allocation = New T() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 26)); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(Of T As {Class, New})() + Dim allocation = New T() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 26)); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreation2Async() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 26)); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreation2Async() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() + where T : struct { - [PerformanceSensitive("uri")] - public void Testing() - where T : struct - { - object allocation = new T(); - } + object allocation = new T(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 29)); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreation2_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(Of T As Structure)() - Dim allocation As Object = New T() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 29)); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreation2_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(Of T As Structure)() + Dim allocation As Object = New T() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 36)); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreation3Async() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 36)); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreation3Async() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() + where T : struct { - [PerformanceSensitive("uri")] - public void Testing() - where T : struct - { - T value = new T(); - } + T value = new T(); } - """); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreation3_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(Of T As Structure)() - Dim value As T = new T() - End Sub - End Class - """); - } + } + """); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreation3_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(Of T As Structure)() + Dim value As T = new T() + End Sub + End Class + """); } diff --git a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/TypeConversionAllocationAnalyzerTests.cs b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/TypeConversionAllocationAnalyzerTests.cs index 331dceb982819..39c7bd518870d 100644 --- a/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/TypeConversionAllocationAnalyzerTests.cs +++ b/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/TypeConversionAllocationAnalyzerTests.cs @@ -4,810 +4,812 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; +using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.TypeConversionAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests +namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + TypeConversionAllocationAnalyzer, + EmptyCodeFixProvider>; + +public sealed class TypeConversionAllocationAnalyzerTests { - public class TypeConversionAllocationAnalyzerTests - { - [Fact] - public Task TypeConversionAllocation_ArgumentSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_ArgumentSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyObject + public class MyObject + { + public MyObject(object obj) { - public MyObject(object obj) - { - } + } - private void ObjCall(object obj) - { - } + private void ObjCall(object obj) + { + } - [PerformanceSensitive("uri")] - public void SomeMethod() - { - ObjCall(10); // Allocation - _ = new MyObject(10); // Allocation - } + [PerformanceSensitive("uri")] + public void SomeMethod() + { + ObjCall(10); // Allocation + _ = new MyObject(10); // Allocation } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(17, 17), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(17, 17), #pragma warning restore RS0030 // Do not use banned APIs #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(18, 26) + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(18, 26) #pragma warning restore RS0030 // Do not use banned APIs - ); + ); - [Fact] - public Task TypeConversionAllocation_ArgumentSyntax_WithDelegatesAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_ArgumentSyntax_WithDelegatesAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var @class = new MyClass(); - @class.ProcessFunc(someObjCall); // implicit, so Allocation - @class.ProcessFunc(new Func(someObjCall)); // Explicit, so NO Allocation - } + var @class = new MyClass(); + @class.ProcessFunc(someObjCall); // implicit, so Allocation + @class.ProcessFunc(new Func(someObjCall)); // Explicit, so NO Allocation + } - public void ProcessFunc(Func func) - { - } + public void ProcessFunc(Func func) + { + } - private string someObjCall(object obj) => null; + private string someObjCall(object obj) => null; + } + + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() + { + var @struct = new MyStruct(); + @struct.ProcessFunc(someObjCall); // implicit allocation + boxing + @struct.ProcessFunc(new Func(someObjCall)); // Explicit allocation + boxing } - public struct MyStruct + public void ProcessFunc(Func func) { - [PerformanceSensitive("uri")] - public void Testing() - { - var @struct = new MyStruct(); - @struct.ProcessFunc(someObjCall); // implicit allocation + boxing - @struct.ProcessFunc(new Func(someObjCall)); // Explicit allocation + boxing - } + } - public void ProcessFunc(Func func) - { - } + private string someObjCall(object obj) => null; + } + """, + // Test0.cs(10,28): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(10, 28, 10, 39), + // Test0.cs(27,29): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(27, 29, 27, 40), + // Test0.cs(27,29): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(27, 29, 27, 40), + // Test0.cs(28,54): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(28, 54, 28, 65)); - private string someObjCall(object obj) => null; - } - """, - // Test0.cs(10,28): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(10, 28, 10, 39), - // Test0.cs(27,29): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(27, 29, 27, 40), - // Test0.cs(27,29): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(27, 29, 27, 40), - // Test0.cs(28,54): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(28, 54, 28, 65)); - - [Fact] - public Task TypeConversionAllocation_ReturnStatementSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyObject - { - public Object Obj1 - { - [PerformanceSensitive("uri")] - get { return 0; } - } + [Fact] + public Task TypeConversionAllocation_ReturnStatementSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + public class MyObject + { + public Object Obj1 + { [PerformanceSensitive("uri")] - public Object Obj2 - { - get { return 0; } - } + get { return 0; } + } + + [PerformanceSensitive("uri")] + public Object Obj2 + { + get { return 0; } } - """, - // Test0.cs(9,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(9,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 22), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 22), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(15,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + // Test0.cs(15,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(15, 22)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(15, 22)); - [Fact] - public Task TypeConversionAllocation_ReturnStatementSyntax_NoAllocAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_ReturnStatementSyntax_NoAllocAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyObject + public class MyObject + { + [PerformanceSensitive("uri")] + public Object ObjNoAllocation1 { get { return 0.ToString(); } } + + public Object ObjNoAllocation2 { [PerformanceSensitive("uri")] - public Object ObjNoAllocation1 { get { return 0.ToString(); } } - - public Object ObjNoAllocation2 - { - [PerformanceSensitive("uri")] - get { return 0.ToString(); } - } + get { return 0.ToString(); } } - """); + } + """); - [Fact] - public Task TypeConversionAllocation_YieldStatementSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_YieldStatementSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + public void SomeMethod() { - public void SomeMethod() + foreach (var item in GetItems()) { - foreach (var item in GetItems()) - { - } - - foreach (var item in GetItemsNoAllocation()) - { - } } - [PerformanceSensitive("uri")] - public IEnumerable GetItems() + foreach (var item in GetItemsNoAllocation()) { - yield return 0; // Allocation - yield break; } + } - [PerformanceSensitive("uri")] - public IEnumerable GetItemsNoAllocation() - { - yield return 0; // NO Allocation (IEnumerable) - yield break; - } + [PerformanceSensitive("uri")] + public IEnumerable GetItems() + { + yield return 0; // Allocation + yield break; + } + + [PerformanceSensitive("uri")] + public IEnumerable GetItemsNoAllocation() + { + yield return 0; // NO Allocation (IEnumerable) + yield break; } - """, - // Test0.cs(21,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(21,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(21, 22)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(21, 22)); - [Fact] - public Task TypeConversionAllocation_BinaryExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_BinaryExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - object x = "blah"; - object a1 = x ?? 0; // Allocation - object a2 = x ?? 0.ToString(); // No Allocation + object x = "blah"; + object a1 = x ?? 0; // Allocation + object a2 = x ?? 0.ToString(); // No Allocation - var b1 = 10 as object; // Allocation - var b2 = 10.ToString() as object; // No Allocation - } + var b1 = 10 as object; // Allocation + var b2 = 10.ToString() as object; // No Allocation } - """, - // Test0.cs(10,26): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(10,26): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 26), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 26), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(13,18): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + // Test0.cs(13,18): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(13, 18)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(13, 18)); - [Fact] - public Task TypeConversionAllocation_BinaryExpressionSyntax_WithDelegatesAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_BinaryExpressionSyntax_WithDelegatesAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Func temp = null; - var result1 = temp ?? someObjCall; // implicit, so Allocation - var result2 = temp ?? new Func(someObjCall); // Explicit, so NO Allocation - } + Func temp = null; + var result1 = temp ?? someObjCall; // implicit, so Allocation + var result2 = temp ?? new Func(someObjCall); // Explicit, so NO Allocation + } - private string someObjCall(object obj) - { - return obj.ToString(); - } + private string someObjCall(object obj) + { + return obj.ToString(); } + } - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Func temp = null; - var result1 = temp ?? someObjCall; // implicit allocation + boxing - var result2 = temp ?? new Func(someObjCall); // Explicit allocation + boxing - } + Func temp = null; + var result1 = temp ?? someObjCall; // implicit allocation + boxing + var result2 = temp ?? new Func(someObjCall); // Explicit allocation + boxing + } - private string someObjCall(object obj) - { - return obj.ToString(); - } + private string someObjCall(object obj) + { + return obj.ToString(); } - """, - // Test0.cs(10,31): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(10, 31, 10, 42), - // Test0.cs(26,31): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(26, 31, 26, 42), - // Test0.cs(26,31): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(26, 31, 26, 42), - // Test0.cs(27,56): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(27, 56, 27, 67)); + } + """, + // Test0.cs(10,31): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(10, 31, 10, 42), + // Test0.cs(26,31): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(26, 31, 26, 42), + // Test0.cs(26,31): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(26, 31, 26, 42), + // Test0.cs(27,56): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(27, 56, 27, 67)); - [Fact] - public Task TypeConversionAllocation_EqualsValueClauseSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_EqualsValueClauseSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() + for (object i = 0;;) // Allocation { - for (object i = 0;;) // Allocation - { - } + } - for (int i = 0;;) // NO Allocation - { - } + for (int i = 0;;) // NO Allocation + { } } - """, - // Test0.cs(9,25): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(9,25): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 25)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 25)); - [Fact] - public Task TypeConversionAllocation_EqualsValueClauseSyntax_WithDelegatesAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_EqualsValueClauseSyntax_WithDelegatesAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Func func2 = someObjCall; // implicit, so Allocation - Func func1 = new Func(someObjCall); // Explicit, so NO Allocation - } + Func func2 = someObjCall; // implicit, so Allocation + Func func1 = new Func(someObjCall); // Explicit, so NO Allocation + } - private string someObjCall(object obj) - { - return obj.ToString(); - } + private string someObjCall(object obj) + { + return obj.ToString(); } + } - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Func func2 = someObjCall; // implicit allocation + boxing - Func func1 = new Func(someObjCall); // Explicit allocation + boxing - } + Func func2 = someObjCall; // implicit allocation + boxing + Func func1 = new Func(someObjCall); // Explicit allocation + boxing + } - private string someObjCall(object obj) - { - return obj.ToString(); - } + private string someObjCall(object obj) + { + return obj.ToString(); } - """, - // Test0.cs(9,38): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(9, 38, 9, 49), - // Test0.cs(24,38): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(24, 38, 24, 49), - // Test0.cs(24,38): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(24, 38, 24, 49), - // Test0.cs(25,63): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(25, 63, 25, 74)); - - [Fact] - [WorkItem(2, "https://github.com/mjsabby/RoslynClrHeapAllocationAnalyzer/issues/2")] - public Task TypeConversionAllocation_EqualsValueClause_ExplicitMethodGroupAllocation_BugAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + } + """, + // Test0.cs(9,38): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(9, 38, 9, 49), + // Test0.cs(24,38): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(24, 38, 24, 49), + // Test0.cs(24,38): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(24, 38, 24, 49), + // Test0.cs(25,63): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(25, 63, 25, 74)); + + [Fact] + [WorkItem(2, "https://github.com/mjsabby/RoslynClrHeapAllocationAnalyzer/issues/2")] + public Task TypeConversionAllocation_EqualsValueClause_ExplicitMethodGroupAllocation_BugAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Action methodGroup = this.Method; - } + Action methodGroup = this.Method; + } - private void Method() - { - } + private void Method() + { } + } - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Action methodGroup = this.Method; - } + Action methodGroup = this.Method; + } - private void Method() - { - } + private void Method() + { } - """, - // Test0.cs(9,30): warning HAA0603: This will allocate a delegate instance + } + """, + // Test0.cs(9,30): warning HAA0603: This will allocate a delegate instance #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(9, 30), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(9, 30), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(22,30): warning HAA0603: This will allocate a delegate instance + // Test0.cs(22,30): warning HAA0603: This will allocate a delegate instance #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(22, 30), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(22, 30), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(22,30): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + // Test0.cs(22,30): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithLocation(22, 30)); - - [Fact] - public Task TypeConversionAllocation_ConditionalExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass - { - [PerformanceSensitive("uri")] - public void Testing() - { - object obj = "test"; - object test1 = true ? 0 : obj; // Allocation - object test2 = true ? 0.ToString() : obj; // NO Allocation - } - } - """, - // Test0.cs(10,31): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithLocation(22, 30)); + + [Fact] + public Task TypeConversionAllocation_ConditionalExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() + { + object obj = "test"; + object test1 = true ? 0 : obj; // Allocation + object test2 = true ? 0.ToString() : obj; // NO Allocation + } + } + """, + // Test0.cs(10,31): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 31)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 31)); - [Fact] - public Task TypeConversionAllocation_CastExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_CastExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var f1 = (object)5; // Allocation - var f2 = (object)"5"; // NO Allocation - } + var f1 = (object)5; // Allocation + var f2 = (object)"5"; // NO Allocation } - """, - // Test0.cs(9,26): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(9,26): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 26)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 26)); - [Fact] - public async Task TypeConversionAllocation_ArgumentWithImplicitStringCastOperatorAsync() - { - const string programWithoutImplicitCastOperator = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_ArgumentWithImplicitStringCastOperatorAsync() + { + const string programWithoutImplicitCastOperator = """ + using System; + using Roslyn.Utilities; - public struct AStruct + public struct AStruct + { + [PerformanceSensitive("uri")] + public static void Dump(AStruct astruct) { - [PerformanceSensitive("uri")] - public static void Dump(AStruct astruct) - { - System.Console.WriteLine(astruct); - } + System.Console.WriteLine(astruct); } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(programWithoutImplicitCastOperator, - // Test0.cs(10,34): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + await VerifyCS.VerifyAnalyzerAsync(programWithoutImplicitCastOperator, + // Test0.cs(10,34): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 34)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 34)); #pragma warning restore RS0030 // Do not use banned APIs - const string programWithImplicitCastOperator = """ - using System; - using Roslyn.Utilities; + const string programWithImplicitCastOperator = """ + using System; + using Roslyn.Utilities; - public struct AStruct - { - public readonly string WrappedString; + public struct AStruct + { + public readonly string WrappedString; - public AStruct(string s) - { - WrappedString = s ?? ""; - } + public AStruct(string s) + { + WrappedString = s ?? ""; + } - [PerformanceSensitive("uri")] - public static void Dump(AStruct astruct) - { - System.Console.WriteLine(astruct); - } + [PerformanceSensitive("uri")] + public static void Dump(AStruct astruct) + { + System.Console.WriteLine(astruct); + } - [PerformanceSensitive("uri")] - public static implicit operator string(AStruct astruct) - { - return astruct.WrappedString; - } + [PerformanceSensitive("uri")] + public static implicit operator string(AStruct astruct) + { + return astruct.WrappedString; } - """; - await VerifyCS.VerifyAnalyzerAsync(programWithImplicitCastOperator); - } + } + """; + await VerifyCS.VerifyAnalyzerAsync(programWithImplicitCastOperator); + } - [Fact] - public async Task TypeConversionAllocation_YieldReturnImplicitStringCastOperatorAsync() - { - const string programWithoutImplicitCastOperator = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_YieldReturnImplicitStringCastOperatorAsync() + { + const string programWithoutImplicitCastOperator = """ + using System; + using Roslyn.Utilities; - public struct AStruct + public struct AStruct + { + [PerformanceSensitive("uri")] + public System.Collections.Generic.IEnumerator GetEnumerator() { - [PerformanceSensitive("uri")] - public System.Collections.Generic.IEnumerator GetEnumerator() - { - yield return this; - } + yield return this; } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(programWithoutImplicitCastOperator, - // Test0.cs(10,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + await VerifyCS.VerifyAnalyzerAsync(programWithoutImplicitCastOperator, + // Test0.cs(10,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 22)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 22)); #pragma warning restore RS0030 // Do not use banned APIs - const string programWithImplicitCastOperator = """ - using System; - using Roslyn.Utilities; + const string programWithImplicitCastOperator = """ + using System; + using Roslyn.Utilities; - public struct AStruct + public struct AStruct + { + [PerformanceSensitive("uri")] + public System.Collections.Generic.IEnumerator GetEnumerator() { - [PerformanceSensitive("uri")] - public System.Collections.Generic.IEnumerator GetEnumerator() - { - yield return this; - } + yield return this; + } - public static implicit operator string(AStruct astruct) - { - return ""; - } + public static implicit operator string(AStruct astruct) + { + return ""; } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(programWithImplicitCastOperator); - } + await VerifyCS.VerifyAnalyzerAsync(programWithImplicitCastOperator); + } - [Fact] - public Task TypeConversionAllocation_InterpolatedStringWithInt_BoxingWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_InterpolatedStringWithInt_BoxingWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - class Program + class Program + { + [PerformanceSensitive("uri")] + void SomeMethod() { - [PerformanceSensitive("uri")] - void SomeMethod() - { - string s = $"{1}"; - } + string s = $"{1}"; } - """, - // Test0.cs(10,23): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(10,23): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 23)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 23)); #if false - [Fact] - public void TypeConversionAllocation_InterpolatedStringWithString_NoWarning() - { - var sampleProgram = @"string s = $""{1.ToString()}"";"; + [Fact] + public void TypeConversionAllocation_InterpolatedStringWithString_NoWarning() + { + var sampleProgram = @"string s = $""{1.ToString()}"";"; - var analyser = new TypeConversionAllocationAnalyzer(); - var info = ProcessCode(analyser, sampleProgram, ImmutableArray.Create(SyntaxKind.Interpolation)); + var analyser = new TypeConversionAllocationAnalyzer(); + var info = ProcessCode(analyser, sampleProgram, ImmutableArray.Create(SyntaxKind.Interpolation)); - Assert.Empty(info.Allocations); - } + Assert.Empty(info.Allocations); + } #endif - [Theory] - [InlineData(@"private readonly System.Func fileExists = System.IO.File.Exists;")] - [InlineData(@"private System.Func fileExists { get; } = System.IO.File.Exists;")] - [InlineData(@"private static System.Func fileExists { get; } = System.IO.File.Exists;")] - [InlineData(@"private static readonly System.Func fileExists = System.IO.File.Exists;")] - public Task TypeConversionAllocation_DelegateAssignmentToReadonly_DoNotWarnAsync(string snippet) - => VerifyCS.VerifyAnalyzerAsync($$""" - using System; - using Roslyn.Utilities; - - class Program - { - [PerformanceSensitive("uri")] - {{snippet}} - } - """, - // Test0.cs(8,68): info HeapAnalyzerReadonlyMethodGroupAllocationRule: This will allocate a delegate instance + [Theory] + [InlineData(@"private readonly System.Func fileExists = System.IO.File.Exists;")] + [InlineData(@"private System.Func fileExists { get; } = System.IO.File.Exists;")] + [InlineData(@"private static System.Func fileExists { get; } = System.IO.File.Exists;")] + [InlineData(@"private static readonly System.Func fileExists = System.IO.File.Exists;")] + public Task TypeConversionAllocation_DelegateAssignmentToReadonly_DoNotWarnAsync(string snippet) + => VerifyCS.VerifyAnalyzerAsync($$""" + using System; + using Roslyn.Utilities; + + class Program + { + [PerformanceSensitive("uri")] + {{snippet}} + } + """, + // Test0.cs(8,68): info HeapAnalyzerReadonlyMethodGroupAllocationRule: This will allocate a delegate instance #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ReadonlyMethodGroupAllocationRule).WithLocation(7, 68)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ReadonlyMethodGroupAllocationRule).WithLocation(7, 68)); - [Fact] - public async Task TypeConversionAllocation_ExpressionBodiedPropertyBoxing_WithBoxingAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; - - class Program - { - [PerformanceSensitive("uri")] - object Obj => 1; - } - """; - - await VerifyCS.VerifyAnalyzerAsync(snippet, - // Test0.cs(8,19): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + [Fact] + public async Task TypeConversionAllocation_ExpressionBodiedPropertyBoxing_WithBoxingAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; + + class Program + { + [PerformanceSensitive("uri")] + object Obj => 1; + } + """; + + await VerifyCS.VerifyAnalyzerAsync(snippet, + // Test0.cs(8,19): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(7, 19)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(7, 19)); #pragma warning restore RS0030 // Do not use banned APIs - } - - [Fact] - public async Task TypeConversionAllocation_ExpressionBodiedPropertyBoxing_WithoutBoxingAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; - - class Program - { - [PerformanceSensitive("uri")] - object Obj => 1.ToString(); - } - """; + } - await VerifyCS.VerifyAnalyzerAsync(snippet); - } + [Fact] + public async Task TypeConversionAllocation_ExpressionBodiedPropertyBoxing_WithoutBoxingAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; + + class Program + { + [PerformanceSensitive("uri")] + object Obj => 1.ToString(); + } + """; + + await VerifyCS.VerifyAnalyzerAsync(snippet); + } - [Fact] - public async Task TypeConversionAllocation_ExpressionBodiedPropertyDelegateAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_ExpressionBodiedPropertyDelegateAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; - class Program - { - void Function(int i) { } + class Program + { + void Function(int i) { } - [PerformanceSensitive("uri")] - Action Obj => Function; - } - """; + [PerformanceSensitive("uri")] + Action Obj => Function; + } + """; - await VerifyCS.VerifyAnalyzerAsync(snippet, - // Test0.cs(10,24): warning HAA0603: This will allocate a delegate instance + await VerifyCS.VerifyAnalyzerAsync(snippet, + // Test0.cs(10,24): warning HAA0603: This will allocate a delegate instance #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(9, 24)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(9, 24)); #pragma warning restore RS0030 // Do not use banned APIs - } + } - [Fact] - public async Task TypeConversionAllocation_ExpressionBodiedPropertyExplicitDelegate_NoWarningAsync() - { - // Tests that an explicit delegate creation does not trigger HAA0603. It should be handled by HAA0502. - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_ExpressionBodiedPropertyExplicitDelegate_NoWarningAsync() + { + // Tests that an explicit delegate creation does not trigger HAA0603. It should be handled by HAA0502. + const string snippet = """ + using System; + using Roslyn.Utilities; - class Program - { - void Function(int i) { } + class Program + { + void Function(int i) { } - [PerformanceSensitive("uri")] - Action Obj => new Action(Function); - } - """; + [PerformanceSensitive("uri")] + Action Obj => new Action(Function); + } + """; - await VerifyCS.VerifyAnalyzerAsync(snippet); - } + await VerifyCS.VerifyAnalyzerAsync(snippet); + } - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_enumeration_type_to_System_Enum_typeAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_enumeration_type_to_System_Enum_typeAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using Roslyn.Utilities; - enum E { A } + enum E { A } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - System.Enum box = E.A; - } + System.Enum box = E.A; } - """, - // Test0.cs(11,27): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(11,27): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 27)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 27)); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Creating_delegate_from_value_type_instance_methodAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Creating_delegate_from_value_type_instance_methodAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - struct S { public void M() {} } + struct S { public void M() {} } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - Action box = new S().M; - } + Action box = new S().M; } - """, - // Test0.cs(12,22): warning HAA0603: This will allocate a delegate instance + } + """, + // Test0.cs(12,22): warning HAA0603: This will allocate a delegate instance #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(11, 22), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(11, 22), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(12,22): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + // Test0.cs(12,22): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithLocation(11, 22)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithLocation(11, 22)); - [Fact] - public async Task TypeConversionAllocation_NoDiagnosticWhenPassingDelegateAsArgumentAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_NoDiagnosticWhenPassingDelegateAsArgumentAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; - struct Foo + struct Foo + { + [PerformanceSensitive("uri")] + void Do(Action process) { - [PerformanceSensitive("uri")] - void Do(Action process) - { - DoMore(process); - } + DoMore(process); + } - void DoMore(Action process) - { - process(); - } + void DoMore(Action process) + { + process(); } - """; - await VerifyCS.VerifyAnalyzerAsync(snippet); - } + } + """; + await VerifyCS.VerifyAnalyzerAsync(snippet); + } - [Fact] - public async Task TypeConversionAllocation_ReportBoxingAllocationForPassingStructInstanceMethodForDelegateConstructorAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_ReportBoxingAllocationForPassingStructInstanceMethodForDelegateConstructorAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var @struct = new MyStruct(); - @struct.ProcessFunc(new Func(FooObjCall)); - } + var @struct = new MyStruct(); + @struct.ProcessFunc(new Func(FooObjCall)); + } - public void ProcessFunc(Func func) - { - } + public void ProcessFunc(Func func) + { + } - private string FooObjCall(object obj) - { - return obj.ToString(); - } + private string FooObjCall(object obj) + { + return obj.ToString(); } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(snippet, - // Test0.cs(11,54): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(10, 54, 10, 64)); - } + await VerifyCS.VerifyAnalyzerAsync(snippet, + // Test0.cs(11,54): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(10, 54, 10, 64)); + } - [Fact] - public async Task TypeConversionAllocation_DoNotReportBoxingAllocationForPassingStructStaticMethodForDelegateConstructorAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_DoNotReportBoxingAllocationForPassingStructStaticMethodForDelegateConstructorAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var @struct = new MyStruct(); - @struct.ProcessFunc(new Func(FooObjCall)); - } + var @struct = new MyStruct(); + @struct.ProcessFunc(new Func(FooObjCall)); + } - public void ProcessFunc(Func func) - { - } + public void ProcessFunc(Func func) + { + } - private static string FooObjCall(object obj) - { - return obj.ToString(); - } + private static string FooObjCall(object obj) + { + return obj.ToString(); } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(snippet); - } + await VerifyCS.VerifyAnalyzerAsync(snippet); + } - [Fact] - public async Task TypeConversionAllocation_DoNotReportInlineDelegateAsStructInstanceMethodsAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_DoNotReportInlineDelegateAsStructInstanceMethodsAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var ints = new[] { 5, 4, 3, 2, 1 }; - Array.Sort(ints, delegate(int x, int y) { return x - y; }); - Array.Sort(ints, (x, y) => x - y); - DoSomething(() => throw new Exception()); - DoSomething(delegate() { throw new Exception(); }); + var ints = new[] { 5, 4, 3, 2, 1 }; + Array.Sort(ints, delegate(int x, int y) { return x - y; }); + Array.Sort(ints, (x, y) => x - y); + DoSomething(() => throw new Exception()); + DoSomething(delegate() { throw new Exception(); }); - DoSomething2(x => throw new Exception()); - } + DoSomething2(x => throw new Exception()); + } - private static void DoSomething(Action action) - { - } + private static void DoSomething(Action action) + { + } - private static void DoSomething2(Action action) - { - } + private static void DoSomething2(Action action) + { } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(snippet); - } + await VerifyCS.VerifyAnalyzerAsync(snippet); } } diff --git a/src/Scripting/Core/ScriptBuilder.cs b/src/Scripting/Core/ScriptBuilder.cs index f345991323d38..68e2708651be0 100644 --- a/src/Scripting/Core/ScriptBuilder.cs +++ b/src/Scripting/Core/ScriptBuilder.cs @@ -152,10 +152,7 @@ private Func> Build( peStream.Position = 0; - if (pdbStreamOpt != null) - { - pdbStreamOpt.Position = 0; - } + pdbStreamOpt?.Position = 0; var assembly = _assemblyLoader.LoadAssemblyFromStream(peStream, pdbStreamOpt); var runtimeEntryPoint = GetEntryPointRuntimeMethod(entryPoint, assembly); diff --git a/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs b/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs index b88af7fc759c5..3783866bf71d3 100644 --- a/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs +++ b/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs @@ -34,10 +34,7 @@ public static void ReportTelemetry() static m => { var histogramLogAggregator = s_histogramLogAggregator.GetValue(ActionInfo.GetInheritanceMarginMembers); - if (histogramLogAggregator != null) - { - histogramLogAggregator.WriteTelemetryPropertiesTo(m, nameof(ActionInfo.GetInheritanceMarginMembers) + "."); - } + histogramLogAggregator?.WriteTelemetryPropertiesTo(m, nameof(ActionInfo.GetInheritanceMarginMembers) + "."); })); } } diff --git a/src/VisualStudio/Core/Def/Utilities/TaskItemsEnum.cs b/src/VisualStudio/Core/Def/Utilities/TaskItemsEnum.cs index d64bf30a8c9ed..b160cefe8ece0 100644 --- a/src/VisualStudio/Core/Def/Utilities/TaskItemsEnum.cs +++ b/src/VisualStudio/Core/Def/Utilities/TaskItemsEnum.cs @@ -29,10 +29,7 @@ int IVsEnumTaskItems.Next(uint celt, IVsTaskItem[] rgelt, uint[] pceltFetched) _next += i; - if (pceltFetched != null) - { - pceltFetched[0] = (uint)i; - } + pceltFetched?[0] = (uint)i; return (i == celt) ? VSConstants.S_OK : VSConstants.S_FALSE; } diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs index f1fed7301863e..278eb376d90ca 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs @@ -185,10 +185,7 @@ private bool ShouldShowAnalyzerContextMenu(IEnumerable items) private void UpdateAnalyzerContextMenu() { - if (_removeMenuItem != null) - { - _removeMenuItem.Enabled = _allowProjectSystemOperations; - } + _removeMenuItem?.Enabled = _allowProjectSystemOperations; } public IContextMenuController DiagnosticContextMenuController @@ -557,10 +554,7 @@ private static void UpdateProjectConfigurationsToUseRuleSetFile(EnvDTE.Project e { var codeAnalysisRuleSetFileProperty = properties?.Item("CodeAnalysisRuleSet"); - if (codeAnalysisRuleSetFileProperty != null) - { - codeAnalysisRuleSetFileProperty.Value = fileName; - } + codeAnalysisRuleSetFileProperty?.Value = fileName; } catch (ArgumentException) { diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingUsingsOnPaste.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingUsingsOnPaste.cs index 1b8c800223168..adbe0cef8d574 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingUsingsOnPaste.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingUsingsOnPaste.cs @@ -14,13 +14,8 @@ namespace Roslyn.VisualStudio.NewIntegrationTests.CSharp; [Trait(Traits.Feature, Traits.Features.AddMissingImports)] -public class CSharpAddMissingUsingsOnPaste : AbstractEditorTest +public sealed class CSharpAddMissingUsingsOnPaste() : AbstractEditorTest(nameof(CSharpAddMissingUsingsOnPaste)) { - public CSharpAddMissingUsingsOnPaste() - : base(nameof(CSharpAddMissingUsingsOnPaste)) - { - } - protected override string LanguageName => LanguageNames.CSharp; [IdeFact] diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs index 88e4c1c58c364..cfb3f83439906 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs @@ -608,7 +608,17 @@ protected static SymbolUsageInfo GetSymbolUsageInfo( while (syntaxFacts.IsQualifiedName(topNameNode.Parent)) topNameNode = topNameNode.Parent; - var isInNamespaceNameContext = syntaxFacts.IsBaseNamespaceDeclaration(topNameNode.Parent); + var parent = topNameNode?.Parent; + + // typeof/sizeof are a special case where we don't want to return a TypeOrNamespaceUsageInfo, but rather a ValueUsageInfo.Name. + // This brings it in line with nameof(...), making all those operators appear in a similar fashion. + if (parent?.RawKind == syntaxFacts.SyntaxKinds.TypeOfExpression || + parent?.RawKind == syntaxFacts.SyntaxKinds.SizeOfExpression) + { + return new(ValueUsageInfo.Name, typeOrNamespaceUsageInfoOpt: null); + } + + var isInNamespaceNameContext = syntaxFacts.IsBaseNamespaceDeclaration(parent); return syntaxFacts.IsInNamespaceOrTypeContext(topNameNode) ? SymbolUsageInfo.Create(GetTypeOrNamespaceUsageInfo()) : GetSymbolUsageInfoCommon(); @@ -677,18 +687,12 @@ SymbolUsageInfo GetSymbolUsageInfoCommon() if (operation is IObjectCreationOperation) return SymbolUsageInfo.Create(TypeOrNamespaceUsageInfo.ObjectCreation); - switch (operation?.Parent) - { - case INameOfOperation: - case ITypeOfOperation: - case ISizeOfOperation: - return SymbolUsageInfo.Create(ValueUsageInfo.Name); - } + // Note: sizeof/typeof also return 'name', but are handled above in GetSymbolUsageInfo. + if (operation?.Parent is INameOfOperation) + return SymbolUsageInfo.Create(ValueUsageInfo.Name); if (node.IsPartOfStructuredTrivia()) - { return SymbolUsageInfo.Create(ValueUsageInfo.Name); - } var symbolInfo = semanticModel.GetSymbolInfo(node, cancellationToken); if (symbolInfo.Symbol != null) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs index 5afb9f1eadcfb..e74bd19a93133 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs @@ -118,11 +118,13 @@ public int Convert(TSyntaxKind kind) where TSyntaxKind : struct public int ReferenceNotEqualsExpression => (int)SyntaxKind.NotEqualsExpression; public int SimpleAssignmentExpression => (int)SyntaxKind.SimpleAssignmentExpression; public int SimpleMemberAccessExpression => (int)SyntaxKind.SimpleMemberAccessExpression; + public int? SizeOfExpression => (int)SyntaxKind.SizeOfExpression; public int? SuppressNullableWarningExpression => (int)SyntaxKind.SuppressNullableWarningExpression; public int TernaryConditionalExpression => (int)SyntaxKind.ConditionalExpression; public int ThisExpression => (int)SyntaxKind.ThisExpression; public int? ThrowExpression => (int)SyntaxKind.ThrowExpression; public int TupleExpression => (int)SyntaxKind.TupleExpression; + public int TypeOfExpression => (int)SyntaxKind.TypeOfExpression; public int? AndPattern => (int)SyntaxKind.AndPattern; public int? ConstantPattern => (int)SyntaxKind.ConstantPattern; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs index 7f6b771c13f4d..4e99b8b60e9ab 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs @@ -919,7 +919,7 @@ bool IsConditionalCastSafeToRemoveDueToConversionToOtherBranch() return false; // Check if 'y' has the same type as 'z'. - if (!otherSideType.Equals(thisSideRewrittenType)) + if (!otherSideType.Equals(thisSideRewrittenType, SymbolEqualityComparer.IncludeNullability)) return false; // Now check that with the (T) cast removed, that the outer `x ? y : z` is still diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs index 5f38dac59b397..e37d16980e7f1 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs @@ -122,18 +122,14 @@ SyntaxKind.ForStatement or if (variableDeclaration.Variables is not [{ Initializer.Value: var initializer } variable]) return false; - // Do not suggest var replacement for stackalloc span expressions. - // This will change the bound type from a span to a pointer. - if (!variableDeclaration.Type.IsKind(SyntaxKind.PointerType)) + // Do not suggest var replacement for stackalloc span expressions. This will change the bound type from a + // span to a pointer. Note: this only applies to `var v = stackalloc ...;` If `stackalloc` is anywhere + // lower (including `var v = (stackalloc ...);`), then this is will be a span, and it will be ok to change + // to use 'var'. + if (!variableDeclaration.Type.IsKind(SyntaxKind.PointerType) && + initializer is StackAllocArrayCreationExpressionSyntax) { - var containsStackAlloc = initializer - .DescendantNodesAndSelf(descendIntoChildren: node => node is not AnonymousFunctionExpressionSyntax) - .Any(node => node.IsKind(SyntaxKind.StackAllocArrayCreationExpression)); - - if (containsStackAlloc) - { - return false; - } + return false; } if (AssignmentSupportsStylePreference( diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/SymbolUsageInfo.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/SymbolUsageInfo.cs index d558d96e2734c..8f485357cbb8b 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/SymbolUsageInfo.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/SymbolUsageInfo.cs @@ -2,10 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Diagnostics; using System.Runtime.Serialization; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis; @@ -15,7 +13,7 @@ namespace Microsoft.CodeAnalysis; /// For methods, fields, properties, events, locals and parameters, this corresponds to values from . /// [DataContract] -internal readonly struct SymbolUsageInfo : IEquatable +internal readonly record struct SymbolUsageInfo { public static readonly SymbolUsageInfo None = Create(ValueUsageInfo.None); @@ -45,28 +43,4 @@ public bool IsReadFrom() public bool IsWrittenTo() => ValueUsageInfoOpt.HasValue && ValueUsageInfoOpt.Value.IsWrittenTo(); - - public bool IsNameOnly() - => ValueUsageInfoOpt.HasValue && ValueUsageInfoOpt.Value.IsNameOnly(); - - public override bool Equals(object? obj) - => obj is SymbolUsageInfo && Equals((SymbolUsageInfo)obj); - - public bool Equals(SymbolUsageInfo other) - { - if (ValueUsageInfoOpt.HasValue) - { - return other.ValueUsageInfoOpt.HasValue && - ValueUsageInfoOpt.Value == other.ValueUsageInfoOpt.Value; - } - else - { - RoslynDebug.Assert(TypeOrNamespaceUsageInfoOpt.HasValue); - return other.TypeOrNamespaceUsageInfoOpt.HasValue && - TypeOrNamespaceUsageInfoOpt.Value == other.TypeOrNamespaceUsageInfoOpt.Value; - } - } - - public override int GetHashCode() - => Hash.Combine(((int?)ValueUsageInfoOpt)?.GetHashCode() ?? 0, ((int?)TypeOrNamespaceUsageInfoOpt)?.GetHashCode() ?? 0); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs index 71cdf02df8537..41981d1cb8dfd 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs @@ -161,11 +161,13 @@ internal interface ISyntaxKinds int ReferenceNotEqualsExpression { get; } int SimpleAssignmentExpression { get; } int SimpleMemberAccessExpression { get; } + int? SizeOfExpression { get; } int? SuppressNullableWarningExpression { get; } int TernaryConditionalExpression { get; } int ThisExpression { get; } int? ThrowExpression { get; } int TupleExpression { get; } + int TypeOfExpression { get; } #endregion diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/ParenthesizedExpressionSyntaxExtensions.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/ParenthesizedExpressionSyntaxExtensions.vb index da471f2baced0..aa7af3efb7949 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/ParenthesizedExpressionSyntaxExtensions.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/ParenthesizedExpressionSyntaxExtensions.vb @@ -346,6 +346,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions ' Cases: ' (1 + 1) * 8 ' (1 + 1).ToString + ' (1 + 1)?.ToString ' (1 + 1)() If TypeOf expression Is BinaryExpressionSyntax OrElse TypeOf expression Is UnaryExpressionSyntax Then @@ -353,6 +354,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Dim parentExpression = TryCast(node.Parent, ExpressionSyntax) If parentExpression IsNot Nothing Then If parentExpression.IsKind(SyntaxKind.SimpleMemberAccessExpression) OrElse + parentExpression.IsKind(SyntaxKind.ConditionalAccessExpression) OrElse parentExpression.IsKind(SyntaxKind.InvocationExpression) Then Return False End If diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb index 0641f531b5c81..104f2d01b47a5 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb @@ -120,11 +120,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageService Public ReadOnly Property ReferenceNotEqualsExpression As Integer = SyntaxKind.IsNotExpression Implements ISyntaxKinds.ReferenceNotEqualsExpression Public ReadOnly Property SimpleAssignmentExpression As Integer = SyntaxKind.SimpleAssignmentStatement Implements ISyntaxKinds.SimpleAssignmentExpression Public ReadOnly Property SimpleMemberAccessExpression As Integer = SyntaxKind.SimpleMemberAccessExpression Implements ISyntaxKinds.SimpleMemberAccessExpression + Public ReadOnly Property SizeOfExpression As Integer? Implements ISyntaxKinds.SizeOfExpression Public ReadOnly Property SuppressNullableWarningExpression As Integer? Implements ISyntaxKinds.SuppressNullableWarningExpression Public ReadOnly Property TernaryConditionalExpression As Integer = SyntaxKind.TernaryConditionalExpression Implements ISyntaxKinds.TernaryConditionalExpression Public ReadOnly Property ThisExpression As Integer = SyntaxKind.MeExpression Implements ISyntaxKinds.ThisExpression Public ReadOnly Property ThrowExpression As Integer? Implements ISyntaxKinds.ThrowExpression Public ReadOnly Property TupleExpression As Integer = SyntaxKind.TupleExpression Implements ISyntaxKinds.TupleExpression + Public ReadOnly Property TypeOfExpression As Integer = SyntaxKind.GetTypeExpression Implements ISyntaxKinds.TypeOfExpression Public ReadOnly Property AndPattern As Integer? Implements ISyntaxKinds.AndPattern Public ReadOnly Property ConstantPattern As Integer? Implements ISyntaxKinds.ConstantPattern diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/CSharpCodeGenerationHelpers.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/CSharpCodeGenerationHelpers.cs index 75d972a22f057..12421618da5cf 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/CSharpCodeGenerationHelpers.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/CSharpCodeGenerationHelpers.cs @@ -172,14 +172,15 @@ public static SyntaxList Insert( CSharpCodeGenerationContextInfo info, IList? availableIndices, Func, TDeclaration?>? after = null, - Func, TDeclaration?>? before = null) + Func, TDeclaration?>? before = null, + Func, int, bool>? canPlaceAtIndex = null) where TDeclaration : SyntaxNode { var index = GetInsertionIndex( declarationList, declaration, info, availableIndices, CSharpDeclarationComparer.WithoutNamesInstance, CSharpDeclarationComparer.WithNamesInstance, - after, before); + after, before, canPlaceAtIndex); availableIndices?.Insert(index, true); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/NamedTypeGenerator.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/NamedTypeGenerator.cs index 31c4d36df8885..a97d4b64fd1aa 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/NamedTypeGenerator.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/NamedTypeGenerator.cs @@ -59,7 +59,11 @@ public static CompilationUnitSyntax AddNamedTypeTo( CancellationToken cancellationToken) { var declaration = GenerateNamedTypeDeclaration(service, namedType, CodeGenerationDestination.CompilationUnit, info, cancellationToken); - var members = Insert(destination.Members, declaration, info, availableIndices); + var members = Insert( + destination.Members, declaration, info, availableIndices, + // We're adding a named type to a compilation unit. If there are any global statements, we must place it after them. + after: static members => members.LastOrDefault(m => m is GlobalStatementSyntax), + canPlaceAtIndex: static (members, index) => index >= members.Count || members[index] is not GlobalStatementSyntax); return destination.WithMembers(members); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CodeGenerationHelpers.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CodeGenerationHelpers.cs index 476a0c1001178..1e653b7a55cab 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CodeGenerationHelpers.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CodeGenerationHelpers.cs @@ -193,11 +193,14 @@ public static int GetInsertionIndex( IComparer comparerWithoutNameCheck, IComparer comparerWithNameCheck, Func, TDeclaration?>? after = null, - Func, TDeclaration?>? before = null) + Func, TDeclaration?>? before = null, + Func, int, bool>? canPlaceAtIndex = null) where TDeclaration : SyntaxNode { Contract.ThrowIfTrue(availableIndices != null && availableIndices.Count != declarationList.Count + 1); + canPlaceAtIndex ??= static (_, _) => true; + // Try to strictly obey the after option by inserting immediately after the member containing the location if (info.Context.AfterThisLocation?.SourceTree is { } afterSourceTree && afterSourceTree.FilePath == declarationList.FirstOrDefault()?.SyntaxTree.FilePath) @@ -207,10 +210,8 @@ public static int GetInsertionIndex( { var index = declarationList.IndexOf(afterMember); index = GetPreferredIndex(index + 1, availableIndices, forward: true); - if (index != -1) - { + if (index != -1 && canPlaceAtIndex(declarationList, index)) return index; - } } } From d2cf001285209742fff9f2d6cf0a0d026287f81f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Thu, 17 Jul 2025 02:17:08 +0000 Subject: [PATCH 07/14] Update dependencies from https://github.com/dotnet/dotnet build 275513 No dependency updates to commit --- eng/Version.Details.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 098b6641ac17b..7ff3964b8fd1d 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,6 +1,6 @@ - + From c8814bbae487c5d8be3bc761f4229a7ec3069da7 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Thu, 17 Jul 2025 15:40:12 +0000 Subject: [PATCH 08/14] Update dependencies from https://github.com/dotnet/dotnet build 275594 Updated Dependencies: System.CommandLine (Version 2.0.0-beta5.25210.1 -> 2.0.0-beta7.25366.104) --- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d9eed2c9df77f..7d0ce186cef0b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,15 +1,15 @@ - + https://github.com/dotnet/roslyn ae1fff344d46976624e68ae17164e0607ab68b10 - - https://github.com/dotnet/command-line-api - e9b0511d7f1128e2bc3be7a658a2a4ea977e602d + + https://github.com/dotnet/dotnet + 53d43a5b167fc56a334068036cfb7849281e00cf diff --git a/eng/Versions.props b/eng/Versions.props index a70c92287985a..ec17e66ea1b53 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -48,7 +48,7 @@ Versions managed by Arcade (see Versions.Details.xml) --> - 2.0.0-beta5.25210.1 + 2.0.0-beta7.25366.104 9.0.0 9.0.0 9.0.0 From 74584f515c0853edfcefcb443122c63a2e56dee5 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Thu, 17 Jul 2025 18:32:45 +0000 Subject: [PATCH 09/14] [VMR] Codeflow 462275d-462275d [[ commit created by automation ]] From a76075de3e8427aa99dab1ead03ac37fc06d9bb8 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Thu, 17 Jul 2025 18:32:46 +0000 Subject: [PATCH 10/14] Update dependencies from https://github.com/dotnet/dotnet build 275638 Updated Dependencies: System.CommandLine (Version 2.0.0-beta7.25366.104 -> 2.0.0-beta7.25367.101) --- eng/Version.Details.xml | 6 +++--- eng/Versions.props | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7d0ce186cef0b..a8b64e2078cec 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,15 +1,15 @@ - + https://github.com/dotnet/roslyn ae1fff344d46976624e68ae17164e0607ab68b10 - + https://github.com/dotnet/dotnet - 53d43a5b167fc56a334068036cfb7849281e00cf + 699b0116eb3df66c4dd7698af4f1cd24ac4547a3 diff --git a/eng/Versions.props b/eng/Versions.props index ec17e66ea1b53..f0cd5e95ad920 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -48,7 +48,7 @@ Versions managed by Arcade (see Versions.Details.xml) --> - 2.0.0-beta7.25366.104 + 2.0.0-beta7.25367.101 9.0.0 9.0.0 9.0.0 From 27b770e108bb4f0c3532253ef7d9568d9765558b Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Fri, 18 Jul 2025 12:48:56 +0000 Subject: [PATCH 11/14] Update dependencies from https://github.com/dotnet/dotnet build 275766 Updated Dependencies: System.CommandLine (Version 2.0.0-beta7.25367.101 -> 2.0.0-beta7.25368.101) --- eng/Version.Details.xml | 6 +++--- eng/Versions.props | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a8b64e2078cec..70810436e0ea1 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,15 +1,15 @@ - + https://github.com/dotnet/roslyn ae1fff344d46976624e68ae17164e0607ab68b10 - + https://github.com/dotnet/dotnet - 699b0116eb3df66c4dd7698af4f1cd24ac4547a3 + 6d3cf3fd5d8b678159dc68b2f9c37114e10a0fab diff --git a/eng/Versions.props b/eng/Versions.props index f0cd5e95ad920..941746f628fa3 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -48,7 +48,7 @@ Versions managed by Arcade (see Versions.Details.xml) --> - 2.0.0-beta7.25367.101 + 2.0.0-beta7.25368.101 9.0.0 9.0.0 9.0.0 From 6dc9350c91159bbbe14efeebd25a2f18446c5441 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Sat, 19 Jul 2025 02:07:39 +0000 Subject: [PATCH 12/14] [VMR] Codeflow 37a47b7-37a47b7 [[ commit created by automation ]] --- ...uilding, Debugging, and Testing on Unix.md | 2 +- ...ding, Debugging, and Testing on Windows.md | 2 +- eng/Directory.Packages.props | 2 +- global.json | 4 +- .../InternalUtilities/EmptyComparer.cs | 31 --------- .../Contracts/EqualityComparerExtensions.cs | 63 +++++++++++++++++++ ...Microsoft.CodeAnalysis.Contracts.projitems | 2 + .../Contracts}/ReferenceEqualityComparer.cs | 4 +- .../Core/Remote/SolutionChecksumUpdater.cs | 24 +++++-- .../Collections/Immutable/Maps/MapTests.cs | 13 +--- .../Test2/Rename/InlineRenameTests.vb | 54 ++++++++++++++++ .../AbstractKeywordCompletionProvider.cs | 13 +--- .../InlineRename/InlineRenameUndoManager.cs | 12 +++- .../Core/CompilerExtensions.projitems | 3 +- 14 files changed, 164 insertions(+), 65 deletions(-) delete mode 100644 src/Compilers/Core/Portable/InternalUtilities/EmptyComparer.cs create mode 100644 src/Dependencies/Contracts/EqualityComparerExtensions.cs rename src/{Compilers/Core/Portable/InternalUtilities => Dependencies/Contracts}/ReferenceEqualityComparer.cs (99%) diff --git a/docs/contributing/Building, Debugging, and Testing on Unix.md b/docs/contributing/Building, Debugging, and Testing on Unix.md index 5d1d326a4d610..6f224b39f7584 100644 --- a/docs/contributing/Building, Debugging, and Testing on Unix.md +++ b/docs/contributing/Building, Debugging, and Testing on Unix.md @@ -12,7 +12,7 @@ Particularly for developers who aren't experienced with .NET Core development on 1. Install [VS Code](https://code.visualstudio.com/Download) - After you install VS Code, install the [C# extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) - Important tip: You can look up editor commands by name by hitting *Ctrl+Shift+P*, or by hitting *Ctrl+P* and typing a `>` character. This will help you get familiar with editor commands mentioned below. On a Mac, use *⌘* instead of *Ctrl*. -1. Install the [.NET 9.0 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/9.0) which matches the `sdk.version` property in [global.json](../../global.json#L3) +1. Install the [.NET 10.0 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/10.0) which matches the `sdk.version` property in [global.json](../../global.json#L3) 3. You can build from VS Code by running the *Run Build Task* command, then selecting an appropriate task such as *build* or *build current project* (the latter builds the containing project for the current file you're viewing in the editor). 4. You can run tests from VS Code by opening a test class in the editor, then using the *Run Tests in Context* and *Debug Tests in Context* editor commands. You may want to bind these commands to keyboard shortcuts that match their Visual Studio equivalents (**Ctrl+R, T** for *Run Tests in Context* and **Ctrl+R, Ctrl+T** for *Debug Tests in Context*). 5. You can launch a new VS Code instance with the language server from your current code by running the "launch vscode with language server" task. diff --git a/docs/contributing/Building, Debugging, and Testing on Windows.md b/docs/contributing/Building, Debugging, and Testing on Windows.md index 235ae3e82854c..cd3d77670b084 100644 --- a/docs/contributing/Building, Debugging, and Testing on Windows.md +++ b/docs/contributing/Building, Debugging, and Testing on Windows.md @@ -20,7 +20,7 @@ The minimal required version of .NET Framework is 4.7.2. - Ensure C# and Visual Basic, MSBuild, and .NET Core are included in the selected individual components - Ensure "Use previews of the .NET Core SDK" is checked in Tools -> Options -> Environment -> Preview Features - Restart Visual Studio -1. Install the [.NET 9.0 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/9.0) which matches the `sdk.version` property in [global.json](../../global.json#L3) +1. Install the [.NET 10.0 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/10.0) which matches the `sdk.version` property in [global.json](../../global.json#L3) 1. [PowerShell 5.0 or newer](https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell). If you are on Windows 10, you are fine; you'll only need to upgrade if you're on earlier versions of Windows. The download link is under the ["Upgrading existing Windows PowerShell"](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-windows-powershell?view=powershell-6#upgrading-existing-windows-powershell) heading. 1. Run Restore.cmd 1. Open Roslyn.sln diff --git a/eng/Directory.Packages.props b/eng/Directory.Packages.props index aa611b4cbb49c..fb7fcdf5f646d 100644 --- a/eng/Directory.Packages.props +++ b/eng/Directory.Packages.props @@ -273,7 +273,7 @@ - + diff --git a/global.json b/global.json index 7495e1ea259c2..748088bed40d1 100644 --- a/global.json +++ b/global.json @@ -1,11 +1,11 @@ { "sdk": { - "version": "10.0.100-preview.5.25277.114", + "version": "10.0.100-preview.6.25358.103", "allowPrerelease": false, "rollForward": "patch" }, "tools": { - "dotnet": "10.0.100-preview.5.25277.114", + "dotnet": "10.0.100-preview.6.25358.103", "vs": { "version": "17.14.0" }, diff --git a/src/Compilers/Core/Portable/InternalUtilities/EmptyComparer.cs b/src/Compilers/Core/Portable/InternalUtilities/EmptyComparer.cs deleted file mode 100644 index 0f61efb45d893..0000000000000 --- a/src/Compilers/Core/Portable/InternalUtilities/EmptyComparer.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using Microsoft.CodeAnalysis; - -namespace Roslyn.Utilities -{ - /// - /// Very cheap trivial comparer that never matches the keys, - /// should only be used in empty dictionaries. - /// - internal sealed class EmptyComparer : IEqualityComparer - { - public static readonly EmptyComparer Instance = new EmptyComparer(); - - private EmptyComparer() - { - } - - bool IEqualityComparer.Equals(object? a, object? b) - => throw ExceptionUtilities.Unreachable(); - - int IEqualityComparer.GetHashCode(object s) - { - // dictionary will call this often - return 0; - } - } -} diff --git a/src/Dependencies/Contracts/EqualityComparerExtensions.cs b/src/Dependencies/Contracts/EqualityComparerExtensions.cs new file mode 100644 index 0000000000000..e67f8320a7aaf --- /dev/null +++ b/src/Dependencies/Contracts/EqualityComparerExtensions.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif + +namespace System.Collections.Generic; + +internal static class RoslynEqualityComparerExtensions +{ +#if NET8_0_OR_GREATER + + // for binary compatibility + public static EqualityComparer Create(Func equals, Func? getHashCode = null) + => EqualityComparer.Create(equals, getHashCode); + +#else + // Implementation based on https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.cs + + extension(EqualityComparer) + { + /// + /// Creates an by using the specified delegates as the implementation of the comparer's + /// and methods. + /// + /// The delegate to use to implement the method. + /// + /// The delegate to use to implement the method. + /// If no delegate is supplied, calls to the resulting comparer's + /// will throw . + /// + /// The new comparer. + public static EqualityComparer Create(Func equals, Func? getHashCode = null) + { + getHashCode ??= _ => throw new NotSupportedException(); + return new DelegateEqualityComparer(equals, getHashCode); + } + } + + private sealed class DelegateEqualityComparer(Func equals, Func getHashCode) : EqualityComparer + { + private readonly Func _equals = equals; + private readonly Func _getHashCode = getHashCode; + + public override bool Equals(T? x, T? y) => + _equals(x, y); + + public override int GetHashCode(T obj) => + _getHashCode(obj); + + public override bool Equals(object? obj) + => obj is DelegateEqualityComparer other && _equals == other._equals && _getHashCode == other._getHashCode; + + public override int GetHashCode() + => unchecked(_equals.GetHashCode() * (int)0xA5555529 + _getHashCode.GetHashCode()); + } +#endif +} + diff --git a/src/Dependencies/Contracts/Microsoft.CodeAnalysis.Contracts.projitems b/src/Dependencies/Contracts/Microsoft.CodeAnalysis.Contracts.projitems index e3725f02a07f8..504f3c43ac0b3 100644 --- a/src/Dependencies/Contracts/Microsoft.CodeAnalysis.Contracts.projitems +++ b/src/Dependencies/Contracts/Microsoft.CodeAnalysis.Contracts.projitems @@ -25,6 +25,8 @@ + + diff --git a/src/Compilers/Core/Portable/InternalUtilities/ReferenceEqualityComparer.cs b/src/Dependencies/Contracts/ReferenceEqualityComparer.cs similarity index 99% rename from src/Compilers/Core/Portable/InternalUtilities/ReferenceEqualityComparer.cs rename to src/Dependencies/Contracts/ReferenceEqualityComparer.cs index 8176987e9e9cd..ce160297459c0 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ReferenceEqualityComparer.cs +++ b/src/Dependencies/Contracts/ReferenceEqualityComparer.cs @@ -4,7 +4,9 @@ using System.Runtime.CompilerServices; -#if NET5_0_OR_GREATER +#nullable enable + +#if NET #pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) [assembly: TypeForwardedTo(typeof(System.Collections.Generic.ReferenceEqualityComparer))] diff --git a/src/EditorFeatures/Core/Remote/SolutionChecksumUpdater.cs b/src/EditorFeatures/Core/Remote/SolutionChecksumUpdater.cs index eb2afb0a1cbea..9a98110210a1f 100644 --- a/src/EditorFeatures/Core/Remote/SolutionChecksumUpdater.cs +++ b/src/EditorFeatures/Core/Remote/SolutionChecksumUpdater.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ErrorReporting; @@ -102,11 +103,24 @@ private void OnWorkspaceChanged(WorkspaceChangeEventArgs _) private void OnWorkspaceChangedImmediate(WorkspaceChangeEventArgs e) { - if (e.Kind == WorkspaceChangeKind.DocumentChanged) + if (e.Kind is WorkspaceChangeKind.DocumentChanged or WorkspaceChangeKind.AdditionalDocumentChanged) { var documentId = e.DocumentId!; - var oldDocument = e.OldSolution.GetRequiredDocument(documentId); - var newDocument = e.NewSolution.GetRequiredDocument(documentId); + TextDocument oldDocument; + TextDocument newDocument; + + if (e.Kind == WorkspaceChangeKind.DocumentChanged) + { + oldDocument = e.OldSolution.GetRequiredDocument(documentId); + newDocument = e.NewSolution.GetRequiredDocument(documentId); + } + else + { + Debug.Assert(e.Kind == WorkspaceChangeKind.AdditionalDocumentChanged); + + oldDocument = e.OldSolution.GetRequiredAdditionalDocument(documentId); + newDocument = e.NewSolution.GetRequiredAdditionalDocument(documentId); + } // Fire-and-forget to dispatch notification of this document change event to the remote side // and return to the caller as quickly as possible. @@ -157,8 +171,8 @@ await client.TryInvokeAsync( } private async Task DispatchSynchronizeTextChangesAsync( - Document oldDocument, - Document newDocument) + TextDocument oldDocument, + TextDocument newDocument) { // Explicitly force a yield point here to ensure this method returns to the caller immediately and that // all work is done off the calling thread. diff --git a/src/EditorFeatures/Test/Collections/Immutable/Maps/MapTests.cs b/src/EditorFeatures/Test/Collections/Immutable/Maps/MapTests.cs index 1908f55551332..c7e93e8b55e96 100644 --- a/src/EditorFeatures/Test/Collections/Immutable/Maps/MapTests.cs +++ b/src/EditorFeatures/Test/Collections/Immutable/Maps/MapTests.cs @@ -82,7 +82,9 @@ public void TestRemove() [Fact] public void TestPathology() { - var map = ImmutableDictionary.Create(new PathologicalComparer()) + var comparer = EqualityComparer.Create(EqualityComparer.Default.Equals, _ => 0); + + var map = ImmutableDictionary.Create(comparer) .Add("1", 1) .Add("2", 2) .Add("3", 3) @@ -118,13 +120,4 @@ public void TestPathology() map = map.Remove("5"); Assert.Empty(map); } - - private sealed class PathologicalComparer : IEqualityComparer - { - public bool Equals(T x, T y) - => EqualityComparer.Default.Equals(x, y); - - public int GetHashCode(T obj) - => 0; - } } diff --git a/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb b/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb index 0d6e86c3b498f..2013f15300b3b 100644 --- a/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb +++ b/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb @@ -2473,5 +2473,59 @@ class [|C|] , host:=host, renameTo:="MyNewProperty") End Using End Sub + + + + Public Sub RenameClassWithAttributeName(host As RenameTestHost) + Using result = RenameEngineResult.Create(_outputHelper, + + + + + + + , host:=host, renameTo:="MyClassAttribute2") + End Using + End Sub + + + + Public Async Function RenameClassWithAttributeName2(host As RenameTestHost) As Task + Using workspace = CreateWorkspaceWithWaiter( + + + + public class [|MyClass$$Attribute|] : System.Attribute + { + public [|MyClassAttribute|]() + { + + } + } + + + , host) + + Dim session = StartSession(workspace) + + ' Type a bit in the file + Dim caretPosition = workspace.Documents.Single(Function(d) d.CursorPosition.HasValue).CursorPosition.Value + Dim textBuffer = workspace.Documents.Single().GetTextBuffer() + + textBuffer.Insert(caretPosition, "2") + + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) + + Await VerifyTagsAreCorrect(workspace) + End Using + End Function End Class End Namespace diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs index 84fe32c5f955d..2c44eb5daa37e 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs @@ -19,7 +19,9 @@ namespace Microsoft.CodeAnalysis.Completion.Providers; internal abstract partial class AbstractKeywordCompletionProvider : LSPCompletionProvider where TContext : SyntaxContext { - private static readonly Comparer s_comparer = new(); + private static readonly EqualityComparer s_comparer = EqualityComparer.Create( + static (x, y) => x?.DisplayText == y?.DisplayText, + static x => x.DisplayText.GetHashCode()); private readonly ImmutableArray> _keywordRecommenders; @@ -72,13 +74,4 @@ private async Task> RecommendKeywordsAsync( public sealed override Task GetTextChangeAsync(Document document, CompletionItem item, char? ch, CancellationToken cancellationToken) => Task.FromResult((TextChange?)new TextChange(item.Span, item.DisplayText)); - - private sealed class Comparer : IEqualityComparer - { - public bool Equals(CompletionItem? x, CompletionItem? y) - => x?.DisplayText == y?.DisplayText; - - public int GetHashCode(CompletionItem obj) - => Hash.Combine(obj.DisplayText.GetHashCode(), obj.DisplayText.GetHashCode()); - } } diff --git a/src/VisualStudio/Core/Def/InlineRename/InlineRenameUndoManager.cs b/src/VisualStudio/Core/Def/InlineRename/InlineRenameUndoManager.cs index 3548aa6d7dc5a..ad7fce549b32a 100644 --- a/src/VisualStudio/Core/Def/InlineRename/InlineRenameUndoManager.cs +++ b/src/VisualStudio/Core/Def/InlineRename/InlineRenameUndoManager.cs @@ -15,6 +15,9 @@ using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageService; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Editor; using Microsoft.VisualStudio.OLE.Interop; using Microsoft.VisualStudio.Text; @@ -171,7 +174,14 @@ public void ApplyCurrentState(ITextBuffer subjectBuffer, object propagateSpansEd return; } - ApplyReplacementText(subjectBuffer, bufferUndoState.TextUndoHistory, propagateSpansEditTag, spans, this.currentState.ReplacementText); + var document = subjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); + var isCaseSensitive = document?.GetLanguageService()?.IsCaseSensitive ?? true; + + // This is where we apply the replacement text to each inline preview in the buffer. + // Needs to remove the "Attribute" suffix, since the inline preview does not include the "Attribute" suffix in the replacement span, + // so that the user does not see the suffix twice. + ApplyReplacementText(subjectBuffer, bufferUndoState.TextUndoHistory, propagateSpansEditTag, spans, + currentState.ReplacementText.GetWithoutAttributeSuffix(isCaseSensitive) ?? currentState.ReplacementText); // Here we create the descriptions for the redo list dropdown. var undoManager = bufferUndoState.UndoManager; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems index 6f9309d886cb3..755a43b260eb3 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems @@ -1,4 +1,4 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) @@ -19,7 +19,6 @@ - From 4edcf0448af20b32aea1b7a76fa42ccea786ee0c Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Sat, 19 Jul 2025 02:07:40 +0000 Subject: [PATCH 13/14] Update dependencies from https://github.com/dotnet/dotnet build 275814 Updated Dependencies: System.CommandLine (Version 2.0.0-beta7.25368.101 -> 2.0.0-beta7.25368.102) --- eng/Version.Details.xml | 6 +++--- eng/Versions.props | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 70810436e0ea1..2810372f932d1 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,15 +1,15 @@ - + https://github.com/dotnet/roslyn ae1fff344d46976624e68ae17164e0607ab68b10 - + https://github.com/dotnet/dotnet - 6d3cf3fd5d8b678159dc68b2f9c37114e10a0fab + 46deba7a696a2f4e00270a11c84a5aff2648dd39 diff --git a/eng/Versions.props b/eng/Versions.props index 941746f628fa3..8c6124f8ac76f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -48,7 +48,7 @@ Versions managed by Arcade (see Versions.Details.xml) --> - 2.0.0-beta7.25368.101 + 2.0.0-beta7.25368.102 9.0.0 9.0.0 9.0.0 From f52a8251adfd56f47f069ec49ef7c162e609634f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Sun, 20 Jul 2025 02:05:44 +0000 Subject: [PATCH 14/14] Update dependencies from https://github.com/dotnet/dotnet build 275898 Updated Dependencies: System.CommandLine (Version 2.0.0-beta7.25368.102 -> 2.0.0-beta7.25368.105) --- eng/Version.Details.xml | 6 +++--- eng/Versions.props | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 2810372f932d1..183605cc387d1 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,15 +1,15 @@ - + https://github.com/dotnet/roslyn ae1fff344d46976624e68ae17164e0607ab68b10 - + https://github.com/dotnet/dotnet - 46deba7a696a2f4e00270a11c84a5aff2648dd39 + 1c92f346e02a8363def6f7bdbcc526d3c579dd74 diff --git a/eng/Versions.props b/eng/Versions.props index 8c6124f8ac76f..a6addc58bf067 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -48,7 +48,7 @@ Versions managed by Arcade (see Versions.Details.xml) --> - 2.0.0-beta7.25368.102 + 2.0.0-beta7.25368.105 9.0.0 9.0.0 9.0.0