From feb2768972cde4a837bc9eb39f1657934d3ef082 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Sat, 2 Apr 2022 20:09:10 +0200 Subject: [PATCH 01/66] Cleanup AbstractBuiltInCodeStyleDiagnosticAnalyzer --- ...BuiltInCodeStyleDiagnosticAnalyzer_Core.cs | 15 +------- .../AbstractFileHeaderDiagnosticAnalyzer.cs | 38 +++++++++---------- 2 files changed, 21 insertions(+), 32 deletions(-) diff --git a/src/Analyzers/Core/Analyzers/AbstractBuiltInCodeStyleDiagnosticAnalyzer_Core.cs b/src/Analyzers/Core/Analyzers/AbstractBuiltInCodeStyleDiagnosticAnalyzer_Core.cs index f5391d9025b5a..d4670f252fdff 100644 --- a/src/Analyzers/Core/Analyzers/AbstractBuiltInCodeStyleDiagnosticAnalyzer_Core.cs +++ b/src/Analyzers/Core/Analyzers/AbstractBuiltInCodeStyleDiagnosticAnalyzer_Core.cs @@ -10,13 +10,8 @@ namespace Microsoft.CodeAnalysis.CodeStyle { internal abstract partial class AbstractBuiltInCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer, IBuiltInAnalyzer { - protected readonly string? DescriptorId; - protected readonly DiagnosticDescriptor Descriptor; - protected readonly LocalizableString _localizableTitle; - protected readonly LocalizableString _localizableMessageFormat; - private AbstractBuiltInCodeStyleDiagnosticAnalyzer( string descriptorId, EnforceOnBuild enforceOnBuild, @@ -25,24 +20,18 @@ internal abstract partial class AbstractBuiltInCodeStyleDiagnosticAnalyzer : Dia bool isUnnecessary, bool configurable) { - DescriptorId = descriptorId; - _localizableTitle = title; - _localizableMessageFormat = messageFormat ?? title; - - Descriptor = CreateDescriptorWithId(DescriptorId, enforceOnBuild, _localizableTitle, _localizableMessageFormat, isUnnecessary: isUnnecessary, isConfigurable: configurable); + Descriptor = CreateDescriptorWithId(descriptorId, enforceOnBuild, title, messageFormat ?? title, isUnnecessary: isUnnecessary, isConfigurable: configurable); SupportedDiagnostics = ImmutableArray.Create(Descriptor); } /// /// Constructor for a code style analyzer with a multiple diagnostic descriptors such that all the descriptors have no unique code style option to configure the descriptors. /// - protected AbstractBuiltInCodeStyleDiagnosticAnalyzer(ImmutableArray supportedDiagnostics) + private AbstractBuiltInCodeStyleDiagnosticAnalyzer(ImmutableArray supportedDiagnostics) { SupportedDiagnostics = supportedDiagnostics; Descriptor = SupportedDiagnostics[0]; - _localizableTitle = Descriptor.Title; - _localizableMessageFormat = Descriptor.MessageFormat; } public CodeActionRequestPriority RequestPriority => CodeActionRequestPriority.Normal; diff --git a/src/Analyzers/Core/Analyzers/FileHeaders/AbstractFileHeaderDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/FileHeaders/AbstractFileHeaderDiagnosticAnalyzer.cs index 4d9824659ce63..8cf81640f1297 100644 --- a/src/Analyzers/Core/Analyzers/FileHeaders/AbstractFileHeaderDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/FileHeaders/AbstractFileHeaderDiagnosticAnalyzer.cs @@ -2,37 +2,37 @@ // 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.Immutable; using System.IO; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; -using Roslyn.Utilities; +using Microsoft.CodeAnalysis.Options; namespace Microsoft.CodeAnalysis.FileHeaders { internal abstract class AbstractFileHeaderDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { + private static readonly LocalizableString s_invalidHeaderTitle = new LocalizableResourceString(nameof(AnalyzersResources.The_file_header_does_not_match_the_required_text), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)); + private static readonly LocalizableString s_invalidHeaderMessage = new LocalizableResourceString(nameof(AnalyzersResources.A_source_file_contains_a_header_that_does_not_match_the_required_text), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)); + private static readonly DiagnosticDescriptor s_invalidHeaderDescriptor = CreateDescriptorForFileHeader(s_invalidHeaderTitle, s_invalidHeaderMessage); + + private static readonly LocalizableString s_missingHeaderTitle = new LocalizableResourceString(nameof(AnalyzersResources.The_file_header_is_missing_or_not_located_at_the_top_of_the_file), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)); + private static readonly LocalizableString s_missingHeaderMessage = new LocalizableResourceString(nameof(AnalyzersResources.A_source_file_is_missing_a_required_header), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)); + private static readonly DiagnosticDescriptor s_missingHeaderDescriptor = CreateDescriptorForFileHeader(s_missingHeaderTitle, s_missingHeaderMessage); + + private static DiagnosticDescriptor CreateDescriptorForFileHeader(LocalizableString title, LocalizableString message) + => CreateDescriptorWithId(IDEDiagnosticIds.FileHeaderMismatch, EnforceOnBuildValues.FileHeaderMismatch, title, message); + protected AbstractFileHeaderDiagnosticAnalyzer(string language) - : base( - IDEDiagnosticIds.FileHeaderMismatch, - EnforceOnBuildValues.FileHeaderMismatch, - CodeStyleOptions2.FileHeaderTemplate, - language, - new LocalizableResourceString(nameof(AnalyzersResources.The_file_header_is_missing_or_not_located_at_the_top_of_the_file), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)), - new LocalizableResourceString(nameof(AnalyzersResources.A_source_file_is_missing_a_required_header), AnalyzersResources.ResourceManager, typeof(AnalyzersResources))) + : base(ImmutableDictionary.Empty + .Add(s_invalidHeaderDescriptor, CodeStyleOptions2.FileHeaderTemplate) + .Add(s_missingHeaderDescriptor, CodeStyleOptions2.FileHeaderTemplate), + language) { - RoslynDebug.AssertNotNull(DescriptorId); - - var invalidHeaderTitle = new LocalizableResourceString(nameof(AnalyzersResources.The_file_header_does_not_match_the_required_text), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)); - var invalidHeaderMessage = new LocalizableResourceString(nameof(AnalyzersResources.A_source_file_contains_a_header_that_does_not_match_the_required_text), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)); - InvalidHeaderDescriptor = CreateDescriptorWithId(DescriptorId, EnforceOnBuildValues.FileHeaderMismatch, invalidHeaderTitle, invalidHeaderMessage); } protected abstract AbstractFileHeaderHelper FileHeaderHelper { get; } - internal DiagnosticDescriptor MissingHeaderDescriptor => Descriptor; - - internal DiagnosticDescriptor InvalidHeaderDescriptor { get; } - public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SyntaxTreeWithoutSemanticsAnalysis; @@ -59,14 +59,14 @@ private void HandleSyntaxTree(SyntaxTreeAnalysisContext context) var fileHeader = FileHeaderHelper.ParseFileHeader(root); if (fileHeader.IsMissing) { - context.ReportDiagnostic(Diagnostic.Create(MissingHeaderDescriptor, fileHeader.GetLocation(tree))); + context.ReportDiagnostic(Diagnostic.Create(s_missingHeaderDescriptor, fileHeader.GetLocation(tree))); return; } var expectedFileHeader = fileHeaderTemplate.Replace("{fileName}", Path.GetFileName(tree.FilePath)); if (!CompareCopyrightText(expectedFileHeader, fileHeader.CopyrightText)) { - context.ReportDiagnostic(Diagnostic.Create(InvalidHeaderDescriptor, fileHeader.GetLocation(tree))); + context.ReportDiagnostic(Diagnostic.Create(s_invalidHeaderDescriptor, fileHeader.GetLocation(tree))); return; } } From 58639aff8fb765dd9acf334c805bc7f7bd50c240 Mon Sep 17 00:00:00 2001 From: "Gen Lu (HE/HIM)" Date: Thu, 16 Jun 2022 17:02:51 -0700 Subject: [PATCH 02/66] Fix GetDescription and GetChange for reference-based completion providers --- .../AsyncCompletion/CommitManager.cs | 2 +- .../Test/Completion/CompletionServiceTests.cs | 24 +++- .../AbstractCompletionProviderTests.cs | 2 +- .../CompletionService.ProviderManager.cs | 105 +++++++++--------- .../Portable/Completion/CompletionService.cs | 16 +-- ...tractCreateServicesOnTextViewConnection.cs | 2 +- 6 files changed, 86 insertions(+), 65 deletions(-) diff --git a/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CommitManager.cs b/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CommitManager.cs index 9cf97c7daa16c..a1b470b712d62 100644 --- a/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CommitManager.cs +++ b/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CommitManager.cs @@ -218,7 +218,7 @@ public IEnumerable PotentialCommitCharacters var view = session.TextView; - var provider = completionService.GetProvider(roslynItem); + var provider = completionService.GetProvider(roslynItem, document.Project); if (provider is ICustomCommitCompletionProvider customCommitProvider) { customCommitProvider.Commit(roslynItem, view, subjectBuffer, triggerSnapshot, commitCharacter); diff --git a/src/EditorFeatures/Test/Completion/CompletionServiceTests.cs b/src/EditorFeatures/Test/Completion/CompletionServiceTests.cs index a0d57073a7993..00c018c26fdbe 100644 --- a/src/EditorFeatures/Test/Completion/CompletionServiceTests.cs +++ b/src/EditorFeatures/Test/Completion/CompletionServiceTests.cs @@ -48,8 +48,17 @@ class Test { var completions = await completionService.GetCompletionsAsync(document, caretPosition, CompletionOptions.Default, OptionValueSet.Empty); Assert.False(completions.IsEmpty); + var item = Assert.Single(completions.ItemsList.Where(item => item.ProviderName == typeof(DebugAssertTestCompletionProvider).FullName)); - Assert.Equal("Assertion failed", item.DisplayText); + Assert.Equal(nameof(DebugAssertTestCompletionProvider), item.DisplayText); + + var expectedDescriptionText = nameof(DebugAssertTestCompletionProvider); + var actualDescriptionText = (await completionService.GetDescriptionAsync(document, item, CompletionOptions.Default, SymbolDescriptionOptions.Default).ConfigureAwait(false))!.Text; + Assert.Equal(expectedDescriptionText, actualDescriptionText); + + var expectedChange = new TextChange(item.Span, nameof(DebugAssertTestCompletionProvider)); + var actualChange = (await completionService.GetChangeAsync(document, item).ConfigureAwait(false)).TextChange; + Assert.True(expectedChange ==actualChange); } private class MockAnalyzerReference : AnalyzerReference, ICompletionProviderFactory @@ -93,11 +102,22 @@ public override bool ShouldTriggerCompletion(SourceText text, int caretPosition, public override async Task ProvideCompletionsAsync(CompletionContext context) { - var completionItem = CompletionItem.Create(displayText: "Assertion failed", displayTextSuffix: "", rules: CompletionItemRules.Default); + var completionItem = CompletionItem.Create(displayText: nameof(DebugAssertTestCompletionProvider), displayTextSuffix: "", rules: CompletionItemRules.Default); context.AddItem(completionItem); context.CompletionListSpan = await GetTextChangeSpanAsync(context.Document, context.CompletionListSpan, context.CancellationToken).ConfigureAwait(false); } + + public override Task GetDescriptionAsync(Document document, CompletionItem item, CancellationToken cancellationToken) + { + return Task.FromResult(CompletionDescription.FromText(nameof(DebugAssertTestCompletionProvider))); + } + + public override Task GetChangeAsync(Document document, CompletionItem item, char? commitKey, CancellationToken cancellationToken) + { + return Task.FromResult(CompletionChange.Create(new TextChange(item.Span, nameof(DebugAssertTestCompletionProvider)))); + } + private static async Task GetTextChangeSpanAsync(Document document, TextSpan startSpan, CancellationToken cancellationToken) { var result = startSpan; diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs index ac3a6a9854c73..a469c49596451 100644 --- a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs @@ -106,7 +106,7 @@ protected static async Task CanUseSpeculativeSemanticModelAsync(Document d internal virtual CompletionService GetCompletionService(Project project) { var completionService = project.LanguageServices.GetRequiredService(); - var completionProviders = completionService.GetImportedProviders(); + var completionProviders = completionService.GetLazyImportedProviders(); var completionProvider = Assert.Single(completionProviders).Value; Assert.IsType(GetCompletionProviderType(), completionProvider); diff --git a/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs b/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs index 8bc7bf282f1b1..4117b1d5e2de3 100644 --- a/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs +++ b/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs @@ -12,6 +12,7 @@ using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Utilities; using Roslyn.Utilities; @@ -25,21 +26,17 @@ private sealed class ProviderManager : IEqualityComparer _nameToProvider = new(); private readonly Dictionary, ImmutableArray> _rolesToProviders; - private readonly Func, ImmutableArray> _createRoleProviders; - private readonly Func _getProviderByName; - - private IEnumerable>? _lazyImportedProviders; + private IReadOnlyList>? _lazyImportedProviders; private readonly CompletionService _service; public ProviderManager(CompletionService service) { _service = service; _rolesToProviders = new Dictionary, ImmutableArray>(this); - _createRoleProviders = CreateRoleProviders; - _getProviderByName = GetProviderByName; } - public IEnumerable> GetImportedProviders() + // Exposed for pre-populating MEF providers. + public IReadOnlyList> GetLazyImportedProviders() { if (_lazyImportedProviders == null) { @@ -57,32 +54,59 @@ public ProviderManager(CompletionService service) return _lazyImportedProviders; } - public ImmutableArray GetAllProviders(ImmutableHashSet roles) + // Exposed for pre-populating project-based providers. + public static ImmutableArray GetProjectCompletionProviders(Project? project) { - var imported = GetImportedProviders() - .Where(lz => lz.Metadata.Roles == null || lz.Metadata.Roles.Length == 0 || roles.Overlaps(lz.Metadata.Roles)) - .Select(lz => lz.Value); - -#pragma warning disable 0618 - // We need to keep supporting built-in providers for a while longer since this is a public API. - // https://github.com/dotnet/roslyn/issues/42367 - var builtin = _service.GetBuiltInProviders(); -#pragma warning restore 0618 + if (project?.Solution.Workspace.Kind == WorkspaceKind.Interactive) + { + // TODO (https://github.com/dotnet/roslyn/issues/4932): Don't restrict completions in Interactive + return ImmutableArray.Empty; + } - return imported.Concat(builtin).ToImmutableArray(); + return ProjectCompletionProvider.GetExtensions(project); } - public ImmutableArray GetProviders(ImmutableHashSet? roles) + private ImmutableArray GetImportedAndBuiltInProviders(ImmutableHashSet? roles) { roles ??= ImmutableHashSet.Empty; lock (_gate) { - return _rolesToProviders.GetOrAdd(roles, _createRoleProviders); + if (!_rolesToProviders.TryGetValue(roles, out var providers)) + { + providers = GetImportedAndBuiltInProvidersWorker(roles); + _rolesToProviders.Add(roles, providers); + } + + return providers; + } + + ImmutableArray GetImportedAndBuiltInProvidersWorker(ImmutableHashSet roles) + { + using var _ = ArrayBuilder.GetInstance(out var providers); + providers.AddRange(GetLazyImportedProviders() + .Where(lz => lz.Metadata.Roles == null || lz.Metadata.Roles.Length == 0 || roles.Overlaps(lz.Metadata.Roles)) + .Select(lz => lz.Value)); + +#pragma warning disable 0618 + // We need to keep supporting built-in providers for a while longer since this is a public API. + // https://github.com/dotnet/roslyn/issues/42367 + providers.AddRange(_service.GetBuiltInProviders()); +#pragma warning restore 0618 + + return providers.ToImmutable(); } } - public CompletionProvider? GetProvider(CompletionItem item) + public ImmutableArray GetProviders(ImmutableHashSet roles, Project? project) + { + using var _ = ArrayBuilder.GetInstance(out var providers); + providers.AddRange(GetImportedAndBuiltInProviders(roles)); + providers.AddRange(GetProjectCompletionProviders(project)); + return providers.ToImmutable(); + } + + public CompletionProvider? GetProvider(CompletionItem item, Project? project) { CompletionProvider? provider = null; @@ -90,8 +114,14 @@ public ImmutableArray GetProviders(ImmutableHashSet? { lock (_gate) { - provider = _nameToProvider.GetOrAdd(item.ProviderName, _getProviderByName); + if (!_nameToProvider.TryGetValue(item.ProviderName, out provider)) + { + provider = GetImportedAndBuiltInProviders(roles: ImmutableHashSet.Empty).FirstOrDefault(p => p.Name == item.ProviderName); + _nameToProvider.Add(item.ProviderName, provider); + } } + + provider ??= GetProjectCompletionProviders(project).FirstOrDefault(p => p.Name == item.ProviderName); } return provider; @@ -100,22 +130,11 @@ public ImmutableArray GetProviders(ImmutableHashSet? public ConcatImmutableArray GetFilteredProviders( Project? project, ImmutableHashSet? roles, CompletionTrigger trigger, in CompletionOptions options) { - var allCompletionProviders = FilterProviders(GetProviders(roles), trigger, options); + var allCompletionProviders = FilterProviders(GetImportedAndBuiltInProviders(roles), trigger, options); var projectCompletionProviders = FilterProviders(GetProjectCompletionProviders(project), trigger, options); return allCompletionProviders.ConcatFast(projectCompletionProviders); } - public static ImmutableArray GetProjectCompletionProviders(Project? project) - { - if (project?.Solution.Workspace.Kind == WorkspaceKind.Interactive) - { - // TODO (https://github.com/dotnet/roslyn/issues/4932): Don't restrict completions in Interactive - return ImmutableArray.Empty; - } - - return ProjectCompletionProvider.GetExtensions(project); - } - private ImmutableArray FilterProviders( ImmutableArray providers, CompletionTrigger trigger, @@ -159,24 +178,6 @@ public static ImmutableArray GetProjectCompletionProviders(P return ImmutableArray.Empty; } - private CompletionProvider? GetProviderByName(string providerName) - { - var providers = GetAllProviders(roles: ImmutableHashSet.Empty); - return providers.FirstOrDefault(p => p.Name == providerName); - } - - private ImmutableArray CreateRoleProviders(ImmutableHashSet roles) - { - var providers = GetAllProviders(roles); - - foreach (var provider in providers) - { - _nameToProvider[provider.Name] = provider; - } - - return providers; - } - bool IEqualityComparer>.Equals([AllowNull] ImmutableHashSet x, [AllowNull] ImmutableHashSet y) { if (x == y) diff --git a/src/Features/Core/Portable/Completion/CompletionService.cs b/src/Features/Core/Portable/Completion/CompletionService.cs index 9228bdff74be0..a0e05014ff939 100644 --- a/src/Features/Core/Portable/Completion/CompletionService.cs +++ b/src/Features/Core/Portable/Completion/CompletionService.cs @@ -194,7 +194,7 @@ public virtual TextSpan GetDefaultCompletionListSpan(SourceText text, int caretP /// internal virtual async Task GetDescriptionAsync(Document document, CompletionItem item, CompletionOptions options, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken = default) { - var provider = GetProvider(item); + var provider = GetProvider(item, document.Project); if (provider is null) return CompletionDescription.Empty; @@ -220,7 +220,7 @@ public virtual TextSpan GetDefaultCompletionListSpan(SourceText text, int caretP char? commitCharacter = null, CancellationToken cancellationToken = default) { - var provider = GetProvider(item); + var provider = GetProvider(item, document.Project); if (provider != null) { // We don't need SemanticModel here, just want to make sure it won't get GC'd before CompletionProviders are able to get it. @@ -392,8 +392,8 @@ public virtual TextSpan GetDefaultCompletionListSpan(SourceText text, int caretP /// /// Don't call. Used for pre-populating MEF providers only. /// - internal IEnumerable> GetImportedProviders() - => _providerManager.GetImportedProviders(); + internal IReadOnlyList> GetLazyImportedProviders() + => _providerManager.GetLazyImportedProviders(); /// /// Don't call. Used for pre-populating NuGet providers only. @@ -401,8 +401,8 @@ public virtual TextSpan GetDefaultCompletionListSpan(SourceText text, int caretP internal static ImmutableArray GetProjectCompletionProviders(Project? project) => ProviderManager.GetProjectCompletionProviders(project); - internal CompletionProvider? GetProvider(CompletionItem item) - => _providerManager.GetProvider(item); + internal CompletionProvider? GetProvider(CompletionItem item, Project? project = null) + => _providerManager.GetProvider(item, project); internal TestAccessor GetTestAccessor() => new(this); @@ -414,8 +414,8 @@ internal TestAccessor GetTestAccessor() public TestAccessor(CompletionService completionServiceWithProviders) => _completionServiceWithProviders = completionServiceWithProviders; - internal ImmutableArray GetAllProviders(ImmutableHashSet roles) - => _completionServiceWithProviders._providerManager.GetAllProviders(roles); + internal ImmutableArray GetAllProviders(ImmutableHashSet roles, Project? project = null) + => _completionServiceWithProviders._providerManager.GetProviders(roles, project); internal async Task GetContextAsync( CompletionProvider provider, diff --git a/src/VisualStudio/Core/Def/LanguageService/AbstractCreateServicesOnTextViewConnection.cs b/src/VisualStudio/Core/Def/LanguageService/AbstractCreateServicesOnTextViewConnection.cs index 6e69728f5a72d..1a1a3fd27da51 100644 --- a/src/VisualStudio/Core/Def/LanguageService/AbstractCreateServicesOnTextViewConnection.cs +++ b/src/VisualStudio/Core/Def/LanguageService/AbstractCreateServicesOnTextViewConnection.cs @@ -115,7 +115,7 @@ private async Task InitializeServicesAsync() // Preload completion providers on a background thread since assembly loads can be slow // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1242321 - _ = languageServices.GetService()?.GetImportedProviders().SelectAsArray(p => p.Value); + _ = languageServices.GetService()?.GetLazyImportedProviders().SelectAsArray(p => p.Value); } } } From 0cc24914f1e4881bccde65b99d088e235893d816 Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Wed, 22 Jun 2022 10:45:53 -0700 Subject: [PATCH 03/66] Add targets file for R2R --- eng/Versions.props | 3 ++ eng/targets/Imports.targets | 1 + eng/targets/ReadyToRun.targets | 53 +++++++++++++++++++ .../Microsoft.CodeAnalysis.CSharp.csproj | 1 + 4 files changed, 58 insertions(+) create mode 100644 eng/targets/ReadyToRun.targets diff --git a/eng/Versions.props b/eng/Versions.props index 4f2432ff6b213..e75c36b1bfbcc 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -304,4 +304,7 @@ true true + + 6.0.2 + diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets index 9645e7e596491..f232b27fd00f2 100644 --- a/eng/targets/Imports.targets +++ b/eng/targets/Imports.targets @@ -3,6 +3,7 @@ + + + + + + + + <_Crossgen2Path>$(NuGetPackageRoot)Microsoft.NETCore.App.crossgen2.$(EnableReadyToRunGeneration)\$(MicrosoftNetCoreAppPackagesVersion)\tools\crossgen2.dll + <_RuntimeLibraryPath>$(NuGetPackageRoot)Microsoft.NETCore.App.Runtime.$(EnableReadyToRunGeneration)\$(MicrosoftNetCoreAppPackagesVersion)\runtimes\$(EnableReadyToRunGeneration)\lib\net6.0 + <_RunCrossgen2>false + <_RunCrossgen2 Condition="'$(EnableReadyToRunGeneration)' != '' and Exists('$(_Crossgen2Path)') and Exists('$(_RuntimeLibraryPath)')">true + + + + <_R2RRuntimeAssemblies Include="$(_RuntimeLibraryPath)\*.dll" /> + + + + <_R2ROptimizeAssemblyPath>@(IntermediateAssembly->'"%(FullPath)"') + <_Crossgen2Args>$(_R2ROptimizeAssemblyPath) --out-near-input --targetarch:x64 --optimize --pdb + <_Crossgen2Args>$(_Crossgen2Args) @(_R2RRuntimeAssemblies->'--reference:"%(FullPath)"', ' ') + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Compilers/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.csproj b/src/Compilers/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.csproj index b31469d28a312..8a9d0233f5082 100644 --- a/src/Compilers/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.csproj +++ b/src/Compilers/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.csproj @@ -8,6 +8,7 @@ netcoreapp3.1;netstandard2.0 true full + win-x64 true From 8da7ea56f119b6b8f909eb9d50990d5cab812b5f Mon Sep 17 00:00:00 2001 From: Gen Lu Date: Wed, 29 Jun 2022 09:36:20 -0700 Subject: [PATCH 04/66] Fix formatting --- .../Test/Completion/CompletionServiceTests.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/EditorFeatures/Test/Completion/CompletionServiceTests.cs b/src/EditorFeatures/Test/Completion/CompletionServiceTests.cs index 00c018c26fdbe..d8c179b3e3d21 100644 --- a/src/EditorFeatures/Test/Completion/CompletionServiceTests.cs +++ b/src/EditorFeatures/Test/Completion/CompletionServiceTests.cs @@ -2,6 +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 Microsoft.CodeAnalysis.Completion; +using Microsoft.CodeAnalysis.Diagnostics; #nullable disable using System; @@ -9,8 +11,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Completion; -using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Options; @@ -58,7 +58,7 @@ class Test { var expectedChange = new TextChange(item.Span, nameof(DebugAssertTestCompletionProvider)); var actualChange = (await completionService.GetChangeAsync(document, item).ConfigureAwait(false)).TextChange; - Assert.True(expectedChange ==actualChange); + Assert.True(expectedChange == actualChange); } private class MockAnalyzerReference : AnalyzerReference, ICompletionProviderFactory @@ -107,7 +107,6 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) context.CompletionListSpan = await GetTextChangeSpanAsync(context.Document, context.CompletionListSpan, context.CancellationToken).ConfigureAwait(false); } - public override Task GetDescriptionAsync(Document document, CompletionItem item, CancellationToken cancellationToken) { return Task.FromResult(CompletionDescription.FromText(nameof(DebugAssertTestCompletionProvider))); From c8b6b92d4e6438df552999ab2834957d8b2b7ba6 Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Fri, 8 Jul 2022 18:00:00 -0700 Subject: [PATCH 05/66] Batch run crossgen when building vsix --- eng/targets/Imports.targets | 1 - eng/targets/ReadyToRun.targets | 53 ----------- .../Microsoft.CodeAnalysis.CSharp.csproj | 1 - ...is.Remote.ServiceHub.CoreComponents.csproj | 90 ++++++++++++++++++- 4 files changed, 86 insertions(+), 59 deletions(-) delete mode 100644 eng/targets/ReadyToRun.targets diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets index f232b27fd00f2..9645e7e596491 100644 --- a/eng/targets/Imports.targets +++ b/eng/targets/Imports.targets @@ -3,7 +3,6 @@ - - - - - - - - <_Crossgen2Path>$(NuGetPackageRoot)Microsoft.NETCore.App.crossgen2.$(EnableReadyToRunGeneration)\$(MicrosoftNetCoreAppPackagesVersion)\tools\crossgen2.dll - <_RuntimeLibraryPath>$(NuGetPackageRoot)Microsoft.NETCore.App.Runtime.$(EnableReadyToRunGeneration)\$(MicrosoftNetCoreAppPackagesVersion)\runtimes\$(EnableReadyToRunGeneration)\lib\net6.0 - <_RunCrossgen2>false - <_RunCrossgen2 Condition="'$(EnableReadyToRunGeneration)' != '' and Exists('$(_Crossgen2Path)') and Exists('$(_RuntimeLibraryPath)')">true - - - - <_R2RRuntimeAssemblies Include="$(_RuntimeLibraryPath)\*.dll" /> - - - - <_R2ROptimizeAssemblyPath>@(IntermediateAssembly->'"%(FullPath)"') - <_Crossgen2Args>$(_R2ROptimizeAssemblyPath) --out-near-input --targetarch:x64 --optimize --pdb - <_Crossgen2Args>$(_Crossgen2Args) @(_R2RRuntimeAssemblies->'--reference:"%(FullPath)"', ' ') - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Compilers/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.csproj b/src/Compilers/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.csproj index 8a9d0233f5082..b31469d28a312 100644 --- a/src/Compilers/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.csproj +++ b/src/Compilers/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.csproj @@ -8,7 +8,6 @@ netcoreapp3.1;netstandard2.0 true full - win-x64 true diff --git a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj index 8ac85a163fffc..64f18a7814b57 100644 --- a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj +++ b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj @@ -6,6 +6,7 @@ net6.0 $(MicrosoftNetCoreAppPackagesVersion) $(MicrosoftNetCoreAppPackagesVersion) + $(MicrosoftNetCoreAppPackagesVersion) @@ -20,19 +21,100 @@ - + + - + + + + <_ProjectReferenceAssemblies Include="@(_ResolvedProjectReferencePaths->'%(FileName)%(Extension)')" /> + + <_AllPublishedAssemblyPaths Include="$(PublishDir)\**\*.dll" Exclude="$(PublishDir)\**\*.resources.dll" /> + <_AllPublishedAssemblies Include="@(_AllPublishedAssemblyPaths->'%(FileName)%(Extension)')" > + <_FullFilePath>%(FullPath) + + + <_NoR2RAssemblies Include="@(_AllPublishedAssemblies)" Exclude="@(_ProjectReferenceAssemblies)" > + <_FullFilePath>%(_AllPublishedAssemblies._FullFilePath) + + <_NoR2RAssemblyPaths Include="@(_NoR2RAssemblies->'%(_FullFilePath)')" /> + + <_RoslynAssemblyPaths Include="@(_AllPublishedAssemblyPaths)" Exclude="@(_NoR2RAssemblyPaths)" /> + + + + $(PublishDir)\CrossGen\ + $(CrossgenWorkFolder)OriginalAssemblies\ + + + + + + + + + <_CrossgenTargetPaths Include="$(OriginalAssemblyFolder)\*.dll" /> + <_RoslynDependencies Include="@(_CrossgenTargetPaths)" /> + + + + + + + + <_Crossgen2Path>$(PkgMicrosoft_NETCore_App_crossgen2_win-x64)\tools\crossgen2.dll + <_R2ROptimizeAssemblyPath>%(_CrossgenTargetPaths.FullPath) + <_R2ROptimizeAssemblyOutputPath>$(PublishDir)\%(_CrossgenTargetPaths.Filename)%(_CrossgenTargetPaths.Extension) + <_RspFilePath>$(CrossgenWorkFolder)%(_CrossgenTargetPaths.Filename).CrossgenArgs.rsp + + + + + + + + + + + + + + + + + + + + + + + + + <_RuntimeLibraries Include="$(PkgMicrosoft_NETCore_App_Runtime_win-x64)\runtimes\win-x64\**\*.dll" /> - <_RuntimeLibraries Include="$(PkgMicrosoft_WindowsDesktop_App_Runtime_win-x64)\runtimes\win-x64\**\*.dll" /> + <_WinRuntimeLibraries Include="$(PkgMicrosoft_WindowsDesktop_App_Runtime_win-x64)\runtimes\win-x64\**\*.dll" /> + <_RuntimeLibrariesInPublishFolder Include="@(_RuntimeLibraries->'$(PublishDir)\%(FileName)%(Extension)')" /> + <_RuntimeLibrariesInPublishFolder Include="@(_WinRuntimeLibraries->'$(PublishDir)\%(FileName)%(Extension)')" /> + <_NonRuntimeAssembliesInPublishFolder Include="$(PublishDir)\*.dll" Exclude="@(_RuntimeLibrariesInPublishFolder)" /> + + + <_ExcludedFiles Include="$(PublishDir)**\Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.*" /> <_ExcludedFiles Include="$(PublishDir)**\*.pdb" /> + <_ExcludedFiles Include="$(CrossgenWorkFolder)**\*" /> + <_ExcludedFiles Include="$(PublishDir)\runtimes\**\*.*" /> - <_ExcludedFiles Include="@(_RuntimeLibraries->'$(PublishDir)\%(FileName)%(Extension)')" /> + <_ExcludedFiles Include="@(_RuntimeLibrariesInPublishFolder)" /> From b16ef1dfb8d10207ddbf61aa1b8207bf659b42fc Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Mon, 11 Jul 2022 12:45:57 -0700 Subject: [PATCH 06/66] Enable .Net Core OOP by default --- src/EditorFeatures/Core/Remote/RemoteHostOptions.cs | 2 +- src/VisualStudio/Core/Def/PackageRegistration.pkgdef | 2 +- .../Core/Def/Remote/VisualStudioRemoteHostClientProvider.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs b/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs index d7d91e233388d..3cf678b68b190 100644 --- a/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs +++ b/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs @@ -28,7 +28,7 @@ internal sealed class RemoteHostOptions // use coreclr host for OOP public static readonly Option2 OOPCoreClrFeatureFlag = new( - FeatureName, nameof(OOPCoreClrFeatureFlag), defaultValue: false, + FeatureName, nameof(OOPCoreClrFeatureFlag), defaultValue: true, new FeatureFlagStorageLocation("Roslyn.ServiceHubCore")); } } diff --git a/src/VisualStudio/Core/Def/PackageRegistration.pkgdef b/src/VisualStudio/Core/Def/PackageRegistration.pkgdef index 2f6fb7dc9256f..9a97496d19184 100644 --- a/src/VisualStudio/Core/Def/PackageRegistration.pkgdef +++ b/src/VisualStudio/Core/Def/PackageRegistration.pkgdef @@ -27,7 +27,7 @@ [$RootKey$\FeatureFlags\Roslyn\ServiceHubCore] "Description"="Run C#/VB out-of-process code analysis on .Net 6 ServiceHub host." -"Value"=dword:00000000 +"Value"=dword:00000001 "Title"="Run C#/VB code analysis on .Net 6 (requires restart)" "PreviewPaneChannels"="IntPreview,int.main" diff --git a/src/VisualStudio/Core/Def/Remote/VisualStudioRemoteHostClientProvider.cs b/src/VisualStudio/Core/Def/Remote/VisualStudioRemoteHostClientProvider.cs index 5a6b3d54e20e0..5b12c9abe2f69 100644 --- a/src/VisualStudio/Core/Def/Remote/VisualStudioRemoteHostClientProvider.cs +++ b/src/VisualStudio/Core/Def/Remote/VisualStudioRemoteHostClientProvider.cs @@ -103,7 +103,7 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) var serviceBroker = brokeredServiceContainer.GetFullAccessServiceBroker(); var configuration = - (_globalOptions.GetOption(RemoteHostOptions.OOPCoreClrFeatureFlag) ? RemoteProcessConfiguration.Core : 0) | + RemoteProcessConfiguration.Core | (_globalOptions.GetOption(RemoteHostOptions.OOPServerGCFeatureFlag) ? RemoteProcessConfiguration.ServerGC : 0) | (_globalOptions.GetOption(SolutionCrawlerRegistrationService.EnableSolutionCrawler) ? RemoteProcessConfiguration.EnableSolutionCrawler : 0); From f9b64d336ad4bf657ca00a98e9cce24438c36133 Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Mon, 11 Jul 2022 15:21:59 -0700 Subject: [PATCH 07/66] crossgen more binaries --- eng/Signing.props | 7 ++++++ ...is.Remote.ServiceHub.CoreComponents.csproj | 25 ++++++++++++------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/eng/Signing.props b/eng/Signing.props index 828f775c2b2a7..536efb81e4f5e 100644 --- a/eng/Signing.props +++ b/eng/Signing.props @@ -41,5 +41,12 @@ + + + + + + + diff --git a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj index 64f18a7814b57..2aad32da54e23 100644 --- a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj +++ b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj @@ -34,19 +34,29 @@ - <_ProjectReferenceAssemblies Include="@(_ResolvedProjectReferencePaths->'%(FileName)%(Extension)')" /> + <_R2RAssemblies Include="@(_ResolvedProjectReferencePaths->'%(FileName)%(Extension)')" /> + + <_R2RAssemblies Include="Microsoft.ServiceHub.Framework.dll" /> + <_R2RAssemblies Include="Microsoft.VisualStudio.Composition.dll" /> + <_R2RAssemblies Include="Microsoft.VisualStudio.Telemetry.dll" /> + <_R2RAssemblies Include="Microsoft.VisualStudio.Threading.dll" /> + <_R2RAssemblies Include="MessagePack.dll" /> + <_R2RAssemblies Include="Nerdback.Streams.dll" /> + <_R2RAssemblies Include="Newtonsoft.Json.dll" /> + <_R2RAssemblies Include="SQLitePCLRaw.batteries_v2.dll" /> + <_R2RAssemblies Include="StreamJsonRpc.dll" /> <_AllPublishedAssemblyPaths Include="$(PublishDir)\**\*.dll" Exclude="$(PublishDir)\**\*.resources.dll" /> <_AllPublishedAssemblies Include="@(_AllPublishedAssemblyPaths->'%(FileName)%(Extension)')" > <_FullFilePath>%(FullPath) - <_NoR2RAssemblies Include="@(_AllPublishedAssemblies)" Exclude="@(_ProjectReferenceAssemblies)" > + <_NoR2RAssemblies Include="@(_AllPublishedAssemblies)" Exclude="@(_R2RAssemblies)" > <_FullFilePath>%(_AllPublishedAssemblies._FullFilePath) <_NoR2RAssemblyPaths Include="@(_NoR2RAssemblies->'%(_FullFilePath)')" /> - <_RoslynAssemblyPaths Include="@(_AllPublishedAssemblyPaths)" Exclude="@(_NoR2RAssemblyPaths)" /> + <_R2RAssemblyPaths Include="@(_AllPublishedAssemblyPaths)" Exclude="@(_NoR2RAssemblyPaths)" /> @@ -54,8 +64,8 @@ $(CrossgenWorkFolder)OriginalAssemblies\ - - + + @@ -65,11 +75,9 @@ <_CrossgenTargetPaths Include="$(OriginalAssemblyFolder)\*.dll" /> <_RoslynDependencies Include="@(_CrossgenTargetPaths)" /> - - - + <_Crossgen2Path>$(PkgMicrosoft_NETCore_App_crossgen2_win-x64)\tools\crossgen2.dll <_R2ROptimizeAssemblyPath>%(_CrossgenTargetPaths.FullPath) @@ -96,7 +104,6 @@ - From d315b246d612c133baab5d4b7679cf8b497bc4c0 Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Tue, 12 Jul 2022 14:25:40 -0700 Subject: [PATCH 08/66] Address review comments --- ...is.Remote.ServiceHub.CoreComponents.csproj | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj index 2aad32da54e23..91f36b61bae82 100644 --- a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj +++ b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj @@ -34,7 +34,8 @@ - <_R2RAssemblies Include="@(_ResolvedProjectReferencePaths->'%(FileName)%(Extension)')" /> + <_R2RAssemblies Include="@(ReferencePath->'%(FileName)%(Extension)')" Condition="'%(ReferenceSourceTarget)' == 'ProjectReference'" /> + <_R2RAssemblies Include="Microsoft.ServiceHub.Framework.dll" /> <_R2RAssemblies Include="Microsoft.VisualStudio.Composition.dll" /> @@ -45,31 +46,31 @@ <_R2RAssemblies Include="Newtonsoft.Json.dll" /> <_R2RAssemblies Include="SQLitePCLRaw.batteries_v2.dll" /> <_R2RAssemblies Include="StreamJsonRpc.dll" /> + <_AllPublishedAssemblyPaths Include="$(PublishDir)\**\*.dll" Exclude="$(PublishDir)\**\*.resources.dll" /> <_AllPublishedAssemblies Include="@(_AllPublishedAssemblyPaths->'%(FileName)%(Extension)')" > <_FullFilePath>%(FullPath) + <_NoR2RAssemblies Include="@(_AllPublishedAssemblies)" Exclude="@(_R2RAssemblies)" > <_FullFilePath>%(_AllPublishedAssemblies._FullFilePath) <_NoR2RAssemblyPaths Include="@(_NoR2RAssemblies->'%(_FullFilePath)')" /> + <_R2RAssemblyPaths Include="@(_AllPublishedAssemblyPaths)" Exclude="@(_NoR2RAssemblyPaths)" /> - $(PublishDir)\CrossGen\ - $(CrossgenWorkFolder)OriginalAssemblies\ + $(PublishDir)\CrossGen\ + $(CrossgenWorkDir)OriginalAssemblies\ - - - - + + + <_CrossgenTargetPaths Include="$(OriginalAssemblyFolder)\*.dll" /> @@ -82,23 +83,22 @@ <_Crossgen2Path>$(PkgMicrosoft_NETCore_App_crossgen2_win-x64)\tools\crossgen2.dll <_R2ROptimizeAssemblyPath>%(_CrossgenTargetPaths.FullPath) <_R2ROptimizeAssemblyOutputPath>$(PublishDir)\%(_CrossgenTargetPaths.Filename)%(_CrossgenTargetPaths.Extension) - <_RspFilePath>$(CrossgenWorkFolder)%(_CrossgenTargetPaths.Filename).CrossgenArgs.rsp + <_RspFilePath>$(CrossgenWorkDir)%(_CrossgenTargetPaths.Filename).CrossgenArgs.rsp - - - - - - - - - + <_RspFileLines Include="$(_R2ROptimizeAssemblyPath)" /> + <_RspFileLines Include="--out:$(_R2ROptimizeAssemblyOutputPath)" /> + <_RspFileLines Include="--targetarch:x64" /> + <_RspFileLines Include="--optimize" /> + <_RspFileLines Include="@(_RuntimeLibraries->'--reference:%(FullPath)')" /> + <_RspFileLines Include="@(_RoslynDependencies->'--reference:%(FullPath)')" /> + <_RspFileLines Include="@(_NonRuntimeAssembliesInPublishFolder->'--reference:%(FullPath)')" Exclude="@(_RoslynDependencies)"/> - + + - + @@ -110,8 +110,10 @@ <_RuntimeLibraries Include="$(PkgMicrosoft_NETCore_App_Runtime_win-x64)\runtimes\win-x64\**\*.dll" /> <_WinRuntimeLibraries Include="$(PkgMicrosoft_WindowsDesktop_App_Runtime_win-x64)\runtimes\win-x64\**\*.dll" /> + <_RuntimeLibrariesInPublishFolder Include="@(_RuntimeLibraries->'$(PublishDir)\%(FileName)%(Extension)')" /> <_RuntimeLibrariesInPublishFolder Include="@(_WinRuntimeLibraries->'$(PublishDir)\%(FileName)%(Extension)')" /> + <_NonRuntimeAssembliesInPublishFolder Include="$(PublishDir)\*.dll" Exclude="@(_RuntimeLibrariesInPublishFolder)" /> @@ -120,7 +122,7 @@ <_ExcludedFiles Include="$(PublishDir)**\Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.*" /> <_ExcludedFiles Include="$(PublishDir)**\*.pdb" /> - <_ExcludedFiles Include="$(CrossgenWorkFolder)**\*" /> + <_ExcludedFiles Include="$(CrossgenWorkDir)**\*" /> <_ExcludedFiles Include="$(PublishDir)\runtimes\**\*.*" /> From 4eac80940b6f895cb92bab4d1d8bd1fe366b3fed Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Wed, 13 Jul 2022 12:30:53 -0700 Subject: [PATCH 09/66] Run crossgen conditionally --- ...is.Remote.ServiceHub.CoreComponents.csproj | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj index 91f36b61bae82..3093f66ea5c44 100644 --- a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj +++ b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj @@ -4,9 +4,10 @@ Exe net6.0 + true $(MicrosoftNetCoreAppPackagesVersion) $(MicrosoftNetCoreAppPackagesVersion) - $(MicrosoftNetCoreAppPackagesVersion) + $(MicrosoftNetCoreAppPackagesVersion) @@ -28,7 +29,7 @@ --> - + @@ -67,18 +68,20 @@ $(PublishDir)\CrossGen\ $(CrossgenWorkDir)OriginalAssemblies\ + + - <_CrossgenTargetPaths Include="$(OriginalAssemblyFolder)\*.dll" /> - <_RoslynDependencies Include="@(_CrossgenTargetPaths)" /> + <_CrossgenTargetsAsDependencies Include="@(_CrossgenTargetPaths)" /> + <_NonCrossgenTargetsAsDependencies Include="@(_NonRuntimeAssembliesInPublishFolder)" Exclude="@(_R2RAssemblyPaths)" /> - + <_Crossgen2Path>$(PkgMicrosoft_NETCore_App_crossgen2_win-x64)\tools\crossgen2.dll <_R2ROptimizeAssemblyPath>%(_CrossgenTargetPaths.FullPath) @@ -91,8 +94,8 @@ <_RspFileLines Include="--targetarch:x64" /> <_RspFileLines Include="--optimize" /> <_RspFileLines Include="@(_RuntimeLibraries->'--reference:%(FullPath)')" /> - <_RspFileLines Include="@(_RoslynDependencies->'--reference:%(FullPath)')" /> - <_RspFileLines Include="@(_NonRuntimeAssembliesInPublishFolder->'--reference:%(FullPath)')" Exclude="@(_RoslynDependencies)"/> + <_RspFileLines Include="@(_CrossgenTargetsAsDependencies->'--reference:%(FullPath)')" /> + <_RspFileLines Include="@(_NonCrossgenTargetsAsDependencies->'--reference:%(FullPath)')" /> @@ -118,7 +121,9 @@ - + + + <_ExcludedFiles Include="$(PublishDir)**\Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.*" /> <_ExcludedFiles Include="$(PublishDir)**\*.pdb" /> From e0259c206dbd6ebb0bbe77f4a9cd87494fda2cbc Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Wed, 13 Jul 2022 12:49:05 -0700 Subject: [PATCH 10/66] Revert "Enable .Net Core OOP by default" This reverts commit b16ef1dfb8d10207ddbf61aa1b8207bf659b42fc. --- src/EditorFeatures/Core/Remote/RemoteHostOptions.cs | 2 +- src/VisualStudio/Core/Def/PackageRegistration.pkgdef | 2 +- .../Core/Def/Remote/VisualStudioRemoteHostClientProvider.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs b/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs index 3cf678b68b190..d7d91e233388d 100644 --- a/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs +++ b/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs @@ -28,7 +28,7 @@ internal sealed class RemoteHostOptions // use coreclr host for OOP public static readonly Option2 OOPCoreClrFeatureFlag = new( - FeatureName, nameof(OOPCoreClrFeatureFlag), defaultValue: true, + FeatureName, nameof(OOPCoreClrFeatureFlag), defaultValue: false, new FeatureFlagStorageLocation("Roslyn.ServiceHubCore")); } } diff --git a/src/VisualStudio/Core/Def/PackageRegistration.pkgdef b/src/VisualStudio/Core/Def/PackageRegistration.pkgdef index 9a97496d19184..2f6fb7dc9256f 100644 --- a/src/VisualStudio/Core/Def/PackageRegistration.pkgdef +++ b/src/VisualStudio/Core/Def/PackageRegistration.pkgdef @@ -27,7 +27,7 @@ [$RootKey$\FeatureFlags\Roslyn\ServiceHubCore] "Description"="Run C#/VB out-of-process code analysis on .Net 6 ServiceHub host." -"Value"=dword:00000001 +"Value"=dword:00000000 "Title"="Run C#/VB code analysis on .Net 6 (requires restart)" "PreviewPaneChannels"="IntPreview,int.main" diff --git a/src/VisualStudio/Core/Def/Remote/VisualStudioRemoteHostClientProvider.cs b/src/VisualStudio/Core/Def/Remote/VisualStudioRemoteHostClientProvider.cs index 5b12c9abe2f69..5a6b3d54e20e0 100644 --- a/src/VisualStudio/Core/Def/Remote/VisualStudioRemoteHostClientProvider.cs +++ b/src/VisualStudio/Core/Def/Remote/VisualStudioRemoteHostClientProvider.cs @@ -103,7 +103,7 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) var serviceBroker = brokeredServiceContainer.GetFullAccessServiceBroker(); var configuration = - RemoteProcessConfiguration.Core | + (_globalOptions.GetOption(RemoteHostOptions.OOPCoreClrFeatureFlag) ? RemoteProcessConfiguration.Core : 0) | (_globalOptions.GetOption(RemoteHostOptions.OOPServerGCFeatureFlag) ? RemoteProcessConfiguration.ServerGC : 0) | (_globalOptions.GetOption(SolutionCrawlerRegistrationService.EnableSolutionCrawler) ? RemoteProcessConfiguration.EnableSolutionCrawler : 0); From 6cd9aa89ddca4306f55892d0f43fdfcaf13eb67a Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Wed, 13 Jul 2022 14:02:02 -0700 Subject: [PATCH 11/66] Address review comments --- ...lysis.Remote.ServiceHub.CoreComponents.csproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj index 3093f66ea5c44..99fdf50629d98 100644 --- a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj +++ b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj @@ -66,18 +66,18 @@ $(PublishDir)\CrossGen\ - $(CrossgenWorkDir)OriginalAssemblies\ + $(CrossgenWorkDir)OriginalAssemblies\ - + - <_CrossgenTargetPaths Include="$(OriginalAssemblyFolder)\*.dll" /> + <_CrossgenTargetPaths Include="$(OriginalAssemblyDir)*.dll" /> <_CrossgenTargetsAsDependencies Include="@(_CrossgenTargetPaths)" /> - <_NonCrossgenTargetsAsDependencies Include="@(_NonRuntimeAssembliesInPublishFolder)" Exclude="@(_R2RAssemblyPaths)" /> + <_NonCrossgenTargetsAsDependencies Include="@(_NonRuntimeAssembliesInPublishDir)" Exclude="@(_R2RAssemblyPaths)" /> @@ -114,10 +114,10 @@ <_RuntimeLibraries Include="$(PkgMicrosoft_NETCore_App_Runtime_win-x64)\runtimes\win-x64\**\*.dll" /> <_WinRuntimeLibraries Include="$(PkgMicrosoft_WindowsDesktop_App_Runtime_win-x64)\runtimes\win-x64\**\*.dll" /> - <_RuntimeLibrariesInPublishFolder Include="@(_RuntimeLibraries->'$(PublishDir)\%(FileName)%(Extension)')" /> - <_RuntimeLibrariesInPublishFolder Include="@(_WinRuntimeLibraries->'$(PublishDir)\%(FileName)%(Extension)')" /> + <_RuntimeLibrariesInPublishDir Include="@(_RuntimeLibraries->'$(PublishDir)\%(FileName)%(Extension)')" /> + <_RuntimeLibrariesInPublishDir Include="@(_WinRuntimeLibraries->'$(PublishDir)\%(FileName)%(Extension)')" /> - <_NonRuntimeAssembliesInPublishFolder Include="$(PublishDir)\*.dll" Exclude="@(_RuntimeLibrariesInPublishFolder)" /> + <_NonRuntimeAssembliesInPublishDir Include="$(PublishDir)\*.dll" Exclude="@(_RuntimeLibrariesInPublishDir)" /> @@ -136,7 +136,7 @@ However, we can't safely exclude shared dependencies from ServiceHub host folder: we might be referencing a higher version, or back-compat might not be guaranteed in the version shipped by host. --> - <_ExcludedFiles Include="@(_RuntimeLibrariesInPublishFolder)" /> + <_ExcludedFiles Include="@(_RuntimeLibrariesInPublishDir)" /> From 624a020151cee65cf7fb7d018ce65c77b32ec503 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Thu, 14 Jul 2022 16:32:17 -0700 Subject: [PATCH 12/66] Do not convert portable pdbs --- eng/Versions.props | 3 +++ eng/pipelines/build-windows-job.yml | 4 ++-- eng/targets/DoNotDeployToSymStore_Workaround.targets | 7 +++++++ eng/targets/Imports.targets | 2 ++ 4 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 eng/targets/DoNotDeployToSymStore_Workaround.targets diff --git a/eng/Versions.props b/eng/Versions.props index 5f13be7efce24..fd84cd488ad26 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -305,6 +305,9 @@ true true + + false + 6.0.6 diff --git a/eng/pipelines/build-windows-job.yml b/eng/pipelines/build-windows-job.yml index 0948f70550426..c19b0c29bd53c 100644 --- a/eng/pipelines/build-windows-job.yml +++ b/eng/pipelines/build-windows-job.yml @@ -37,13 +37,13 @@ jobs: displayName: Restore inputs: filePath: eng/build.ps1 - arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -restore -binaryLog + arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -restore -binaryLog /p:NoPdbConversion=true - task: PowerShell@2 displayName: Build inputs: filePath: eng/build.ps1 - arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -build -publish -binaryLog -skipDocumentation ${{ parameters.buildArguments }} + arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -build -publish -binaryLog -skipDocumentation /p:NoPdbConversion=true ${{ parameters.buildArguments }} - task: PowerShell@2 displayName: Prepare Unit Tests diff --git a/eng/targets/DoNotDeployToSymStore_Workaround.targets b/eng/targets/DoNotDeployToSymStore_Workaround.targets new file mode 100644 index 0000000000000..42d9c7317db84 --- /dev/null +++ b/eng/targets/DoNotDeployToSymStore_Workaround.targets @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets index 9645e7e596491..cdfee80b844b4 100644 --- a/eng/targets/Imports.targets +++ b/eng/targets/Imports.targets @@ -358,4 +358,6 @@ AlwaysCreate="true" Condition="'@(ReferencesCopiedInThisBuild)' != ''"/> + + From 4855b6d0e98a3f2b2f2f8e72a1536b3fce7ad165 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Thu, 14 Jul 2022 16:44:46 -0700 Subject: [PATCH 13/66] do not create vsixes on build --- eng/Versions.props | 3 +++ eng/pipelines/build-windows-job.yml | 4 ++-- eng/targets/Imports.targets | 2 +- eng/targets/Vsdconfig.targets | 4 ++-- .../arm64/Microsoft.CodeAnalysis.Compilers.Setup.arm64.csproj | 2 +- .../x64/Microsoft.CodeAnalysis.Compilers.Setup.x64.csproj | 2 +- .../x86/Microsoft.CodeAnalysis.Compilers.Setup.x86.csproj | 2 +- 7 files changed, 11 insertions(+), 8 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index fd84cd488ad26..8475e8c10f5cc 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -308,6 +308,9 @@ false + + false + 6.0.6 diff --git a/eng/pipelines/build-windows-job.yml b/eng/pipelines/build-windows-job.yml index c19b0c29bd53c..568da5ad0faf6 100644 --- a/eng/pipelines/build-windows-job.yml +++ b/eng/pipelines/build-windows-job.yml @@ -37,13 +37,13 @@ jobs: displayName: Restore inputs: filePath: eng/build.ps1 - arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -restore -binaryLog /p:NoPdbConversion=true + arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -restore -binaryLog /p:NoPdbConversion=true /p:NoVsixGeneration=true - task: PowerShell@2 displayName: Build inputs: filePath: eng/build.ps1 - arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -build -publish -binaryLog -skipDocumentation /p:NoPdbConversion=true ${{ parameters.buildArguments }} + arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -build -publish -binaryLog -skipDocumentation /p:NoPdbConversion=true /p:NoVsixGeneration=true ${{ parameters.buildArguments }} - task: PowerShell@2 displayName: Prepare Unit Tests diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets index cdfee80b844b4..5fce2aa6f2e5b 100644 --- a/eng/targets/Imports.targets +++ b/eng/targets/Imports.targets @@ -1,7 +1,7 @@  - + + + + + + \ No newline at end of file diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets index 5fce2aa6f2e5b..e11fc4183b682 100644 --- a/eng/targets/Imports.targets +++ b/eng/targets/Imports.targets @@ -360,4 +360,5 @@ + diff --git a/eng/targets/Settings.props b/eng/targets/Settings.props index b1fc441419e74..a26b3231ad3f0 100644 --- a/eng/targets/Settings.props +++ b/eng/targets/Settings.props @@ -43,6 +43,10 @@ enable + + false + + - true + true false false From 0780243f88dcc40d386b12456f1fb3864e6e8a89 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Fri, 15 Jul 2022 11:05:40 -0700 Subject: [PATCH 17/66] remove NoPdbConversion and instead use UsingToolPdbConverter --- eng/Versions.props | 3 --- eng/pipelines/build-windows-job.yml | 4 ++-- eng/targets/Imports.targets | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 8475e8c10f5cc..6e2ff2d3b9927 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -305,9 +305,6 @@ true true - - false - false diff --git a/eng/pipelines/build-windows-job.yml b/eng/pipelines/build-windows-job.yml index 60f4c9b1aeb9f..ebf1b6a5c20b9 100644 --- a/eng/pipelines/build-windows-job.yml +++ b/eng/pipelines/build-windows-job.yml @@ -37,13 +37,13 @@ jobs: displayName: Restore inputs: filePath: eng/build.ps1 - arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -restore -binaryLog /p:NoPdbConversion=true /p:NoVsixGeneration=true /p:NoGenerateSatelliteAssemblies=true + arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -restore -binaryLog /p:UsingToolPdbConverter=false /p:NoVsixGeneration=true /p:NoGenerateSatelliteAssemblies=true - task: PowerShell@2 displayName: Build inputs: filePath: eng/build.ps1 - arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -build -binaryLog -skipDocumentation /p:NoPdbConversion=true /p:NoVsixGeneration=true /p:NoGenerateSatelliteAssemblies=true /p:NoPublishReadyToRun=true ${{ parameters.buildArguments }} + arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -build -binaryLog -skipDocumentation /p:UsingToolPdbConverter=false /p:NoVsixGeneration=true /p:NoGenerateSatelliteAssemblies=true /p:NoPublishReadyToRun=true ${{ parameters.buildArguments }} - task: PowerShell@2 displayName: Prepare Unit Tests diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets index e11fc4183b682..1b79d59b091c0 100644 --- a/eng/targets/Imports.targets +++ b/eng/targets/Imports.targets @@ -359,6 +359,6 @@ Condition="'@(ReferencesCopiedInThisBuild)' != ''"/> - + From e3fb2c4fb5d510e5fcedfc544b8b2ed4cc04414d Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Fri, 15 Jul 2022 11:08:52 -0700 Subject: [PATCH 18/66] use UsingToolVSSDK instead of NoVsixGeneration --- eng/Versions.props | 3 --- eng/pipelines/build-windows-job.yml | 4 ++-- eng/targets/Imports.targets | 2 +- eng/targets/Vsdconfig.targets | 4 ++-- .../arm64/Microsoft.CodeAnalysis.Compilers.Setup.arm64.csproj | 2 +- .../x64/Microsoft.CodeAnalysis.Compilers.Setup.x64.csproj | 2 +- .../x86/Microsoft.CodeAnalysis.Compilers.Setup.x86.csproj | 2 +- 7 files changed, 8 insertions(+), 11 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 6e2ff2d3b9927..5f13be7efce24 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -305,9 +305,6 @@ true true - - false - 6.0.6 diff --git a/eng/pipelines/build-windows-job.yml b/eng/pipelines/build-windows-job.yml index ebf1b6a5c20b9..cd6f984318093 100644 --- a/eng/pipelines/build-windows-job.yml +++ b/eng/pipelines/build-windows-job.yml @@ -37,13 +37,13 @@ jobs: displayName: Restore inputs: filePath: eng/build.ps1 - arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -restore -binaryLog /p:UsingToolPdbConverter=false /p:NoVsixGeneration=true /p:NoGenerateSatelliteAssemblies=true + arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -restore -binaryLog /p:UsingToolPdbConverter=false /p:UsingToolVSSDK=false /p:NoGenerateSatelliteAssemblies=true - task: PowerShell@2 displayName: Build inputs: filePath: eng/build.ps1 - arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -build -binaryLog -skipDocumentation /p:UsingToolPdbConverter=false /p:NoVsixGeneration=true /p:NoGenerateSatelliteAssemblies=true /p:NoPublishReadyToRun=true ${{ parameters.buildArguments }} + arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -build -binaryLog -skipDocumentation /p:UsingToolPdbConverter=false /p:UsingToolVSSDK=false /p:NoGenerateSatelliteAssemblies=true /p:NoPublishReadyToRun=true ${{ parameters.buildArguments }} - task: PowerShell@2 displayName: Prepare Unit Tests diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets index 1b79d59b091c0..1f2f517ff27a5 100644 --- a/eng/targets/Imports.targets +++ b/eng/targets/Imports.targets @@ -1,7 +1,7 @@  - + - true + true false false From 82f68857849334f68f909b4142cc29e673f9582b Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Fri, 15 Jul 2022 11:45:16 -0700 Subject: [PATCH 21/66] define new GenerateSatelliteAssemblies property --- eng/pipelines/build-windows-job.yml | 4 ++-- eng/targets/Imports.targets | 2 +- eng/targets/Settings.props | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/eng/pipelines/build-windows-job.yml b/eng/pipelines/build-windows-job.yml index 34ddf87ce96a7..df41f8ea2a4ee 100644 --- a/eng/pipelines/build-windows-job.yml +++ b/eng/pipelines/build-windows-job.yml @@ -37,13 +37,13 @@ jobs: displayName: Restore inputs: filePath: eng/build.ps1 - arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -restore -binaryLog /p:UsingToolPdbConverter=false /p:UsingToolVSSDK=false /p:EnableXlfLocalization=false + arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -restore -binaryLog /p:UsingToolPdbConverter=false /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false - task: PowerShell@2 displayName: Build inputs: filePath: eng/build.ps1 - arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -build -binaryLog -skipDocumentation /p:UsingToolPdbConverter=false /p:UsingToolVSSDK=false /p:EnableXlfLocalization=false /p:PublishReadyToRun=false ${{ parameters.buildArguments }} + arguments: -configuration ${{ parameters.configuration }} -prepareMachine -ci -build -binaryLog -skipDocumentation /p:UsingToolPdbConverter=false /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false /p:PublishReadyToRun=false ${{ parameters.buildArguments }} - task: PowerShell@2 displayName: Prepare Unit Tests diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets index e1f7d06784cb0..1f4ad40af1007 100644 --- a/eng/targets/Imports.targets +++ b/eng/targets/Imports.targets @@ -360,5 +360,5 @@ - + diff --git a/eng/targets/Settings.props b/eng/targets/Settings.props index b1fc441419e74..2e32381deeb70 100644 --- a/eng/targets/Settings.props +++ b/eng/targets/Settings.props @@ -39,6 +39,9 @@ Microsoft.Common.CurrentVersion.targets to see how it is consumed --> false + + true + false enable @@ -53,6 +56,13 @@ false false + + + + false + - 3.8.0 + 4.1.0 7.0.0-alpha.1.22060.1 3.1.4097 17.2.32 diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/CachingSourceGenerator.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/CachingSourceGenerator.cs deleted file mode 100644 index 6872819048150..0000000000000 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/CachingSourceGenerator.cs +++ /dev/null @@ -1,116 +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. - -// We only build the Source Generator in the netstandard target -#if NETSTANDARD - -using System; -using System.Collections.Immutable; -using System.Diagnostics; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Threading; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; - -namespace CSharpSyntaxGenerator -{ - public abstract class CachingSourceGenerator : ISourceGenerator - { - /// - /// ⚠ This value may be accessed by multiple threads. - /// - private static readonly WeakReference s_cachedResult = new(null); - - protected abstract bool TryGetRelevantInput(in GeneratorExecutionContext context, out AdditionalText? input, out SourceText? inputText); - - protected abstract bool TryGenerateSources( - AdditionalText input, - SourceText inputText, - out ImmutableArray<(string hintName, SourceText sourceText)> sources, - out ImmutableArray diagnostics, - CancellationToken cancellationToken); - - public void Initialize(GeneratorInitializationContext context) - { - } - - public void Execute(GeneratorExecutionContext context) - { - if (!TryGetRelevantInput(in context, out var input, out var inputText)) - { - return; - } - - // Get the current input checksum, which will either be used for verifying the current cache or updating it - // with the new results. - var currentChecksum = inputText.GetChecksum(); - - // Read the current cached result once to avoid race conditions - if (s_cachedResult.TryGetTarget(out var cachedResult) - && cachedResult.Checksum.SequenceEqual(currentChecksum)) - { - // Add the previously-cached sources, and leave the cache as it was - AddSources(in context, sources: cachedResult.Sources); - return; - } - - if (TryGenerateSources(input, inputText, out var sources, out var diagnostics, context.CancellationToken)) - { - AddSources(in context, sources); - - if (diagnostics.IsEmpty) - { - var result = new CachedSourceGeneratorResult(currentChecksum, sources); - - // Default Large Object Heap size threshold - // https://github.com/dotnet/runtime/blob/c9d69e38d0e54bea5d188593ef6c3b30139f3ab1/src/coreclr/src/gc/gc.h#L111 - const int Threshold = 85000; - - // Overwrite the cached result with the new result. This is an opportunistic cache, so as long as - // the write is atomic (which it is for SetTarget) synchronization is unnecessary. We allocate an - // array on the Large Object Heap (which is always part of Generation 2) and give it a reference to - // the cached object to ensure this weak reference is not reclaimed prior to a full GC pass. - var largeArray = new CachedSourceGeneratorResult[Threshold / Unsafe.SizeOf()]; - Debug.Assert(GC.GetGeneration(largeArray) >= 2); - largeArray[0] = result; - s_cachedResult.SetTarget(result); - GC.KeepAlive(largeArray); - } - else - { - // Invalidate the cache since we cannot currently cache diagnostics - s_cachedResult.SetTarget(null); - } - } - else - { - // Invalidate the cache since generation failed - s_cachedResult.SetTarget(null); - } - - // Always report the diagnostics (if any) - foreach (var diagnostic in diagnostics) - { - context.ReportDiagnostic(diagnostic); - } - } - - private static void AddSources( - in GeneratorExecutionContext context, - ImmutableArray<(string hintName, SourceText sourceText)> sources) - { - foreach (var (hintName, sourceText) in sources) - { - context.AddSource(hintName, sourceText); - } - } - - private sealed record CachedSourceGeneratorResult( - ImmutableArray Checksum, - ImmutableArray<(string hintName, SourceText sourceText)> Sources); - } -} - -#endif diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceGenerator.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceGenerator.cs index 6ef5b01266f72..e4590e6a99e0d 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceGenerator.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceGenerator.cs @@ -11,7 +11,6 @@ using System.Collections.Immutable; using System.IO; using System.Linq; -using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Xml; @@ -22,7 +21,7 @@ namespace CSharpSyntaxGenerator { [Generator] - public sealed class SourceGenerator : CachingSourceGenerator + public sealed class SourceGenerator : IIncrementalGenerator { private static readonly DiagnosticDescriptor s_MissingSyntaxXml = new DiagnosticDescriptor( "CSSG1001", @@ -48,61 +47,64 @@ public sealed class SourceGenerator : CachingSourceGenerator defaultSeverity: DiagnosticSeverity.Error, isEnabledByDefault: true); - protected override bool TryGetRelevantInput(in GeneratorExecutionContext context, out AdditionalText? input, out SourceText? inputText) + public void Initialize(IncrementalGeneratorInitializationContext context) { - input = context.AdditionalFiles.SingleOrDefault(a => Path.GetFileName(a.Path) == "Syntax.xml"); - if (input == null) - { - context.ReportDiagnostic(Diagnostic.Create(s_MissingSyntaxXml, location: null)); - inputText = null; - return false; - } + var syntaxXmlFiles = context.AdditionalTextsProvider.Where(at => Path.GetFileName(at.Path) == "Syntax.xml").Collect(); - inputText = input.GetText(); - if (inputText == null) + context.RegisterSourceOutput(syntaxXmlFiles, static (context, syntaxXmlFiles) => { - context.ReportDiagnostic(Diagnostic.Create(s_UnableToReadSyntaxXml, location: null)); - return false; - } + var input = syntaxXmlFiles.SingleOrDefault(); + + if (input == null) + { + context.ReportDiagnostic(Diagnostic.Create(s_MissingSyntaxXml, location: null)); + return; + } + + var inputText = input.GetText(); + if (inputText == null) + { + context.ReportDiagnostic(Diagnostic.Create(s_UnableToReadSyntaxXml, location: null)); + return; + } + + Tree tree; + + try + { + var reader = XmlReader.Create(new SourceTextReader(inputText), new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit }); + var serializer = new XmlSerializer(typeof(Tree)); + tree = (Tree)serializer.Deserialize(reader); + } + catch (InvalidOperationException ex) when (ex.InnerException is XmlException) + { + var xmlException = (XmlException)ex.InnerException; + + var line = inputText.Lines[xmlException.LineNumber - 1]; // LineNumber is one-based. + int offset = xmlException.LinePosition - 1; // LinePosition is one-based + var position = line.Start + offset; + var span = new TextSpan(position, 0); + var lineSpan = inputText.Lines.GetLinePositionSpan(span); + + context.ReportDiagnostic( + Diagnostic.Create( + s_SyntaxXmlError, + location: Location.Create(input.Path, span, lineSpan), + xmlException.Message)); + + return; - return true; + } + + DoGeneration(tree, context, context.CancellationToken); + }); } - protected override bool TryGenerateSources( - AdditionalText input, - SourceText inputText, - out ImmutableArray<(string hintName, SourceText sourceText)> sources, - out ImmutableArray diagnostics, + private static void DoGeneration( + Tree tree, + SourceProductionContext context, CancellationToken cancellationToken) { - Tree tree; - var reader = XmlReader.Create(new SourceTextReader(inputText), new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit }); - - try - { - var serializer = new XmlSerializer(typeof(Tree)); - tree = (Tree)serializer.Deserialize(reader); - } - catch (InvalidOperationException ex) when (ex.InnerException is XmlException) - { - var xmlException = (XmlException)ex.InnerException; - - var line = inputText.Lines[xmlException.LineNumber - 1]; // LineNumber is one-based. - int offset = xmlException.LinePosition - 1; // LinePosition is one-based - var position = line.Start + offset; - var span = new TextSpan(position, 0); - var lineSpan = inputText.Lines.GetLinePositionSpan(span); - - sources = default; - diagnostics = ImmutableArray.Create( - Diagnostic.Create( - s_SyntaxXmlError, - location: Location.Create(input.Path, span, lineSpan), - xmlException.Message)); - - return false; - } - TreeFlattening.FlattenChildren(tree); var sourcesBuilder = ImmutableArray.CreateBuilder<(string hintName, SourceText sourceText)>(); @@ -110,10 +112,6 @@ protected override bool TryGetRelevantInput(in GeneratorExecutionContext context addResult(writer => SourceWriter.WriteInternal(writer, tree, cancellationToken), "Syntax.xml.Internal.Generated.cs"); addResult(writer => SourceWriter.WriteSyntax(writer, tree, cancellationToken), "Syntax.xml.Syntax.Generated.cs"); - sources = sourcesBuilder.ToImmutable(); - diagnostics = ImmutableArray.Empty; - return true; - void addResult(Action writeFunction, string hintName) { // Write out the contents to a StringBuilder to avoid creating a single large string @@ -126,7 +124,7 @@ void addResult(Action writeFunction, string hintName) // And create a SourceText from the StringBuilder, once again avoiding allocating a single massive string var sourceText = SourceText.From(new StringBuilderReader(stringBuilder), stringBuilder.Length, encoding: Encoding.UTF8); - sourcesBuilder.Add((hintName, sourceText)); + context.AddSource(hintName, sourceText); } } From 7552131bc3f47f31f34d0e9eb30e3762d508a60c Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 18 Jul 2022 11:00:35 -0700 Subject: [PATCH 24/66] Use actual equivalence keys, not loc strings to distinguish helpers --- .../UseExpressionBodyForAccessorsHelper.cs | 2 ++ .../UseExpressionBodyForConstructorsHelper.cs | 2 ++ ...ressionBodyForConversionOperatorsHelper.cs | 2 ++ .../UseExpressionBodyForIndexersHelper.cs | 2 ++ ...UseExpressionBodyForLocalFunctionHelper.cs | 2 ++ .../UseExpressionBodyForMethodsHelper.cs | 2 ++ .../UseExpressionBodyForOperatorsHelper.cs | 2 ++ .../UseExpressionBodyForPropertiesHelper.cs | 2 ++ .../Helpers/UseExpressionBodyHelper.cs | 5 +++++ .../Helpers/UseExpressionBodyHelper`1.cs | 8 +++++++ ...seExpressionBodyCodeRefactoringProvider.cs | 22 +++++++++---------- 11 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs index 9873326d450e2..398a7a30e7f01 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs @@ -21,6 +21,8 @@ private UseExpressionBodyForAccessorsHelper() EnforceOnBuildValues.UseExpressionBodyForAccessors, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_accessors), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_accessors), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), + nameof(CSharpAnalyzersResources.Use_expression_body_for_accessors), + nameof(CSharpAnalyzersResources.Use_block_body_for_accessors), CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, ImmutableArray.Create(SyntaxKind.GetAccessorDeclaration, SyntaxKind.SetAccessorDeclaration, SyntaxKind.InitAccessorDeclaration, SyntaxKind.AddAccessorDeclaration, SyntaxKind.RemoveAccessorDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs index f4594ebec841f..bb67bb6a6b271 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs @@ -21,6 +21,8 @@ private UseExpressionBodyForConstructorsHelper() EnforceOnBuildValues.UseExpressionBodyForConstructors, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_constructors), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_constructors), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), + nameof(CSharpAnalyzersResources.Use_expression_body_for_constructors), + nameof(CSharpAnalyzersResources.Use_block_body_for_constructors), CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, ImmutableArray.Create(SyntaxKind.ConstructorDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs index 25c8aa1d403b4..dfb8e37b264c5 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs @@ -21,6 +21,8 @@ private UseExpressionBodyForConversionOperatorsHelper() EnforceOnBuildValues.UseExpressionBodyForConversionOperators, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_conversion_operators), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_conversion_operators), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), + nameof(CSharpAnalyzersResources.Use_expression_body_for_conversion_operators), + nameof(CSharpAnalyzersResources.Use_block_body_for_conversion_operators), CSharpCodeStyleOptions.PreferExpressionBodiedOperators, ImmutableArray.Create(SyntaxKind.ConversionOperatorDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs index 172a3494e6165..3691a1016ceca 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs @@ -24,6 +24,8 @@ private UseExpressionBodyForIndexersHelper() EnforceOnBuildValues.UseExpressionBodyForIndexers, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_indexers), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_indexers), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), + nameof(CSharpAnalyzersResources.Use_expression_body_for_indexers), + nameof(CSharpAnalyzersResources.Use_block_body_for_indexers), CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, ImmutableArray.Create(SyntaxKind.IndexerDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs index f5db5c1bf4288..6ef23c1514b2e 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs @@ -24,6 +24,8 @@ private UseExpressionBodyForLocalFunctionHelper() EnforceOnBuildValues.UseExpressionBodyForLocalFunctions, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_local_functions), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_local_functions), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), + nameof(CSharpAnalyzersResources.Use_expression_body_for_local_functions), + nameof(CSharpAnalyzersResources.Use_block_body_for_local_functions), CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, ImmutableArray.Create(SyntaxKind.LocalFunctionStatement)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs index 3cfd363852a1d..bdb183891ee8b 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs @@ -24,6 +24,8 @@ private UseExpressionBodyForMethodsHelper() EnforceOnBuildValues.UseExpressionBodyForMethods, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_methods), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_methods), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), + nameof(CSharpAnalyzersResources.Use_expression_body_for_methods), + nameof(CSharpAnalyzersResources.Use_block_body_for_methods), CSharpCodeStyleOptions.PreferExpressionBodiedMethods, ImmutableArray.Create(SyntaxKind.MethodDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs index 644c5f0ac6a54..a29e46f8a0cad 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs @@ -23,6 +23,8 @@ private UseExpressionBodyForOperatorsHelper() EnforceOnBuildValues.UseExpressionBodyForOperators, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_operators), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_operators), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), + nameof(CSharpAnalyzersResources.Use_expression_body_for_operators), + nameof(CSharpAnalyzersResources.Use_block_body_for_operators), CSharpCodeStyleOptions.PreferExpressionBodiedOperators, ImmutableArray.Create(SyntaxKind.OperatorDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs index 8e7730e35ca1b..b67a3887a6de8 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs @@ -24,6 +24,8 @@ private UseExpressionBodyForPropertiesHelper() EnforceOnBuildValues.UseExpressionBodyForProperties, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_properties), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_properties), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), + nameof(CSharpAnalyzersResources.Use_expression_body_for_properties), + nameof(CSharpAnalyzersResources.Use_block_body_for_properties), CSharpCodeStyleOptions.PreferExpressionBodiedProperties, ImmutableArray.Create(SyntaxKind.PropertyDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs index 7c24c14eb8c1b..346adcb75381d 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs @@ -14,8 +14,13 @@ namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody internal abstract class UseExpressionBodyHelper { public abstract Option2> Option { get; } + public abstract LocalizableString UseExpressionBodyTitle { get; } public abstract LocalizableString UseBlockBodyTitle { get; } + + public abstract string UseExpressionBodyEquivalenceKey { get; } + public abstract string UseBlockBodyEquivalenceKey { get; } + public abstract string DiagnosticId { get; } public abstract EnforceOnBuild EnforceOnBuild { get; } public abstract ImmutableArray SyntaxKinds { get; } diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs index 305cf17c8608c..6d14dc4f51793 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs @@ -31,6 +31,8 @@ internal abstract class UseExpressionBodyHelper : UseExpressionBod public override Option2> Option { get; } public override LocalizableString UseExpressionBodyTitle { get; } public override LocalizableString UseBlockBodyTitle { get; } + public override string UseExpressionBodyEquivalenceKey { get; } + public override string UseBlockBodyEquivalenceKey { get; } public override string DiagnosticId { get; } public override EnforceOnBuild EnforceOnBuild { get; } public override ImmutableArray SyntaxKinds { get; } @@ -40,14 +42,20 @@ internal abstract class UseExpressionBodyHelper : UseExpressionBod EnforceOnBuild enforceOnBuild, LocalizableString useExpressionBodyTitle, LocalizableString useBlockBodyTitle, + string useExpressionBodyEquivalenceKey, + string useBlockBodyEquivalenceKey, Option2> option, ImmutableArray syntaxKinds) { + Contract.ThrowIfTrue(useExpressionBodyEquivalenceKey == useBlockBodyEquivalenceKey); + DiagnosticId = diagnosticId; EnforceOnBuild = enforceOnBuild; Option = option; UseExpressionBodyTitle = useExpressionBodyTitle; UseBlockBodyTitle = useBlockBodyTitle; + UseExpressionBodyEquivalenceKey = useExpressionBodyEquivalenceKey; + UseBlockBodyEquivalenceKey = useBlockBodyEquivalenceKey; SyntaxKinds = syntaxKinds; } diff --git a/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs index acb42ecd773e4..6128992a36d11 100644 --- a/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs @@ -33,8 +33,8 @@ internal class UseExpressionBodyCodeRefactoringProvider : SyntaxEditorBasedCodeR { private static readonly ImmutableArray _helpers = UseExpressionBodyHelper.Helpers; - private static readonly BidirectionalMap<(UseExpressionBodyHelper helper, bool useExpressionBody), string> s_helperToTitleMap - = CreateHelperToTitleMap(UseExpressionBodyHelper.Helpers); + private static readonly BidirectionalMap<(UseExpressionBodyHelper helper, bool useExpressionBody), string> s_helperToEquivalenceKeyMap + = CreateHelperToEquivalenceKeyMap(UseExpressionBodyHelper.Helpers); [ImportingConstructor] [SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")] @@ -42,7 +42,7 @@ public UseExpressionBodyCodeRefactoringProvider() { } - private static BidirectionalMap<(UseExpressionBodyHelper helper, bool useExpressionBody), string> CreateHelperToTitleMap( + private static BidirectionalMap<(UseExpressionBodyHelper helper, bool useExpressionBody), string> CreateHelperToEquivalenceKeyMap( ImmutableArray helpers) { return new BidirectionalMap<(UseExpressionBodyHelper helper, bool useExpressionBody), string>(GetKeyValuePairs(helpers)); @@ -52,8 +52,8 @@ public UseExpressionBodyCodeRefactoringProvider() { foreach (var helper in helpers) { - yield return KeyValuePairUtil.Create((helper, useExpressionBody: true), helper.UseExpressionBodyTitle.ToString()); - yield return KeyValuePairUtil.Create((helper, useExpressionBody: false), helper.UseBlockBodyTitle.ToString()); + yield return KeyValuePairUtil.Create((helper, useExpressionBody: true), helper.UseExpressionBodyEquivalenceKey); + yield return KeyValuePairUtil.Create((helper, useExpressionBody: false), helper.UseBlockBodyEquivalenceKey); } } } @@ -125,28 +125,26 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte var succeeded = false; if (helper.CanOfferUseExpressionBody(preference, declaration, forAnalyzer: false)) { - var title = s_helperToTitleMap[(helper, useExpressionBody: true)]; context.RegisterRefactoring( CodeAction.Create( - title, + helper.UseExpressionBodyTitle.ToString(), c => UpdateDocumentAsync( document, root, declaration, helper, useExpressionBody: true, cancellationToken: c), - title), + s_helperToEquivalenceKeyMap[(helper, useExpressionBody: true)]), declaration.Span); succeeded = true; } if (helper.CanOfferUseBlockBody(preference, declaration, forAnalyzer: false, out _, out _)) { - var title = s_helperToTitleMap[(helper, useExpressionBody: false)]; context.RegisterRefactoring( CodeAction.Create( - title, + helper.UseBlockBodyTitle.ToString(), c => UpdateDocumentAsync( document, root, declaration, helper, useExpressionBody: false, cancellationToken: c), - title), + s_helperToEquivalenceKeyMap[(helper, useExpressionBody: false)]), declaration.Span); succeeded = true; } @@ -200,7 +198,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte CancellationToken cancellationToken) { Debug.Assert(equivalenceKey != null); - var (helper, useExpressionBody) = s_helperToTitleMap[equivalenceKey]; + var (helper, useExpressionBody) = s_helperToEquivalenceKeyMap[equivalenceKey]; var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var options = (CSharpCodeGenerationOptions)await document.GetCodeGenerationOptionsAsync(optionsProvider, cancellationToken).ConfigureAwait(false); From efd58898e292d0986e8f585dba7f6957337d1563 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 18 Jul 2022 11:02:35 -0700 Subject: [PATCH 25/66] Simplify --- ...seExpressionBodyCodeRefactoringProvider.cs | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs index 6128992a36d11..2dae7aff2d78c 100644 --- a/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs @@ -20,7 +20,6 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -33,8 +32,8 @@ internal class UseExpressionBodyCodeRefactoringProvider : SyntaxEditorBasedCodeR { private static readonly ImmutableArray _helpers = UseExpressionBodyHelper.Helpers; - private static readonly BidirectionalMap<(UseExpressionBodyHelper helper, bool useExpressionBody), string> s_helperToEquivalenceKeyMap - = CreateHelperToEquivalenceKeyMap(UseExpressionBodyHelper.Helpers); + private static readonly ImmutableDictionary s_equivalenceKeyToHelperMap + = CreateHelperMap(UseExpressionBodyHelper.Helpers); [ImportingConstructor] [SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")] @@ -42,18 +41,18 @@ public UseExpressionBodyCodeRefactoringProvider() { } - private static BidirectionalMap<(UseExpressionBodyHelper helper, bool useExpressionBody), string> CreateHelperToEquivalenceKeyMap( + private static ImmutableDictionary CreateHelperMap( ImmutableArray helpers) { - return new BidirectionalMap<(UseExpressionBodyHelper helper, bool useExpressionBody), string>(GetKeyValuePairs(helpers)); + return ImmutableDictionary.CreateRange(GetKeyValuePairs(helpers)); - static IEnumerable> GetKeyValuePairs( + static IEnumerable> GetKeyValuePairs( ImmutableArray helpers) { foreach (var helper in helpers) { - yield return KeyValuePairUtil.Create((helper, useExpressionBody: true), helper.UseExpressionBodyEquivalenceKey); - yield return KeyValuePairUtil.Create((helper, useExpressionBody: false), helper.UseBlockBodyEquivalenceKey); + yield return KeyValuePairUtil.Create(helper.UseExpressionBodyEquivalenceKey, (helper, useExpressionBody: true)); + yield return KeyValuePairUtil.Create(helper.UseBlockBodyEquivalenceKey, (helper, useExpressionBody: false)); } } } @@ -131,7 +130,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte c => UpdateDocumentAsync( document, root, declaration, helper, useExpressionBody: true, cancellationToken: c), - s_helperToEquivalenceKeyMap[(helper, useExpressionBody: true)]), + helper.UseExpressionBodyEquivalenceKey), declaration.Span); succeeded = true; } @@ -144,7 +143,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte c => UpdateDocumentAsync( document, root, declaration, helper, useExpressionBody: false, cancellationToken: c), - s_helperToEquivalenceKeyMap[(helper, useExpressionBody: false)]), + helper.UseBlockBodyEquivalenceKey), declaration.Span); succeeded = true; } @@ -198,7 +197,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte CancellationToken cancellationToken) { Debug.Assert(equivalenceKey != null); - var (helper, useExpressionBody) = s_helperToEquivalenceKeyMap[equivalenceKey]; + var (helper, useExpressionBody) = s_equivalenceKeyToHelperMap[equivalenceKey]; var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var options = (CSharpCodeGenerationOptions)await document.GetCodeGenerationOptionsAsync(optionsProvider, cancellationToken).ConfigureAwait(false); From e27397741749d5e5e75422eff77abf7e39b827e1 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 18 Jul 2022 11:21:30 -0700 Subject: [PATCH 26/66] Simplify --- .../UseExpressionBodyForAccessorsHelper.cs | 2 -- .../UseExpressionBodyForConstructorsHelper.cs | 2 -- ...ressionBodyForConversionOperatorsHelper.cs | 2 -- .../UseExpressionBodyForIndexersHelper.cs | 2 -- ...UseExpressionBodyForLocalFunctionHelper.cs | 2 -- .../UseExpressionBodyForMethodsHelper.cs | 2 -- .../UseExpressionBodyForOperatorsHelper.cs | 2 -- .../UseExpressionBodyForPropertiesHelper.cs | 2 -- .../Helpers/UseExpressionBodyHelper.cs | 3 --- .../Helpers/UseExpressionBodyHelper`1.cs | 8 -------- ...seExpressionBodyCodeRefactoringProvider.cs | 20 +++++++++---------- 11 files changed, 10 insertions(+), 37 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs index 398a7a30e7f01..9873326d450e2 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs @@ -21,8 +21,6 @@ private UseExpressionBodyForAccessorsHelper() EnforceOnBuildValues.UseExpressionBodyForAccessors, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_accessors), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_accessors), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), - nameof(CSharpAnalyzersResources.Use_expression_body_for_accessors), - nameof(CSharpAnalyzersResources.Use_block_body_for_accessors), CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, ImmutableArray.Create(SyntaxKind.GetAccessorDeclaration, SyntaxKind.SetAccessorDeclaration, SyntaxKind.InitAccessorDeclaration, SyntaxKind.AddAccessorDeclaration, SyntaxKind.RemoveAccessorDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs index bb67bb6a6b271..f4594ebec841f 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs @@ -21,8 +21,6 @@ private UseExpressionBodyForConstructorsHelper() EnforceOnBuildValues.UseExpressionBodyForConstructors, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_constructors), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_constructors), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), - nameof(CSharpAnalyzersResources.Use_expression_body_for_constructors), - nameof(CSharpAnalyzersResources.Use_block_body_for_constructors), CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, ImmutableArray.Create(SyntaxKind.ConstructorDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs index dfb8e37b264c5..25c8aa1d403b4 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs @@ -21,8 +21,6 @@ private UseExpressionBodyForConversionOperatorsHelper() EnforceOnBuildValues.UseExpressionBodyForConversionOperators, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_conversion_operators), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_conversion_operators), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), - nameof(CSharpAnalyzersResources.Use_expression_body_for_conversion_operators), - nameof(CSharpAnalyzersResources.Use_block_body_for_conversion_operators), CSharpCodeStyleOptions.PreferExpressionBodiedOperators, ImmutableArray.Create(SyntaxKind.ConversionOperatorDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs index 3691a1016ceca..172a3494e6165 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs @@ -24,8 +24,6 @@ private UseExpressionBodyForIndexersHelper() EnforceOnBuildValues.UseExpressionBodyForIndexers, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_indexers), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_indexers), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), - nameof(CSharpAnalyzersResources.Use_expression_body_for_indexers), - nameof(CSharpAnalyzersResources.Use_block_body_for_indexers), CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, ImmutableArray.Create(SyntaxKind.IndexerDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs index 6ef23c1514b2e..f5db5c1bf4288 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs @@ -24,8 +24,6 @@ private UseExpressionBodyForLocalFunctionHelper() EnforceOnBuildValues.UseExpressionBodyForLocalFunctions, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_local_functions), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_local_functions), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), - nameof(CSharpAnalyzersResources.Use_expression_body_for_local_functions), - nameof(CSharpAnalyzersResources.Use_block_body_for_local_functions), CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, ImmutableArray.Create(SyntaxKind.LocalFunctionStatement)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs index bdb183891ee8b..3cfd363852a1d 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs @@ -24,8 +24,6 @@ private UseExpressionBodyForMethodsHelper() EnforceOnBuildValues.UseExpressionBodyForMethods, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_methods), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_methods), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), - nameof(CSharpAnalyzersResources.Use_expression_body_for_methods), - nameof(CSharpAnalyzersResources.Use_block_body_for_methods), CSharpCodeStyleOptions.PreferExpressionBodiedMethods, ImmutableArray.Create(SyntaxKind.MethodDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs index a29e46f8a0cad..644c5f0ac6a54 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs @@ -23,8 +23,6 @@ private UseExpressionBodyForOperatorsHelper() EnforceOnBuildValues.UseExpressionBodyForOperators, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_operators), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_operators), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), - nameof(CSharpAnalyzersResources.Use_expression_body_for_operators), - nameof(CSharpAnalyzersResources.Use_block_body_for_operators), CSharpCodeStyleOptions.PreferExpressionBodiedOperators, ImmutableArray.Create(SyntaxKind.OperatorDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs index b67a3887a6de8..8e7730e35ca1b 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs @@ -24,8 +24,6 @@ private UseExpressionBodyForPropertiesHelper() EnforceOnBuildValues.UseExpressionBodyForProperties, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_properties), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_properties), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), - nameof(CSharpAnalyzersResources.Use_expression_body_for_properties), - nameof(CSharpAnalyzersResources.Use_block_body_for_properties), CSharpCodeStyleOptions.PreferExpressionBodiedProperties, ImmutableArray.Create(SyntaxKind.PropertyDeclaration)) { diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs index 346adcb75381d..f88dbdee8d5ef 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs @@ -18,9 +18,6 @@ internal abstract class UseExpressionBodyHelper public abstract LocalizableString UseExpressionBodyTitle { get; } public abstract LocalizableString UseBlockBodyTitle { get; } - public abstract string UseExpressionBodyEquivalenceKey { get; } - public abstract string UseBlockBodyEquivalenceKey { get; } - public abstract string DiagnosticId { get; } public abstract EnforceOnBuild EnforceOnBuild { get; } public abstract ImmutableArray SyntaxKinds { get; } diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs index 6d14dc4f51793..305cf17c8608c 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs @@ -31,8 +31,6 @@ internal abstract class UseExpressionBodyHelper : UseExpressionBod public override Option2> Option { get; } public override LocalizableString UseExpressionBodyTitle { get; } public override LocalizableString UseBlockBodyTitle { get; } - public override string UseExpressionBodyEquivalenceKey { get; } - public override string UseBlockBodyEquivalenceKey { get; } public override string DiagnosticId { get; } public override EnforceOnBuild EnforceOnBuild { get; } public override ImmutableArray SyntaxKinds { get; } @@ -42,20 +40,14 @@ internal abstract class UseExpressionBodyHelper : UseExpressionBod EnforceOnBuild enforceOnBuild, LocalizableString useExpressionBodyTitle, LocalizableString useBlockBodyTitle, - string useExpressionBodyEquivalenceKey, - string useBlockBodyEquivalenceKey, Option2> option, ImmutableArray syntaxKinds) { - Contract.ThrowIfTrue(useExpressionBodyEquivalenceKey == useBlockBodyEquivalenceKey); - DiagnosticId = diagnosticId; EnforceOnBuild = enforceOnBuild; Option = option; UseExpressionBodyTitle = useExpressionBodyTitle; UseBlockBodyTitle = useBlockBodyTitle; - UseExpressionBodyEquivalenceKey = useExpressionBodyEquivalenceKey; - UseBlockBodyEquivalenceKey = useBlockBodyEquivalenceKey; SyntaxKinds = syntaxKinds; } diff --git a/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs index 2dae7aff2d78c..c3516bcb11376 100644 --- a/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs @@ -32,8 +32,8 @@ internal class UseExpressionBodyCodeRefactoringProvider : SyntaxEditorBasedCodeR { private static readonly ImmutableArray _helpers = UseExpressionBodyHelper.Helpers; - private static readonly ImmutableDictionary s_equivalenceKeyToHelperMap - = CreateHelperMap(UseExpressionBodyHelper.Helpers); + private static readonly BidirectionalMap<(UseExpressionBodyHelper helper, bool useExpressionBody), string> s_equivalenceKeyMap + = CreateEquivalanceKeyMap(UseExpressionBodyHelper.Helpers); [ImportingConstructor] [SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")] @@ -41,18 +41,18 @@ public UseExpressionBodyCodeRefactoringProvider() { } - private static ImmutableDictionary CreateHelperMap( + private static BidirectionalMap<(UseExpressionBodyHelper helper, bool useExpressionBody), string> CreateEquivalanceKeyMap( ImmutableArray helpers) { - return ImmutableDictionary.CreateRange(GetKeyValuePairs(helpers)); + return new BidirectionalMap<(UseExpressionBodyHelper helper, bool useExpressionBody), string>(GetKeyValuePairs(helpers)); - static IEnumerable> GetKeyValuePairs( + static IEnumerable> GetKeyValuePairs( ImmutableArray helpers) { foreach (var helper in helpers) { - yield return KeyValuePairUtil.Create(helper.UseExpressionBodyEquivalenceKey, (helper, useExpressionBody: true)); - yield return KeyValuePairUtil.Create(helper.UseBlockBodyEquivalenceKey, (helper, useExpressionBody: false)); + yield return KeyValuePairUtil.Create((helper, useExpressionBody: true), helper.GetType().Name + "_UseExpressionBody"); + yield return KeyValuePairUtil.Create((helper, useExpressionBody: false), helper.GetType().Name + "_UseBlockBody"); } } } @@ -130,7 +130,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte c => UpdateDocumentAsync( document, root, declaration, helper, useExpressionBody: true, cancellationToken: c), - helper.UseExpressionBodyEquivalenceKey), + s_equivalenceKeyMap[(helper, useExpressionBody: true)]), declaration.Span); succeeded = true; } @@ -143,7 +143,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte c => UpdateDocumentAsync( document, root, declaration, helper, useExpressionBody: false, cancellationToken: c), - helper.UseBlockBodyEquivalenceKey), + s_equivalenceKeyMap[(helper, useExpressionBody: false)]), declaration.Span); succeeded = true; } @@ -197,7 +197,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte CancellationToken cancellationToken) { Debug.Assert(equivalenceKey != null); - var (helper, useExpressionBody) = s_equivalenceKeyToHelperMap[equivalenceKey]; + var (helper, useExpressionBody) = s_equivalenceKeyMap[equivalenceKey]; var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var options = (CSharpCodeGenerationOptions)await document.GetCodeGenerationOptionsAsync(optionsProvider, cancellationToken).ConfigureAwait(false); From f8bcc2c5b7db5e8069cbe215b4d38481a0ba24f9 Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Mon, 18 Jul 2022 11:21:49 -0700 Subject: [PATCH 27/66] Update src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs --- .../UseExpressionBody/Helpers/UseExpressionBodyHelper.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs index f88dbdee8d5ef..7c24c14eb8c1b 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs @@ -14,10 +14,8 @@ namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody internal abstract class UseExpressionBodyHelper { public abstract Option2> Option { get; } - public abstract LocalizableString UseExpressionBodyTitle { get; } public abstract LocalizableString UseBlockBodyTitle { get; } - public abstract string DiagnosticId { get; } public abstract EnforceOnBuild EnforceOnBuild { get; } public abstract ImmutableArray SyntaxKinds { get; } From c1f7769cb0ffd7bd50993c3051b5fb0a62d04512 Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Mon, 18 Jul 2022 12:13:49 -0700 Subject: [PATCH 28/66] Fix target input/output --- ...is.Remote.ServiceHub.CoreComponents.csproj | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj index 99fdf50629d98..27d43135a4705 100644 --- a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj +++ b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj @@ -49,7 +49,7 @@ <_R2RAssemblies Include="StreamJsonRpc.dll" /> - <_AllPublishedAssemblyPaths Include="$(PublishDir)\**\*.dll" Exclude="$(PublishDir)\**\*.resources.dll" /> + <_AllPublishedAssemblyPaths Include="$(PublishDir)**\*.dll" Exclude="$(PublishDir)**\*.resources.dll" /> <_AllPublishedAssemblies Include="@(_AllPublishedAssemblyPaths->'%(FileName)%(Extension)')" > <_FullFilePath>%(FullPath) @@ -65,7 +65,7 @@ - $(PublishDir)\CrossGen\ + $(PublishDir)CrossGen\ $(CrossgenWorkDir)OriginalAssemblies\ @@ -75,17 +75,23 @@ - <_CrossgenTargetPaths Include="$(OriginalAssemblyDir)*.dll" /> - <_CrossgenTargetsAsDependencies Include="@(_CrossgenTargetPaths)" /> - <_NonCrossgenTargetsAsDependencies Include="@(_NonRuntimeAssembliesInPublishDir)" Exclude="@(_R2RAssemblyPaths)" /> + <_CrossgenTargetsAsDependencies Include="$(OriginalAssemblyDir)*.dll" /> + <_NonCrossgenTargetsAsDependencies Include="@(_NonRuntimeAssembliesInPublishDir)" Exclude="@(_R2RAssemblyPaths)" /> + <_CrossgenTargetPaths Include="@(_CrossgenTargetsAsDependencies)"> + $(PublishDir)%(_CrossgenTargetsAsDependencies.Filename)%(_CrossgenTargetsAsDependencies.Extension) + - + <_Crossgen2Path>$(PkgMicrosoft_NETCore_App_crossgen2_win-x64)\tools\crossgen2.dll <_R2ROptimizeAssemblyPath>%(_CrossgenTargetPaths.FullPath) - <_R2ROptimizeAssemblyOutputPath>$(PublishDir)\%(_CrossgenTargetPaths.Filename)%(_CrossgenTargetPaths.Extension) + <_R2ROptimizeAssemblyOutputPath>$(PublishDir)%(_CrossgenTargetPaths.Filename)%(_CrossgenTargetPaths.Extension) <_RspFilePath>$(CrossgenWorkDir)%(_CrossgenTargetPaths.Filename).CrossgenArgs.rsp @@ -114,10 +120,10 @@ <_RuntimeLibraries Include="$(PkgMicrosoft_NETCore_App_Runtime_win-x64)\runtimes\win-x64\**\*.dll" /> <_WinRuntimeLibraries Include="$(PkgMicrosoft_WindowsDesktop_App_Runtime_win-x64)\runtimes\win-x64\**\*.dll" /> - <_RuntimeLibrariesInPublishDir Include="@(_RuntimeLibraries->'$(PublishDir)\%(FileName)%(Extension)')" /> - <_RuntimeLibrariesInPublishDir Include="@(_WinRuntimeLibraries->'$(PublishDir)\%(FileName)%(Extension)')" /> + <_RuntimeLibrariesInPublishDir Include="@(_RuntimeLibraries->'$(PublishDir)%(FileName)%(Extension)')" /> + <_RuntimeLibrariesInPublishDir Include="@(_WinRuntimeLibraries->'$(PublishDir)%(FileName)%(Extension)')" /> - <_NonRuntimeAssembliesInPublishDir Include="$(PublishDir)\*.dll" Exclude="@(_RuntimeLibrariesInPublishDir)" /> + <_NonRuntimeAssembliesInPublishDir Include="$(PublishDir)*.dll" Exclude="@(_RuntimeLibrariesInPublishDir)" /> @@ -130,7 +136,7 @@ <_ExcludedFiles Include="$(CrossgenWorkDir)**\*" /> - <_ExcludedFiles Include="$(PublishDir)\runtimes\**\*.*" /> + <_ExcludedFiles Include="$(PublishDir)runtimes\**\*.*" /> + + diff --git a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj index 27d43135a4705..b5293b278ffeb 100644 --- a/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj +++ b/src/Workspaces/Remote/ServiceHub.CoreComponents/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.csproj @@ -38,6 +38,7 @@ <_R2RAssemblies Include="@(ReferencePath->'%(FileName)%(Extension)')" Condition="'%(ReferenceSourceTarget)' == 'ProjectReference'" /> + <_R2RAssemblies Include="Microsoft.CodeAnalysis.Elfie.dll" /> <_R2RAssemblies Include="Microsoft.ServiceHub.Framework.dll" /> <_R2RAssemblies Include="Microsoft.VisualStudio.Composition.dll" /> <_R2RAssemblies Include="Microsoft.VisualStudio.Telemetry.dll" /> @@ -47,6 +48,7 @@ <_R2RAssemblies Include="Newtonsoft.Json.dll" /> <_R2RAssemblies Include="SQLitePCLRaw.batteries_v2.dll" /> <_R2RAssemblies Include="StreamJsonRpc.dll" /> + <_R2RAssemblies Include="System.IO.Pipelines.dll" /> <_AllPublishedAssemblyPaths Include="$(PublishDir)**\*.dll" Exclude="$(PublishDir)**\*.resources.dll" /> From 5030cd43fa32bd67f4da3dededd205110ad800b4 Mon Sep 17 00:00:00 2001 From: Joey Robichaud Date: Mon, 18 Jul 2022 16:47:53 -0700 Subject: [PATCH 39/66] Fix PR Validation pipeline (#62757) * Remove token --- azure-pipelines-pr-validation.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines-pr-validation.yml b/azure-pipelines-pr-validation.yml index 5e9856ef8a557..0d026f18ccbe8 100644 --- a/azure-pipelines-pr-validation.yml +++ b/azure-pipelines-pr-validation.yml @@ -32,12 +32,12 @@ variables: - group: DotNet-Roslyn-SDLValidation-Params - group: DotNet-Roslyn-Insertion-Variables - # To retrieve OptProf data we need to authenticate to the VS drop storage. - # If the pipeline is running in DevDiv, the account has access to the VS drop storage. # Get $AccessToken-dotnet-build-bot-public-repo from DotNet-GitHub-Versions-Repo-Write - group: DotNet-GitHub-Versions-Repo-Write + # To retrieve OptProf data we need to authenticate to the VS drop storage. + # If the pipeline is running in DevDiv, the account has access to the VS drop storage. - name: _DevDivDropAccessToken - value: $(System.AccessToken) + value: '' stages: - stage: build From 4d58c5ecf54f7e0f695d098e14a3d3fd1949e22b Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Mon, 18 Jul 2022 23:32:28 -0700 Subject: [PATCH 40/66] Update src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs Co-authored-by: David Wengier --- .../FindReferences/Finders/AbstractReferenceFinder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs index 13f7f4e0e8e82..27e91435c4e33 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs @@ -216,7 +216,8 @@ protected static Task> FindMatchingIdentifierTokensA token.GetLocation(), isImplicit: false, GetSymbolUsageInfo(token.Parent, state, cancellationToken), - GetAdditionalFindUsagesProperties(token.Parent, state), reason)); + GetAdditionalFindUsagesProperties(token.Parent, state), + reason)); } protected static ValueTask> FindReferencesInTokensAsync( From 5ac3f140ac2256915aeb80eb503c8944ac199952 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Jul 2022 11:50:45 -0700 Subject: [PATCH 41/66] Remove all notifications that hte lightbulb needs to be refreshed --- .../SuggestedActionsSource.State.cs | 6 -- .../Suggestions/SuggestedActionsSource.cs | 86 +------------------ 2 files changed, 1 insertion(+), 91 deletions(-) diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.State.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.State.cs index 591e08e8161de..ff1d79fb557ea 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.State.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.State.cs @@ -26,7 +26,6 @@ protected sealed class State : IDisposable // mutable state public Workspace? Workspace { get; set; } - public int LastSolutionVersionReported; public State(SuggestedActionsSource source, SuggestedActionsSourceProvider owner, ITextView textView, ITextBuffer textBuffer) { @@ -36,17 +35,12 @@ public State(SuggestedActionsSource source, SuggestedActionsSourceProvider owner TextView = textView; SubjectBuffer = textBuffer; Registration = Workspace.GetWorkspaceRegistration(textBuffer.AsTextContainer()); - LastSolutionVersionReported = InvalidSolutionVersion; } void IDisposable.Dispose() { if (Workspace != null) - { - Workspace.Services.GetRequiredService().StatusChanged -= _source.OnWorkspaceStatusChanged; - Workspace.DocumentActiveContextChanged -= _source.OnActiveContextChanged; Workspace.WorkspaceChanged -= _source.OnWorkspaceChanged; - } if (Registration != null) Registration.WorkspaceChanged -= _source.OnWorkspaceChanged; diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs index a17775590827b..72215be9c09ad 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs @@ -40,7 +40,7 @@ private abstract partial class SuggestedActionsSource : ForegroundThreadAffiniti private readonly ReferenceCountedDisposable _state; - public event EventHandler? SuggestedActionsChanged; + public event EventHandler? SuggestedActionsChanged { add { } remove { } } public readonly IGlobalOptionService GlobalOptions; @@ -447,11 +447,7 @@ private static string GetFixCategory(DiagnosticSeverity severity) } if (!result.UpToDate) - { - // reset solution version number so that we can raise suggested action changed event - Volatile.Write(ref state.Target.LastSolutionVersionReported, InvalidSolutionVersion); return null; - } } return null; @@ -524,16 +520,6 @@ private void OnWorkspaceChanged(object sender, EventArgs e) if (state is null) return; - // REVIEW: this event should give both old and new workspace as argument so that - // one doesn't need to hold onto workspace in field. - - // remove existing event registration - if (state.Target.Workspace != null) - { - state.Target.Workspace.Services.GetRequiredService().StatusChanged -= OnWorkspaceStatusChanged; - state.Target.Workspace.DocumentActiveContextChanged -= OnActiveContextChanged; - } - // REVIEW: why one need to get new workspace from registration? why not just pass in the new workspace? // add new event registration RegisterEventsToWorkspace(state, state.Target.Registration.Workspace); @@ -544,81 +530,11 @@ private void RegisterEventsToWorkspace(ReferenceCountedDisposable state, state.Target.Workspace = workspace; if (state.Target.Workspace == null) - { return; - } - state.Target.Workspace.DocumentActiveContextChanged += OnActiveContextChanged; - state.Target.Workspace.Services.GetRequiredService().StatusChanged += OnWorkspaceStatusChanged; state.Target.Workspace.WorkspaceChanged += OnWorkspaceChanged; } - private void OnWorkspaceChanged(object? sender, WorkspaceChangeEventArgs e) - { - switch (e.Kind) - { - // Only care about document changes here, the call to OnSuggestedActionsChange - // will filter and make sure the event only gets sent if its relevant to this buffer. - case WorkspaceChangeKind.DocumentAdded: - case WorkspaceChangeKind.DocumentRemoved: - case WorkspaceChangeKind.DocumentReloaded: - case WorkspaceChangeKind.DocumentChanged: - OnSuggestedActionsChanged(e.NewSolution.Workspace, e.DocumentId, e.NewSolution.WorkspaceVersion); - break; - default: - break; - } - } - - private void OnActiveContextChanged(object sender, DocumentActiveContextChangedEventArgs e) - { - // REVIEW: it would be nice for changed event to pass in both old and new document. - OnSuggestedActionsChanged(e.Solution.Workspace, e.NewActiveContextDocumentId, e.Solution.WorkspaceVersion); - } - - private void OnWorkspaceStatusChanged(object sender, EventArgs args) - { - using var state = _state.TryAddReference(); - if (state is null) - return; - - var document = state.Target.SubjectBuffer.AsTextContainer().GetOpenDocumentInCurrentContext(); - if (document == null) - { - // document is already closed - return; - } - - // ask editor to refresh light-bulb when workspace solution status is changed - this.SuggestedActionsChanged?.Invoke(this, EventArgs.Empty); - } - - private void OnSuggestedActionsChanged(Workspace currentWorkspace, DocumentId? currentDocumentId, int solutionVersion) - { - using var state = _state.TryAddReference(); - if (state is null) - return; - - var buffer = state.Target.SubjectBuffer; - var workspace = buffer.GetWorkspace(); - - // workspace is not ready, nothing to do. - if (workspace == null || workspace != currentWorkspace) - { - return; - } - - if (currentDocumentId != workspace.GetDocumentIdInCurrentContext(buffer.AsTextContainer()) || - solutionVersion == Volatile.Read(ref state.Target.LastSolutionVersionReported)) - { - return; - } - - this.SuggestedActionsChanged?.Invoke(this, EventArgs.Empty); - - Volatile.Write(ref state.Target.LastSolutionVersionReported, solutionVersion); - } - public async Task GetSuggestedActionCategoriesAsync(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken) { using var state = _state.TryAddReference(); From 20f24796228112df9c83dab32732908c1ab16bb8 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Jul 2022 12:44:17 -0700 Subject: [PATCH 42/66] Allow ApplyChangesOperation to try to merge in safe text changes --- .../Operations/ApplyChangesOperation.cs | 106 +++++++++++++++++- .../Operations/CodeActionOperation.cs | 2 +- .../Shared/Extensions/ProjectExtensions.cs | 14 +-- .../Core/Portable/Workspace/Workspace.cs | 6 +- 4 files changed, 112 insertions(+), 16 deletions(-) diff --git a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs index b0880608a24f7..93ebaaaae2845 100644 --- a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs +++ b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs @@ -3,9 +3,13 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; +using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CodeActions @@ -39,11 +43,105 @@ public override void Apply(Workspace workspace, CancellationToken cancellationTo => workspace.TryApplyChanges(ChangedSolution, new ProgressTracker()); internal sealed override Task TryApplyAsync( - Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + Workspace workspace, Solution originalSolution, IProgressTracker progressTracker, CancellationToken cancellationToken) { - return workspace.TryApplyChanges(ChangedSolution, progressTracker) - ? SpecializedTasks.True - : SpecializedTasks.False; + var currentSolution = workspace.CurrentSolution; + + // if there was no intermediary edit, just apply the change fully. + if (ChangedSolution.WorkspaceVersion == currentSolution.WorkspaceVersion) + return Task.FromResult(workspace.TryApplyChanges(ChangedSolution, progressTracker)); + + // Otherwise, we need to see what changes were actually made and see if we can apply them. The general rules are: + // + // 1. we only support text changes when doing merges. Any other changes to projects/documents are not + // supported because it's very unclear what impact they may have wrt other workspace updates that have + // already happened. + // + // 2. For text changes, we only support it if the current text of the document we're changing itself has not + // changed. This means we can merge in edits if there were changes to unrelated files, but not if there + // are changes to the current file. We could consider relaxing this in the future, esp. if we make use + // of some sort of text-merging-library to handle this. However, the user would then have to handle diff + // markers being inserted into their code that they then have to handle. + + var solutionChanges = this.ChangedSolution.GetChanges(originalSolution); + + if (solutionChanges.GetAddedProjects().Count() > 0 || + solutionChanges.GetAddedAnalyzerReferences().Count() > 0 || + solutionChanges.GetRemovedProjects().Count() > 0 || + solutionChanges.GetRemovedAnalyzerReferences().Count() > 0) + { + return SpecializedTasks.False; + } + + // Take the actual current solution the workspace is pointing to and fork it with just the text changes the + // code action wanted to make. Then apply that fork back into the workspace. + var forkedSolution = currentSolution; + + foreach (var changedProject in solutionChanges.GetProjectChanges()) + { + // We only support text changes. If we see any other changes to this project, bail out immediately. + if (changedProject.GetAddedAdditionalDocuments().Count() > 0 || + changedProject.GetAddedAnalyzerConfigDocuments().Count() > 0 || + changedProject.GetAddedAnalyzerReferences().Count() > 0 || + changedProject.GetAddedDocuments().Count() > 0 || + changedProject.GetAddedMetadataReferences().Count() > 0 || + changedProject.GetAddedProjectReferences().Count() > 0 || + changedProject.GetRemovedAdditionalDocuments().Count() > 0 || + changedProject.GetRemovedAnalyzerConfigDocuments().Count() > 0 || + changedProject.GetRemovedAnalyzerReferences().Count() > 0 || + changedProject.GetRemovedDocuments().Count() > 0 || + changedProject.GetRemovedMetadataReferences().Count() > 0 || + changedProject.GetRemovedProjectReferences().Count() > 0) + { + return SpecializedTasks.False; + } + + if (!ProcessDocuments(changedProject, changedProject.GetChangedDocuments(), static (s, i) => s.GetRequiredDocument(i), static (s, i, t) => s.WithDocumentText(i, t)) || + !ProcessDocuments(changedProject, changedProject.GetChangedAdditionalDocuments(), static (s, i) => s.GetRequiredAdditionalDocument(i), static (s, i, t) => s.WithAdditionalDocumentText(i, t)) || + !ProcessDocuments(changedProject, changedProject.GetChangedAnalyzerConfigDocuments(), static (s, i) => s.GetRequiredAnalyzerConfigDocument(i), static (s, i, t) => s.WithAnalyzerConfigDocumentText(i, t))) + { + return SpecializedTasks.False; + } + } + + return Task.FromResult(workspace.TryApplyChanges(forkedSolution, progressTracker)); + + bool ProcessDocuments( + ProjectChanges changedProject, + IEnumerable changedDocuments, + Func getDocument, + Func withDocumentText) + { + var sawChangedDocument = false; + + foreach (var documentId in changedDocuments) + { + sawChangedDocument = true; + + var originalDocument = getDocument(changedProject.OldProject.Solution, documentId); + var changedDocument = getDocument(changedProject.NewProject.Solution, documentId); + + // it has to be a text change the operation wants to make. If the operation is making some other + // sort of change, we can't merge this operation in. + if (!changedDocument.HasTextChanged(originalDocument, ignoreUnchangeableDocument: false)) + return false; + + // If the document has gone away, we definitely cannot apply a text change to it. + var currentDocument = getDocument(currentSolution, documentId); + if (currentDocument is null) + return false; + + // If the file contents changed in the current workspace, then we can't apply this change to it. + // Note: we could potentially try to do a 3-way merge in the future, including handling conflicts + // with that. For now though, we'll leave that out of scope. + if (originalDocument.HasTextChanged(currentDocument, ignoreUnchangeableDocument: false)) + return false; + + forkedSolution = withDocumentText(forkedSolution, documentId, changedDocument.GetTextSynchronously(cancellationToken)); + } + + return sawChangedDocument; + } } } } diff --git a/src/Workspaces/Core/Portable/CodeActions/Operations/CodeActionOperation.cs b/src/Workspaces/Core/Portable/CodeActions/Operations/CodeActionOperation.cs index 6be64736ceb75..1a0c465fc9f6d 100644 --- a/src/Workspaces/Core/Portable/CodeActions/Operations/CodeActionOperation.cs +++ b/src/Workspaces/Core/Portable/CodeActions/Operations/CodeActionOperation.cs @@ -31,7 +31,7 @@ public virtual void Apply(Workspace workspace, CancellationToken cancellationTok /// Called by the host environment to apply the effect of the operation. /// This method is guaranteed to be called on the UI thread. /// - internal virtual Task TryApplyAsync(Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + internal virtual Task TryApplyAsync(Workspace workspace, Solution originalSolution, IProgressTracker progressTracker, CancellationToken cancellationToken) { // It is a requirement that this method be called on the UI thread. So it's safe for us to call // into .Apply without any threading operations here. diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/ProjectExtensions.cs b/src/Workspaces/Core/Portable/Shared/Extensions/ProjectExtensions.cs index a39298e965a5f..b22b35955e68e 100644 --- a/src/Workspaces/Core/Portable/Shared/Extensions/ProjectExtensions.cs +++ b/src/Workspaces/Core/Portable/Shared/Extensions/ProjectExtensions.cs @@ -35,15 +35,13 @@ internal static Project WithSolutionOptions(this Project project, OptionSet opti => project.Solution.GetDocumentIdsWithFilePath(filePath).FirstOrDefault(id => id.ProjectId == project.Id); public static Document GetRequiredDocument(this Project project, DocumentId documentId) - { - var document = project.GetDocument(documentId); - if (document == null) - { - throw new InvalidOperationException(WorkspaceExtensionsResources.The_solution_does_not_contain_the_specified_document); - } + => project.GetDocument(documentId) ?? throw new InvalidOperationException(WorkspaceExtensionsResources.The_solution_does_not_contain_the_specified_document); - return document; - } + public static TextDocument GetRequiredAdditionalDocument(this Project project, DocumentId documentId) + => project.GetAdditionalDocument(documentId) ?? throw new InvalidOperationException(WorkspaceExtensionsResources.The_solution_does_not_contain_the_specified_document); + + public static TextDocument GetRequiredAnalyzerConfigDocument(this Project project, DocumentId documentId) + => project.GetAnalyzerConfigDocument(documentId) ?? throw new InvalidOperationException(WorkspaceExtensionsResources.The_solution_does_not_contain_the_specified_document); public static TextDocument GetRequiredTextDocument(this Project project, DocumentId documentId) { diff --git a/src/Workspaces/Core/Portable/Workspace/Workspace.cs b/src/Workspaces/Core/Portable/Workspace/Workspace.cs index 8fd316e7f0aaf..a06f54e18d318 100644 --- a/src/Workspaces/Core/Portable/Workspace/Workspace.cs +++ b/src/Workspaces/Core/Portable/Workspace/Workspace.cs @@ -1941,9 +1941,9 @@ protected virtual void ApplyAnalyzerConfigDocumentTextChanged(DocumentId id, Sou this.OnAnalyzerConfigDocumentTextLoaderChanged(id, TextLoader.From(TextAndVersion.Create(text, VersionStamp.Create()))); } - #endregion +#endregion - #region Checks and Asserts +#region Checks and Asserts /// /// Throws an exception is the solution is not empty. /// @@ -2197,6 +2197,6 @@ protected virtual string GetAdditionalDocumentName(DocumentId documentId) protected virtual string GetAnalyzerConfigDocumentName(DocumentId documentId) => GetDocumentName(documentId); - #endregion +#endregion } } From 31183f577dbedf960c45b9bc0c9f6edbf904f76b Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Tue, 19 Jul 2022 13:02:58 -0700 Subject: [PATCH 43/66] Address review comments --- .../OverrideCompletionProviderTests.cs | 6 ++--- .../Test/Completion/CompletionServiceTests.cs | 6 ++--- .../AbstractCompletionProviderTests.cs | 6 ++--- .../CompletionService.ProviderManager.cs | 26 +++++++++---------- .../Portable/Completion/CompletionService.cs | 4 +-- .../VisualBasicCompletionService.vb | 2 +- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs index bf9b80b7f84f0..187ebb72b50bb 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs @@ -2376,7 +2376,7 @@ public override void set_Bar(int bay, int value) var completionList = await GetCompletionListAsync(service, document, position, triggerInfo); var completionItem = completionList.ItemsList.First(i => CompareItems(i.DisplayText, "Bar[int bay]")); - if (service.GetProvider(completionItem) is ICustomCommitCompletionProvider customCommitCompletionProvider) + if (service.GetProvider(completionItem, document.Project) is ICustomCommitCompletionProvider customCommitCompletionProvider) { var textView = testWorkspace.GetTestDocument(documentId).GetTextView(); customCommitCompletionProvider.Commit(completionItem, textView, textView.TextBuffer, textView.TextSnapshot, '\t'); @@ -2633,7 +2633,7 @@ public override bool Equals(object obj) var completionList = await GetCompletionListAsync(service, document, position, triggerInfo); var completionItem = completionList.ItemsList.First(i => CompareItems(i.DisplayText, "Equals(object obj)")); - if (service.GetProvider(completionItem) is ICustomCommitCompletionProvider customCommitCompletionProvider) + if (service.GetProvider(completionItem, document.Project) is ICustomCommitCompletionProvider customCommitCompletionProvider) { var textView = testWorkspace.GetTestDocument(documentId).GetTextView(); customCommitCompletionProvider.Commit(completionItem, textView, textView.TextBuffer, textView.TextSnapshot, '\t'); @@ -2689,7 +2689,7 @@ public override bool Equals(object obj) var completionList = await GetCompletionListAsync(service, document, cursorPosition, triggerInfo); var completionItem = completionList.ItemsList.First(i => CompareItems(i.DisplayText, "Equals(object obj)")); - if (service.GetProvider(completionItem) is ICustomCommitCompletionProvider customCommitCompletionProvider) + if (service.GetProvider(completionItem, document.Project) is ICustomCommitCompletionProvider customCommitCompletionProvider) { var textView = testWorkspace.GetTestDocument(documentId).GetTextView(); customCommitCompletionProvider.Commit(completionItem, textView, textView.TextBuffer, textView.TextSnapshot, '\t'); diff --git a/src/EditorFeatures/Test/Completion/CompletionServiceTests.cs b/src/EditorFeatures/Test/Completion/CompletionServiceTests.cs index d8c179b3e3d21..bfb89ce4f2c9d 100644 --- a/src/EditorFeatures/Test/Completion/CompletionServiceTests.cs +++ b/src/EditorFeatures/Test/Completion/CompletionServiceTests.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. -using Microsoft.CodeAnalysis.Completion; -using Microsoft.CodeAnalysis.Diagnostics; #nullable disable using System; @@ -11,6 +9,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Options; @@ -58,7 +58,7 @@ class Test { var expectedChange = new TextChange(item.Span, nameof(DebugAssertTestCompletionProvider)); var actualChange = (await completionService.GetChangeAsync(document, item).ConfigureAwait(false)).TextChange; - Assert.True(expectedChange == actualChange); + Assert.Equal(expectedChange, actualChange); } private class MockAnalyzerReference : AnalyzerReference, ICompletionProviderFactory diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs index 69191c5fd8641..c586d584242fc 100644 --- a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs @@ -111,8 +111,8 @@ protected static async Task CanUseSpeculativeSemanticModelAsync(Document d internal virtual CompletionService GetCompletionService(Project project) { var completionService = project.LanguageServices.GetRequiredService(); - var completionProviders = completionService.GetLazyImportedProviders(); - var completionProvider = Assert.Single(completionProviders).Value; + var completionProviders = completionService.GetTestAccessor().GetAllProviders(ImmutableHashSet.Empty, project); + var completionProvider = Assert.Single(completionProviders); Assert.IsType(GetCompletionProviderType(), completionProvider); return completionService; @@ -475,7 +475,7 @@ private async Task VerifyCustomCommitProviderCheckResultsAsync(Document document Assert.Contains(itemToCommit, items.Select(x => x.DisplayText), GetStringComparer()); var firstItem = items.First(i => CompareItems(i.DisplayText, itemToCommit)); - if (service.GetProvider(firstItem) is ICustomCommitCompletionProvider customCommitCompletionProvider) + if (service.GetProvider(firstItem, document.Project) is ICustomCommitCompletionProvider customCommitCompletionProvider) { VerifyCustomCommitWorker(service, customCommitCompletionProvider, firstItem, codeBeforeCommit, expectedCodeAfterCommit, commitChar); } diff --git a/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs b/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs index 4117b1d5e2de3..06e5d5ce03e4d 100644 --- a/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs +++ b/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs @@ -35,7 +35,6 @@ public ProviderManager(CompletionService service) _rolesToProviders = new Dictionary, ImmutableArray>(this); } - // Exposed for pre-populating MEF providers. public IReadOnlyList> GetLazyImportedProviders() { if (_lazyImportedProviders == null) @@ -54,10 +53,9 @@ public ProviderManager(CompletionService service) return _lazyImportedProviders; } - // Exposed for pre-populating project-based providers. public static ImmutableArray GetProjectCompletionProviders(Project? project) { - if (project?.Solution.Workspace.Kind == WorkspaceKind.Interactive) + if (project is null || project.Solution.Workspace.Kind == WorkspaceKind.Interactive) { // TODO (https://github.com/dotnet/roslyn/issues/4932): Don't restrict completions in Interactive return ImmutableArray.Empty; @@ -98,6 +96,9 @@ ImmutableArray GetImportedAndBuiltInProvidersWorker(Immutabl } } + /// + /// Don't call. For test only. + /// public ImmutableArray GetProviders(ImmutableHashSet roles, Project? project) { using var _ = ArrayBuilder.GetInstance(out var providers); @@ -108,23 +109,22 @@ public ImmutableArray GetProviders(ImmutableHashSet public CompletionProvider? GetProvider(CompletionItem item, Project? project) { + if (item.ProviderName == null) + return null; + CompletionProvider? provider = null; + using var _ = PooledDelegates.GetPooledFunction(static (p, n) => p.Name == n, item.ProviderName, out Func isNameMatchingProviderPredicate); - if (item.ProviderName != null) + lock (_gate) { - lock (_gate) + if (!_nameToProvider.TryGetValue(item.ProviderName, out provider)) { - if (!_nameToProvider.TryGetValue(item.ProviderName, out provider)) - { - provider = GetImportedAndBuiltInProviders(roles: ImmutableHashSet.Empty).FirstOrDefault(p => p.Name == item.ProviderName); - _nameToProvider.Add(item.ProviderName, provider); - } + provider = GetImportedAndBuiltInProviders(roles: ImmutableHashSet.Empty).FirstOrDefault(isNameMatchingProviderPredicate); + _nameToProvider.Add(item.ProviderName, provider); } - - provider ??= GetProjectCompletionProviders(project).FirstOrDefault(p => p.Name == item.ProviderName); } - return provider; + return provider ?? GetProjectCompletionProviders(project).FirstOrDefault(isNameMatchingProviderPredicate); } public ConcatImmutableArray GetFilteredProviders( diff --git a/src/Features/Core/Portable/Completion/CompletionService.cs b/src/Features/Core/Portable/Completion/CompletionService.cs index a0e05014ff939..1a6120df15451 100644 --- a/src/Features/Core/Portable/Completion/CompletionService.cs +++ b/src/Features/Core/Portable/Completion/CompletionService.cs @@ -398,10 +398,10 @@ public virtual TextSpan GetDefaultCompletionListSpan(SourceText text, int caretP /// /// Don't call. Used for pre-populating NuGet providers only. /// - internal static ImmutableArray GetProjectCompletionProviders(Project? project) + internal static ImmutableArray GetProjectCompletionProviders(Project project) => ProviderManager.GetProjectCompletionProviders(project); - internal CompletionProvider? GetProvider(CompletionItem item, Project? project = null) + internal CompletionProvider? GetProvider(CompletionItem item, Project? project) => _providerManager.GetProvider(item, project); internal TestAccessor GetTestAccessor() diff --git a/src/Features/VisualBasic/Portable/Completion/VisualBasicCompletionService.vb b/src/Features/VisualBasic/Portable/Completion/VisualBasicCompletionService.vb index 97eebf32c3f2f..1e0d79b383c7a 100644 --- a/src/Features/VisualBasic/Portable/Completion/VisualBasicCompletionService.vb +++ b/src/Features/VisualBasic/Portable/Completion/VisualBasicCompletionService.vb @@ -105,7 +105,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion End Function Private Function GetChangeText(item As CompletionItem) As String - Dim provider = TryCast(GetProvider(item), CommonCompletionProvider) + Dim provider = TryCast(GetProvider(item, project:=Nothing), CommonCompletionProvider) If provider IsNot Nothing Then ' TODO: Document Is Not available in this code path.. what about providers that need to reconstruct information before producing text? Dim result = provider.GetTextChangeAsync(Nothing, item, Nothing, CancellationToken.None).Result From 52db56483aaab931e3ff01c81e6e2fdcae54be36 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Jul 2022 13:19:21 -0700 Subject: [PATCH 44/66] Allow lightbulb to apply even with intermediary project change --- .../Preview/PreviewExceptionTests.cs | 6 +- .../PreviewChangesSuggestedAction.cs | 10 +++- .../SuggestedActionWithNestedActions.cs | 24 +++++--- .../SuggestedActionWithNestedFlavors.cs | 16 ++++-- .../AbstractFixAllSuggestedAction.cs | 10 +++- .../CodeFixSuggestedAction.cs | 11 +++- .../CodeRefactoringSuggestedAction.cs | 3 +- .../FixAllCodeFixSuggestedAction.cs | 11 +++- .../FixAllCodeRefactoringSuggestedAction.cs | 11 +++- .../SuggestedActions/SuggestedAction.cs | 13 ++++- .../Suggestions/SuggestedActionsSource.cs | 12 ++-- .../CodeActionEditHandlerService.cs | 20 ++++--- .../ICodeActionEditHandlerService.cs | 7 ++- ...TaggerProvider.RenameTrackingCodeAction.cs | 3 +- .../AbstractCodeActionOrUserDiagnosticTest.cs | 8 +-- .../CodeActions/AbstractCodeActionTest.cs | 2 +- .../RenameTracking/RenameTrackingTestState.cs | 2 +- .../Test2/Rename/InlineRenameTests.vb | 1 + .../AssemblyReferenceCodeAction.cs | 5 +- .../InstallPackageAndAddImportCodeAction.cs | 5 +- .../ProjectSymbolReferenceCodeAction.cs | 5 +- ...stallPackageDirectlyCodeActionOperation.cs | 2 +- .../ChangeSignatureCodeActionOperation.cs | 11 ++-- .../UnifiedSuggestedActionSet.cs | 4 ++ .../UnifiedSuggestedActionsSource.cs | 57 +++++++++++++------ ...StudioDiagnosticListTableCommandHandler.cs | 1 + .../VisualStudioSuppressionFixService.cs | 3 + .../AnalyzersCommandHandler.cs | 2 + .../Operations/ApplyChangesOperation.cs | 33 ++++++----- 29 files changed, 202 insertions(+), 96 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/CodeActions/Preview/PreviewExceptionTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/Preview/PreviewExceptionTests.cs index 8f0061371aedd..24f285b1d9a71 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/Preview/PreviewExceptionTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/Preview/PreviewExceptionTests.cs @@ -72,7 +72,7 @@ private static async Task GetPreview(TestWorkspace workspace, CodeRefactoringPro var suggestedAction = new CodeRefactoringSuggestedAction( workspace.ExportProvider.GetExportedValue(), workspace.ExportProvider.GetExportedValue(), - workspace, textBuffer, provider, codeActions.First(), fixAllFlavors: null); + workspace, workspace.CurrentSolution, textBuffer, provider, codeActions.First(), fixAllFlavors: null); await suggestedAction.GetPreviewAsync(CancellationToken.None); Assert.True(extensionManager.IsDisabled(provider)); Assert.False(extensionManager.IsIgnored(provider)); @@ -85,7 +85,7 @@ private static void DisplayText(TestWorkspace workspace, CodeRefactoringProvider var suggestedAction = new CodeRefactoringSuggestedAction( workspace.ExportProvider.GetExportedValue(), workspace.ExportProvider.GetExportedValue(), - workspace, textBuffer, provider, codeActions.First(), fixAllFlavors: null); + workspace, workspace.CurrentSolution, textBuffer, provider, codeActions.First(), fixAllFlavors: null); _ = suggestedAction.DisplayText; Assert.True(extensionManager.IsDisabled(provider)); Assert.False(extensionManager.IsIgnored(provider)); @@ -98,7 +98,7 @@ private static async Task ActionSets(TestWorkspace workspace, CodeRefactoringPro var suggestedAction = new CodeRefactoringSuggestedAction( workspace.ExportProvider.GetExportedValue(), workspace.ExportProvider.GetExportedValue(), - workspace, textBuffer, provider, codeActions.First(), fixAllFlavors: null); + workspace, workspace.CurrentSolution, textBuffer, provider, codeActions.First(), fixAllFlavors: null); _ = await suggestedAction.GetActionSetsAsync(CancellationToken.None); Assert.True(extensionManager.IsDisabled(provider)); Assert.False(extensionManager.IsIgnored(provider)); diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/PreviewChanges/PreviewChangesSuggestedAction.cs b/src/EditorFeatures/Core.Wpf/Suggestions/PreviewChanges/PreviewChangesSuggestedAction.cs index 084e72e3c4414..73254d07b4829 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/PreviewChanges/PreviewChangesSuggestedAction.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/PreviewChanges/PreviewChangesSuggestedAction.cs @@ -23,10 +23,11 @@ private sealed partial class PreviewChangesSuggestedAction : SuggestedAction IThreadingContext threadingContext, SuggestedActionsSourceProvider sourceProvider, Workspace workspace, + Solution originalSolution, ITextBuffer subjectBuffer, object provider, PreviewChangesCodeAction codeAction) - : base(threadingContext, sourceProvider, workspace, subjectBuffer, provider, codeAction) + : base(threadingContext, sourceProvider, workspace, originalSolution, subjectBuffer, provider, codeAction) { } @@ -47,8 +48,11 @@ private sealed partial class PreviewChangesSuggestedAction : SuggestedAction return new PreviewChangesSuggestedAction( suggestedAction.ThreadingContext, - suggestedAction.SourceProvider, suggestedAction.Workspace, - suggestedAction.SubjectBuffer, suggestedAction.Provider, + suggestedAction.SourceProvider, + suggestedAction.Workspace, + suggestedAction.OriginalSolution, + suggestedAction.SubjectBuffer, + suggestedAction.Provider, new PreviewChangesCodeAction( suggestedAction.Workspace, suggestedAction.CodeAction, changeSummary)); } diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionWithNestedActions.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionWithNestedActions.cs index be030502e72cc..16a51d6c876e6 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionWithNestedActions.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionWithNestedActions.cs @@ -27,10 +27,14 @@ internal sealed class SuggestedActionWithNestedActions : SuggestedAction public SuggestedActionWithNestedActions( IThreadingContext threadingContext, - SuggestedActionsSourceProvider sourceProvider, Workspace workspace, - ITextBuffer subjectBuffer, object provider, - CodeAction codeAction, ImmutableArray nestedActionSets) - : base(threadingContext, sourceProvider, workspace, subjectBuffer, provider, codeAction) + SuggestedActionsSourceProvider sourceProvider, + Workspace workspace, + Solution originalSolution, + ITextBuffer subjectBuffer, + object provider, + CodeAction codeAction, + ImmutableArray nestedActionSets) + : base(threadingContext, sourceProvider, workspace, originalSolution, subjectBuffer, provider, codeAction) { Debug.Assert(!nestedActionSets.IsDefaultOrEmpty); NestedActionSets = nestedActionSets; @@ -38,10 +42,14 @@ internal sealed class SuggestedActionWithNestedActions : SuggestedAction public SuggestedActionWithNestedActions( IThreadingContext threadingContext, - SuggestedActionsSourceProvider sourceProvider, Workspace workspace, - ITextBuffer subjectBuffer, object provider, - CodeAction codeAction, SuggestedActionSet nestedActionSet) - : this(threadingContext, sourceProvider, workspace, subjectBuffer, provider, codeAction, ImmutableArray.Create(nestedActionSet)) + SuggestedActionsSourceProvider sourceProvider, + Workspace workspace, + Solution originalSolution, + ITextBuffer subjectBuffer, + object provider, + CodeAction codeAction, + SuggestedActionSet nestedActionSet) + : this(threadingContext, sourceProvider, workspace, originalSolution, subjectBuffer, provider, codeAction, ImmutableArray.Create(nestedActionSet)) { } diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionWithNestedFlavors.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionWithNestedFlavors.cs index 51f5466d78777..9c24f9de28e09 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionWithNestedFlavors.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionWithNestedFlavors.cs @@ -38,11 +38,19 @@ internal abstract partial class SuggestedActionWithNestedFlavors : SuggestedActi public SuggestedActionWithNestedFlavors( IThreadingContext threadingContext, SuggestedActionsSourceProvider sourceProvider, - Workspace workspace, ITextBuffer subjectBuffer, - object provider, CodeAction codeAction, + Workspace workspace, + Solution originalSolution, + ITextBuffer subjectBuffer, + object provider, + CodeAction codeAction, SuggestedActionSet additionalFlavors) - : base(threadingContext, sourceProvider, workspace, subjectBuffer, - provider, codeAction) + : base(threadingContext, + sourceProvider, + workspace, + originalSolution, + subjectBuffer, + provider, + codeAction) { _additionalFlavors = additionalFlavors; } diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/AbstractFixAllSuggestedAction.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/AbstractFixAllSuggestedAction.cs index d09b011255ac2..c3b68680e7f48 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/AbstractFixAllSuggestedAction.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/AbstractFixAllSuggestedAction.cs @@ -28,12 +28,18 @@ internal abstract class AbstractFixAllSuggestedAction : SuggestedAction IThreadingContext threadingContext, SuggestedActionsSourceProvider sourceProvider, Workspace workspace, + Solution originalSolution, ITextBuffer subjectBuffer, IFixAllState fixAllState, CodeAction originalCodeAction, AbstractFixAllCodeAction fixAllCodeAction) - : base(threadingContext, sourceProvider, workspace, subjectBuffer, - fixAllState.FixAllProvider, fixAllCodeAction) + : base(threadingContext, + sourceProvider, + workspace, + originalSolution, + subjectBuffer, + fixAllState.FixAllProvider, + fixAllCodeAction) { OriginalCodeAction = originalCodeAction; FixAllState = fixAllState; diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/CodeFixSuggestedAction.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/CodeFixSuggestedAction.cs index 1a56faba462d8..401a5b19750e7 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/CodeFixSuggestedAction.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/CodeFixSuggestedAction.cs @@ -26,13 +26,20 @@ internal sealed class CodeFixSuggestedAction : SuggestedActionWithNestedFlavors, IThreadingContext threadingContext, SuggestedActionsSourceProvider sourceProvider, Workspace workspace, + Solution originalSolution, ITextBuffer subjectBuffer, CodeFix fix, object provider, CodeAction action, SuggestedActionSet fixAllFlavors) - : base(threadingContext, sourceProvider, workspace, subjectBuffer, - provider, action, fixAllFlavors) + : base(threadingContext, + sourceProvider, + workspace, + originalSolution, + subjectBuffer, + provider, + action, + fixAllFlavors) { CodeFix = fix; } diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/CodeRefactoringSuggestedAction.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/CodeRefactoringSuggestedAction.cs index ac14b9c18cd06..2b179ecd6e5e9 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/CodeRefactoringSuggestedAction.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/CodeRefactoringSuggestedAction.cs @@ -24,11 +24,12 @@ internal sealed class CodeRefactoringSuggestedAction : SuggestedActionWithNested IThreadingContext threadingContext, SuggestedActionsSourceProvider sourceProvider, Workspace workspace, + Solution originalSolution, ITextBuffer subjectBuffer, CodeRefactoringProvider provider, CodeAction codeAction, SuggestedActionSet fixAllFlavors) - : base(threadingContext, sourceProvider, workspace, subjectBuffer, provider, codeAction, fixAllFlavors) + : base(threadingContext, sourceProvider, workspace, originalSolution, subjectBuffer, provider, codeAction, fixAllFlavors) { CodeRefactoringProvider = provider; } diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/FixAllCodeFixSuggestedAction.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/FixAllCodeFixSuggestedAction.cs index 9148893d8ab65..290609d9551c6 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/FixAllCodeFixSuggestedAction.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/FixAllCodeFixSuggestedAction.cs @@ -25,12 +25,19 @@ internal sealed partial class FixAllCodeFixSuggestedAction : AbstractFixAllSugge IThreadingContext threadingContext, SuggestedActionsSourceProvider sourceProvider, Workspace workspace, + Solution originalSolution, ITextBuffer subjectBuffer, IFixAllState fixAllState, Diagnostic diagnostic, CodeAction originalCodeAction) - : base(threadingContext, sourceProvider, workspace, subjectBuffer, fixAllState, - originalCodeAction, new FixAllCodeAction(fixAllState)) + : base(threadingContext, + sourceProvider, + workspace, + originalSolution, + subjectBuffer, + fixAllState, + originalCodeAction, + new FixAllCodeAction(fixAllState)) { Diagnostic = diagnostic; } diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/FixAllCodeRefactoringSuggestedAction.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/FixAllCodeRefactoringSuggestedAction.cs index fa7b3a833dfa5..c4320a1f7bd12 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/FixAllCodeRefactoringSuggestedAction.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/FixAllCodeRefactoringSuggestedAction.cs @@ -21,11 +21,18 @@ internal sealed class FixAllCodeRefactoringSuggestedAction : AbstractFixAllSugge IThreadingContext threadingContext, SuggestedActionsSourceProvider sourceProvider, Workspace workspace, + Solution originalSolution, ITextBuffer subjectBuffer, IFixAllState fixAllState, CodeAction originalCodeAction) - : base(threadingContext, sourceProvider, workspace, subjectBuffer, fixAllState, - originalCodeAction, new FixAllCodeRefactoringCodeAction(fixAllState)) + : base(threadingContext, + sourceProvider, + workspace, + originalSolution, + subjectBuffer, + fixAllState, + originalCodeAction, + new FixAllCodeRefactoringCodeAction(fixAllState)) { } } diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/SuggestedAction.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/SuggestedAction.cs index 1152683034ec6..8c5e3934cdce4 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/SuggestedAction.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActions/SuggestedAction.cs @@ -35,6 +35,7 @@ internal abstract partial class SuggestedAction : ForegroundThreadAffinitizedObj protected readonly SuggestedActionsSourceProvider SourceProvider; protected readonly Workspace Workspace; + protected readonly Solution OriginalSolution; protected readonly ITextBuffer SubjectBuffer; protected readonly object Provider; @@ -46,6 +47,7 @@ internal abstract partial class SuggestedAction : ForegroundThreadAffinitizedObj IThreadingContext threadingContext, SuggestedActionsSourceProvider sourceProvider, Workspace workspace, + Solution originalSolution, ITextBuffer subjectBuffer, object provider, CodeAction codeAction) @@ -56,6 +58,7 @@ internal abstract partial class SuggestedAction : ForegroundThreadAffinitizedObj SourceProvider = sourceProvider; Workspace = workspace; + OriginalSolution = originalSolution; SubjectBuffer = subjectBuffer; Provider = provider; CodeAction = codeAction; @@ -164,9 +167,13 @@ private async Task InvokeWorkerAsync(IProgressTracker progressTracker, Cancellat var document = this.SubjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); await EditHandler.ApplyAsync( - Workspace, document, - operations.ToImmutableArray(), CodeAction.Title, - progressTracker, cancellationToken).ConfigureAwait(false); + Workspace, + OriginalSolution, + document, + operations.ToImmutableArray(), + CodeAction.Title, + progressTracker, + cancellationToken).ConfigureAwait(false); } } } diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs index 72215be9c09ad..b7758e49fd243 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs @@ -215,6 +215,8 @@ public bool TryGetTelemetryId(out Guid telemetryId) if (unifiedSuggestedActionSet == null) return null; + var originalSolution = unifiedSuggestedActionSet.OriginalSolution; + return new SuggestedActionSet( unifiedSuggestedActionSet.CategoryName, unifiedSuggestedActionSet.Actions.SelectAsArray(set => ConvertToSuggestedAction(set)), @@ -227,21 +229,21 @@ ISuggestedAction ConvertToSuggestedAction(IUnifiedSuggestedAction unifiedSuggest => unifiedSuggestedAction switch { UnifiedCodeFixSuggestedAction codeFixAction => new CodeFixSuggestedAction( - ThreadingContext, owner, codeFixAction.Workspace, subjectBuffer, + ThreadingContext, owner, codeFixAction.Workspace, originalSolution, subjectBuffer, codeFixAction.CodeFix, codeFixAction.Provider, codeFixAction.OriginalCodeAction, ConvertToSuggestedActionSet(codeFixAction.FixAllFlavors, owner, subjectBuffer)), UnifiedCodeRefactoringSuggestedAction codeRefactoringAction => new CodeRefactoringSuggestedAction( - ThreadingContext, owner, codeRefactoringAction.Workspace, subjectBuffer, + ThreadingContext, owner, codeRefactoringAction.Workspace, originalSolution, subjectBuffer, codeRefactoringAction.CodeRefactoringProvider, codeRefactoringAction.OriginalCodeAction, ConvertToSuggestedActionSet(codeRefactoringAction.FixAllFlavors, owner, subjectBuffer)), UnifiedFixAllCodeFixSuggestedAction fixAllAction => new FixAllCodeFixSuggestedAction( - ThreadingContext, owner, fixAllAction.Workspace, subjectBuffer, + ThreadingContext, owner, fixAllAction.Workspace, originalSolution, subjectBuffer, fixAllAction.FixAllState, fixAllAction.Diagnostic, fixAllAction.OriginalCodeAction), UnifiedFixAllCodeRefactoringSuggestedAction fixAllCodeRefactoringAction => new FixAllCodeRefactoringSuggestedAction( - ThreadingContext, owner, fixAllCodeRefactoringAction.Workspace, subjectBuffer, + ThreadingContext, owner, fixAllCodeRefactoringAction.Workspace, originalSolution, subjectBuffer, fixAllCodeRefactoringAction.FixAllState, fixAllCodeRefactoringAction.OriginalCodeAction), UnifiedSuggestedActionWithNestedActions nestedAction => new SuggestedActionWithNestedActions( - ThreadingContext, owner, nestedAction.Workspace, subjectBuffer, + ThreadingContext, owner, nestedAction.Workspace, originalSolution, subjectBuffer, nestedAction.Provider ?? this, nestedAction.OriginalCodeAction, nestedAction.NestedActionSets.SelectAsArray((s, arg) => ConvertToSuggestedActionSet(s, arg.owner, arg.subjectBuffer), (owner, subjectBuffer))), _ => throw ExceptionUtilities.Unreachable diff --git a/src/EditorFeatures/Core/CodeActions/CodeActionEditHandlerService.cs b/src/EditorFeatures/Core/CodeActions/CodeActionEditHandlerService.cs index adea3ae0fde1b..3aff8234b2547 100644 --- a/src/EditorFeatures/Core/CodeActions/CodeActionEditHandlerService.cs +++ b/src/EditorFeatures/Core/CodeActions/CodeActionEditHandlerService.cs @@ -100,9 +100,12 @@ internal class CodeActionEditHandlerService : ICodeActionEditHandlerService } public async Task ApplyAsync( - Workspace workspace, Document? fromDocument, + Workspace workspace, + Solution originalSolution, + Document? fromDocument, ImmutableArray operations, - string title, IProgressTracker progressTracker, + string title, + IProgressTracker progressTracker, CancellationToken cancellationToken) { // Much of the work we're going to do will be on the UI thread, so switch there preemptively. @@ -148,7 +151,7 @@ internal class CodeActionEditHandlerService : ICodeActionEditHandlerService _threadingContext.ThrowIfNotOnUIThread(); applied = await operations.Single().TryApplyAsync( - workspace, progressTracker, cancellationToken).ConfigureAwait(true); + workspace, originalSolution, progressTracker, cancellationToken).ConfigureAwait(true); } catch (Exception ex) when (FatalError.ReportAndPropagateUnlessCanceled(ex, cancellationToken)) { @@ -174,7 +177,7 @@ internal class CodeActionEditHandlerService : ICodeActionEditHandlerService { // Come back to the UI thread after processing the operations so we can commit the transaction applied = await ProcessOperationsAsync( - workspace, operations, progressTracker, cancellationToken).ConfigureAwait(true); + workspace, originalSolution, operations, progressTracker, cancellationToken).ConfigureAwait(true); } catch (Exception ex) when (FatalError.ReportAndPropagateUnlessCanceled(ex, cancellationToken)) { @@ -265,8 +268,11 @@ internal class CodeActionEditHandlerService : ICodeActionEditHandlerService /// if all expected are applied successfully; /// otherwise, . private async Task ProcessOperationsAsync( - Workspace workspace, ImmutableArray operations, - IProgressTracker progressTracker, CancellationToken cancellationToken) + Workspace workspace, + Solution originalSolution, + ImmutableArray operations, + IProgressTracker progressTracker, + CancellationToken cancellationToken) { await this._threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); @@ -284,7 +290,7 @@ internal class CodeActionEditHandlerService : ICodeActionEditHandlerService } _threadingContext.ThrowIfNotOnUIThread(); - applied &= await operation.TryApplyAsync(workspace, progressTracker, cancellationToken).ConfigureAwait(true); + applied &= await operation.TryApplyAsync(workspace, originalSolution, progressTracker, cancellationToken).ConfigureAwait(true); } return applied; diff --git a/src/EditorFeatures/Core/CodeActions/ICodeActionEditHandlerService.cs b/src/EditorFeatures/Core/CodeActions/ICodeActionEditHandlerService.cs index ff34e723b9ed3..846715efef1fa 100644 --- a/src/EditorFeatures/Core/CodeActions/ICodeActionEditHandlerService.cs +++ b/src/EditorFeatures/Core/CodeActions/ICodeActionEditHandlerService.cs @@ -18,9 +18,12 @@ internal interface ICodeActionEditHandlerService Workspace workspace, ImmutableArray operations, CancellationToken cancellationToken); Task ApplyAsync( - Workspace workspace, Document? fromDocument, + Workspace workspace, + Solution originalSolution, + Document? fromDocument, ImmutableArray operations, - string title, IProgressTracker progressTracker, + string title, + IProgressTracker progressTracker, CancellationToken cancellationToken); } } diff --git a/src/EditorFeatures/Core/RenameTracking/RenameTrackingTaggerProvider.RenameTrackingCodeAction.cs b/src/EditorFeatures/Core/RenameTracking/RenameTrackingTaggerProvider.RenameTrackingCodeAction.cs index b253eaa2b6058..99b9f0a80dedc 100644 --- a/src/EditorFeatures/Core/RenameTracking/RenameTrackingTaggerProvider.RenameTrackingCodeAction.cs +++ b/src/EditorFeatures/Core/RenameTracking/RenameTrackingTaggerProvider.RenameTrackingCodeAction.cs @@ -118,7 +118,8 @@ public RenameTrackingCommitterOperation(RenameTrackingCommitter committer, IThre _threadingContext = threadingContext; } - internal override async Task TryApplyAsync(Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + internal override async Task TryApplyAsync( + Workspace workspace, Solution originalSolution, IProgressTracker progressTracker, CancellationToken cancellationToken) { var error = await _committer.TryCommitAsync(cancellationToken).ConfigureAwait(false); if (error == null) diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs index 48b1f7fb7d9f0..eb53a2ff7791d 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs @@ -766,16 +766,14 @@ static void VerifyExpectedDocumentText(string expected, string actual) Tuple result = null; foreach (var operation in operations) { - if (operation is ApplyChangesOperation && result == null) + if (operation is ApplyChangesOperation applyChangesOperation && result == null) { - var oldSolution = workspace.CurrentSolution; - var newSolution = ((ApplyChangesOperation)operation).ChangedSolution; - result = Tuple.Create(oldSolution, newSolution); + result = Tuple.Create(workspace.CurrentSolution, applyChangesOperation.ChangedSolution); } else if (operation.ApplyDuringTests) { var oldSolution = workspace.CurrentSolution; - await operation.TryApplyAsync(workspace, new ProgressTracker(), CancellationToken.None); + await operation.TryApplyAsync(workspace, oldSolution, new ProgressTracker(), CancellationToken.None); var newSolution = workspace.CurrentSolution; result = Tuple.Create(oldSolution, newSolution); } diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs index 0cc536d9d6345..07f4dd868a160 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs @@ -131,7 +131,7 @@ protected override Task> GetDiagnosticsWorkerAsync(Te await VerifyPreviewContents(workspace, expectedPreviewContents, operations); var applyChangesOperation = operations.OfType().First(); - await applyChangesOperation.TryApplyAsync(workspace, new ProgressTracker(), CancellationToken.None); + await applyChangesOperation.TryApplyAsync(workspace, workspace.CurrentSolution, new ProgressTracker(), CancellationToken.None); foreach (var document in workspace.Documents) { diff --git a/src/EditorFeatures/Test/RenameTracking/RenameTrackingTestState.cs b/src/EditorFeatures/Test/RenameTracking/RenameTrackingTestState.cs index 85b953bc897c5..b0698e67f4b3e 100644 --- a/src/EditorFeatures/Test/RenameTracking/RenameTrackingTestState.cs +++ b/src/EditorFeatures/Test/RenameTracking/RenameTrackingTestState.cs @@ -201,7 +201,7 @@ public async Task AssertTag(string expectedFromName, string expectedToName, bool var operations = (await codeAction.GetOperationsAsync(CancellationToken.None)).ToArray(); Assert.Equal(1, operations.Length); - await operations[0].TryApplyAsync(this.Workspace, new ProgressTracker(), CancellationToken.None); + await operations[0].TryApplyAsync(this.Workspace, this.Workspace.CurrentSolution, new ProgressTracker(), CancellationToken.None); } } diff --git a/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb b/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb index ba8115be3ea92..99f85203bcd0d 100644 --- a/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb +++ b/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb @@ -1303,6 +1303,7 @@ class C Await editHandler.ApplyAsync( workspace, + workspace.CurrentSolution, workspace.CurrentSolution.GetDocument(workspace.Documents.Single().Id), Await actions.First().NestedCodeActions.First().GetOperationsAsync(CancellationToken.None), "unused", diff --git a/src/Features/Core/Portable/AddImport/CodeActions/AssemblyReferenceCodeAction.cs b/src/Features/Core/Portable/AddImport/CodeActions/AssemblyReferenceCodeAction.cs index a31b78f31ccbc..ca2b0f94a064c 100644 --- a/src/Features/Core/Portable/AddImport/CodeActions/AssemblyReferenceCodeAction.cs +++ b/src/Features/Core/Portable/AddImport/CodeActions/AssemblyReferenceCodeAction.cs @@ -79,13 +79,14 @@ public override void Apply(Workspace workspace, CancellationToken cancellationTo operation.Apply(workspace, cancellationToken); } - internal override Task TryApplyAsync(Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + internal override Task TryApplyAsync( + Workspace workspace, Solution originalSolution, IProgressTracker progressTracker, CancellationToken cancellationToken) { var operation = GetApplyChangesOperation(workspace); if (operation is null) return SpecializedTasks.False; - return operation.TryApplyAsync(workspace, progressTracker, cancellationToken); + return operation.TryApplyAsync(workspace, originalSolution, progressTracker, cancellationToken); } private ApplyChangesOperation? GetApplyChangesOperation(Workspace workspace) diff --git a/src/Features/Core/Portable/AddImport/CodeActions/InstallPackageAndAddImportCodeAction.cs b/src/Features/Core/Portable/AddImport/CodeActions/InstallPackageAndAddImportCodeAction.cs index b87c15ce4b770..4ba21c98e321a 100644 --- a/src/Features/Core/Portable/AddImport/CodeActions/InstallPackageAndAddImportCodeAction.cs +++ b/src/Features/Core/Portable/AddImport/CodeActions/InstallPackageAndAddImportCodeAction.cs @@ -113,7 +113,8 @@ private class InstallPackageAndAddImportOperation : CodeActionOperation internal override bool ApplyDuringTests => _installPackageOperation.ApplyDuringTests; public override string Title => _installPackageOperation.Title; - internal override async Task TryApplyAsync(Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + internal override async Task TryApplyAsync( + Workspace workspace, Solution originalSolution, IProgressTracker progressTracker, CancellationToken cancellationToken) { var newSolution = workspace.CurrentSolution.WithDocumentText( _changedDocumentId, _newText); @@ -121,7 +122,7 @@ internal override async Task TryApplyAsync(Workspace workspace, IProgressT // First make the changes to add the import to the document. if (workspace.TryApplyChanges(newSolution, progressTracker)) { - if (await _installPackageOperation.TryApplyAsync(workspace, progressTracker, cancellationToken).ConfigureAwait(true)) + if (await _installPackageOperation.TryApplyAsync(workspace, originalSolution, progressTracker, cancellationToken).ConfigureAwait(true)) { return true; } diff --git a/src/Features/Core/Portable/AddImport/CodeActions/ProjectSymbolReferenceCodeAction.cs b/src/Features/Core/Portable/AddImport/CodeActions/ProjectSymbolReferenceCodeAction.cs index bd97d46177c1b..05f98f38e3083 100644 --- a/src/Features/Core/Portable/AddImport/CodeActions/ProjectSymbolReferenceCodeAction.cs +++ b/src/Features/Core/Portable/AddImport/CodeActions/ProjectSymbolReferenceCodeAction.cs @@ -71,12 +71,13 @@ public override void Apply(Workspace workspace, CancellationToken cancellationTo _applyOperation.Apply(workspace, cancellationToken); } - internal override Task TryApplyAsync(Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + internal override Task TryApplyAsync( + Workspace workspace, Solution originalSolution, IProgressTracker progressTracker, CancellationToken cancellationToken) { if (!CanApply(workspace)) return SpecializedTasks.False; - return _applyOperation.TryApplyAsync(workspace, progressTracker, cancellationToken); + return _applyOperation.TryApplyAsync(workspace, originalSolution, progressTracker, cancellationToken); } private bool CanApply(Workspace workspace) diff --git a/src/Features/Core/Portable/AddPackage/InstallPackageDirectlyCodeActionOperation.cs b/src/Features/Core/Portable/AddPackage/InstallPackageDirectlyCodeActionOperation.cs index b801a1082739b..a0df4193efe6d 100644 --- a/src/Features/Core/Portable/AddPackage/InstallPackageDirectlyCodeActionOperation.cs +++ b/src/Features/Core/Portable/AddPackage/InstallPackageDirectlyCodeActionOperation.cs @@ -70,7 +70,7 @@ internal class InstallPackageDirectlyCodeActionOperation : CodeActionOperation internal override bool ApplyDuringTests => true; internal override Task TryApplyAsync( - Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + Workspace workspace, Solution originalSolution, IProgressTracker progressTracker, CancellationToken cancellationToken) { return _installerService.TryInstallPackageAsync( workspace, _document.Id, _source, _packageName, diff --git a/src/Features/Core/Portable/ChangeSignature/ChangeSignatureCodeActionOperation.cs b/src/Features/Core/Portable/ChangeSignature/ChangeSignatureCodeActionOperation.cs index 56dd2cf72a0ba..7735857a43d9e 100644 --- a/src/Features/Core/Portable/ChangeSignature/ChangeSignatureCodeActionOperation.cs +++ b/src/Features/Core/Portable/ChangeSignature/ChangeSignatureCodeActionOperation.cs @@ -31,19 +31,16 @@ public ChangeSignatureCodeActionOperation(Solution changedSolution, string? conf internal override bool ApplyDuringTests => true; - public sealed override void Apply(Workspace workspace, CancellationToken cancellationToken) - => ApplyWorker(workspace, new ProgressTracker()); - /// /// Show the confirmation message, if available, before attempting to apply the changes. /// internal sealed override Task TryApplyAsync( - Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + Workspace workspace, Solution originalSolution, IProgressTracker progressTracker, CancellationToken cancellationToken) { - return ApplyWorker(workspace, progressTracker) ? SpecializedTasks.True : SpecializedTasks.False; + return ApplyWorker(workspace, originalSolution, progressTracker, cancellationToken) ? SpecializedTasks.True : SpecializedTasks.False; } - private bool ApplyWorker(Workspace workspace, IProgressTracker progressTracker) + private bool ApplyWorker(Workspace workspace, Solution originalSolution, IProgressTracker progressTracker, CancellationToken cancellationToken) { if (ConfirmationMessage != null) { @@ -54,7 +51,7 @@ private bool ApplyWorker(Workspace workspace, IProgressTracker progressTracker) } } - return workspace.TryApplyChanges(ChangedSolution, progressTracker); + return ApplyChangesOperation.ApplyOrMergeChanges(workspace, originalSolution, ChangedSolution, progressTracker, cancellationToken); } } } diff --git a/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionSet.cs b/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionSet.cs index ca4d99cfea496..fa593e7edc71f 100644 --- a/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionSet.cs +++ b/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionSet.cs @@ -13,6 +13,8 @@ namespace Microsoft.CodeAnalysis.UnifiedSuggestions /// internal class UnifiedSuggestedActionSet { + public Solution OriginalSolution { get; } + public string? CategoryName { get; } public ImmutableArray Actions { get; } @@ -24,12 +26,14 @@ internal class UnifiedSuggestedActionSet public TextSpan? ApplicableToSpan { get; } public UnifiedSuggestedActionSet( + Solution originalSolution, string? categoryName, ImmutableArray actions, object? title, UnifiedSuggestedActionSetPriority priority, TextSpan? applicableToSpan) { + OriginalSolution = originalSolution; CategoryName = categoryName; Actions = actions; Title = title; diff --git a/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs b/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs index b922ed7c4b78a..ce7c6084d0dce 100644 --- a/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs +++ b/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs @@ -42,6 +42,8 @@ internal class UnifiedSuggestedActionsSource Func addOperationScope, CancellationToken cancellationToken) { + var originalSolution = document.Project.Solution; + // Intentionally switch to a threadpool thread to compute fixes. We do not want to accidentally // run any of this on the UI thread and potentially allow any code to take a dependency on that. var fixes = await Task.Run(() => codeFixService.GetFixesAsync( @@ -54,7 +56,7 @@ internal class UnifiedSuggestedActionsSource cancellationToken), cancellationToken).ConfigureAwait(false); var filteredFixes = fixes.WhereAsArray(c => c.Fixes.Length > 0); - var organizedFixes = await OrganizeFixesAsync(workspace, filteredFixes, cancellationToken).ConfigureAwait(false); + var organizedFixes = await OrganizeFixesAsync(workspace, originalSolution, filteredFixes, cancellationToken).ConfigureAwait(false); return organizedFixes; } @@ -64,6 +66,7 @@ internal class UnifiedSuggestedActionsSource /// private static async Task> OrganizeFixesAsync( Workspace workspace, + Solution originalSolution, ImmutableArray fixCollections, CancellationToken cancellationToken) { @@ -71,10 +74,10 @@ internal class UnifiedSuggestedActionsSource using var _ = ArrayBuilder.GetInstance(out var order); // First group fixes by diagnostic and priority. - await GroupFixesAsync(workspace, fixCollections, map, order, cancellationToken).ConfigureAwait(false); + await GroupFixesAsync(workspace, originalSolution, fixCollections, map, order, cancellationToken).ConfigureAwait(false); // Then prioritize between the groups. - var prioritizedFixes = PrioritizeFixGroups(map.ToImmutable(), order.ToImmutable(), workspace); + var prioritizedFixes = PrioritizeFixGroups(originalSolution, map.ToImmutable(), order.ToImmutable(), workspace); return prioritizedFixes; } @@ -83,17 +86,19 @@ internal class UnifiedSuggestedActionsSource /// private static async Task GroupFixesAsync( Workspace workspace, + Solution originalSolution, ImmutableArray fixCollections, IDictionary> map, ArrayBuilder order, CancellationToken cancellationToken) { foreach (var fixCollection in fixCollections) - await ProcessFixCollectionAsync(workspace, map, order, fixCollection, cancellationToken).ConfigureAwait(false); + await ProcessFixCollectionAsync(workspace, originalSolution, map, order, fixCollection, cancellationToken).ConfigureAwait(false); } private static async Task ProcessFixCollectionAsync( Workspace workspace, + Solution originalSolution, IDictionary> map, ArrayBuilder order, CodeFixCollection fixCollection, @@ -105,11 +110,11 @@ internal class UnifiedSuggestedActionsSource var nonSupressionCodeFixes = fixes.WhereAsArray(f => !IsTopLevelSuppressionAction(f.Action)); var supressionCodeFixes = fixes.WhereAsArray(f => IsTopLevelSuppressionAction(f.Action)); - await AddCodeActionsAsync(workspace, map, order, fixCollection, GetFixAllSuggestedActionSetAsync, nonSupressionCodeFixes).ConfigureAwait(false); + await AddCodeActionsAsync(workspace, originalSolution, map, order, fixCollection, GetFixAllSuggestedActionSetAsync, nonSupressionCodeFixes).ConfigureAwait(false); // Add suppression fixes to the end of a given SuggestedActionSet so that they // always show up last in a group. - await AddCodeActionsAsync(workspace, map, order, fixCollection, GetFixAllSuggestedActionSetAsync, supressionCodeFixes).ConfigureAwait(false); + await AddCodeActionsAsync(workspace, originalSolution, map, order, fixCollection, GetFixAllSuggestedActionSetAsync, supressionCodeFixes).ConfigureAwait(false); return; @@ -118,36 +123,40 @@ internal class UnifiedSuggestedActionsSource => GetUnifiedFixAllSuggestedActionSetAsync( codeAction, fixCount, fixCollection.FixAllState, fixCollection.SupportedScopes, fixCollection.FirstDiagnostic, - workspace, cancellationToken); + workspace, originalSolution, cancellationToken); } private static async Task AddCodeActionsAsync( - Workspace workspace, IDictionary> map, - ArrayBuilder order, CodeFixCollection fixCollection, + Workspace workspace, + Solution originalSolution, + IDictionary> map, + ArrayBuilder order, + CodeFixCollection fixCollection, Func> getFixAllSuggestedActionSetAsync, ImmutableArray codeFixes) { foreach (var fix in codeFixes) { - var unifiedSuggestedAction = await GetUnifiedSuggestedActionAsync(fix.Action, fix).ConfigureAwait(false); + var unifiedSuggestedAction = await GetUnifiedSuggestedActionAsync(originalSolution, fix.Action, fix).ConfigureAwait(false); AddFix(fix, unifiedSuggestedAction, map, order); } return; // Local functions - async Task GetUnifiedSuggestedActionAsync(CodeAction action, CodeFix fix) + async Task GetUnifiedSuggestedActionAsync(Solution originalSolution, CodeAction action, CodeFix fix) { if (action.NestedCodeActions.Length > 0) { using var _ = ArrayBuilder.GetInstance(action.NestedCodeActions.Length, out var unifiedNestedActions); foreach (var nestedAction in action.NestedCodeActions) { - var unifiedNestedAction = await GetUnifiedSuggestedActionAsync(nestedAction, fix).ConfigureAwait(false); + var unifiedNestedAction = await GetUnifiedSuggestedActionAsync(originalSolution, nestedAction, fix).ConfigureAwait(false); unifiedNestedActions.Add(unifiedNestedAction); } var set = new UnifiedSuggestedActionSet( + originalSolution, categoryName: null, actions: unifiedNestedActions.ToImmutable(), title: null, @@ -204,6 +213,7 @@ static CodeFixGroupKey GetGroupKey(CodeFix fix) ImmutableArray supportedScopes, Diagnostic firstDiagnostic, Workspace workspace, + Solution originalSolution, CancellationToken cancellationToken) { if (fixAllState == null) @@ -244,6 +254,7 @@ static CodeFixGroupKey GetGroupKey(CodeFix fix) } return new UnifiedSuggestedActionSet( + originalSolution, categoryName: null, actions: fixAllSuggestedActions.ToImmutable(), title: CodeFixesResources.Fix_all_occurrences_in, @@ -264,6 +275,7 @@ static CodeFixGroupKey GetGroupKey(CodeFix fix) /// always show up last after all other fixes (and refactorings) for the selected line of code. /// private static ImmutableArray PrioritizeFixGroups( + Solution originalSolution, ImmutableDictionary> map, ImmutableArray order, Workspace workspace) @@ -277,11 +289,11 @@ static CodeFixGroupKey GetGroupKey(CodeFix fix) var actions = map[groupKey]; var nonSuppressionActions = actions.Where(a => !IsTopLevelSuppressionAction(a.OriginalCodeAction)).ToImmutableArray(); - AddUnifiedSuggestedActionsSet(nonSuppressionActions, groupKey, nonSuppressionSets); + AddUnifiedSuggestedActionsSet(originalSolution, nonSuppressionActions, groupKey, nonSuppressionSets); var suppressionActions = actions.Where(a => IsTopLevelSuppressionAction(a.OriginalCodeAction) && !IsBulkConfigurationAction(a.OriginalCodeAction)).ToImmutableArray(); - AddUnifiedSuggestedActionsSet(suppressionActions, groupKey, suppressionSets); + AddUnifiedSuggestedActionsSet(originalSolution, suppressionActions, groupKey, suppressionSets); bulkConfigurationActions.AddRange(actions.Where(a => IsBulkConfigurationAction(a.OriginalCodeAction))); } @@ -292,6 +304,7 @@ static CodeFixGroupKey GetGroupKey(CodeFix fix) if (bulkConfigurationActions.Count > 0) { var bulkConfigurationSet = new UnifiedSuggestedActionSet( + originalSolution, UnifiedPredefinedSuggestedActionCategoryNames.CodeFix, bulkConfigurationActions.ToImmutable(), title: null, @@ -314,6 +327,7 @@ static CodeFixGroupKey GetGroupKey(CodeFix fix) // to get the span and category for the new top level suggested action. var (span, category) = CombineSpansAndCategory(suppressionSets); var wrappingSet = new UnifiedSuggestedActionSet( + originalSolution, category, actions: ImmutableArray.Create(wrappingSuggestedAction), title: CodeFixesResources.Suppress_or_Configure_issues, @@ -368,6 +382,7 @@ static CodeFixGroupKey GetGroupKey(CodeFix fix) } private static void AddUnifiedSuggestedActionsSet( + Solution originalSolution, ImmutableArray actions, CodeFixGroupKey groupKey, ArrayBuilder sets) @@ -380,7 +395,7 @@ static CodeFixGroupKey GetGroupKey(CodeFix fix) Debug.Assert(groupKey.Item1.HasTextSpan); var category = GetFixCategory(groupKey.Item1.Severity); sets.Add(new UnifiedSuggestedActionSet( - category, group.ToImmutableArray(), title: null, priority, applicableToSpan: groupKey.Item1.GetTextSpan())); + originalSolution, category, group.ToImmutableArray(), title: null, priority, applicableToSpan: groupKey.Item1.GetTextSpan())); } } @@ -491,6 +506,8 @@ bool IsActionAndSpanApplicable((CodeAction action, TextSpan? applicableSpan) act CodeRefactoring refactoring, CancellationToken cancellationToken) { + var originalSolution = document.Project.Solution; + using var _ = ArrayBuilder.GetInstance(out var refactoringSuggestedActions); foreach (var (action, applicableToSpan) in refactoring.CodeActions) @@ -509,6 +526,7 @@ bool IsActionAndSpanApplicable((CodeAction action, TextSpan? applicableSpan) act // and therefore the complexity of determining the closest one isn't worth the benefit // of slightly more correct orderings in certain edge cases. return new UnifiedSuggestedActionSet( + originalSolution, UnifiedPredefinedSuggestedActionCategoryNames.Refactoring, actions: actions, title: null, @@ -528,6 +546,7 @@ async Task GetUnifiedSuggestedActionSetAsync(CodeAction } var set = new UnifiedSuggestedActionSet( + originalSolution, categoryName: null, actions: nestedActions.ToImmutable(), title: null, @@ -577,6 +596,8 @@ async Task GetUnifiedSuggestedActionSetAsync(CodeAction return null; } + var originalSolution = document.Project.Solution; + using var fixAllSuggestedActionsDisposer = ArrayBuilder.GetInstance(out var fixAllSuggestedActions); foreach (var scope in fixAllProviderInfo.SupportedScopes) { @@ -601,6 +622,7 @@ async Task GetUnifiedSuggestedActionSetAsync(CodeAction } return new UnifiedSuggestedActionSet( + originalSolution, categoryName: null, actions: fixAllSuggestedActions.ToImmutable(), title: CodeFixesResources.Fix_all_occurrences_in, @@ -698,7 +720,7 @@ private static UnifiedSuggestedActionSetPriority GetUnifiedSuggestedActionSetPri private static UnifiedSuggestedActionSet WithPriority( UnifiedSuggestedActionSet set, UnifiedSuggestedActionSetPriority priority) - => new(set.CategoryName, set.Actions, set.Title, priority, set.ApplicableToSpan); + => new(set.OriginalSolution, set.CategoryName, set.Actions, set.Title, priority, set.ApplicableToSpan); private static ImmutableArray InlineActionSetsIfDesirable( ImmutableArray actionSets, @@ -731,6 +753,7 @@ private static UnifiedSuggestedActionSet InlineActions(UnifiedSuggestedActionSet } return new UnifiedSuggestedActionSet( + actionSet.OriginalSolution, actionSet.CategoryName, newActions.ToImmutable(), actionSet.Title, @@ -770,7 +793,7 @@ private static UnifiedSuggestedActionSet InlineActions(UnifiedSuggestedActionSet return actions.Count == 0 ? null - : new UnifiedSuggestedActionSet(set.CategoryName, actions.ToImmutable(), set.Title, set.Priority, set.ApplicableToSpan); + : new UnifiedSuggestedActionSet(set.OriginalSolution, set.CategoryName, actions.ToImmutable(), set.Title, set.Priority, set.ApplicableToSpan); } } } diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs index 7d0b1ee59b307..484c26ebaaa59 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs @@ -206,6 +206,7 @@ private async Task SetSeverityHandlerAsync(ReportDiagnostic reportDiagnostic, Di using var scope = context.AddScope(allowCancellation: true, ServicesVSResources.Updating_severity); await _editHandlerService.ApplyAsync( _workspace, + project.Solution, fromDocument: null, operations: operations, title: ServicesVSResources.Updating_severity, diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs index d2ab4e9629909..4aad5d6f4558f 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs @@ -254,6 +254,8 @@ private async Task ApplySuppressionFixAsync(IEnumerable? diagnos try { using var token = _listener.BeginAsyncOperation(nameof(ApplySuppressionFix)); + + var originalSolution = _workspace.CurrentSolution; var title = GetFixTitle(isAddSuppression); var waitDialogMessage = GetWaitDialogMessage(isAddSuppression); @@ -389,6 +391,7 @@ private async Task ApplySuppressionFixAsync(IEnumerable? diagnos using var scope = context.AddScope(allowCancellation: true, description: waitDialogMessage); await _editHandlerService.ApplyAsync( _workspace, + originalSolution, fromDocument: null, operations: operations, title: title, diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs index a9ed1e085e463..76a6aa6c19e6e 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs @@ -431,6 +431,7 @@ private async Task SetSeverityHandlerAsync(VisualStudioWorkspaceImpl workspace, allowCancellation: true, showProgress: true); + var originalSolution = workspace.CurrentSolution; var selectedAction = MapSelectedItemToReportDiagnostic(selectedItem); if (!selectedAction.HasValue) return; @@ -465,6 +466,7 @@ private async Task SetSeverityHandlerAsync(VisualStudioWorkspaceImpl workspace, var operations = ImmutableArray.Create(new ApplyChangesOperation(newSolution)); await editHandlerService.ApplyAsync( _workspace, + originalSolution, fromDocument: null, operations: operations, title: ServicesVSResources.Updating_severity, diff --git a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs index 93ebaaaae2845..b040f95d1e916 100644 --- a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs +++ b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs @@ -42,14 +42,21 @@ public ApplyChangesOperation(Solution changedSolution) public override void Apply(Workspace workspace, CancellationToken cancellationToken) => workspace.TryApplyChanges(ChangedSolution, new ProgressTracker()); - internal sealed override Task TryApplyAsync( - Workspace workspace, Solution originalSolution, IProgressTracker progressTracker, CancellationToken cancellationToken) + internal sealed override Task TryApplyAsync(Workspace workspace, Solution originalSolution, IProgressTracker progressTracker, CancellationToken cancellationToken) + => Task.FromResult(ApplyOrMergeChanges(workspace, originalSolution, ChangedSolution, progressTracker, cancellationToken)); + + internal static bool ApplyOrMergeChanges( + Workspace workspace, + Solution originalSolution, + Solution changedSolution, + IProgressTracker progressTracker, + CancellationToken cancellationToken) { var currentSolution = workspace.CurrentSolution; // if there was no intermediary edit, just apply the change fully. - if (ChangedSolution.WorkspaceVersion == currentSolution.WorkspaceVersion) - return Task.FromResult(workspace.TryApplyChanges(ChangedSolution, progressTracker)); + if (changedSolution.WorkspaceVersion == currentSolution.WorkspaceVersion) + return workspace.TryApplyChanges(changedSolution, progressTracker); // Otherwise, we need to see what changes were actually made and see if we can apply them. The general rules are: // @@ -63,14 +70,14 @@ public override void Apply(Workspace workspace, CancellationToken cancellationTo // of some sort of text-merging-library to handle this. However, the user would then have to handle diff // markers being inserted into their code that they then have to handle. - var solutionChanges = this.ChangedSolution.GetChanges(originalSolution); + var solutionChanges = changedSolution.GetChanges(originalSolution); if (solutionChanges.GetAddedProjects().Count() > 0 || solutionChanges.GetAddedAnalyzerReferences().Count() > 0 || solutionChanges.GetRemovedProjects().Count() > 0 || solutionChanges.GetRemovedAnalyzerReferences().Count() > 0) { - return SpecializedTasks.False; + return false; } // Take the actual current solution the workspace is pointing to and fork it with just the text changes the @@ -93,20 +100,20 @@ public override void Apply(Workspace workspace, CancellationToken cancellationTo changedProject.GetRemovedMetadataReferences().Count() > 0 || changedProject.GetRemovedProjectReferences().Count() > 0) { - return SpecializedTasks.False; + return false; } - if (!ProcessDocuments(changedProject, changedProject.GetChangedDocuments(), static (s, i) => s.GetRequiredDocument(i), static (s, i, t) => s.WithDocumentText(i, t)) || - !ProcessDocuments(changedProject, changedProject.GetChangedAdditionalDocuments(), static (s, i) => s.GetRequiredAdditionalDocument(i), static (s, i, t) => s.WithAdditionalDocumentText(i, t)) || - !ProcessDocuments(changedProject, changedProject.GetChangedAnalyzerConfigDocuments(), static (s, i) => s.GetRequiredAnalyzerConfigDocument(i), static (s, i, t) => s.WithAnalyzerConfigDocumentText(i, t))) + if (!TryForkTextChanges(changedProject, changedProject.GetChangedDocuments(), static (s, i) => s.GetRequiredDocument(i), static (s, i, t) => s.WithDocumentText(i, t)) || + !TryForkTextChanges(changedProject, changedProject.GetChangedAdditionalDocuments(), static (s, i) => s.GetRequiredAdditionalDocument(i), static (s, i, t) => s.WithAdditionalDocumentText(i, t)) || + !TryForkTextChanges(changedProject, changedProject.GetChangedAnalyzerConfigDocuments(), static (s, i) => s.GetRequiredAnalyzerConfigDocument(i), static (s, i, t) => s.WithAnalyzerConfigDocumentText(i, t))) { - return SpecializedTasks.False; + return false; } } - return Task.FromResult(workspace.TryApplyChanges(forkedSolution, progressTracker)); + return workspace.TryApplyChanges(forkedSolution, progressTracker); - bool ProcessDocuments( + bool TryForkTextChanges( ProjectChanges changedProject, IEnumerable changedDocuments, Func getDocument, From c3f027c313eced4a8f1f6c794902af73f4135e33 Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Tue, 19 Jul 2022 13:28:21 -0700 Subject: [PATCH 45/66] Use TestAccessor pattern --- .../CompletionService.ProviderManager.cs | 32 ++++++++++++------- .../Portable/Completion/CompletionService.cs | 2 +- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs b/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs index 06e5d5ce03e4d..4d34024285e77 100644 --- a/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs +++ b/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs @@ -96,17 +96,6 @@ ImmutableArray GetImportedAndBuiltInProvidersWorker(Immutabl } } - /// - /// Don't call. For test only. - /// - public ImmutableArray GetProviders(ImmutableHashSet roles, Project? project) - { - using var _ = ArrayBuilder.GetInstance(out var providers); - providers.AddRange(GetImportedAndBuiltInProviders(roles)); - providers.AddRange(GetProjectCompletionProviders(project)); - return providers.ToImmutable(); - } - public CompletionProvider? GetProvider(CompletionItem item, Project? project) { if (item.ProviderName == null) @@ -231,6 +220,27 @@ protected override bool TryGetExtensionsFromReference(AnalyzerReference referenc return false; } } + + internal TestAccessor GetTestAccessor() + => new(this); + + internal readonly struct TestAccessor + { + private readonly ProviderManager _providerManager; + + public TestAccessor(ProviderManager providerManager) + { + _providerManager = providerManager; + } + + public ImmutableArray GetProviders(ImmutableHashSet roles, Project? project) + { + using var _ = ArrayBuilder.GetInstance(out var providers); + providers.AddRange(_providerManager.GetImportedAndBuiltInProviders(roles)); + providers.AddRange(GetProjectCompletionProviders(project)); + return providers.ToImmutable(); + } + } } } } diff --git a/src/Features/Core/Portable/Completion/CompletionService.cs b/src/Features/Core/Portable/Completion/CompletionService.cs index 1a6120df15451..3a86d9ed97acd 100644 --- a/src/Features/Core/Portable/Completion/CompletionService.cs +++ b/src/Features/Core/Portable/Completion/CompletionService.cs @@ -415,7 +415,7 @@ public TestAccessor(CompletionService completionServiceWithProviders) => _completionServiceWithProviders = completionServiceWithProviders; internal ImmutableArray GetAllProviders(ImmutableHashSet roles, Project? project = null) - => _completionServiceWithProviders._providerManager.GetProviders(roles, project); + => _completionServiceWithProviders._providerManager.GetTestAccessor().GetProviders(roles, project); internal async Task GetContextAsync( CompletionProvider provider, From 71b8348df15cb21741f88cacba752d4d94dedc70 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Jul 2022 15:48:19 -0700 Subject: [PATCH 46/66] Add tests --- .../CodeActions/ApplyChangesOperationTests.cs | 272 ++++++++++++++++++ .../Operations/ApplyChangesOperation.cs | 57 ++-- 2 files changed, 304 insertions(+), 25 deletions(-) create mode 100644 src/EditorFeatures/CSharpTest/CodeActions/ApplyChangesOperationTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ApplyChangesOperationTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/ApplyChangesOperationTests.cs new file mode 100644 index 0000000000000..d6ba2aabeaf4d --- /dev/null +++ b/src/EditorFeatures/CSharpTest/CodeActions/ApplyChangesOperationTests.cs @@ -0,0 +1,272 @@ +// 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; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings; +using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Editor.UnitTests.Preview; +using Microsoft.CodeAnalysis.Editor.UnitTests; +using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.CodeActions; +using System.Threading; +using Roslyn.Test.Utilities; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Shared.Utilities; +using Microsoft.CodeAnalysis.Text; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeActions +{ + public class ApplyChangesOperationTests : AbstractCSharpCodeActionTest + { + protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters) + => new MyCodeRefactoringProvider((Func)parameters.fixProviderData); + + private class MyCodeRefactoringProvider : CodeRefactoringProvider + { + private readonly Func _changeSolution; + + public MyCodeRefactoringProvider(Func changeSolution) + { + _changeSolution = changeSolution; + } + + public sealed override Task ComputeRefactoringsAsync(CodeRefactoringContext context) + { + var codeAction = new TestCodeAction(_changeSolution(context.Document.Project.Solution)); + context.RegisterRefactoring(codeAction); + return Task.CompletedTask; + } + + private sealed class TestCodeAction : CodeAction + { + private readonly Solution _changedSolution; + + public TestCodeAction(Solution changedSolution) + { + _changedSolution = changedSolution; + } + + public override string Title => "Title"; + + protected override Task GetChangedSolutionAsync(CancellationToken cancellationToken) + => Task.FromResult(_changedSolution); + } + } + + [WpfFact, WorkItem(1419139, "https://devdiv.visualstudio.com/DevDiv/_queries/edit/1419139")] + public async Task TestMakeTextChangeWithInterveningEditToDifferentFile() + { + // This should succeed as the code action is trying to edit a file that is not touched by the actual + // workspace edit that already went in. + await TestSuccessfulApplicationAsync( +@" + + +class Program1 +{ +} + + +class Program2 +{ +} + + +", + codeActionTransform: solution => + { + var document1 = solution.Projects.Single().Documents.Single(d => d.FilePath!.Contains("Program1")); + return solution.WithDocumentText(document1.Id, SourceText.From("NewProgram1Content")); + }, + intermediaryTransform: solution => + { + var document2 = solution.Projects.Single().Documents.Single(d => d.FilePath!.Contains("Program2")); + return solution.WithDocumentText(document2.Id, SourceText.From("NewProgram2Content")); + }); + } + + [WpfFact, WorkItem(1419139, "https://devdiv.visualstudio.com/DevDiv/_queries/edit/1419139")] + public async Task TestMakeTextChangeWithInterveningRemovalToDifferentFile() + { + // This should succeed as the code action is trying to edit a file that is not touched by the actual + // workspace edit that already went in. + await TestSuccessfulApplicationAsync( +@" + + +class Program1 +{ +} + + +class Program2 +{ +} + + +", + codeActionTransform: solution => + { + var document1 = solution.Projects.Single().Documents.Single(d => d.FilePath!.Contains("Program1")); + return solution.WithDocumentText(document1.Id, SourceText.From("NewProgram1Content")); + }, + intermediaryTransform: solution => + { + var document2 = solution.Projects.Single().Documents.Single(d => d.FilePath!.Contains("Program2")); + return solution.RemoveDocument(document2.Id); + }); + } + + [WpfFact, WorkItem(1419139, "https://devdiv.visualstudio.com/DevDiv/_queries/edit/1419139")] + public async Task TestMakeTextChangeWithInterveningEditToSameFile() + { + // This should fail as the code action is trying to edit a file that is was already edited by the actual + // workspace edit that already went in. + await TestFailureApplicationAsync( +@" + + +class Program1 +{ +} + + +class Program2 +{ +} + + +", + codeActionTransform: solution => + { + var document1 = solution.Projects.Single().Documents.Single(d => d.FilePath!.Contains("Program1")); + return solution.WithDocumentText(document1.Id, SourceText.From("NewProgram1Content1")); + }, + intermediaryTransform: solution => + { + var document1 = solution.Projects.Single().Documents.Single(d => d.FilePath!.Contains("Program1")); + return solution.WithDocumentText(document1.Id, SourceText.From("NewProgram1Content2")); + }); + } + + [WpfFact, WorkItem(1419139, "https://devdiv.visualstudio.com/DevDiv/_queries/edit/1419139")] + public async Task TestMakeTextChangeWithInterveningRemovalOfThatFile() + { + // This should fail as the code action is trying to edit a file that is subsequently removed. + await TestFailureApplicationAsync( +@" + + +class Program1 +{ +} + + +class Program2 +{ +} + + +", + codeActionTransform: solution => + { + var document1 = solution.Projects.Single().Documents.Single(d => d.FilePath!.Contains("Program1")); + return solution.WithDocumentText(document1.Id, SourceText.From("NewProgram1Content1")); + }, + intermediaryTransform: solution => + { + var document1 = solution.Projects.Single().Documents.Single(d => d.FilePath!.Contains("Program1")); + return solution.RemoveDocument(document1.Id); + }); + } + + [WpfFact, WorkItem(1419139, "https://devdiv.visualstudio.com/DevDiv/_queries/edit/1419139")] + public async Task TestMakeProjectChangeWithInterveningTextEdit() + { + // This should fail as we don't want to make non-text changes that may have undesirable results to the solution + // given the intervening edits. + await TestFailureApplicationAsync( +@" + + +class Program1 +{ +} + + +class Program2 +{ +} + + +", + codeActionTransform: solution => + { + var document1 = solution.Projects.Single().Documents.Single(d => d.FilePath!.Contains("Program1")); + return solution.RemoveDocument(document1.Id); + }, + intermediaryTransform: solution => + { + var document2 = solution.Projects.Single().Documents.Single(d => d.FilePath!.Contains("Program2")); + return solution.WithDocumentText(document2.Id, SourceText.From("NewProgram1Content2")); + }); + } + + private async Task TestSuccessfulApplicationAsync( + string workspaceXml, + Func codeActionTransform, + Func intermediaryTransform) + { + await TestApplicationAsync(workspaceXml, codeActionTransform, intermediaryTransform, success: true); + } + + private async Task TestFailureApplicationAsync( + string workspaceXml, + Func codeActionTransform, + Func intermediaryTransform) + { + await TestApplicationAsync(workspaceXml, codeActionTransform, intermediaryTransform, success: false); + } + + private async Task TestApplicationAsync( + string workspaceXml, + Func codeActionTransform, + Func intermediaryTransform, + bool success) + { + var parameters = new TestParameters(fixProviderData: codeActionTransform); + using var workspace = CreateWorkspaceFromOptions(workspaceXml, parameters); + + var originalSolution = workspace.CurrentSolution; + + var document = GetDocument(workspace); + var provider = CreateCodeRefactoringProvider(workspace, parameters); + + var refactorings = new List(); + var context = new CodeRefactoringContext(document, new TextSpan(), refactorings.Add, CancellationToken.None); + + // Compute refactorings based on the original solution. + await provider.ComputeRefactoringsAsync(context); + var action = refactorings.Single(); + var operations = await action.GetOperationsAsync(CancellationToken.None); + var operation = operations.Single(); + + // Now make an intermediary edit to the workspace that is applied back in. + var changedSolution = intermediaryTransform(originalSolution); + Assert.True(workspace.TryApplyChanges(changedSolution)); + + // Now try to apply the refactoring, even though an intervening edit happened. + var result = await operation.TryApplyAsync(workspace, originalSolution, new ProgressTracker(), CancellationToken.None); + + Assert.Equal(success, result); + } + } +} diff --git a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs index b040f95d1e916..8687a49fe1c19 100644 --- a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs +++ b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs @@ -72,10 +72,10 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution var solutionChanges = changedSolution.GetChanges(originalSolution); - if (solutionChanges.GetAddedProjects().Count() > 0 || - solutionChanges.GetAddedAnalyzerReferences().Count() > 0 || - solutionChanges.GetRemovedProjects().Count() > 0 || - solutionChanges.GetRemovedAnalyzerReferences().Count() > 0) + if (solutionChanges.GetAddedProjects().Any() || + solutionChanges.GetAddedAnalyzerReferences().Any() || + solutionChanges.GetRemovedProjects().Any() || + solutionChanges.GetRemovedAnalyzerReferences().Any()) { return false; } @@ -87,25 +87,33 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution foreach (var changedProject in solutionChanges.GetProjectChanges()) { // We only support text changes. If we see any other changes to this project, bail out immediately. - if (changedProject.GetAddedAdditionalDocuments().Count() > 0 || - changedProject.GetAddedAnalyzerConfigDocuments().Count() > 0 || - changedProject.GetAddedAnalyzerReferences().Count() > 0 || - changedProject.GetAddedDocuments().Count() > 0 || - changedProject.GetAddedMetadataReferences().Count() > 0 || - changedProject.GetAddedProjectReferences().Count() > 0 || - changedProject.GetRemovedAdditionalDocuments().Count() > 0 || - changedProject.GetRemovedAnalyzerConfigDocuments().Count() > 0 || - changedProject.GetRemovedAnalyzerReferences().Count() > 0 || - changedProject.GetRemovedDocuments().Count() > 0 || - changedProject.GetRemovedMetadataReferences().Count() > 0 || - changedProject.GetRemovedProjectReferences().Count() > 0) + if (changedProject.GetAddedAdditionalDocuments().Any() || + changedProject.GetAddedAnalyzerConfigDocuments().Any() || + changedProject.GetAddedAnalyzerReferences().Any() || + changedProject.GetAddedDocuments().Any() || + changedProject.GetAddedMetadataReferences().Any() || + changedProject.GetAddedProjectReferences().Any() || + changedProject.GetRemovedAdditionalDocuments().Any() || + changedProject.GetRemovedAnalyzerConfigDocuments().Any() || + changedProject.GetRemovedAnalyzerReferences().Any() || + changedProject.GetRemovedDocuments().Any() || + changedProject.GetRemovedMetadataReferences().Any() || + changedProject.GetRemovedProjectReferences().Any()) { return false; } - if (!TryForkTextChanges(changedProject, changedProject.GetChangedDocuments(), static (s, i) => s.GetRequiredDocument(i), static (s, i, t) => s.WithDocumentText(i, t)) || - !TryForkTextChanges(changedProject, changedProject.GetChangedAdditionalDocuments(), static (s, i) => s.GetRequiredAdditionalDocument(i), static (s, i, t) => s.WithAdditionalDocumentText(i, t)) || - !TryForkTextChanges(changedProject, changedProject.GetChangedAnalyzerConfigDocuments(), static (s, i) => s.GetRequiredAnalyzerConfigDocument(i), static (s, i, t) => s.WithAnalyzerConfigDocumentText(i, t))) + // We have to at least have some changed document + if (!changedProject.GetChangedDocuments().Any() && + !changedProject.GetChangedAdditionalDocuments().Any() && + !changedProject.GetChangedAnalyzerConfigDocuments().Any()) + { + return false; + } + + if (!TryForkTextChanges(changedProject, changedProject.GetChangedDocuments(), static (s, i) => s.GetDocument(i), static (s, i, t) => s.WithDocumentText(i, t)) || + !TryForkTextChanges(changedProject, changedProject.GetChangedAdditionalDocuments(), static (s, i) => s.GetAdditionalDocument(i), static (s, i, t) => s.WithAdditionalDocumentText(i, t)) || + !TryForkTextChanges(changedProject, changedProject.GetChangedAnalyzerConfigDocuments(), static (s, i) => s.GetAnalyzerConfigDocument(i), static (s, i, t) => s.WithAnalyzerConfigDocumentText(i, t))) { return false; } @@ -116,18 +124,17 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution bool TryForkTextChanges( ProjectChanges changedProject, IEnumerable changedDocuments, - Func getDocument, + Func getDocument, Func withDocumentText) { - var sawChangedDocument = false; - foreach (var documentId in changedDocuments) { - sawChangedDocument = true; - var originalDocument = getDocument(changedProject.OldProject.Solution, documentId); var changedDocument = getDocument(changedProject.NewProject.Solution, documentId); + Contract.ThrowIfNull(originalDocument); + Contract.ThrowIfNull(changedDocument); + // it has to be a text change the operation wants to make. If the operation is making some other // sort of change, we can't merge this operation in. if (!changedDocument.HasTextChanged(originalDocument, ignoreUnchangeableDocument: false)) @@ -147,7 +154,7 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution forkedSolution = withDocumentText(forkedSolution, documentId, changedDocument.GetTextSynchronously(cancellationToken)); } - return sawChangedDocument; + return true; } } } From 78035e5dc232ff3fe478c2be5585b19fdf826da8 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Jul 2022 15:56:13 -0700 Subject: [PATCH 47/66] Add telemetry --- .../Operations/ApplyChangesOperation.cs | 24 ++++++++++++++++++- .../Compiler/Core/Log/FunctionId.cs | 14 +++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs index 8687a49fe1c19..4831b1b5f59a2 100644 --- a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs +++ b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Text; @@ -56,7 +57,15 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution // if there was no intermediary edit, just apply the change fully. if (changedSolution.WorkspaceVersion == currentSolution.WorkspaceVersion) - return workspace.TryApplyChanges(changedSolution, progressTracker); + { + var result = workspace.TryApplyChanges(changedSolution, progressTracker); + + Logger.Log( + result ? FunctionId.ApplyChangesOperation_WorkspaceVersionMatch_ApplicationSucceeded : FunctionId.ApplyChangesOperation_WorkspaceVersionMatch_ApplicationFailed, + logLevel: LogLevel.Information); + + return result; + } // Otherwise, we need to see what changes were actually made and see if we can apply them. The general rules are: // @@ -77,6 +86,7 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution solutionChanges.GetRemovedProjects().Any() || solutionChanges.GetRemovedAnalyzerReferences().Any()) { + Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_IncompatibleSolutionChange, logLevel: LogLevel.Information); return false; } @@ -100,6 +110,7 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution changedProject.GetRemovedMetadataReferences().Any() || changedProject.GetRemovedProjectReferences().Any()) { + Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_IncompatibleProjectChange, logLevel: LogLevel.Information); return false; } @@ -108,6 +119,7 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution !changedProject.GetChangedAdditionalDocuments().Any() && !changedProject.GetChangedAnalyzerConfigDocuments().Any()) { + Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_NoChangedDocument, logLevel: LogLevel.Information); return false; } @@ -119,6 +131,7 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution } } + Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationSucceeded, logLevel: LogLevel.Information); return workspace.TryApplyChanges(forkedSolution, progressTracker); bool TryForkTextChanges( @@ -138,18 +151,27 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution // it has to be a text change the operation wants to make. If the operation is making some other // sort of change, we can't merge this operation in. if (!changedDocument.HasTextChanged(originalDocument, ignoreUnchangeableDocument: false)) + { + Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_NoTextChange, logLevel: LogLevel.Information); return false; + } // If the document has gone away, we definitely cannot apply a text change to it. var currentDocument = getDocument(currentSolution, documentId); if (currentDocument is null) + { + Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_DocumentRemoved, logLevel: LogLevel.Information); return false; + } // If the file contents changed in the current workspace, then we can't apply this change to it. // Note: we could potentially try to do a 3-way merge in the future, including handling conflicts // with that. For now though, we'll leave that out of scope. if (originalDocument.HasTextChanged(currentDocument, ignoreUnchangeableDocument: false)) + { + Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_TextChangeConflict, logLevel: LogLevel.Information); return false; + } forkedSolution = withDocumentText(forkedSolution, documentId, changedDocument.GetTextSynchronously(cancellationToken)); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs index b488968f7bbe9..ffe3ce4f8dd9e 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs @@ -548,5 +548,19 @@ internal enum FunctionId Refactoring_FixAllOccurrencesPreviewChanges = 563, LSP_UsedForkedSolution = 571, + + ApplyChangesOperation_WorkspaceVersionMatch_ApplicationSucceeded = 580, + ApplyChangesOperation_WorkspaceVersionMatch_ApplicationFailed = 581, + ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationSucceeded = 582, + ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_IncompatibleSolutionChange = 583, + ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_IncompatibleProjectChange = 584, + ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_NoChangedDocument = 585, + ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_NoTextChange = 586, + ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_DocumentRemoved = 587, + ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_TextChangeConflict = 588, + + // please leave the range up through 600 free in case we need to add more items to learn more about ApplyChangesOperation results. + + Next = 600 } } From 353711a49fb8fa169d087e5896b77b9f3397fab1 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Jul 2022 16:02:42 -0700 Subject: [PATCH 48/66] Remove unnecessary callbacks --- .../SuggestedActionsSource.State.cs | 9 +------ .../Suggestions/SuggestedActionsSource.cs | 25 ------------------- 2 files changed, 1 insertion(+), 33 deletions(-) diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.State.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.State.cs index ff1d79fb557ea..84f880c93f75d 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.State.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.State.cs @@ -24,8 +24,7 @@ protected sealed class State : IDisposable public readonly ITextBuffer SubjectBuffer; public readonly WorkspaceRegistration Registration; - // mutable state - public Workspace? Workspace { get; set; } + public Workspace? Workspace => Registration.Workspace; public State(SuggestedActionsSource source, SuggestedActionsSourceProvider owner, ITextView textView, ITextBuffer textBuffer) { @@ -39,12 +38,6 @@ public State(SuggestedActionsSource source, SuggestedActionsSourceProvider owner void IDisposable.Dispose() { - if (Workspace != null) - Workspace.WorkspaceChanged -= _source.OnWorkspaceChanged; - - if (Registration != null) - Registration.WorkspaceChanged -= _source.OnWorkspaceChanged; - if (TextView != null) TextView.Closed -= _source.OnTextViewClosed; } diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs index b7758e49fd243..91b48d7373ada 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs @@ -59,10 +59,6 @@ private abstract partial class SuggestedActionsSource : ForegroundThreadAffiniti _state = new ReferenceCountedDisposable(new State(this, owner, textView, textBuffer)); _state.Target.TextView.Closed += OnTextViewClosed; - - RegisterEventsToWorkspace(_state, _state.Target.Registration.Workspace); - - _state.Target.Registration.WorkspaceChanged += OnWorkspaceChanged; } public void Dispose() @@ -516,27 +512,6 @@ private static string GetFixCategory(DiagnosticSeverity severity) private void OnTextViewClosed(object sender, EventArgs e) => Dispose(); - private void OnWorkspaceChanged(object sender, EventArgs e) - { - using var state = _state.TryAddReference(); - if (state is null) - return; - - // REVIEW: why one need to get new workspace from registration? why not just pass in the new workspace? - // add new event registration - RegisterEventsToWorkspace(state, state.Target.Registration.Workspace); - } - - private void RegisterEventsToWorkspace(ReferenceCountedDisposable state, Workspace? workspace) - { - state.Target.Workspace = workspace; - - if (state.Target.Workspace == null) - return; - - state.Target.Workspace.WorkspaceChanged += OnWorkspaceChanged; - } - public async Task GetSuggestedActionCategoriesAsync(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken) { using var state = _state.TryAddReference(); From 0fac96d604c56be4f9558e5c7f4065ca378dc080 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Jul 2022 16:06:49 -0700 Subject: [PATCH 49/66] Simplify --- .../Operations/ApplyChangesOperation.cs | 42 ++++++------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs index 4831b1b5f59a2..f6b27a50fdfc0 100644 --- a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs +++ b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -115,38 +116,20 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution } // We have to at least have some changed document - if (!changedProject.GetChangedDocuments().Any() && - !changedProject.GetChangedAdditionalDocuments().Any() && - !changedProject.GetChangedAnalyzerConfigDocuments().Any()) - { - Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_NoChangedDocument, logLevel: LogLevel.Information); - return false; - } + var changedDocuments = changedProject.GetChangedDocuments() + .Concat(changedProject.GetChangedAdditionalDocuments()) + .Concat(changedProject.GetChangedAnalyzerConfigDocuments()).ToImmutableArray(); - if (!TryForkTextChanges(changedProject, changedProject.GetChangedDocuments(), static (s, i) => s.GetDocument(i), static (s, i, t) => s.WithDocumentText(i, t)) || - !TryForkTextChanges(changedProject, changedProject.GetChangedAdditionalDocuments(), static (s, i) => s.GetAdditionalDocument(i), static (s, i, t) => s.WithAdditionalDocumentText(i, t)) || - !TryForkTextChanges(changedProject, changedProject.GetChangedAnalyzerConfigDocuments(), static (s, i) => s.GetAnalyzerConfigDocument(i), static (s, i, t) => s.WithAnalyzerConfigDocumentText(i, t))) + if (changedDocuments.Length == 0) { + Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_NoChangedDocument, logLevel: LogLevel.Information); return false; } - } - Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationSucceeded, logLevel: LogLevel.Information); - return workspace.TryApplyChanges(forkedSolution, progressTracker); - - bool TryForkTextChanges( - ProjectChanges changedProject, - IEnumerable changedDocuments, - Func getDocument, - Func withDocumentText) - { foreach (var documentId in changedDocuments) { - var originalDocument = getDocument(changedProject.OldProject.Solution, documentId); - var changedDocument = getDocument(changedProject.NewProject.Solution, documentId); - - Contract.ThrowIfNull(originalDocument); - Contract.ThrowIfNull(changedDocument); + var originalDocument = changedProject.OldProject.Solution.GetRequiredTextDocument(documentId); + var changedDocument = changedProject.NewProject.Solution.GetRequiredTextDocument(documentId); // it has to be a text change the operation wants to make. If the operation is making some other // sort of change, we can't merge this operation in. @@ -157,7 +140,7 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution } // If the document has gone away, we definitely cannot apply a text change to it. - var currentDocument = getDocument(currentSolution, documentId); + var currentDocument = currentSolution.GetDocument(documentId); if (currentDocument is null) { Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_DocumentRemoved, logLevel: LogLevel.Information); @@ -173,11 +156,12 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution return false; } - forkedSolution = withDocumentText(forkedSolution, documentId, changedDocument.GetTextSynchronously(cancellationToken)); + forkedSolution = forkedSolution.WithTextDocumentText(documentId, changedDocument.GetTextSynchronously(cancellationToken)); } - - return true; } + + Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationSucceeded, logLevel: LogLevel.Information); + return workspace.TryApplyChanges(forkedSolution, progressTracker); } } } From 1aa15880c789e5a0d8e71b61dd8b510b01747b89 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Jul 2022 16:11:03 -0700 Subject: [PATCH 50/66] Lint --- .../CodeActions/ApplyChangesOperationTests.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ApplyChangesOperationTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/ApplyChangesOperationTests.cs index d6ba2aabeaf4d..73ca22fec77ab 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/ApplyChangesOperationTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/ApplyChangesOperationTests.cs @@ -5,21 +5,14 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; +using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings; -using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics; -using Microsoft.CodeAnalysis.Editor.UnitTests.Preview; -using Microsoft.CodeAnalysis.Editor.UnitTests; -using Microsoft.CodeAnalysis.Test.Utilities; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CodeActions; -using System.Threading; -using Roslyn.Test.Utilities; -using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings; using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Text; +using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeActions From 2f0abc4f14d3612d4c92d9090c0422c6eaf29b00 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Jul 2022 16:39:44 -0700 Subject: [PATCH 51/66] Get document properly --- .../Portable/CodeActions/Operations/ApplyChangesOperation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs index f6b27a50fdfc0..999f3b8b42d07 100644 --- a/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs +++ b/src/Workspaces/Core/Portable/CodeActions/Operations/ApplyChangesOperation.cs @@ -140,7 +140,7 @@ internal sealed override Task TryApplyAsync(Workspace workspace, Solution } // If the document has gone away, we definitely cannot apply a text change to it. - var currentDocument = currentSolution.GetDocument(documentId); + var currentDocument = currentSolution.GetTextDocument(documentId); if (currentDocument is null) { Logger.Log(FunctionId.ApplyChangesOperation_WorkspaceVersionMismatch_ApplicationFailed_DocumentRemoved, logLevel: LogLevel.Information); From 5613ede9b713098431fe2db7f72204e2a1e1ccdc Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Jul 2022 19:08:53 -0700 Subject: [PATCH 52/66] formatting --- src/Workspaces/Core/Portable/Workspace/Workspace.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Workspaces/Core/Portable/Workspace/Workspace.cs b/src/Workspaces/Core/Portable/Workspace/Workspace.cs index a06f54e18d318..8fd316e7f0aaf 100644 --- a/src/Workspaces/Core/Portable/Workspace/Workspace.cs +++ b/src/Workspaces/Core/Portable/Workspace/Workspace.cs @@ -1941,9 +1941,9 @@ protected virtual void ApplyAnalyzerConfigDocumentTextChanged(DocumentId id, Sou this.OnAnalyzerConfigDocumentTextLoaderChanged(id, TextLoader.From(TextAndVersion.Create(text, VersionStamp.Create()))); } -#endregion + #endregion -#region Checks and Asserts + #region Checks and Asserts /// /// Throws an exception is the solution is not empty. /// @@ -2197,6 +2197,6 @@ protected virtual string GetAdditionalDocumentName(DocumentId documentId) protected virtual string GetAnalyzerConfigDocumentName(DocumentId documentId) => GetDocumentName(documentId); -#endregion + #endregion } } From 2c5235ea82a24b64a33aeb23152c38c75346c631 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Jul 2022 22:05:01 -0700 Subject: [PATCH 53/66] Unused variable --- .../Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs index 3299c00f8e22b..c19a0afe3b1d4 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs @@ -45,8 +45,6 @@ internal partial class SuggestedActionsSourceProvider : ISuggestedActionsSourceP private static readonly Guid s_visualBasicSourceGuid = new Guid("4de30e93-3e0c-40c2-a4ba-1124da4539f6"); private static readonly Guid s_xamlSourceGuid = new Guid("a0572245-2eab-4c39-9f61-06a6d8c5ddda"); - private const int InvalidSolutionVersion = -1; - private readonly IThreadingContext _threadingContext; private readonly ICodeRefactoringService _codeRefactoringService; private readonly ICodeFixService _codeFixService; From b20319625bafb1c78fe73186174e54cf0cf4bee9 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 20 Jul 2022 09:33:27 -0700 Subject: [PATCH 54/66] No need to roundtrip symbol --- .../Rename/ConflictEngine/ConflictResolver.cs | 3 ++- .../Portable/Rename/IRemoteRenamerService.cs | 20 +++++-------------- .../Core/Portable/Rename/RenameLocations.cs | 2 +- .../Services/Renamer/RemoteRenamerService.cs | 9 +++++++-- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.cs index 3f1da65195396..e03378bc2d9cf 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.cs @@ -51,12 +51,13 @@ internal static partial class ConflictResolver var client = await RemoteHostClient.TryGetClientAsync(solution.Workspace, cancellationToken).ConfigureAwait(false); if (client != null) { + var serializableSymbol = SerializableSymbolAndProjectId.Dehydrate(renameLocationSet.Solution, renameLocationSet.Symbol, cancellationToken); var serializableLocationSet = renameLocationSet.Dehydrate(solution, cancellationToken); var nonConflictSymbolIds = nonConflictSymbols?.SelectAsArray(s => SerializableSymbolAndProjectId.Dehydrate(solution, s, cancellationToken)) ?? default; var result = await client.TryInvokeAsync( solution, - (service, solutionInfo, callbackId, cancellationToken) => service.ResolveConflictsAsync(solutionInfo, callbackId, serializableLocationSet, replacementText, nonConflictSymbolIds, cancellationToken), + (service, solutionInfo, callbackId, cancellationToken) => service.ResolveConflictsAsync(solutionInfo, callbackId, serializableSymbol, serializableLocationSet, replacementText, nonConflictSymbolIds, cancellationToken), callbackTarget: new RemoteOptionsProvider(solution.Workspace.Services, renameLocationSet.FallbackOptions), cancellationToken).ConfigureAwait(false); diff --git a/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs b/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs index 755c613890c60..d94198c99869a 100644 --- a/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs +++ b/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs @@ -55,6 +55,7 @@ internal interface ICallback // : IRemoteOptionsCallback ValueTask ResolveConflictsAsync( Checksum solutionChecksum, RemoteServiceCallbackId callbackId, + SerializableSymbolAndProjectId symbolAndProjectId, SerializableRenameLocations renameLocationSet, string replacementText, ImmutableArray nonConflictSymbolIds, @@ -203,22 +204,15 @@ internal partial class RenameLocations { public SerializableRenameLocations Dehydrate(Solution solution, CancellationToken cancellationToken) => new( - SerializableSymbolAndProjectId.Dehydrate(solution, Symbol, cancellationToken), Options, SerializableSearchResult.Dehydrate(solution, _result, cancellationToken)); - internal static async Task TryRehydrateAsync(Solution solution, CodeCleanupOptionsProvider fallbackOptions, SerializableRenameLocations locations, CancellationToken cancellationToken) + internal static async Task TryRehydrateAsync( + Solution solution, ISymbol symbol, CodeCleanupOptionsProvider fallbackOptions, SerializableRenameLocations locations, CancellationToken cancellationToken) { if (locations == null) return null; - if (locations.Symbol == null) - return null; - - var symbol = await locations.Symbol.TryRehydrateAsync(solution, cancellationToken).ConfigureAwait(false); - if (symbol == null) - return null; - Contract.ThrowIfNull(locations.Result); return new RenameLocations( @@ -234,17 +228,13 @@ public SerializableRenameLocations Dehydrate(Solution solution, CancellationToke internal sealed class SerializableRenameLocations { [DataMember(Order = 0)] - public readonly SerializableSymbolAndProjectId? Symbol; - - [DataMember(Order = 1)] public readonly SymbolRenameOptions Options; - [DataMember(Order = 2)] + [DataMember(Order = 1)] public readonly SerializableSearchResult? Result; - public SerializableRenameLocations(SerializableSymbolAndProjectId? symbol, SymbolRenameOptions options, SerializableSearchResult? result) + public SerializableRenameLocations(SymbolRenameOptions options, SerializableSearchResult? result) { - Symbol = symbol; Options = options; Result = result; } diff --git a/src/Workspaces/Core/Portable/Rename/RenameLocations.cs b/src/Workspaces/Core/Portable/Rename/RenameLocations.cs index b9114cc0b035f..999119b4f7a2f 100644 --- a/src/Workspaces/Core/Portable/Rename/RenameLocations.cs +++ b/src/Workspaces/Core/Portable/Rename/RenameLocations.cs @@ -92,7 +92,7 @@ internal sealed partial class RenameLocations if (result.HasValue && result.Value != null) { var rehydrated = await TryRehydrateAsync( - solution, fallbackOptions, result.Value, cancellationToken).ConfigureAwait(false); + solution, symbol, fallbackOptions, result.Value, cancellationToken).ConfigureAwait(false); if (rehydrated != null) return rehydrated; diff --git a/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs b/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs index e1b0bcfeac5c4..b002584a53938 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs @@ -85,7 +85,6 @@ private CodeCleanupOptionsProvider GetClientOptionsProvider(RemoteServiceCallbac var result = await RenameLocations.FindLocationsAsync( symbol, solution, options, fallbackOptions, cancellationToken).ConfigureAwait(false); - return result.Dehydrate(solution, cancellationToken); }, cancellationToken); } @@ -93,6 +92,7 @@ private CodeCleanupOptionsProvider GetClientOptionsProvider(RemoteServiceCallbac public ValueTask ResolveConflictsAsync( Checksum solutionChecksum, RemoteServiceCallbackId callbackId, + SerializableSymbolAndProjectId symbolAndProjectId, SerializableRenameLocations renameLocationSet, string replacementText, ImmutableArray nonConflictSymbolIds, @@ -100,11 +100,16 @@ private CodeCleanupOptionsProvider GetClientOptionsProvider(RemoteServiceCallbac { return RunServiceAsync(solutionChecksum, async solution => { + var symbol = await symbolAndProjectId.TryRehydrateAsync(solution, cancellationToken).ConfigureAwait(false); + if (symbol is null) + return null; + var nonConflictSymbols = await GetNonConflictSymbolsAsync(solution, nonConflictSymbolIds, cancellationToken).ConfigureAwait(false); var fallbackOptions = GetClientOptionsProvider(callbackId); - var rehydratedSet = await RenameLocations.TryRehydrateAsync(solution, fallbackOptions, renameLocationSet, cancellationToken).ConfigureAwait(false); + var rehydratedSet = await RenameLocations.TryRehydrateAsync( + solution, symbol, fallbackOptions, renameLocationSet, cancellationToken).ConfigureAwait(false); if (rehydratedSet == null) return null; From f58801c516aa27644ffe6e69c0adb848206a2b51 Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Wed, 20 Jul 2022 09:35:07 -0700 Subject: [PATCH 55/66] Update src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs --- .../Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs b/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs index b002584a53938..37bccd4d54aa5 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/Renamer/RemoteRenamerService.cs @@ -85,6 +85,7 @@ private CodeCleanupOptionsProvider GetClientOptionsProvider(RemoteServiceCallbac var result = await RenameLocations.FindLocationsAsync( symbol, solution, options, fallbackOptions, cancellationToken).ConfigureAwait(false); + return result.Dehydrate(solution, cancellationToken); }, cancellationToken); } From 6fa6c04adb24fac44366b77c9a13a324b91580ea Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 20 Jul 2022 16:51:29 +0000 Subject: [PATCH 56/66] Update dependencies from https://github.com/dotnet/source-build-externals build 20220719.2 (#62787) [main] Update dependencies from dotnet/source-build-externals --- eng/Version.Details.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0eb399d7ab8c7..120d54df68bd1 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -6,9 +6,9 @@ 7e80445ee82adbf9a8e6ae601ac5e239d982afaa - + https://github.com/dotnet/source-build-externals - abff160e44e7b81ade066d176639fc6d78527478 + 3a88d1dbd4557702aa2cb89d5f8bf927bb263a3b From d72634113d9d36c539732aaf3a188faac26dd7d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Matou=C5=A1ek?= Date: Wed, 20 Jul 2022 09:52:07 -0700 Subject: [PATCH 57/66] Clean up global options usage in tests (#62692) * Clean up global options usage in tests * Fix nres --- .../PartialMethodCompletionProviderTests.cs | 13 +++-- .../EncapsulateFieldTestState.cs | 6 +- .../EventHookup/EventHookupTestState.cs | 2 +- .../Formatting/FormattingEngineTests.cs | 10 ++-- .../SmartTokenFormatterFormatRangeTests.cs | 14 +++-- .../InlineDiagnosticsTaggerProviderTests.cs | 3 +- .../CSharpTest/Intents/IntentTestsBase.cs | 8 +-- .../Squiggles/ErrorSquiggleProducerTests.cs | 9 ++- .../ChangeSignatureTestState.cs | 6 +- .../CodeGenerationTests.CSharp.cs | 4 +- .../CodeGeneration/CodeGenerationTests.cs | 12 +--- .../AbstractSimplificationTests.vb | 25 ++++----- .../BlockSimplificationTests.vb | 6 +- .../TypeInferenceSimplifierTests.vb | 48 ++++------------ .../Simplification/TypeNameSimplifierTest.vb | 56 +++++++++---------- .../Extensions/WorkspaceExtensions.cs | 33 ----------- .../Formatting/CoreFormatterTestsBase.cs | 15 +---- .../TestUtilities/Workspaces/TestWorkspace.cs | 8 +-- .../SimplifyTypeNamesTests.vb | 2 +- .../Squiggles/ErrorSquiggleProducerTests.vb | 10 ++-- ...alStudioDiagnosticAnalyzerExecutorTests.cs | 8 +-- .../CodeModel/AbstractCodeElementTests`1.vb | 12 ++-- .../CodeModel/AbstractCodeModelObjectTests.vb | 3 +- .../CSharpCompletionSnippetNoteTests.vb | 5 +- .../Core/Test/Snippets/SnippetTestState.vb | 7 +-- .../VisualBasicSnippetExpansionClientTests.vb | 14 +++-- .../Formatting/FormattingTriviaTests.cs | 8 +-- 27 files changed, 132 insertions(+), 215 deletions(-) delete mode 100644 src/EditorFeatures/TestUtilities/Extensions/WorkspaceExtensions.cs diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs index 3c25273d529b6..a97e57b113c82 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Completion.Providers; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -780,9 +781,9 @@ public async Task ExpressionBodyMethod() using var workspaceFixture = GetOrCreateWorkspaceFixture(); var workspace = workspaceFixture.Target.GetWorkspace(ExportProvider); - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options.WithChangedOption( - CSharpCodeStyleOptions.PreferExpressionBodiedMethods, - new CodeStyleOption2(ExpressionBodyPreference.WhenPossible, NotificationOption2.Silent)))); + workspace.GlobalOptions.SetGlobalOption( + new OptionKey(CSharpCodeStyleOptions.PreferExpressionBodiedMethods), + new CodeStyleOption2(ExpressionBodyPreference.WhenPossible, NotificationOption2.Silent)); var text = @"using System; partial class Bar @@ -811,9 +812,9 @@ public async Task ExpressionBodyMethodExtended() using var workspaceFixture = GetOrCreateWorkspaceFixture(); var workspace = workspaceFixture.Target.GetWorkspace(ExportProvider); - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options.WithChangedOption( - CSharpCodeStyleOptions.PreferExpressionBodiedMethods, - new CodeStyleOption2(ExpressionBodyPreference.WhenPossible, NotificationOption2.Silent)))); + workspace.GlobalOptions.SetGlobalOption( + new OptionKey(CSharpCodeStyleOptions.PreferExpressionBodiedMethods), + new CodeStyleOption2(ExpressionBodyPreference.WhenPossible, NotificationOption2.Silent)); var text = @"using System; partial class Bar diff --git a/src/EditorFeatures/CSharpTest/EncapsulateField/EncapsulateFieldTestState.cs b/src/EditorFeatures/CSharpTest/EncapsulateField/EncapsulateFieldTestState.cs index 0a6f36ff347bd..265554d58dc92 100644 --- a/src/EditorFeatures/CSharpTest/EncapsulateField/EncapsulateFieldTestState.cs +++ b/src/EditorFeatures/CSharpTest/EncapsulateField/EncapsulateFieldTestState.cs @@ -14,6 +14,7 @@ using Microsoft.CodeAnalysis.Editor.UnitTests.Utilities; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Notification; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Text.Editor.Commanding.Commands; using Xunit; @@ -42,9 +43,8 @@ public static EncapsulateFieldTestState Create(string markup) { var workspace = TestWorkspace.CreateCSharp(markup, composition: EditorTestCompositions.EditorFeatures); - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options - .WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithSilentEnforcement) - .WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithSilentEnforcement))); + workspace.GlobalOptions.SetGlobalOption(new OptionKey(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors), CSharpCodeStyleOptions.NeverWithSilentEnforcement); + workspace.GlobalOptions.SetGlobalOption(new OptionKey(CSharpCodeStyleOptions.PreferExpressionBodiedProperties), CSharpCodeStyleOptions.NeverWithSilentEnforcement); return new EncapsulateFieldTestState(workspace); } diff --git a/src/EditorFeatures/CSharpTest/EventHookup/EventHookupTestState.cs b/src/EditorFeatures/CSharpTest/EventHookup/EventHookupTestState.cs index 6f15921ec319f..795994e817064 100644 --- a/src/EditorFeatures/CSharpTest/EventHookup/EventHookupTestState.cs +++ b/src/EditorFeatures/CSharpTest/EventHookup/EventHookupTestState.cs @@ -41,7 +41,7 @@ public EventHookupTestState(XElement workspaceElement, OptionsCollection options _testSessionHookupMutex = new Mutex(false); _commandHandler.TESTSessionHookupMutex = _testSessionHookupMutex; - Workspace.ApplyOptions(options); + options?.SetGlobalOptions(Workspace.GlobalOptions); } public static EventHookupTestState CreateTestState(string markup, OptionsCollection options = null) diff --git a/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs b/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs index b6f76845174b2..8fd5720572086 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs @@ -2180,7 +2180,7 @@ public void SeparateGroups_KeepMultipleLinesBetweenGroups() using MS.B; "; - AssertFormatWithView(expected, code, (GenerationOptions.SeparateImportDirectiveGroups, true)); + AssertFormatWithView(expected, code, new OptionsCollection(LanguageNames.CSharp) { { GenerationOptions.SeparateImportDirectiveGroups, true } }); } [WorkItem(25003, "https://github.com/dotnet/roslyn/issues/25003")] @@ -2209,7 +2209,7 @@ namespace N; using MS.B; "; - AssertFormatWithView(expected, code, (GenerationOptions.SeparateImportDirectiveGroups, true)); + AssertFormatWithView(expected, code, new OptionsCollection(LanguageNames.CSharp) { { GenerationOptions.SeparateImportDirectiveGroups, true } }); } [WorkItem(25003, "https://github.com/dotnet/roslyn/issues/25003")] @@ -2230,7 +2230,7 @@ public void SeparateGroups_DoNotGroupIfNotSorted() using MS.A; "; - AssertFormatWithView(expected, code, (GenerationOptions.SeparateImportDirectiveGroups, true)); + AssertFormatWithView(expected, code, new OptionsCollection(LanguageNames.CSharp) { { GenerationOptions.SeparateImportDirectiveGroups, true } }); } [WorkItem(25003, "https://github.com/dotnet/roslyn/issues/25003")] @@ -2252,7 +2252,7 @@ public void SeparateGroups_GroupIfSorted() using MS.B; "; - AssertFormatWithView(expected, code, (GenerationOptions.SeparateImportDirectiveGroups, true)); + AssertFormatWithView(expected, code, new OptionsCollection(LanguageNames.CSharp) { { GenerationOptions.SeparateImportDirectiveGroups, true } }); } [WorkItem(25003, "https://github.com/dotnet/roslyn/issues/25003")] @@ -2274,7 +2274,7 @@ public void SeparateGroups_GroupIfSorted_RecognizeSystemNotFirst() using System.B; "; - AssertFormatWithView(expected, code, (GenerationOptions.SeparateImportDirectiveGroups, true)); + AssertFormatWithView(expected, code, new OptionsCollection(LanguageNames.CSharp) { { GenerationOptions.SeparateImportDirectiveGroups, true } }); } [WpfFact] diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs index dd7221eea0b44..4d161f57cfd25 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs @@ -24,6 +24,7 @@ using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text.Shared.Extensions; using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Editor.Commanding.Commands; using Roslyn.Test.Utilities; using Xunit; @@ -3538,16 +3539,17 @@ internal static void AutoFormatToken(string markup, string expected, bool useTab using var workspace = TestWorkspace.CreateCSharp(markup); - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options - .WithChangedOption(FormattingOptions2.UseTabs, LanguageNames.CSharp, useTabs))); - var subjectDocument = workspace.Documents.Single(); + var textBuffer = subjectDocument.GetTextBuffer(); + var optionsService = workspace.GetService(); + var editorOptions = optionsService.Factory.GetOptions(textBuffer); + editorOptions.SetOptionValue(DefaultOptions.ConvertTabsToSpacesOptionId, !useTabs); var commandHandler = workspace.GetService(); - var typedChar = subjectDocument.GetTextBuffer().CurrentSnapshot.GetText(subjectDocument.CursorPosition.Value - 1, 1); - commandHandler.ExecuteCommand(new TypeCharCommandArgs(subjectDocument.GetTextView(), subjectDocument.GetTextBuffer(), typedChar[0]), () => { }, TestCommandExecutionContext.Create()); + var typedChar = textBuffer.CurrentSnapshot.GetText(subjectDocument.CursorPosition.Value - 1, 1); + commandHandler.ExecuteCommand(new TypeCharCommandArgs(subjectDocument.GetTextView(), textBuffer, typedChar[0]), () => { }, TestCommandExecutionContext.Create()); - var newSnapshot = subjectDocument.GetTextBuffer().CurrentSnapshot; + var newSnapshot = textBuffer.CurrentSnapshot; Assert.Equal(expected, newSnapshot.GetText()); } diff --git a/src/EditorFeatures/CSharpTest/InlineDiagnostics/InlineDiagnosticsTaggerProviderTests.cs b/src/EditorFeatures/CSharpTest/InlineDiagnostics/InlineDiagnosticsTaggerProviderTests.cs index 4fb1e8e6dfd76..d3a9182971b5b 100644 --- a/src/EditorFeatures/CSharpTest/InlineDiagnostics/InlineDiagnosticsTaggerProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/InlineDiagnostics/InlineDiagnosticsTaggerProviderTests.cs @@ -6,6 +6,7 @@ using System.Collections.Immutable; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.InlineDiagnostics; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions; using Microsoft.CodeAnalysis.Editor.UnitTests.Squiggles; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; @@ -55,7 +56,7 @@ private static async Task>> GetTag private static async Task>> GetTagSpansAsync(TestWorkspace workspace) { - workspace.ApplyOptions(new[] { KeyValuePairUtil.Create(new OptionKey2(InlineDiagnosticsOptions.EnableInlineDiagnostics, LanguageNames.CSharp), (object)true) }); + workspace.GlobalOptions.SetGlobalOption(new OptionKey(InlineDiagnosticsOptions.EnableInlineDiagnostics, LanguageNames.CSharp), true); return (await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace)).Item2; } } diff --git a/src/EditorFeatures/CSharpTest/Intents/IntentTestsBase.cs b/src/EditorFeatures/CSharpTest/Intents/IntentTestsBase.cs index 503b898166e48..5df8cb07118ce 100644 --- a/src/EditorFeatures/CSharpTest/Intents/IntentTestsBase.cs +++ b/src/EditorFeatures/CSharpTest/Intents/IntentTestsBase.cs @@ -47,11 +47,9 @@ public class IntentTestsBase string? priorText = null) { var documentSet = additionalDocuments.Prepend(activeDocument).ToArray(); - using var workspace = TestWorkspace.CreateCSharp(documentSet, exportProvider: EditorTestCompositions.EditorFeatures.ExportProviderFactory.CreateExportProvider()); - if (options != null) - { - workspace.ApplyOptions(options!); - } + + using var workspace = TestWorkspace.CreateCSharp(documentSet, composition: EditorTestCompositions.EditorFeatures); + options?.SetGlobalOptions(workspace.GlobalOptions); var intentSource = workspace.ExportProvider.GetExportedValue(); diff --git a/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs b/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs index 15e89613a0593..3029955e4462a 100644 --- a/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs +++ b/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs @@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions; using Microsoft.CodeAnalysis.Editor.UnitTests.Squiggles; @@ -111,13 +112,11 @@ void Test() "; using var workspace = TestWorkspace.Create(workspaceXml, composition: SquiggleUtilities.CompositionWithSolutionCrawler); - var options = new Dictionary(); var language = workspace.Projects.Single().Language; - var preferIntrinsicPredefinedTypeOption = new OptionKey2(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, language); - var preferIntrinsicPredefinedTypeOptionValue = new CodeStyleOption2(value: true, notification: NotificationOption2.Error); - options.Add(preferIntrinsicPredefinedTypeOption, preferIntrinsicPredefinedTypeOptionValue); - workspace.ApplyOptions(options); + workspace.GlobalOptions.SetGlobalOption( + new OptionKey(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, language), + new CodeStyleOption2(value: true, notification: NotificationOption2.Error)); var analyzerMap = new Dictionary> { diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs b/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs index 79b1e6cd84079..c1db91f12c6d9 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs @@ -44,11 +44,7 @@ public static ChangeSignatureTestState Create(string markup, string languageName _ => throw new ArgumentException("Invalid language name.") }; - if (options != null) - { - workspace.ApplyOptions(options); - } - + options?.SetGlobalOptions(workspace.GlobalOptions); return new ChangeSignatureTestState(workspace); } diff --git a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs index 529e64816b069..18efe090391c1 100644 --- a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs +++ b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs @@ -14,6 +14,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; @@ -1091,7 +1092,8 @@ public async Task AddIndexer2() parameters: Parameters(Parameter(typeof(int), "i")), getStatements: "return String.Empty;", isIndexer: true, - options: new Dictionary { + options: new OptionsCollection(LanguageNames.CSharp) + { { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithSilentEnforcement }, { CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.NeverWithSilentEnforcement }, }); diff --git a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs index 28aa4628ac235..2978885e64b52 100644 --- a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs +++ b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs @@ -14,6 +14,7 @@ using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.Formatting; using Microsoft.CodeAnalysis.CSharp.Simplification; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; @@ -427,7 +428,7 @@ public partial class CodeGenerationTests ImmutableArray> parameters = default, bool isIndexer = false, CodeGenerationContext context = null, - IDictionary options = null) + OptionsCollection options = null) { // This assumes that tests will not use place holders for get/set statements at the same time if (getStatements != null) @@ -442,14 +443,7 @@ public partial class CodeGenerationTests using var testContext = await TestContext.CreateAsync(initial, expected); var workspace = testContext.Workspace; - if (options != null) - { - var optionSet = workspace.Options; - foreach (var (key, value) in options) - optionSet = optionSet.WithChangedOption(key, value); - - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(optionSet)); - } + options?.SetGlobalOptions(workspace.GlobalOptions); var typeSymbol = GetTypeSymbol(type)(testContext.SemanticModel); var getParameterSymbols = GetParameterSymbols(parameters, testContext); diff --git a/src/EditorFeatures/Test2/Simplification/AbstractSimplificationTests.vb b/src/EditorFeatures/Test2/Simplification/AbstractSimplificationTests.vb index 6e604bb4e1624..82bba15dcf661 100644 --- a/src/EditorFeatures/Test2/Simplification/AbstractSimplificationTests.vb +++ b/src/EditorFeatures/Test2/Simplification/AbstractSimplificationTests.vb @@ -5,6 +5,7 @@ Imports System.Collections.Immutable Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.CSharp +Imports Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.Options @@ -16,7 +17,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification <[UseExportProvider]> Public MustInherit Class AbstractSimplificationTests - Private Protected Shared Async Function TestAsync(definition As XElement, expected As XElement, Optional options As Dictionary(Of OptionKey2, Object) = Nothing, Optional csharpParseOptions As CSharpParseOptions = Nothing) As System.Threading.Tasks.Task + Private Protected Shared Async Function TestAsync(definition As XElement, expected As XElement, Optional options As OptionsCollection = Nothing, Optional csharpParseOptions As CSharpParseOptions = Nothing) As System.Threading.Tasks.Task Using workspace = CreateTestWorkspace(definition, csharpParseOptions) Dim simplifiedDocument = Await SimplifyAsync(workspace, options).ConfigureAwait(False) Await AssertCodeEqual(expected, simplifiedDocument) @@ -35,11 +36,11 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification Return workspace End Function - Protected Shared Function SimplifyAsync(workspace As TestWorkspace) As System.Threading.Tasks.Task(Of Document) + Protected Shared Function SimplifyAsync(workspace As TestWorkspace) As Task(Of Document) Return SimplifyAsync(workspace, Nothing) End Function - Private Shared Async Function SimplifyAsync(workspace As TestWorkspace, options As Dictionary(Of OptionKey2, Object)) As System.Threading.Tasks.Task(Of Document) + Private Shared Async Function SimplifyAsync(workspace As TestWorkspace, options As OptionsCollection) As Task(Of Document) Dim hostDocument = workspace.Documents.Single() Dim spansToAddSimplifierAnnotation = hostDocument.AnnotatedSpans.Where(Function(kvp) kvp.Key.StartsWith("Simplify", StringComparison.Ordinal)) @@ -60,10 +61,12 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification Return Await SimplifyAsync(workspace, spansToAddSimplifierAnnotation, explicitSpansToSimplifyWithin, options) End Function - Private Shared Async Function SimplifyAsync(workspace As Workspace, - listOfLabelToAddSimplifierAnnotationSpans As IEnumerable(Of KeyValuePair(Of String, ImmutableArray(Of TextSpan))), - explicitSpansToSimplifyWithin As ImmutableArray(Of TextSpan), - options As Dictionary(Of OptionKey2, Object)) As Task(Of Document) + Private Shared Async Function SimplifyAsync( + workspace As TestWorkspace, + listOfLabelToAddSimplifierAnnotationSpans As IEnumerable(Of KeyValuePair(Of String, ImmutableArray(Of TextSpan))), + explicitSpansToSimplifyWithin As ImmutableArray(Of TextSpan), + options As OptionsCollection) As Task(Of Document) + Dim document = workspace.CurrentSolution.Projects.Single().Documents.Single() Dim root = Await document.GetSyntaxRootAsync() @@ -105,16 +108,12 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification End Select Next - Dim optionSet = workspace.Options - If options IsNot Nothing Then - For Each entry In options - optionSet = optionSet.WithChangedOption(entry.Key, entry.Value) - Next - End If + options?.SetGlobalOptions(workspace.GlobalOptions) document = document.WithSyntaxRoot(root) #Disable Warning RS0030 ' Do Not used banned APIs + Dim optionSet = options?.ToOptionSet() Dim simplifiedDocument As Document If Not explicitSpansToSimplifyWithin.IsDefaultOrEmpty Then simplifiedDocument = Await Simplifier.ReduceAsync(document, explicitSpansToSimplifyWithin, optionSet) diff --git a/src/EditorFeatures/Test2/Simplification/BlockSimplificationTests.vb b/src/EditorFeatures/Test2/Simplification/BlockSimplificationTests.vb index 90fc0be533c87..b674f4d52aa79 100644 --- a/src/EditorFeatures/Test2/Simplification/BlockSimplificationTests.vb +++ b/src/EditorFeatures/Test2/Simplification/BlockSimplificationTests.vb @@ -4,13 +4,17 @@ Imports Microsoft.CodeAnalysis.CodeStyle Imports Microsoft.CodeAnalysis.CSharp.CodeStyle +Imports Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions Imports Microsoft.CodeAnalysis.Options Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification Public Class SimplificationTests Inherits AbstractSimplificationTests - Private Shared ReadOnly DoNotPreferBraces As Dictionary(Of OptionKey2, Object) = New Dictionary(Of OptionKey2, Object) From {{New OptionKey2(CSharpCodeStyleOptions.PreferBraces), New CodeStyleOption2(Of PreferBracesPreference)(PreferBracesPreference.None, NotificationOption2.Silent)}} + Private Shared ReadOnly DoNotPreferBraces As New OptionsCollection(LanguageNames.VisualBasic) From + { + {CSharpCodeStyleOptions.PreferBraces, New CodeStyleOption2(Of PreferBracesPreference)(PreferBracesPreference.None, NotificationOption2.Silent)} + } Public Async Function TestCSharp_DoNotSimplifyIfBlock() As Task diff --git a/src/EditorFeatures/Test2/Simplification/TypeInferenceSimplifierTests.vb b/src/EditorFeatures/Test2/Simplification/TypeInferenceSimplifierTests.vb index db2fd3f44ea15..0b3a2b744932a 100644 --- a/src/EditorFeatures/Test2/Simplification/TypeInferenceSimplifierTests.vb +++ b/src/EditorFeatures/Test2/Simplification/TypeInferenceSimplifierTests.vb @@ -70,9 +70,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification End Module - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function @@ -102,9 +100,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification End Module - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function @@ -167,9 +163,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification End Class - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function @@ -204,9 +198,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification End Module - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function @@ -255,9 +247,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification End Class - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function @@ -305,9 +295,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification End Module - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function @@ -358,9 +346,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification End Module - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function @@ -409,9 +395,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification End Class - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function #Region "Type Argument Expand/Reduce for Generic Method Calls - 639136" @@ -469,9 +453,7 @@ class D : C }]]> - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function @@ -524,9 +506,7 @@ End Class ]]> - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function @@ -570,9 +550,7 @@ Namespace X End Namespace - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function @@ -620,9 +598,7 @@ Namespace Y End Namespace - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {} - - Await TestAsync(input, expected, simplificationOptionSet) + Await TestAsync(input, expected) End Function #End Region diff --git a/src/EditorFeatures/Test2/Simplification/TypeNameSimplifierTest.vb b/src/EditorFeatures/Test2/Simplification/TypeNameSimplifierTest.vb index 1cd3243a5bf57..6a6d36c273d19 100644 --- a/src/EditorFeatures/Test2/Simplification/TypeNameSimplifierTest.vb +++ b/src/EditorFeatures/Test2/Simplification/TypeNameSimplifierTest.vb @@ -4,6 +4,7 @@ Imports Microsoft.CodeAnalysis.CodeStyle Imports Microsoft.CodeAnalysis.CSharp.CodeStyle +Imports Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Simplification @@ -1470,7 +1471,7 @@ class C1 Public Async Function TestCSharpSimplifyToVarLocalDeclaration() As Task - Dim simplificationOption = New Dictionary(Of OptionKey2, Object) From { + Dim simplificationOption = New OptionsCollection(LanguageNames.CSharp) From { {CSharpCodeStyleOptions.VarForBuiltInTypes, CodeStyleOptions2.TrueWithSilentEnforcement}, {CSharpCodeStyleOptions.VarWhenTypeIsApparent, CodeStyleOptions2.TrueWithSilentEnforcement}, {CSharpCodeStyleOptions.VarElsewhere, CodeStyleOptions2.TrueWithSilentEnforcement} @@ -1508,7 +1509,7 @@ class Program Public Async Function TestCSharpSimplifyToVarForeachDecl() As Task - Dim simplificationOption = New Dictionary(Of OptionKey2, Object) From { + Dim simplificationOption = New OptionsCollection(LanguageNames.CSharp) From { {CSharpCodeStyleOptions.VarForBuiltInTypes, CodeStyleOptions2.TrueWithSilentEnforcement}, {CSharpCodeStyleOptions.VarWhenTypeIsApparent, CodeStyleOptions2.TrueWithSilentEnforcement}, {CSharpCodeStyleOptions.VarElsewhere, CodeStyleOptions2.TrueWithSilentEnforcement} @@ -1548,7 +1549,7 @@ class Program Public Async Function TestCSharpSimplifyToVarCorrect() As Task - Dim simplificationOption = New Dictionary(Of OptionKey2, Object) From { + Dim simplificationOption = New OptionsCollection(LanguageNames.CSharp) From { {CSharpCodeStyleOptions.VarForBuiltInTypes, CodeStyleOptions2.TrueWithSilentEnforcement}, {CSharpCodeStyleOptions.VarWhenTypeIsApparent, CodeStyleOptions2.TrueWithSilentEnforcement}, {CSharpCodeStyleOptions.VarElsewhere, CodeStyleOptions2.TrueWithSilentEnforcement} @@ -1618,7 +1619,7 @@ class Program Public Async Function TestCSharpSimplifyToVarCorrect_QualifiedTypeNames() As Task - Dim simplificationOption = New Dictionary(Of OptionKey2, Object) From { + Dim simplificationOption = New OptionsCollection(LanguageNames.CSharp) From { {CSharpCodeStyleOptions.VarForBuiltInTypes, CodeStyleOptions2.TrueWithSilentEnforcement}, {CSharpCodeStyleOptions.VarWhenTypeIsApparent, CodeStyleOptions2.TrueWithSilentEnforcement}, {CSharpCodeStyleOptions.VarElsewhere, CodeStyleOptions2.TrueWithSilentEnforcement} @@ -1667,9 +1668,6 @@ class Program Public Async Function TestCSharpSimplifyToVarDontSimplify() As Task - - Dim simplificationOption = New Dictionary(Of OptionKey2, Object) From {} - Dim input = @@ -1724,7 +1722,7 @@ class Program } - Await TestAsync(input, expected, simplificationOption) + Await TestAsync(input, expected) End Function @@ -2025,8 +2023,6 @@ class E Public Async Function TestDoNotSimplifyToGenericName() As Task - Dim simplificationOption = New Dictionary(Of OptionKey2, Object) From {} - Dim input = @@ -2081,13 +2077,11 @@ class E }]]> - Await TestAsync(input, expected, simplificationOption) + Await TestAsync(input, expected) End Function Public Async Function TestDontSimplifyAllNodes_SimplifyNestedType() As Task - Dim simplificationOption = New Dictionary(Of OptionKey2, Object) From {} - Dim input = @@ -2143,7 +2137,7 @@ static class M } }]]> - Await TestAsync(input, expected, simplificationOption) + Await TestAsync(input, expected) End Function @@ -2524,7 +2518,10 @@ class C } ]]> - Dim simplificationOptionSet = New Dictionary(Of OptionKey2, Object) From {{New OptionKey2(CodeStyleOptions2.QualifyFieldAccess, LanguageNames.CSharp), New CodeStyleOption2(Of Boolean)(True, NotificationOption2.Error)}} + Dim simplificationOptionSet = New OptionsCollection(LanguageNames.CSharp) From + { + {CodeStyleOptions2.QualifyFieldAccess, New CodeStyleOption2(Of Boolean)(True, NotificationOption2.Error)} + } Await TestAsync(input, expected, simplificationOptionSet) End Function @@ -4829,8 +4826,6 @@ End Class Public Async Function TestVisualBasic_DoNotSimplifyToGenericName() As Task - Dim simplificationOption = New Dictionary(Of OptionKey2, Object) From {} - Dim input = @@ -4877,13 +4872,11 @@ End Class ]]> - Await TestAsync(input, expected, simplificationOption) + Await TestAsync(input, expected) End Function Public Async Function TestVisualBasic_TestDontSimplifyAllNodes_SimplifyNestedType() As Task - Dim simplificationOption = New Dictionary(Of OptionKey2, Object) From {} - Dim input = @@ -4927,7 +4920,7 @@ NotInheritable Class M End Sub End Class]]> - Await TestAsync(input, expected, simplificationOption) + Await TestAsync(input, expected) End Function @@ -5953,27 +5946,28 @@ End Class #Region "Helpers" - Private Protected Shared Function QualifyFieldAccessOption(languageName As String) As Dictionary(Of OptionKey2, Object) - Return New Dictionary(Of OptionKey2, Object) From {{New OptionKey2(CodeStyleOptions2.QualifyFieldAccess, languageName), New CodeStyleOption2(Of Boolean)(True, NotificationOption2.Error)}} + Private Protected Shared Function QualifyFieldAccessOption(languageName As String) As OptionsCollection + Return New OptionsCollection(languageName) From {{CodeStyleOptions2.QualifyFieldAccess, New CodeStyleOption2(Of Boolean)(True, NotificationOption2.Error)}} End Function - Private Protected Shared Function QualifyPropertyAccessOption(languageName As String) As Dictionary(Of OptionKey2, Object) + Private Protected Shared Function QualifyPropertyAccessOption(languageName As String) As OptionsCollection Return QualifyPropertyAccessOptionWithNotification(languageName, NotificationOption2.Error) End Function - Private Protected Shared Function QualifyMethodAccessOption(languageName As String) As Dictionary(Of OptionKey2, Object) - Return New Dictionary(Of OptionKey2, Object) From {{New OptionKey2(CodeStyleOptions2.QualifyMethodAccess, languageName), New CodeStyleOption2(Of Boolean)(True, NotificationOption2.Error)}} + Private Protected Shared Function QualifyMethodAccessOption(languageName As String) As OptionsCollection + Return New OptionsCollection(languageName) From {{CodeStyleOptions2.QualifyMethodAccess, New CodeStyleOption2(Of Boolean)(True, NotificationOption2.Error)}} End Function - Private Protected Shared Function QualifyEventAccessOption(languageName As String) As Dictionary(Of OptionKey2, Object) - Return New Dictionary(Of OptionKey2, Object) From {{New OptionKey2(CodeStyleOptions2.QualifyEventAccess, languageName), New CodeStyleOption2(Of Boolean)(True, NotificationOption2.Error)}} + Private Protected Shared Function QualifyEventAccessOption(languageName As String) As OptionsCollection + Return New OptionsCollection(languageName) From {{CodeStyleOptions2.QualifyEventAccess, New CodeStyleOption2(Of Boolean)(True, NotificationOption2.Error)}} End Function - Private Protected Shared Function QualifyPropertyAccessOptionWithNotification(languageName As String, notification As NotificationOption2) As Dictionary(Of OptionKey2, Object) - Return New Dictionary(Of OptionKey2, Object) From {{New OptionKey2(CodeStyleOptions2.QualifyPropertyAccess, languageName), New CodeStyleOption2(Of Boolean)(True, notification)}} + Private Protected Shared Function QualifyPropertyAccessOptionWithNotification(languageName As String, notification As NotificationOption2) As OptionsCollection + Return New OptionsCollection(languageName) From {{CodeStyleOptions2.QualifyPropertyAccess, New CodeStyleOption2(Of Boolean)(True, notification)}} End Function - Private Shared ReadOnly DontPreferIntrinsicPredefinedTypeKeywordInDeclaration As Dictionary(Of OptionKey2, Object) = New Dictionary(Of OptionKey2, Object) From {{New OptionKey2(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, LanguageNames.VisualBasic), CodeStyleOption2(Of Boolean).Default}} + Private Shared ReadOnly DontPreferIntrinsicPredefinedTypeKeywordInDeclaration As New OptionsCollection(LanguageNames.VisualBasic) From + {{CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, CodeStyleOption2(Of Boolean).Default}} #End Region diff --git a/src/EditorFeatures/TestUtilities/Extensions/WorkspaceExtensions.cs b/src/EditorFeatures/TestUtilities/Extensions/WorkspaceExtensions.cs deleted file mode 100644 index bf1e38f52d926..0000000000000 --- a/src/EditorFeatures/TestUtilities/Extensions/WorkspaceExtensions.cs +++ /dev/null @@ -1,33 +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 System.Linq; -using Microsoft.CodeAnalysis.Options; - -namespace Microsoft.CodeAnalysis.Editor.UnitTests.Extensions -{ - public static class WorkspaceExtensions - { - public static void ApplyOptions(this Workspace workspace, IReadOnlyCollection>? options) - => workspace.ApplyOptions(options?.Select(kvp => (kvp.Key, kvp.Value))); - - internal static void ApplyOptions(this Workspace workspace, IReadOnlyCollection>? options) - => workspace.ApplyOptions(options?.Select(kvp => ((OptionKey)kvp.Key, kvp.Value))); - - private static void ApplyOptions(this Workspace workspace, IEnumerable<(OptionKey key, object value)>? options) - { - if (options != null) - { - var optionSet = workspace.Options; - foreach (var option in options) - { - optionSet = optionSet.WithChangedOption(option.key, option.value); - } - - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(optionSet)); - } - } - } -} diff --git a/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs b/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs index c90df388686f6..9c13bf8c76dab 100644 --- a/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs +++ b/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs @@ -123,25 +123,16 @@ protected CoreFormatterTestsBase(ITestOutputHelper output) Assert.Equal(expectedIndentation, actualIndentation); } - private protected void AssertFormatWithView(string expectedWithMarker, string codeWithMarker, params (PerLanguageOption2 option, bool enabled)[] options) + private protected void AssertFormatWithView(string expectedWithMarker, string codeWithMarker, OptionsCollection options = null) { AssertFormatWithView(expectedWithMarker, codeWithMarker, parseOptions: null, options); } - private protected void AssertFormatWithView(string expectedWithMarker, string codeWithMarker, ParseOptions parseOptions, params (PerLanguageOption2 option, bool enabled)[] options) + private protected void AssertFormatWithView(string expectedWithMarker, string codeWithMarker, ParseOptions parseOptions, OptionsCollection options = null) { using var workspace = CreateWorkspace(codeWithMarker, parseOptions); - if (options != null) - { - var optionSet = workspace.Options; - foreach (var option in options) - { - optionSet = optionSet.WithChangedOption(option.option, GetLanguageName(), option.enabled); - } - - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(optionSet)); - } + options?.SetGlobalOptions(workspace.GlobalOptions); // set up caret position var testDocument = workspace.Documents.Single(); diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace.cs index 373b02b4edf44..6c43c13519a35 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace.cs @@ -834,11 +834,11 @@ internal ITextBuffer2 GetOrCreateBufferForPath(string? filePath, IContentType co // Ensure that the editor options on the text buffer matches that of the options that can be directly set in the workspace var editorOptions = ExportProvider.GetExportedValue().GetOptions(textBuffer); - var workspaceOptions = this.Options; + var globalOptions = GlobalOptions; - editorOptions.SetOptionValue(DefaultOptions.ConvertTabsToSpacesOptionId, !workspaceOptions.GetOption(FormattingOptions.UseTabs, languageName)); - editorOptions.SetOptionValue(DefaultOptions.TabSizeOptionId, workspaceOptions.GetOption(FormattingOptions.TabSize, languageName)); - editorOptions.SetOptionValue(DefaultOptions.IndentSizeOptionId, workspaceOptions.GetOption(FormattingOptions.IndentationSize, languageName)); + editorOptions.SetOptionValue(DefaultOptions.ConvertTabsToSpacesOptionId, !globalOptions.GetOption(FormattingOptions2.UseTabs, languageName)); + editorOptions.SetOptionValue(DefaultOptions.TabSizeOptionId, globalOptions.GetOption(FormattingOptions2.TabSize, languageName)); + editorOptions.SetOptionValue(DefaultOptions.IndentSizeOptionId, globalOptions.GetOption(FormattingOptions2.IndentationSize, languageName)); return textBuffer; }); diff --git a/src/EditorFeatures/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests.vb b/src/EditorFeatures/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests.vb index dccafe36519ac..b12e1d6a041a5 100644 --- a/src/EditorFeatures/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests.vb +++ b/src/EditorFeatures/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests.vb @@ -2421,7 +2421,7 @@ End Module Dim parameters2 As New TestParameters() Using workspace = CreateWorkspaceFromOptions(source.ToString(), parameters2) - workspace.ApplyOptions(PreferIntrinsicPredefinedTypeEverywhere()) + PreferIntrinsicPredefinedTypeEverywhere().SetGlobalOptions(workspace.GlobalOptions) Dim diagnostics = (Await GetDiagnosticsAsync(workspace, parameters2)).Where(Function(d) d.Id = IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId) Assert.Equal(1, diagnostics.Count) End Using diff --git a/src/EditorFeatures/VisualBasicTest/Squiggles/ErrorSquiggleProducerTests.vb b/src/EditorFeatures/VisualBasicTest/Squiggles/ErrorSquiggleProducerTests.vb index 6f0feff42f842..d64ebac340f80 100644 --- a/src/EditorFeatures/VisualBasicTest/Squiggles/ErrorSquiggleProducerTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Squiggles/ErrorSquiggleProducerTests.vb @@ -8,6 +8,7 @@ Imports Microsoft.CodeAnalysis.Classification Imports Microsoft.CodeAnalysis.CodeStyle Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo +Imports Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Squiggles Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces @@ -114,12 +115,11 @@ End Class" } Using workspace = TestWorkspace.CreateVisualBasic(content, composition:=SquiggleUtilities.CompositionWithSolutionCrawler) - Dim options As New Dictionary(Of OptionKey2, Object) Dim language = workspace.Projects.Single().Language - Dim preferIntrinsicPredefinedTypeOption = New OptionKey2(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, language) - Dim preferIntrinsicPredefinedTypeOptionValue = New CodeStyleOption2(Of Boolean)(value:=True, notification:=NotificationOption2.Error) - options.Add(preferIntrinsicPredefinedTypeOption, preferIntrinsicPredefinedTypeOptionValue) - workspace.ApplyOptions(options) + + workspace.GlobalOptions.SetGlobalOption( + New OptionKey(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, language), + New CodeStyleOption2(Of Boolean)(value:=True, notification:=NotificationOption2.Error)) Dim diagnosticsAndSpans = Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider, IErrorTag).GetDiagnosticsAndErrorSpans(workspace, analyzerMap) Dim spans = diagnosticsAndSpans.Item1.Zip(diagnosticsAndSpans.Item2, Function(diagostic, span) (diagostic, span)).OrderBy(Function(s) s.span.Span.Span.Start).ToImmutableArray() diff --git a/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs b/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs index f022a616398f7..cbcc7416ec972 100644 --- a/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs +++ b/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs @@ -173,14 +173,12 @@ void Method() }"; using var workspace = CreateWorkspace(LanguageNames.CSharp, code); var analyzerType = typeof(CSharpUseExplicitTypeDiagnosticAnalyzer); + var analyzerReference = new AnalyzerFileReference(analyzerType.Assembly.Location, new TestAnalyzerAssemblyLoader()); + workspace.TryApplyChanges(workspace.CurrentSolution.WithAnalyzerReferences(new[] { analyzerReference })); var ideAnalyzerOptions = IdeAnalyzerOptions.GetDefault(workspace.Services.GetLanguageServices(LanguageNames.CSharp)); - - var options = workspace.Options - .WithChangedOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent, new CodeStyleOption(false, NotificationOption.Suggestion)); - - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(options).WithAnalyzerReferences(new[] { analyzerReference })); + workspace.GlobalOptions.SetGlobalOption(new OptionKey(CSharpCodeStyleOptions.VarWhenTypeIsApparent), new CodeStyleOption(false, NotificationOption.Suggestion)); // run analysis var project = workspace.CurrentSolution.Projects.First(); diff --git a/src/VisualStudio/Core/Test/CodeModel/AbstractCodeElementTests`1.vb b/src/VisualStudio/Core/Test/CodeModel/AbstractCodeElementTests`1.vb index 3b513002dec61..3f06c7c0fed64 100644 --- a/src/VisualStudio/Core/Test/CodeModel/AbstractCodeElementTests`1.vb +++ b/src/VisualStudio/Core/Test/CodeModel/AbstractCodeElementTests`1.vb @@ -4,6 +4,7 @@ Imports System.Runtime.InteropServices Imports System.Threading.Tasks +Imports Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions Imports Microsoft.CodeAnalysis.Options @@ -53,16 +54,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel Private Protected Overloads Async Function TestElementUpdate( code As XElement, expectedCode As XElement, updater As Action(Of TCodeElement), - Optional options As IDictionary(Of OptionKey2, Object) = Nothing, + Optional options As OptionsCollection = Nothing, Optional editorConfig As String = "") As Task Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code, editorConfig)) Dim workspace = state.Workspace - If options IsNot Nothing Then - For Each kvp In options - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options _ - .WithChangedOption(kvp.Key, kvp.Value))) - Next - End If + options?.SetGlobalOptions(workspace.GlobalOptions) Dim codeElement = GetCodeElement(state) Assert.NotNull(codeElement) @@ -776,7 +772,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel Private Protected Overrides Async Function TestAddProperty( code As XElement, expectedCode As XElement, data As PropertyData, - Optional options As IDictionary(Of OptionKey2, Object) = Nothing, + Optional options As OptionsCollection = Nothing, Optional editorConfig As String = "") As Task Await TestElementUpdate(code, expectedCode, Sub(codeElement) diff --git a/src/VisualStudio/Core/Test/CodeModel/AbstractCodeModelObjectTests.vb b/src/VisualStudio/Core/Test/CodeModel/AbstractCodeModelObjectTests.vb index eb5f854a07363..88f978f61f1e3 100644 --- a/src/VisualStudio/Core/Test/CodeModel/AbstractCodeModelObjectTests.vb +++ b/src/VisualStudio/Core/Test/CodeModel/AbstractCodeModelObjectTests.vb @@ -3,6 +3,7 @@ ' See the LICENSE file in the project root for more information. Imports System.Threading.Tasks +Imports Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Test.Utilities @@ -69,7 +70,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel Private Protected Overridable Function TestAddProperty( code As XElement, expectedCode As XElement, data As PropertyData, - Optional options As IDictionary(Of OptionKey2, Object) = Nothing, + Optional options As OptionsCollection = Nothing, Optional editorConfig As String = "") As Task Throw New NotImplementedException End Function diff --git a/src/VisualStudio/Core/Test/Completion/CSharpCompletionSnippetNoteTests.vb b/src/VisualStudio/Core/Test/Completion/CSharpCompletionSnippetNoteTests.vb index c67cb86f91aa1..c4e90b69046e3 100644 --- a/src/VisualStudio/Core/Test/Completion/CSharpCompletionSnippetNoteTests.vb +++ b/src/VisualStudio/Core/Test/Completion/CSharpCompletionSnippetNoteTests.vb @@ -6,6 +6,7 @@ Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Completion Imports Microsoft.CodeAnalysis.Editor.Shared.Options Imports Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense +Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Snippets Imports Microsoft.CodeAnalysis.Test.Utilities Imports Roslyn.Test.Utilities @@ -117,9 +118,7 @@ class C Dim testSnippetInfoService = DirectCast(state.Workspace.Services.GetLanguageServices(LanguageNames.CSharp).GetService(Of ISnippetInfoService)(), TestCSharpSnippetInfoService) testSnippetInfoService.SetSnippetShortcuts({"for"}) - Dim workspace = state.Workspace - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options _ - .WithChangedOption(InternalFeatureOnOffOptions.Snippets, False))) + state.Workspace.GlobalOptions.SetGlobalOption(New OptionKey(InternalFeatureOnOffOptions.Snippets), False) state.SendTypeChars("for") Await state.AssertCompletionSession() diff --git a/src/VisualStudio/Core/Test/Snippets/SnippetTestState.vb b/src/VisualStudio/Core/Test/Snippets/SnippetTestState.vb index 1b4f51e8b4707..b94fc5cfead78 100644 --- a/src/VisualStudio/Core/Test/Snippets/SnippetTestState.vb +++ b/src/VisualStudio/Core/Test/Snippets/SnippetTestState.vb @@ -42,8 +42,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Snippets excludedTypes:={GetType(IIntelliSensePresenter(Of ISignatureHelpPresenterSession, ISignatureHelpSession)), GetType(FormatCommandHandler)}.Concat(If(excludedTypes, {})).ToList(), includeFormatCommandHandler:=False) - Workspace.TryApplyChanges(Workspace.CurrentSolution.WithOptions(Workspace.Options _ - .WithChangedOption(InternalFeatureOnOffOptions.Snippets, True))) + Workspace.GlobalOptions.SetGlobalOption(New OptionKey(InternalFeatureOnOffOptions.Snippets), True) Dim mockSVsServiceProvider = New Mock(Of SVsServiceProvider)(MockBehavior.Strict) mockSVsServiceProvider.Setup(Function(s) s.GetService(GetType(SVsTextManager))).Returns(Nothing) @@ -104,9 +103,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Snippets Dim state = New SnippetTestState(workspaceXml, languageName, startActiveSession, extraParts, excludedTypes:=Enumerable.Empty(Of Type), WorkspaceKind.Interactive) - Dim workspace = state.Workspace - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options _ - .WithChangedOption(InternalFeatureOnOffOptions.Snippets, False))) + state.Workspace.GlobalOptions.SetGlobalOption(New OptionKey(InternalFeatureOnOffOptions.Snippets), False) Return state End Function diff --git a/src/VisualStudio/Core/Test/Snippets/VisualBasicSnippetExpansionClientTests.vb b/src/VisualStudio/Core/Test/Snippets/VisualBasicSnippetExpansionClientTests.vb index 5928f5ea5cfa4..9c157f568a9eb 100644 --- a/src/VisualStudio/Core/Test/Snippets/VisualBasicSnippetExpansionClientTests.vb +++ b/src/VisualStudio/Core/Test/Snippets/VisualBasicSnippetExpansionClientTests.vb @@ -351,22 +351,24 @@ End Class Using workspace = TestWorkspace.Create(workspaceXml, openDocuments:=False) Dim document = workspace.Documents.Single() + Dim optionsService = workspace.GetService(Of EditorOptionsService)() + Dim textBuffer = document.GetTextBuffer() + Dim editorOptions = optionsService.Factory.GetOptions(textBuffer) - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options _ - .WithChangedOption(FormattingOptions.UseTabs, document.Project.Language, True) _ - .WithChangedOption(FormattingOptions.TabSize, document.Project.Language, tabSize) _ - .WithChangedOption(FormattingOptions.IndentationSize, document.Project.Language, tabSize))) + editorOptions.SetOptionValue(DefaultOptions.ConvertTabsToSpacesOptionId, False) + editorOptions.SetOptionValue(DefaultOptions.TabSizeOptionId, tabSize) + editorOptions.SetOptionValue(DefaultOptions.IndentSizeOptionId, tabSize) Dim snippetExpansionClient = New SnippetExpansionClient( workspace.ExportProvider.GetExportedValue(Of IThreadingContext), Guids.CSharpLanguageServiceId, document.GetTextView(), - document.GetTextBuffer(), + textBuffer, signatureHelpControllerProvider:=Nothing, editorCommandHandlerServiceFactory:=Nothing, Nothing, workspace.ExportProvider.GetExports(Of ArgumentProvider, OrderableLanguageMetadata)().ToImmutableArray(), - workspace.GetService(Of EditorOptionsService)()) + optionsService) SnippetExpansionClientTestsHelper.TestFormattingAndCaretPosition(snippetExpansionClient, document, expectedResult, tabSize * 3) End Using diff --git a/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs b/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs index d46a293a5d52a..1bc2e2c62a883 100644 --- a/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs +++ b/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs @@ -12,6 +12,7 @@ using System.Threading.Tasks; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Formatting; +using System; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Formatting { @@ -1790,11 +1791,10 @@ class F string s; }"; var tree = SyntaxFactory.ParseCompilationUnit(code); - - var newLineText = SyntaxFactory.ElasticEndOfLine(DefaultWorkspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp)); + var newLine = Environment.NewLine; tree = tree.ReplaceTokens(tree.DescendantTokens(descendIntoTrivia: true) - .Where(tr => tr.IsKind(SyntaxKind.EndOfDirectiveToken)), (o, r) => o.WithTrailingTrivia(o.LeadingTrivia.Add(newLineText)) + .Where(tr => tr.IsKind(SyntaxKind.EndOfDirectiveToken)), (o, r) => o.WithTrailingTrivia(o.LeadingTrivia.Add(SyntaxFactory.ElasticEndOfLine(newLine))) .WithLeadingTrivia(SyntaxFactory.TriviaList()) .WithAdditionalAnnotations(SyntaxAnnotation.ElasticAnnotation)); @@ -1804,7 +1804,7 @@ class F { Common = new SyntaxFormattingOptions.CommonOptions { - LineFormatting = new LineFormattingOptions { UseTabs = true } + LineFormatting = new LineFormattingOptions { UseTabs = true, NewLine = newLine } } }; From 202e95d4d1ad6f8971884732fe9e39dc8a5a64ab Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 20 Jul 2022 10:15:51 -0700 Subject: [PATCH 58/66] Inline members --- .../Portable/Rename/IRemoteRenamerService.cs | 93 +++++++++++++++++-- .../Core/Portable/Rename/RenameLocations.cs | 26 +++--- 2 files changed, 100 insertions(+), 19 deletions(-) diff --git a/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs b/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs index d94198c99869a..c9ac0129d71a3 100644 --- a/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs +++ b/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs @@ -75,6 +75,8 @@ public ValueTask GetOptionsAsync(RemoteServiceCallbackId cal => ((RemoteOptionsProvider)GetCallback(callbackId)).GetOptionsAsync(language, cancellationToken); } +#if false + [DataContract] internal class SerializableSearchResult { @@ -133,6 +135,8 @@ public async Task RehydrateAsync(Solution solution } } +#endif + [DataContract] internal readonly struct SerializableRenameLocation { @@ -205,7 +209,9 @@ internal partial class RenameLocations public SerializableRenameLocations Dehydrate(Solution solution, CancellationToken cancellationToken) => new( Options, - SerializableSearchResult.Dehydrate(solution, _result, cancellationToken)); + Locations.Select(SerializableRenameLocation.Dehydrate).ToArray(), + ImplicitLocations.IsDefault ? null : ImplicitLocations.Select(loc => SerializableReferenceLocation.Dehydrate(loc, cancellationToken)).ToArray(), + ReferencedSymbols.IsDefault ? null : ReferencedSymbols.Select(s => SerializableSymbolAndProjectId.Dehydrate(solution, s, cancellationToken)).ToArray()); internal static async Task TryRehydrateAsync( Solution solution, ISymbol symbol, CodeCleanupOptionsProvider fallbackOptions, SerializableRenameLocations locations, CancellationToken cancellationToken) @@ -213,15 +219,76 @@ public SerializableRenameLocations Dehydrate(Solution solution, CancellationToke if (locations == null) return null; - Contract.ThrowIfNull(locations.Result); + ImmutableArray implicitLocations = default; + ImmutableArray referencedSymbols = default; + + Contract.ThrowIfNull(locations.Locations); + + using var _1 = ArrayBuilder.GetInstance(locations.Locations.Length, out var locBuilder); + foreach (var loc in locations.Locations) + locBuilder.Add(await loc.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); + + if (locations.ImplicitLocations != null) + { + using var _2 = ArrayBuilder.GetInstance(locations.ImplicitLocations.Length, out var builder); + foreach (var loc in locations.ImplicitLocations) + builder.Add(await loc.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); + + implicitLocations = builder.ToImmutable(); + } + + if (locations.ReferencedSymbols != null) + { + using var _3 = ArrayBuilder.GetInstance(locations.ReferencedSymbols.Length, out var builder); + foreach (var referencedSymbol in locations.ReferencedSymbols) + builder.AddIfNotNull(await referencedSymbol.TryRehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); + + referencedSymbols = builder.ToImmutable(); + } return new RenameLocations( symbol, solution, locations.Options, fallbackOptions, - await locations.Result.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); + locBuilder.ToImmutableHashSet(), + implicitLocations, + referencedSymbols); } + + //public async Task RehydrateAsync(Solution solution, CancellationToken cancellationToken) + //{ + // ImmutableArray implicitLocations = default; + // ImmutableArray referencedSymbols = default; + + // Contract.ThrowIfNull(Locations); + + // using var _1 = ArrayBuilder.GetInstance(Locations.Length, out var locBuilder); + // foreach (var loc in Locations) + // locBuilder.Add(await loc.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); + + // var locations = locBuilder.ToImmutableHashSet(); + + // if (ImplicitLocations != null) + // { + // using var _2 = ArrayBuilder.GetInstance(ImplicitLocations.Length, out var builder); + // foreach (var loc in ImplicitLocations) + // builder.Add(await loc.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); + + // implicitLocations = builder.ToImmutable(); + // } + + // if (ReferencedSymbols != null) + // { + // using var _3 = ArrayBuilder.GetInstance(ReferencedSymbols.Length, out var builder); + // foreach (var symbol in ReferencedSymbols) + // builder.AddIfNotNull(await symbol.TryRehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); + + // referencedSymbols = builder.ToImmutable(); + // } + + // return new RenameLocations.SearchResult(locations, implicitLocations, referencedSymbols); + //} } [DataContract] @@ -230,13 +297,27 @@ internal sealed class SerializableRenameLocations [DataMember(Order = 0)] public readonly SymbolRenameOptions Options; + // We use arrays so we can represent default immutable arrays. + [DataMember(Order = 1)] - public readonly SerializableSearchResult? Result; + public SerializableRenameLocation[]? Locations; + + [DataMember(Order = 2)] + public SerializableReferenceLocation[]? ImplicitLocations; - public SerializableRenameLocations(SymbolRenameOptions options, SerializableSearchResult? result) + [DataMember(Order = 3)] + public SerializableSymbolAndProjectId[]? ReferencedSymbols; + + public SerializableRenameLocations( + SymbolRenameOptions options, + SerializableRenameLocation[]? locations, + SerializableReferenceLocation[]? implicitLocations, + SerializableSymbolAndProjectId[]? referencedSymbols) { Options = options; - Result = result; + Locations = locations; + ImplicitLocations = implicitLocations; + ReferencedSymbols = referencedSymbols; } } diff --git a/src/Workspaces/Core/Portable/Rename/RenameLocations.cs b/src/Workspaces/Core/Portable/Rename/RenameLocations.cs index 999119b4f7a2f..d12818cda110a 100644 --- a/src/Workspaces/Core/Portable/Rename/RenameLocations.cs +++ b/src/Workspaces/Core/Portable/Rename/RenameLocations.cs @@ -31,24 +31,26 @@ internal sealed partial class RenameLocations public readonly SymbolRenameOptions Options; public readonly CodeCleanupOptionsProvider FallbackOptions; - private readonly SearchResult _result; - - public ISet Locations => _result.Locations; - public ImmutableArray ReferencedSymbols => _result.ReferencedSymbols; - public ImmutableArray ImplicitLocations => _result.ImplicitLocations; + public readonly ImmutableHashSet Locations; + public readonly ImmutableArray ImplicitLocations; + public readonly ImmutableArray ReferencedSymbols; private RenameLocations( ISymbol symbol, Solution solution, SymbolRenameOptions options, CodeCleanupOptionsProvider fallbackOptions, - SearchResult result) + ImmutableHashSet locations, + ImmutableArray implicitLocations, + ImmutableArray referencedSymbols) { Solution = solution; Symbol = symbol; Options = options; FallbackOptions = fallbackOptions; - _result = result; + Locations = locations; + ReferencedSymbols = referencedSymbols; + ImplicitLocations = implicitLocations; } internal static RenameLocations Create( @@ -61,8 +63,7 @@ internal sealed partial class RenameLocations CodeCleanupOptionsProvider fallbackOptions) { return new RenameLocations( - symbol, solution, options, fallbackOptions, - new SearchResult(locations, implicitLocations, referencedSymbols)); + symbol, solution, options, fallbackOptions, locations, implicitLocations, referencedSymbols); } /// @@ -157,10 +158,9 @@ internal sealed partial class RenameLocations return new RenameLocations( symbol, solution, options, cleanupOptions, - new SearchResult( - mergedLocations.ToImmutable(), - mergedImplicitLocations.ToImmutable(), - mergedReferencedSymbols.ToImmutable())); + mergedLocations.ToImmutable(), + mergedImplicitLocations.ToImmutable(), + mergedReferencedSymbols.ToImmutable()); } } From 7714b3d65133c09bf7dd10bab4f06298917e600a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 20 Jul 2022 10:16:30 -0700 Subject: [PATCH 59/66] Delete --- .../Portable/Rename/IRemoteRenamerService.cs | 96 ------------------- 1 file changed, 96 deletions(-) diff --git a/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs b/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs index c9ac0129d71a3..8736560c35724 100644 --- a/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs +++ b/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs @@ -75,68 +75,6 @@ public ValueTask GetOptionsAsync(RemoteServiceCallbackId cal => ((RemoteOptionsProvider)GetCallback(callbackId)).GetOptionsAsync(language, cancellationToken); } -#if false - - [DataContract] - internal class SerializableSearchResult - { - // We use arrays so we can represent default immutable arrays. - - [DataMember(Order = 0)] - public SerializableRenameLocation[]? Locations; - - [DataMember(Order = 1)] - public SerializableReferenceLocation[]? ImplicitLocations; - - [DataMember(Order = 2)] - public SerializableSymbolAndProjectId[]? ReferencedSymbols; - - [return: NotNullIfNotNull("result")] - public static SerializableSearchResult? Dehydrate(Solution solution, RenameLocations.SearchResult? result, CancellationToken cancellationToken) - => result == null ? null : new SerializableSearchResult - { - Locations = result.Locations.Select(SerializableRenameLocation.Dehydrate).ToArray(), - ImplicitLocations = result.ImplicitLocations.IsDefault ? null : result.ImplicitLocations.Select(loc => SerializableReferenceLocation.Dehydrate(loc, cancellationToken)).ToArray(), - ReferencedSymbols = result.ReferencedSymbols.IsDefault ? null : result.ReferencedSymbols.Select(s => SerializableSymbolAndProjectId.Dehydrate(solution, s, cancellationToken)).ToArray(), - }; - - public async Task RehydrateAsync(Solution solution, CancellationToken cancellationToken) - { - ImmutableArray implicitLocations = default; - ImmutableArray referencedSymbols = default; - - Contract.ThrowIfNull(Locations); - - using var _1 = ArrayBuilder.GetInstance(Locations.Length, out var locBuilder); - foreach (var loc in Locations) - locBuilder.Add(await loc.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); - - var locations = locBuilder.ToImmutableHashSet(); - - if (ImplicitLocations != null) - { - using var _2 = ArrayBuilder.GetInstance(ImplicitLocations.Length, out var builder); - foreach (var loc in ImplicitLocations) - builder.Add(await loc.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); - - implicitLocations = builder.ToImmutable(); - } - - if (ReferencedSymbols != null) - { - using var _3 = ArrayBuilder.GetInstance(ReferencedSymbols.Length, out var builder); - foreach (var symbol in ReferencedSymbols) - builder.AddIfNotNull(await symbol.TryRehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); - - referencedSymbols = builder.ToImmutable(); - } - - return new RenameLocations.SearchResult(locations, implicitLocations, referencedSymbols); - } - } - -#endif - [DataContract] internal readonly struct SerializableRenameLocation { @@ -255,40 +193,6 @@ public SerializableRenameLocations Dehydrate(Solution solution, CancellationToke implicitLocations, referencedSymbols); } - - //public async Task RehydrateAsync(Solution solution, CancellationToken cancellationToken) - //{ - // ImmutableArray implicitLocations = default; - // ImmutableArray referencedSymbols = default; - - // Contract.ThrowIfNull(Locations); - - // using var _1 = ArrayBuilder.GetInstance(Locations.Length, out var locBuilder); - // foreach (var loc in Locations) - // locBuilder.Add(await loc.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); - - // var locations = locBuilder.ToImmutableHashSet(); - - // if (ImplicitLocations != null) - // { - // using var _2 = ArrayBuilder.GetInstance(ImplicitLocations.Length, out var builder); - // foreach (var loc in ImplicitLocations) - // builder.Add(await loc.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); - - // implicitLocations = builder.ToImmutable(); - // } - - // if (ReferencedSymbols != null) - // { - // using var _3 = ArrayBuilder.GetInstance(ReferencedSymbols.Length, out var builder); - // foreach (var symbol in ReferencedSymbols) - // builder.AddIfNotNull(await symbol.TryRehydrateAsync(solution, cancellationToken).ConfigureAwait(false)); - - // referencedSymbols = builder.ToImmutable(); - // } - - // return new RenameLocations.SearchResult(locations, implicitLocations, referencedSymbols); - //} } [DataContract] From 4eabf9fc73560a2b75de8eade44793a694fc67c2 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Wed, 20 Jul 2022 10:33:27 -0700 Subject: [PATCH 60/66] Optimize away unchecked conversions between nint and nuint types. (#62774) Fixes #60944. --- .../Test/Emit2/Emit/NumericIntPtrTests.cs | 635 ++++++++++++++++-- .../Semantic/Semantics/NativeIntegerTests.cs | 161 ++++- .../Portable/CodeGen/ILBuilderConversions.cs | 2 + 3 files changed, 717 insertions(+), 81 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Emit/NumericIntPtrTests.cs b/src/Compilers/CSharp/Test/Emit2/Emit/NumericIntPtrTests.cs index f13e5bbf05260..350d7e781bee2 100644 --- a/src/Compilers/CSharp/Test/Emit2/Emit/NumericIntPtrTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Emit/NumericIntPtrTests.cs @@ -1234,15 +1234,14 @@ static void Main() var verifier = CompileAndVerify(comp, expectedOutput: @"1"); verifier.VerifyIL("Program.F", @"{ - // Code size 17 (0x11) + // Code size 16 (0x10) .maxstack 2 IL_0000: volatile. IL_0002: ldsfld ""nint Program.F1"" IL_0007: volatile. IL_0009: ldsfld ""nuint Program.F2"" - IL_000e: conv.i - IL_000f: add - IL_0010: ret + IL_000e: add + IL_000f: ret }"); } @@ -3348,7 +3347,7 @@ .maxstack 1 conversions(sourceType: "long", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "ulong", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "nint", destType: "nint", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "nuint", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); + conversions(sourceType: "nuint", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "float", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "double", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "decimal", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, @@ -3369,7 +3368,7 @@ .maxstack 1 IL_0007: ret }"); conversions(sourceType: "System.IntPtr", destType: "nint", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "System.UIntPtr", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); + conversions(sourceType: "System.UIntPtr", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); // nullable type to nint conversions(sourceType: "E?", destType: "nint", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "E")); @@ -3391,7 +3390,17 @@ .maxstack 1 IL_0002: call ""nint nint?.Value.get"" IL_0007: ret }"); - conversions(sourceType: "nuint?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); + conversions(sourceType: "nuint?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nuint nuint?.Value.get"" + IL_0007: ret +} +", + expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); conversions(sourceType: "float?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "float"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "float")); conversions(sourceType: "double?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "double"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "double")); conversions(sourceType: "decimal?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, @@ -3421,7 +3430,17 @@ .maxstack 1 IL_0002: call ""nint nint?.Value.get"" IL_0007: ret }"); - conversions(sourceType: "System.UIntPtr?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); + conversions(sourceType: "System.UIntPtr?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nuint nuint?.Value.get"" + IL_0007: ret +} +", + expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); // type to nullable nint conversions(sourceType: "object", destType: "nint?", Unboxing, expectedImplicitIL: null, @@ -3491,7 +3510,17 @@ .maxstack 1 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); - conversions(sourceType: "nuint", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); + conversions(sourceType: "nuint", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nint?..ctor(nint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "float", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "double", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "decimal", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, @@ -3528,7 +3557,17 @@ .maxstack 1 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); - conversions(sourceType: "System.UIntPtr", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); + conversions(sourceType: "System.UIntPtr", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nint?..ctor(nint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); // nullable type to nullable nint conversions(sourceType: "E?", destType: "nint?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "E", "nint")); @@ -3543,7 +3582,29 @@ .maxstack 1 conversions(sourceType: "long?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "long", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "long", "nint")); conversions(sourceType: "ulong?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "ulong", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "ulong", "nint")); conversions(sourceType: "nint?", destType: "nint?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "nuint?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "nuint", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); + conversions(sourceType: "nuint?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nuint? V_0, + nint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nuint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nuint nuint?.GetValueOrDefault()"" + IL_001c: newobj ""nint?..ctor(nint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); conversions(sourceType: "float?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "float", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "float", "nint")); conversions(sourceType: "double?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "double", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "double", "nint")); conversions(sourceType: "decimal?", destType: "nint?", ExplicitNullableNumeric, null, @@ -3590,7 +3651,29 @@ .maxstack 1 IL_0027: ret }"); conversions(sourceType: "System.IntPtr?", destType: "nint?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "System.UIntPtr?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "nuint", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); + conversions(sourceType: "System.UIntPtr?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nuint? V_0, + nint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nuint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nuint nuint?.GetValueOrDefault()"" + IL_001c: newobj ""nint?..ctor(nint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); // nint to type conversions(sourceType: "nint", destType: "object", Boxing, @@ -3642,7 +3725,7 @@ .maxstack 1 IL_0007: ret }"); conversions(sourceType: "nint", destType: "System.IntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "nint", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); + conversions(sourceType: "nint", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); // nint to nullable type conversions(sourceType: "nint", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i4", "E"), expectedCheckedIL: convToNullableT("conv.ovf.i4", "E")); @@ -3692,7 +3775,17 @@ .maxstack 1 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); - conversions(sourceType: "nint", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); + conversions(sourceType: "nint", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nuint?..ctor(nuint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); // nullable nint to type conversions(sourceType: "nint?", destType: "object", Boxing, @@ -3744,7 +3837,17 @@ .maxstack 1 IL_0002: call ""nint nint?.Value.get"" IL_0007: ret }"); - conversions(sourceType: "nint?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); + conversions(sourceType: "nint?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nint nint?.Value.get"" + IL_0007: ret +} +", + expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); // nullable nint to nullable type conversions(sourceType: "nint?", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i4", "nint", "E"), expectedCheckedIL: convFromToNullableT("conv.ovf.i4", "nint", "E")); @@ -3804,7 +3907,29 @@ .maxstack 1 IL_0027: ret }"); conversions(sourceType: "nint?", destType: "System.IntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "nint?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "nint", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); + conversions(sourceType: "nint?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nint? V_0, + nuint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nuint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nint nint?.GetValueOrDefault()"" + IL_001c: newobj ""nuint?..ctor(nuint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); // type to nuint conversions(sourceType: "object", destType: "nuint", Unboxing, expectedImplicitIL: null, @@ -3829,7 +3954,7 @@ .maxstack 1 conversions(sourceType: "uint", destType: "nuint", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "long", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "ulong", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u.un")); - conversions(sourceType: "nint", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); + conversions(sourceType: "nint", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "nuint", destType: "nuint", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "float", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "double", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); @@ -3850,7 +3975,7 @@ .maxstack 1 IL_0006: conv.ovf.u.un IL_0007: ret }"); - conversions(sourceType: "System.IntPtr", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); + conversions(sourceType: "System.IntPtr", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "System.UIntPtr", destType: "nuint", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // nullable type to nuint @@ -3865,7 +3990,17 @@ .maxstack 1 conversions(sourceType: "uint?", destType: "nuint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "uint")); conversions(sourceType: "long?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "long"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "long")); conversions(sourceType: "ulong?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "ulong"), expectedCheckedIL: convFromNullableT("conv.ovf.u.un", "ulong")); - conversions(sourceType: "nint?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); + conversions(sourceType: "nint?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nint nint?.Value.get"" + IL_0007: ret +} +", + expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); conversions(sourceType: "nuint?", destType: "nuint", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) @@ -3895,7 +4030,15 @@ .maxstack 1 IL_000c: conv.ovf.u.un IL_000d: ret }"); - conversions(sourceType: "System.IntPtr?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); + conversions(sourceType: "System.IntPtr?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@"{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nint nint?.Value.get"" + IL_0007: ret +}", + expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); conversions(sourceType: "System.UIntPtr?", destType: "nuint", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) @@ -3942,7 +4085,17 @@ .maxstack 1 conversions(sourceType: "uint", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint")); conversions(sourceType: "long", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "ulong", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u.un", "nuint")); - conversions(sourceType: "nint", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); + conversions(sourceType: "nint", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nuint?..ctor(nuint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "nuint", destType: "nuint?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) @@ -3979,7 +4132,17 @@ .maxstack 1 IL_0007: newobj ""nuint?..ctor(nuint)"" IL_000c: ret }"); - conversions(sourceType: "System.IntPtr", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); + conversions(sourceType: "System.IntPtr", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nuint?..ctor(nuint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "System.UIntPtr", destType: "nuint?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) @@ -4008,7 +4171,29 @@ .maxstack 1 conversions(sourceType: "uint?", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "uint", "nuint"), expectedExplicitIL: convFromToNullableT("conv.u", "uint", "nuint")); conversions(sourceType: "long?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "long", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "long", "nuint")); conversions(sourceType: "ulong?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "ulong", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u.un", "ulong", "nuint")); - conversions(sourceType: "nint?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "nint", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); + conversions(sourceType: "nint?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nint? V_0, + nuint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nuint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nint nint?.GetValueOrDefault()"" + IL_001c: newobj ""nuint?..ctor(nuint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); conversions(sourceType: "nuint?", destType: "nuint?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "float?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "float", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "float", "nuint")); conversions(sourceType: "double?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "double", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "double", "nuint")); @@ -4055,7 +4240,29 @@ .maxstack 1 IL_0022: newobj ""nuint?..ctor(nuint)"" IL_0027: ret }"); - conversions(sourceType: "System.IntPtr?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "nint", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); + conversions(sourceType: "System.IntPtr?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nint? V_0, + nuint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nuint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nint nint?.GetValueOrDefault()"" + IL_001c: newobj ""nuint?..ctor(nuint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "nuint?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // nuint to type @@ -4107,7 +4314,7 @@ .maxstack 1 IL_0002: call ""decimal decimal.op_Implicit(ulong)"" IL_0007: ret }"); - conversions(sourceType: "nuint", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); + conversions(sourceType: "nuint", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "nuint", destType: "System.UIntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // nuint to nullable type @@ -4143,7 +4350,17 @@ .maxstack 1 IL_0007: newobj ""decimal?..ctor(decimal)"" IL_000c: ret }"); - conversions(sourceType: "nuint", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); + conversions(sourceType: "nuint", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nint?..ctor(nint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "nuint", destType: "System.UIntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) @@ -4202,7 +4419,17 @@ .maxstack 1 IL_0008: call ""decimal decimal.op_Implicit(ulong)"" IL_000d: ret }"); - conversions(sourceType: "nuint?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); + conversions(sourceType: "nuint?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nuint nuint?.Value.get"" + IL_0007: ret +} +", + expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); conversions(sourceType: "nuint?", destType: "System.UIntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) @@ -4269,7 +4496,29 @@ .maxstack 1 IL_0022: newobj ""decimal?..ctor(decimal)"" IL_0027: ret }"); - conversions(sourceType: "nuint?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "nuint", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); + conversions(sourceType: "nuint?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nuint? V_0, + nint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nuint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nuint nuint?.GetValueOrDefault()"" + IL_001c: newobj ""nint?..ctor(nint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); conversions(sourceType: "nuint?", destType: "System.UIntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // System.IntPtr to type @@ -4325,7 +4574,7 @@ .maxstack 1 IL_0007: ret }"); conversions(sourceType: "System.IntPtr", destType: "System.IntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); + conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); // System.IntPtr to nullable type conversions(sourceType: "System.IntPtr", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i4", "E"), expectedCheckedIL: convToNullableT("conv.ovf.i4", "E")); @@ -4375,7 +4624,17 @@ .maxstack 1 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); - conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); + conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nuint?..ctor(nuint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); // nullable System.IntPtr to type conversions(sourceType: "System.IntPtr?", destType: "object", Boxing, @@ -4427,7 +4686,17 @@ .maxstack 1 IL_0002: call ""nint nint?.Value.get"" IL_0007: ret }"); - conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); + conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nint nint?.Value.get"" + IL_0007: ret +} +", + expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); // nullable System.IntPtr to nullable type conversions(sourceType: "System.IntPtr?", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i4", "nint", "E"), expectedCheckedIL: convFromToNullableT("conv.ovf.i4", "nint", "E")); @@ -4487,7 +4756,29 @@ .maxstack 1 IL_0027: ret }"); conversions(sourceType: "System.IntPtr?", destType: "System.IntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "nint", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); + conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nint? V_0, + nuint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nuint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nint nint?.GetValueOrDefault()"" + IL_001c: newobj ""nuint?..ctor(nuint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); // type to System.IntPtr conversions(sourceType: "object", destType: "System.IntPtr", Unboxing, expectedImplicitIL: null, @@ -4513,7 +4804,7 @@ .maxstack 1 conversions(sourceType: "long", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "ulong", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "nint", destType: "System.IntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "nuint", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); + conversions(sourceType: "nuint", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "float", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "double", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "decimal", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, @@ -4533,7 +4824,7 @@ .maxstack 1 IL_0006: conv.ovf.i IL_0007: ret }"); - conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); + conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); // type to nullable System.IntPtr conversions(sourceType: "object", destType: "System.IntPtr?", Unboxing, expectedImplicitIL: null, @@ -4603,7 +4894,17 @@ .maxstack 1 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); - conversions(sourceType: "nuint", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); + conversions(sourceType: "nuint", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nint?..ctor(nint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "float", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "double", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "decimal", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, @@ -4640,7 +4941,17 @@ .maxstack 1 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); - conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); + conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nint?..ctor(nint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); // nullable type to System.IntPtr conversions(sourceType: "E?", destType: "System.IntPtr", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "E")); @@ -4662,7 +4973,17 @@ .maxstack 1 IL_0002: call ""nint nint?.Value.get"" IL_0007: ret }"); - conversions(sourceType: "nuint?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); + conversions(sourceType: "nuint?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nuint nuint?.Value.get"" + IL_0007: ret +} +", + expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); conversions(sourceType: "float?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "float"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "float")); conversions(sourceType: "double?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "double"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "double")); conversions(sourceType: "decimal?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, @@ -4692,7 +5013,17 @@ .maxstack 1 IL_0002: call ""nint nint?.Value.get"" IL_0007: ret }"); - conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); + conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nuint nuint?.Value.get"" + IL_0007: ret +} +", + expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); // nullable type to nullable System.IntPtr conversions(sourceType: "E?", destType: "System.IntPtr?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "E", "nint")); @@ -4707,7 +5038,29 @@ .maxstack 1 conversions(sourceType: "long?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "long", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "long", "nint")); conversions(sourceType: "ulong?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "ulong", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "ulong", "nint")); conversions(sourceType: "nint?", destType: "System.IntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "nuint?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "nuint", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); + conversions(sourceType: "nuint?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nuint? V_0, + nint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nuint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nuint nuint?.GetValueOrDefault()"" + IL_001c: newobj ""nint?..ctor(nint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); conversions(sourceType: "float?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "float", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "float", "nint")); conversions(sourceType: "double?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "double", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "double", "nint")); conversions(sourceType: "decimal?", destType: "System.IntPtr?", ExplicitNullableNumeric, null, @@ -4754,7 +5107,29 @@ .maxstack 1 IL_0027: ret }"); conversions(sourceType: "System.IntPtr?", destType: "System.IntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "nuint", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); + conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nuint? V_0, + nint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nuint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nuint nuint?.GetValueOrDefault()"" + IL_001c: newobj ""nint?..ctor(nint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); // System.UIntPtr to type conversions(sourceType: "System.UIntPtr", destType: "object", Boxing, @@ -4805,7 +5180,7 @@ .maxstack 1 IL_0002: call ""decimal decimal.op_Implicit(ulong)"" IL_0007: ret }"); - conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); + conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "System.UIntPtr", destType: "System.UIntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // System.UIntPtr to nullable type @@ -4841,7 +5216,17 @@ .maxstack 1 IL_0007: newobj ""decimal?..ctor(decimal)"" IL_000c: ret }"); - conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); + conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nint?..ctor(nint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "System.UIntPtr", destType: "System.UIntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) @@ -4900,7 +5285,17 @@ .maxstack 1 IL_0008: call ""decimal decimal.op_Implicit(ulong)"" IL_000d: ret }"); - conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); + conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nuint nuint?.Value.get"" + IL_0007: ret +} +", + expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "System.UIntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) @@ -4967,7 +5362,29 @@ .maxstack 1 IL_0022: newobj ""decimal?..ctor(decimal)"" IL_0027: ret }"); - conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "nuint", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); + conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nuint? V_0, + nint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nuint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nuint nuint?.GetValueOrDefault()"" + IL_001c: newobj ""nint?..ctor(nint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); conversions(sourceType: "System.UIntPtr?", destType: "System.UIntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // type to System.UIntPtr @@ -4993,7 +5410,7 @@ .maxstack 1 conversions(sourceType: "uint", destType: "System.UIntPtr", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "long", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "ulong", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u.un")); - conversions(sourceType: "nint", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); + conversions(sourceType: "nint", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "nuint", destType: "System.UIntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "float", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "double", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); @@ -5014,7 +5431,7 @@ .maxstack 1 IL_0006: conv.ovf.u.un IL_0007: ret }"); - conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); + conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "System.UIntPtr", destType: "System.UIntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // type to nullable System.UIntPtr @@ -5054,7 +5471,17 @@ .maxstack 1 conversions(sourceType: "uint", destType: "System.UIntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint")); conversions(sourceType: "long", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "ulong", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u.un", "nuint")); - conversions(sourceType: "nint", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); + conversions(sourceType: "nint", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nuint?..ctor(nuint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "nuint", destType: "System.UIntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) @@ -5091,7 +5518,17 @@ .maxstack 1 IL_0007: newobj ""nuint?..ctor(nuint)"" IL_000c: ret }"); - conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); + conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nuint?..ctor(nuint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "System.UIntPtr", destType: "System.UIntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) @@ -5120,7 +5557,17 @@ .maxstack 1 conversions(sourceType: "uint?", destType: "System.UIntPtr", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "uint")); conversions(sourceType: "long?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "long"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "long")); conversions(sourceType: "ulong?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "ulong"), expectedCheckedIL: convFromNullableT("conv.ovf.u.un", "ulong")); - conversions(sourceType: "nint?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); + conversions(sourceType: "nint?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nint nint?.Value.get"" + IL_0007: ret +} +", + expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); conversions(sourceType: "nuint?", destType: "System.UIntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) @@ -5150,7 +5597,17 @@ .maxstack 1 IL_000c: conv.ovf.u.un IL_000d: ret }"); - conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); + conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nint nint?.Value.get"" + IL_0007: ret +} +", + expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); conversions(sourceType: "System.UIntPtr?", destType: "System.UIntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) @@ -5172,7 +5629,29 @@ .maxstack 1 conversions(sourceType: "uint?", destType: "System.UIntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "uint", "nuint"), expectedExplicitIL: convFromToNullableT("conv.u", "uint", "nuint")); conversions(sourceType: "long?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "long", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "long", "nuint")); conversions(sourceType: "ulong?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "ulong", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u.un", "ulong", "nuint")); - conversions(sourceType: "nint?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "nint", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); + conversions(sourceType: "nint?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nint? V_0, + nuint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nuint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nint nint?.GetValueOrDefault()"" + IL_001c: newobj ""nuint?..ctor(nuint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); conversions(sourceType: "nuint?", destType: "System.UIntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "float?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "float", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "float", "nuint")); conversions(sourceType: "double?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "double", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "double", "nuint")); @@ -5219,7 +5698,29 @@ .maxstack 1 IL_0022: newobj ""nuint?..ctor(nuint)"" IL_0027: ret }"); - conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "nint", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); + conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nint? V_0, + nuint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nuint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nint nint?.GetValueOrDefault()"" + IL_001c: newobj ""nuint?..ctor(nuint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "System.UIntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); return; @@ -8633,11 +9134,11 @@ public void Int64Conversions() { convert(fromType: "nint", toType: "ulong", "int.MinValue", "18446744071562067968", "conv.i8", "System.OverflowException", "conv.ovf.u8"); convert(fromType: "nint", toType: "ulong", "int.MaxValue", "2147483647", "conv.i8", "2147483647", "conv.ovf.u8"); - convert(fromType: "nint", toType: "nuint", "int.MinValue", IntPtr.Size == 4 ? "2147483648" : "18446744071562067968", "conv.u", "System.OverflowException", "conv.ovf.u"); - convert(fromType: "nint", toType: "nuint", "int.MaxValue", "2147483647", "conv.u", "2147483647", "conv.ovf.u"); + convert(fromType: "nint", toType: "nuint", "int.MinValue", IntPtr.Size == 4 ? "2147483648" : "18446744071562067968", null, "System.OverflowException", "conv.ovf.u"); + convert(fromType: "nint", toType: "nuint", "int.MaxValue", "2147483647", null, "2147483647", "conv.ovf.u"); convert(fromType: "nuint", toType: "long", "uint.MaxValue", "4294967295", "conv.u8", "4294967295", "conv.ovf.i8.un"); - convert(fromType: "nuint", toType: "nint", "uint.MaxValue", IntPtr.Size == 4 ? "-1" : "4294967295", "conv.i", IntPtr.Size == 4 ? "System.OverflowException" : "4294967295", "conv.ovf.i.un"); + convert(fromType: "nuint", toType: "nint", "uint.MaxValue", IntPtr.Size == 4 ? "-1" : "4294967295", null, IntPtr.Size == 4 ? "System.OverflowException" : "4294967295", "conv.ovf.i.un"); string nintMinValue = IntPtr.Size == 4 ? int.MinValue.ToString() : long.MinValue.ToString(); string nintMaxValue = IntPtr.Size == 4 ? int.MaxValue.ToString() : long.MaxValue.ToString(); @@ -8645,11 +9146,11 @@ public void Int64Conversions() convert(fromType: "nint", toType: "ulong", nintMinValue, IntPtr.Size == 4 ? "18446744071562067968" : "9223372036854775808", "conv.i8", "System.OverflowException", "conv.ovf.u8"); convert(fromType: "nint", toType: "ulong", nintMaxValue, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.i8", IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.ovf.u8"); - convert(fromType: "nint", toType: "nuint", nintMinValue, IntPtr.Size == 4 ? "2147483648" : "9223372036854775808", "conv.u", "System.OverflowException", "conv.ovf.u"); - convert(fromType: "nint", toType: "nuint", nintMaxValue, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.u", IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.ovf.u"); + convert(fromType: "nint", toType: "nuint", nintMinValue, IntPtr.Size == 4 ? "2147483648" : "9223372036854775808", null, "System.OverflowException", "conv.ovf.u"); + convert(fromType: "nint", toType: "nuint", nintMaxValue, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", null, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.ovf.u"); convert(fromType: "nuint", toType: "long", nuintMaxValue, IntPtr.Size == 4 ? "4294967295" : "-1", "conv.u8", IntPtr.Size == 4 ? "4294967295" : "System.OverflowException", "conv.ovf.i8.un"); - convert(fromType: "nuint", toType: "nint", nuintMaxValue, "-1", "conv.i", "System.OverflowException", "conv.ovf.i.un"); + convert(fromType: "nuint", toType: "nint", nuintMaxValue, "-1", null, "System.OverflowException", "conv.ovf.i.un"); void convert(string fromType, string toType, string fromValue, string toValueUnchecked, string toConvUnchecked, string toValueChecked, string toConvChecked) { @@ -8683,7 +9184,14 @@ static void Main() $@"{toValueUnchecked} {toValueChecked}"); - verifier.VerifyIL("Program.Convert", + verifier.VerifyIL("Program.Convert", toConvUnchecked is null ? +@" +{ + // Code size 2 (0x2) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ret +}" : $@"{{ // Code size 3 (0x3) .maxstack 1 @@ -9269,6 +9777,13 @@ public void SignedToUnsignedConversions_Explicit(string type) }}"; var comp = CreateNumericIntPtrCompilation(source, references: new[] { MscorlibRefWithoutSharingCachedSymbols }); var verifier = CompileAndVerify(comp); + string expectedExplicitILNop = +@"{ + // Code size 2 (0x2) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ret +}"; string expectedExplicitILA = @"{ // Code size 3 (0x3) @@ -9297,7 +9812,7 @@ .maxstack 1 verifier.VerifyIL("NativeInts.Explicit2", expectedExplicitILA); verifier.VerifyIL("NativeInts.Explicit3", expectedExplicitILA); verifier.VerifyIL("NativeInts.Explicit4", expectedExplicitILB); - verifier.VerifyIL("NativeInts.Explicit5", expectedExplicitILB); + verifier.VerifyIL("NativeInts.Explicit5", expectedExplicitILNop); verifier.VerifyIL("NativeInts.Checked1", expectedCheckedIL); verifier.VerifyIL("NativeInts.Checked2", expectedCheckedIL); verifier.VerifyIL("NativeInts.Checked3", expectedCheckedIL); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs index 7e6e68185b96c..cd55dd14b21f6 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs @@ -4286,15 +4286,14 @@ static void Main() var verifier = CompileAndVerify(source, expectedOutput: @"1"); verifier.VerifyIL("Program.F", @"{ - // Code size 17 (0x11) + // Code size 16 (0x10) .maxstack 2 IL_0000: volatile. IL_0002: ldsfld ""nint Program.F1"" IL_0007: volatile. IL_0009: ldsfld ""nuint Program.F2"" - IL_000e: conv.i - IL_000f: add - IL_0010: ret + IL_000e: add + IL_000f: ret }"); } @@ -7661,7 +7660,7 @@ .maxstack 1 conversions(sourceType: "long", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "ulong", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "nint", destType: "nint", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "nuint", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); + conversions(sourceType: "nuint", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "float", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "double", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "decimal", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, @@ -7702,7 +7701,16 @@ .maxstack 1 IL_0002: call ""nint nint?.Value.get"" IL_0007: ret }"); - conversions(sourceType: "nuint?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); + conversions(sourceType: "nuint?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nuint nuint?.Value.get"" + IL_0007: ret +}", + expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); conversions(sourceType: "float?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "float"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "float")); conversions(sourceType: "double?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "double"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "double")); conversions(sourceType: "decimal?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, @@ -7800,7 +7808,16 @@ .maxstack 1 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); - conversions(sourceType: "nuint", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); + conversions(sourceType: "nuint", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nint?..ctor(nint)"" + IL_0006: ret +}", + expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "float", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "double", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "decimal", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, @@ -7850,7 +7867,28 @@ .maxstack 1 conversions(sourceType: "long?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "long", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "long", "nint")); conversions(sourceType: "ulong?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "ulong", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "ulong", "nint")); conversions(sourceType: "nint?", destType: "nint?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); - conversions(sourceType: "nuint?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "nuint", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); + conversions(sourceType: "nuint?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nuint? V_0, + nint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nuint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nuint nuint?.GetValueOrDefault()"" + IL_001c: newobj ""nint?..ctor(nint)"" + IL_0021: ret +}", + expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); conversions(sourceType: "float?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "float", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "float", "nint")); conversions(sourceType: "double?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "double", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "double", "nint")); conversions(sourceType: "decimal?", destType: "nint?", ExplicitNullableNumeric, null, @@ -8126,7 +8164,7 @@ .maxstack 1 conversions(sourceType: "uint", destType: "nuint", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "long", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "ulong", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u.un")); - conversions(sourceType: "nint", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); + conversions(sourceType: "nint", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "nuint", destType: "nuint", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "float", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "double", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); @@ -8160,7 +8198,16 @@ .maxstack 1 conversions(sourceType: "uint?", destType: "nuint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "uint")); conversions(sourceType: "long?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "long"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "long")); conversions(sourceType: "ulong?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "ulong"), expectedCheckedIL: convFromNullableT("conv.ovf.u.un", "ulong")); - conversions(sourceType: "nint?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); + conversions(sourceType: "nint?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 8 (0x8) + .maxstack 1 + IL_0000: ldarga.s V_0 + IL_0002: call ""nint nint?.Value.get"" + IL_0007: ret +}", + expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); conversions(sourceType: "nuint?", destType: "nuint", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) @@ -8235,7 +8282,17 @@ .maxstack 1 conversions(sourceType: "uint", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint")); conversions(sourceType: "long", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "ulong", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u.un", "nuint")); - conversions(sourceType: "nint", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); + conversions(sourceType: "nint", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: newobj ""nuint?..ctor(nuint)"" + IL_0006: ret +} +", + expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "nuint", destType: "nuint?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) @@ -8299,7 +8356,29 @@ .maxstack 1 conversions(sourceType: "uint?", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "uint", "nuint"), expectedExplicitIL: convFromToNullableT("conv.u", "uint", "nuint")); conversions(sourceType: "long?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "long", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "long", "nuint")); conversions(sourceType: "ulong?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "ulong", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u.un", "ulong", "nuint")); - conversions(sourceType: "nint?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "nint", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); + conversions(sourceType: "nint?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: +@" +{ + // Code size 34 (0x22) + .maxstack 1 + .locals init (nint? V_0, + nuint? V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call ""bool nint?.HasValue.get"" + IL_0009: brtrue.s IL_0015 + IL_000b: ldloca.s V_1 + IL_000d: initobj ""nuint?"" + IL_0013: ldloc.1 + IL_0014: ret + IL_0015: ldloca.s V_0 + IL_0017: call ""nint nint?.GetValueOrDefault()"" + IL_001c: newobj ""nuint?..ctor(nuint)"" + IL_0021: ret +} +", + expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); conversions(sourceType: "nuint?", destType: "nuint?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "float?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "float", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "float", "nuint")); conversions(sourceType: "double?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "double", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "double", "nuint")); @@ -13433,11 +13512,11 @@ public void Int64Conversions() { convert(fromType: "nint", toType: "ulong", "int.MinValue", "18446744071562067968", "conv.i8", "System.OverflowException", "conv.ovf.u8"); convert(fromType: "nint", toType: "ulong", "int.MaxValue", "2147483647", "conv.i8", "2147483647", "conv.ovf.u8"); - convert(fromType: "nint", toType: "nuint", "int.MinValue", IntPtr.Size == 4 ? "2147483648" : "18446744071562067968", "conv.u", "System.OverflowException", "conv.ovf.u"); - convert(fromType: "nint", toType: "nuint", "int.MaxValue", "2147483647", "conv.u", "2147483647", "conv.ovf.u"); + convert(fromType: "nint", toType: "nuint", "int.MinValue", IntPtr.Size == 4 ? "2147483648" : "18446744071562067968", null, "System.OverflowException", "conv.ovf.u"); + convert(fromType: "nint", toType: "nuint", "int.MaxValue", "2147483647", null, "2147483647", "conv.ovf.u"); convert(fromType: "nuint", toType: "long", "uint.MaxValue", "4294967295", "conv.u8", "4294967295", "conv.ovf.i8.un"); - convert(fromType: "nuint", toType: "nint", "uint.MaxValue", IntPtr.Size == 4 ? "-1" : "4294967295", "conv.i", IntPtr.Size == 4 ? "System.OverflowException" : "4294967295", "conv.ovf.i.un"); + convert(fromType: "nuint", toType: "nint", "uint.MaxValue", IntPtr.Size == 4 ? "-1" : "4294967295", null, IntPtr.Size == 4 ? "System.OverflowException" : "4294967295", "conv.ovf.i.un"); string nintMinValue = IntPtr.Size == 4 ? int.MinValue.ToString() : long.MinValue.ToString(); string nintMaxValue = IntPtr.Size == 4 ? int.MaxValue.ToString() : long.MaxValue.ToString(); @@ -13445,11 +13524,11 @@ public void Int64Conversions() convert(fromType: "nint", toType: "ulong", nintMinValue, IntPtr.Size == 4 ? "18446744071562067968" : "9223372036854775808", "conv.i8", "System.OverflowException", "conv.ovf.u8"); convert(fromType: "nint", toType: "ulong", nintMaxValue, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.i8", IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.ovf.u8"); - convert(fromType: "nint", toType: "nuint", nintMinValue, IntPtr.Size == 4 ? "2147483648" : "9223372036854775808", "conv.u", "System.OverflowException", "conv.ovf.u"); - convert(fromType: "nint", toType: "nuint", nintMaxValue, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.u", IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.ovf.u"); + convert(fromType: "nint", toType: "nuint", nintMinValue, IntPtr.Size == 4 ? "2147483648" : "9223372036854775808", null, "System.OverflowException", "conv.ovf.u"); + convert(fromType: "nint", toType: "nuint", nintMaxValue, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", null, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.ovf.u"); convert(fromType: "nuint", toType: "long", nuintMaxValue, IntPtr.Size == 4 ? "4294967295" : "-1", "conv.u8", IntPtr.Size == 4 ? "4294967295" : "System.OverflowException", "conv.ovf.i8.un"); - convert(fromType: "nuint", toType: "nint", nuintMaxValue, "-1", "conv.i", "System.OverflowException", "conv.ovf.i.un"); + convert(fromType: "nuint", toType: "nint", nuintMaxValue, "-1", null, "System.OverflowException", "conv.ovf.i.un"); void convert(string fromType, string toType, string fromValue, string toValueUnchecked, string toConvUnchecked, string toValueChecked, string toConvChecked) { @@ -13480,8 +13559,15 @@ static void Main() var verifier = CompileAndVerify(source, parseOptions: TestOptions.Regular9, expectedOutput: $@"{toValueUnchecked} {toValueChecked}"); - verifier.VerifyIL("Program.Convert", - $@"{{ + verifier.VerifyIL("Program.Convert", toConvUnchecked is null ? +@" +{ + // Code size 2 (0x2) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ret +}" : +$@"{{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 @@ -14494,6 +14580,13 @@ public void SignedToUnsignedConversions_Explicit() }"; var comp = CreateCompilation(source); var verifier = CompileAndVerify(source); + string expectedExplicitILNop = +@"{ + // Code size 2 (0x2) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ret +}"; string expectedExplicitILA = @"{ // Code size 3 (0x3) @@ -14522,7 +14615,7 @@ .maxstack 1 verifier.VerifyIL("NativeInts.Explicit2", expectedExplicitILA); verifier.VerifyIL("NativeInts.Explicit3", expectedExplicitILA); verifier.VerifyIL("NativeInts.Explicit4", expectedExplicitILB); - verifier.VerifyIL("NativeInts.Explicit5", expectedExplicitILB); + verifier.VerifyIL("NativeInts.Explicit5", expectedExplicitILNop); verifier.VerifyIL("NativeInts.Checked1", expectedCheckedIL); verifier.VerifyIL("NativeInts.Checked2", expectedCheckedIL); verifier.VerifyIL("NativeInts.Checked3", expectedCheckedIL); @@ -15534,5 +15627,31 @@ class C Diagnostic(ErrorCode.ERR_BadBinaryOps, $"x {op} count").WithArguments(op, type, "int").WithLocation(5, 16) ); } + + [Theory] + [CombinatorialData] + [WorkItem(60944, "https://github.com/dotnet/roslyn/issues/60944")] + public void NopConversions([CombinatorialValues("nint", "nuint")] string inputType, [CombinatorialValues("nint", "nuint")] string outputType) + { + var source = +@"class Program +{ + static " + outputType + @" F1(" + inputType + @" x) + { + return unchecked((" + outputType + @")x); + } +}"; + var comp = CreateCompilation(source); + var verifier = CompileAndVerify(comp).VerifyDiagnostics(); + verifier.VerifyIL("Program.F1", +@" +{ + // Code size 2 (0x2) + .maxstack 1 + IL_0000: ldarg.0 + IL_0001: ret +} +"); + } } } diff --git a/src/Compilers/Core/Portable/CodeGen/ILBuilderConversions.cs b/src/Compilers/Core/Portable/CodeGen/ILBuilderConversions.cs index f3f42b1d9a983..53e9a6aae240b 100644 --- a/src/Compilers/Core/Portable/CodeGen/ILBuilderConversions.cs +++ b/src/Compilers/Core/Portable/CodeGen/ILBuilderConversions.cs @@ -128,6 +128,7 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.IntPtr: + case Microsoft.Cci.PrimitiveTypeCode.UIntPtr when !@checked: break; // NOP case Microsoft.Cci.PrimitiveTypeCode.Int8: case Microsoft.Cci.PrimitiveTypeCode.Int16: @@ -166,6 +167,7 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.UIntPtr: + case Microsoft.Cci.PrimitiveTypeCode.IntPtr when !@checked: case Microsoft.Cci.PrimitiveTypeCode.Pointer: case Microsoft.Cci.PrimitiveTypeCode.FunctionPointer: break; // NOP From b6cc719fd00040e5d4190677ac68448a8e58c380 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Wed, 20 Jul 2022 19:34:47 +0200 Subject: [PATCH 61/66] Delete obsolete internal options (#62746) --- .../Completion/CSharpCompletionOptions.cs | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 src/Features/CSharp/Portable/Completion/CSharpCompletionOptions.cs diff --git a/src/Features/CSharp/Portable/Completion/CSharpCompletionOptions.cs b/src/Features/CSharp/Portable/Completion/CSharpCompletionOptions.cs deleted file mode 100644 index e05db432b493a..0000000000000 --- a/src/Features/CSharp/Portable/Completion/CSharpCompletionOptions.cs +++ /dev/null @@ -1,18 +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; -using Microsoft.CodeAnalysis.Options; - -namespace Microsoft.CodeAnalysis.CSharp.Completion -{ - internal static class CSharpCompletionOptions - { - [Obsolete("This option is superceded by CompletionOptions.Metadata.EnterKeyBehavior")] - public static readonly Option2 AddNewLineOnEnterAfterFullyTypedWord = new Option2(nameof(CSharpCompletionOptions), nameof(AddNewLineOnEnterAfterFullyTypedWord), defaultValue: false); - - [Obsolete("This option is superceded by CompletionOptions.Metadata.SnippetsBehavior")] - public static readonly Option2 IncludeSnippets = new Option2(nameof(CSharpCompletionOptions), nameof(IncludeSnippets), defaultValue: true); - } -} From a6a37f6bb823a039278328f6c7143995cb622251 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Wed, 20 Jul 2022 19:35:02 +0200 Subject: [PATCH 62/66] Fix NRE in nullable walker (#62773) * Fix NRE in nullable walker * Update NullableWalker.cs * Apply suggestions from code review --- .../Portable/FlowAnalysis/NullableWalker.cs | 4 +- .../Test/Semantic/Semantics/LambdaTests.cs | 37 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index e3489598e428c..0d539ff4a3380 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -7875,12 +7875,13 @@ void reportBadDelegateParameter(BindingDiagnosticBag bag, MethodSymbol sourceInv _ => (null, ImmutableArray.Empty), }; +#nullable enable case ConversionKind.AnonymousFunction: if (conversionOperand is BoundLambda lambda) { var delegateType = targetType.GetDelegateType(); VisitLambda(lambda, delegateType, stateForLambda); - if (reportRemainingWarnings) + if (reportRemainingWarnings && delegateType is not null) { ReportNullabilityMismatchWithTargetDelegate(diagnosticLocationOpt, delegateType, lambda); } @@ -7890,6 +7891,7 @@ void reportBadDelegateParameter(BindingDiagnosticBag bag, MethodSymbol sourceInv return TypeWithState.Create(targetType, NullableFlowState.NotNull); } break; +#nullable disable case ConversionKind.FunctionType: resultState = NullableFlowState.NotNull; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs index 3d2966a9aacc0..df26acaf747ee 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs @@ -6782,5 +6782,42 @@ static void Main() Assert.Equal(RefKind.In, lambdas[1].Parameters[0].RefKind); Assert.Equal(RefKind.Out, lambdas[2].Parameters[0].RefKind); } + + [WorkItem(61013, "https://github.com/dotnet/roslyn/issues/61013")] + [Fact] + public void InvalidCast() + { + var source = """ + using System; + #nullable enable + internal class Program + { + void Main(string[] args) + { + Choice(args.Length > 0 + ? (Action)(() => DS1() + : () => DS2(args[0])); + } + + void DS1() + { } + + void DS2(string a) + { } + + void Choice(Action a) + { + a(); + } + } + """; + + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); + + var syntaxTree = comp.SyntaxTrees[0]; + var action = syntaxTree.GetRoot().DescendantNodes().OfType().First(id => id.Identifier.ValueText == "Action"); + var model = comp.GetSemanticModel(syntaxTree); + AssertEx.Equal("System.Action", model.GetTypeInfo(action).Type.ToTestDisplayString()); + } } } From 9b223129683564f96003f994c9a552f51e7dae32 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Wed, 20 Jul 2022 19:42:12 +0200 Subject: [PATCH 63/66] Remove unused parameter (#62685) --- src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxTests.cs index e1c947a75c290..b7a7bafc05a6f 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxTests.cs @@ -18,7 +18,7 @@ private static void AssertIncompleteSubmission(string code) Assert.False(SyntaxFactory.IsCompleteSubmission(SyntaxFactory.ParseSyntaxTree(code, options: TestOptions.Script))); } - private static void AssertCompleteSubmission(string code, bool isComplete = true) + private static void AssertCompleteSubmission(string code) { Assert.True(SyntaxFactory.IsCompleteSubmission(SyntaxFactory.ParseSyntaxTree(code, options: TestOptions.Script))); } From 1c480b07dbd55e2dce5580fc6a3e5b468d53c64d Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 21 Jul 2022 03:49:00 +1000 Subject: [PATCH 64/66] Find the right symbol when following type forwards (#62406) --- ...mplementationAssemblyLookupServiceTests.cs | 150 ++++++++++++++++-- .../PdbSourceDocumentTests.cs | 65 +++++++- .../ImplementationAssemblyLookupService.cs | 9 +- ...rceDocumentMetadataAsSourceFileProvider.cs | 4 +- 4 files changed, 206 insertions(+), 22 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/PdbSourceDocument/ImplementationAssemblyLookupServiceTests.cs b/src/EditorFeatures/CSharpTest/PdbSourceDocument/ImplementationAssemblyLookupServiceTests.cs index 80bd80ba40c7f..52e8f4a35a791 100644 --- a/src/EditorFeatures/CSharpTest/PdbSourceDocument/ImplementationAssemblyLookupServiceTests.cs +++ b/src/EditorFeatures/CSharpTest/PdbSourceDocument/ImplementationAssemblyLookupServiceTests.cs @@ -188,6 +188,126 @@ public class C }); } + [Fact] + public async Task FollowTypeForwards_Namespace() + { + var source = @" +namespace A +{ + namespace B + { + public class C + { + public class D + { + // A change + public event System.EventHandler [|E|] { add { } remove { } } + } + } + } +}"; + var typeForwardSource = @" +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(A.B.C))] +"; + + await RunTestAsync(async path => + { + MarkupTestFile.GetSpan(source, out var metadataSource, out var expectedSpan); + + // Compile reference assembly + var sourceText = SourceText.From(metadataSource, encoding: Encoding.UTF8); + var (project, symbol) = await CompileAndFindSymbolAsync(path, Location.Embedded, Location.Embedded, sourceText, c => c.GetMember("A.B.C.D.E"), buildReferenceAssembly: true); + + // Compile implementation assembly to a different DLL + var dllFilePath = Path.Combine(path, "implementation.dll"); + var sourceCodePath = Path.Combine(path, "implementation.cs"); + var pdbFilePath = Path.Combine(path, "implementation.pdb"); + var assemblyName = "implementation"; + + var workspace = TestWorkspace.Create(@$" + + + +", composition: GetTestComposition()); + + var implProject = workspace.CurrentSolution.Projects.First(); + CompileTestSource(dllFilePath, sourceCodePath, pdbFilePath, assemblyName, sourceText, implProject, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); + + // Compile type forwarding implementation DLL + var typeForwardDllFilePath = Path.Combine(path, "typeforward.dll"); + assemblyName = "typeforward"; + + implProject = implProject.AddMetadataReference(MetadataReference.CreateFromFile(dllFilePath)); + sourceText = SourceText.From(typeForwardSource, Encoding.UTF8); + CompileTestSource(typeForwardDllFilePath, sourceCodePath, pdbFilePath, assemblyName, sourceText, implProject, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); + + var service = workspace.GetService(); + + var foundImplementationFilePath = service.FollowTypeForwards(symbol, typeForwardDllFilePath, new NoDuplicatesLogger()); + Assert.Equal(dllFilePath, foundImplementationFilePath); + }); + } + + [Fact] + public async Task FollowTypeForwards_Generics() + { + var source = @" +namespace A +{ + namespace B + { + public class C + { + public class D + { + // A change + public event System.EventHandler [|E|] { add { } remove { } } + } + } + } +}"; + var typeForwardSource = @" +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(A.B.C<>))] +"; + + await RunTestAsync(async path => + { + MarkupTestFile.GetSpan(source, out var metadataSource, out var expectedSpan); + + // Compile reference assembly + var sourceText = SourceText.From(metadataSource, encoding: Encoding.UTF8); + var (project, symbol) = await CompileAndFindSymbolAsync(path, Location.Embedded, Location.Embedded, sourceText, c => c.GetMember("A.B.C.D.E"), buildReferenceAssembly: true); + + // Compile implementation assembly to a different DLL + var dllFilePath = Path.Combine(path, "implementation.dll"); + var sourceCodePath = Path.Combine(path, "implementation.cs"); + var pdbFilePath = Path.Combine(path, "implementation.pdb"); + var assemblyName = "implementation"; + + var workspace = TestWorkspace.Create(@$" + + + +", composition: GetTestComposition()); + + var implProject = workspace.CurrentSolution.Projects.First(); + CompileTestSource(dllFilePath, sourceCodePath, pdbFilePath, assemblyName, sourceText, implProject, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); + + // Compile type forwarding implementation DLL + var typeForwardDllFilePath = Path.Combine(path, "typeforward.dll"); + assemblyName = "typeforward"; + + implProject = implProject.AddMetadataReference(MetadataReference.CreateFromFile(dllFilePath)); + sourceText = SourceText.From(typeForwardSource, Encoding.UTF8); + CompileTestSource(typeForwardDllFilePath, sourceCodePath, pdbFilePath, assemblyName, sourceText, implProject, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); + + var service = workspace.GetService(); + + var foundImplementationFilePath = service.FollowTypeForwards(symbol, typeForwardDllFilePath, new NoDuplicatesLogger()); + Assert.Equal(dllFilePath, foundImplementationFilePath); + }); + } + [Fact] public async Task FollowTypeForwards_NestedType() { @@ -402,28 +522,36 @@ public class C var typeForwardDllFilePath = Path.Combine(path, "typeforward.dll"); assemblyName = "typeforward"; - implProject = implProject.AddMetadataReference(MetadataReference.CreateFromFile(dllFilePath)); - sourceText = SourceText.From(typeForwardSource, Encoding.UTF8); - CompileTestSource(typeForwardDllFilePath, sourceCodePath, pdbFilePath, assemblyName, sourceText, implProject, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); + implProject = workspace.CurrentSolution.Projects.First().AddMetadataReference(MetadataReference.CreateFromFile(dllFilePath)); + var typeForwardSourceText = SourceText.From(typeForwardSource, Encoding.UTF8); + CompileTestSource(typeForwardDllFilePath, sourceCodePath, pdbFilePath, assemblyName, typeForwardSourceText, implProject, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); - var typeForward2DllFilePath = Path.Combine(path, "typeforward2.dll"); - assemblyName = "typeforward2"; + // Now compile a new implementation in realimplementation.dll + var realImplementationDllFilePath = Path.Combine(path, "realimplementation.dll"); + assemblyName = "realimplementation"; - implProject = implProject.AddMetadataReference(MetadataReference.CreateFromFile(typeForwardDllFilePath)); - sourceText = SourceText.From(typeForwardSource, Encoding.UTF8); - CompileTestSource(typeForward2DllFilePath, sourceCodePath, pdbFilePath, assemblyName, sourceText, implProject, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); + implProject = workspace.CurrentSolution.Projects.First(); + CompileTestSource(realImplementationDllFilePath, sourceCodePath, pdbFilePath, assemblyName, sourceText, implProject, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); + + // Now compile a new implementation.dll that typeforwards to realimplementation.dll + assemblyName = "implementation"; + + implProject = workspace.CurrentSolution.Projects.First().AddMetadataReference(MetadataReference.CreateFromFile(realImplementationDllFilePath)); + CompileTestSource(dllFilePath, sourceCodePath, pdbFilePath, assemblyName, typeForwardSourceText, implProject, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); var service = workspace.GetService(); - Assert.Equal(dllFilePath, service.FollowTypeForwards(symbol, typeForward2DllFilePath, new NoDuplicatesLogger())); + var foundImplementationFilePath = service.FollowTypeForwards(symbol, typeForwardDllFilePath, new NoDuplicatesLogger()); + Assert.Equal(realImplementationDllFilePath, foundImplementationFilePath); // We need the DLLs to exist, in order for some checks to pass correct, but to ensure // that the file isn't read, we just zero it out. File.WriteAllBytes(typeForwardDllFilePath, Array.Empty()); - File.WriteAllBytes(typeForward2DllFilePath, Array.Empty()); + File.WriteAllBytes(realImplementationDllFilePath, Array.Empty()); File.WriteAllBytes(dllFilePath, Array.Empty()); - Assert.Equal(dllFilePath, service.FollowTypeForwards(symbol, typeForward2DllFilePath, new NoDuplicatesLogger())); + foundImplementationFilePath = service.FollowTypeForwards(symbol, typeForwardDllFilePath, new NoDuplicatesLogger()); + Assert.Equal(realImplementationDllFilePath, foundImplementationFilePath); }); } diff --git a/src/EditorFeatures/CSharpTest/PdbSourceDocument/PdbSourceDocumentTests.cs b/src/EditorFeatures/CSharpTest/PdbSourceDocument/PdbSourceDocumentTests.cs index 59fc5c3a401ca..51c4f0a787903 100644 --- a/src/EditorFeatures/CSharpTest/PdbSourceDocument/PdbSourceDocumentTests.cs +++ b/src/EditorFeatures/CSharpTest/PdbSourceDocument/PdbSourceDocumentTests.cs @@ -457,6 +457,50 @@ public class C { } } +"; + + await RunTestAsync(async path => + { + MarkupTestFile.GetSpan(source, out var metadataSource, out var expectedSpan); + + var packDir = Directory.CreateDirectory(Path.Combine(path, "packs", "MyPack.Ref", "1.0", "ref", "net6.0")).FullName; + var dataDir = Directory.CreateDirectory(Path.Combine(path, "packs", "MyPack.Ref", "1.0", "data")).FullName; + var sharedDir = Directory.CreateDirectory(Path.Combine(path, "shared", "MyPack", "1.0")).FullName; + + var sourceText = SourceText.From(metadataSource, Encoding.UTF8); + var (project, symbol) = await CompileAndFindSymbolAsync(packDir, Location.Embedded, Location.Embedded, sourceText, c => c.GetMember("C.M"), buildReferenceAssembly: true); + + var workspace = TestWorkspace.Create(@$" + + + +", composition: GetTestComposition()); + + var implProject = workspace.CurrentSolution.Projects.First(); + + // Compile implementation assembly + CompileTestSource(sharedDir, sourceText, project, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); + + // Create FrameworkList.xml + File.WriteAllText(Path.Combine(dataDir, "FrameworkList.xml"), """ + + + """); + + await GenerateFileAndVerifyAsync(project, symbol, Location.Embedded, metadataSource.ToString(), expectedSpan, expectNullResult: false); + }); + } + + [Fact] + public async Task Net6SdkLayout_TypeForward() + { + var source = @" +public class [|C|] +{ + public void M(string d) + { + } +} "; var typeForwardSource = @" [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(C))] @@ -471,7 +515,7 @@ public class C var sharedDir = Directory.CreateDirectory(Path.Combine(path, "shared", "MyPack", "1.0")).FullName; var sourceText = SourceText.From(metadataSource, Encoding.UTF8); - var (project, symbol) = await CompileAndFindSymbolAsync(packDir, Location.Embedded, Location.Embedded, sourceText, c => c.GetMember("C.M"), buildReferenceAssembly: true); + var (project, symbol) = await CompileAndFindSymbolAsync(packDir, Location.Embedded, Location.Embedded, sourceText, c => c.GetMember("C"), buildReferenceAssembly: true); var workspace = TestWorkspace.Create(@$" @@ -482,15 +526,20 @@ public class C var implProject = workspace.CurrentSolution.Projects.First(); // Compile implementation assembly - CompileTestSource(sharedDir, sourceText, project, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); + var implementationDllFilePath = Path.Combine(sharedDir, "implementation.dll"); + var sourceCodePath = Path.Combine(sharedDir, "implementation.cs"); + var pdbFilePath = Path.Combine(sharedDir, "implementation.pdb"); + var assemblyName = "implementation"; + + CompileTestSource(implementationDllFilePath, sourceCodePath, pdbFilePath, assemblyName, sourceText, project, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); - // Compile type forwarding implementation DLL - var typeForwardDllFilePath = Path.Combine(sharedDir, "typeforward.dll"); - var sourceCodePath = Path.Combine(sharedDir, "typeforward.cs"); - var pdbFilePath = Path.Combine(sharedDir, "typeforward.pdb"); - var assemblyName = "typeforward"; + // Compile type forwarding implementation DLL, that looks like reference.dll + var typeForwardDllFilePath = Path.Combine(sharedDir, "reference.dll"); + sourceCodePath = Path.Combine(sharedDir, "reference.cs"); + pdbFilePath = Path.Combine(sharedDir, "reference.pdb"); + assemblyName = "reference"; - implProject = implProject.AddMetadataReference(MetadataReference.CreateFromFile(GetDllPath(sharedDir))); + implProject = implProject.AddMetadataReference(MetadataReference.CreateFromFile(implementationDllFilePath)); sourceText = SourceText.From(typeForwardSource, Encoding.UTF8); CompileTestSource(typeForwardDllFilePath, sourceCodePath, pdbFilePath, assemblyName, sourceText, implProject, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); diff --git a/src/Features/Core/Portable/PdbSourceDocument/ImplementationAssemblyLookupService.cs b/src/Features/Core/Portable/PdbSourceDocument/ImplementationAssemblyLookupService.cs index e06c69826cd20..f6fa8cbf50d7d 100644 --- a/src/Features/Core/Portable/PdbSourceDocument/ImplementationAssemblyLookupService.cs +++ b/src/Features/Core/Portable/PdbSourceDocument/ImplementationAssemblyLookupService.cs @@ -20,6 +20,12 @@ namespace Microsoft.CodeAnalysis.PdbSourceDocument [Export(typeof(IImplementationAssemblyLookupService)), Shared] internal class ImplementationAssemblyLookupService : IImplementationAssemblyLookupService { + // We need to generate the namespace name in the same format that is used in metadata, which + // is SymbolDisplayFormat.QualifiedNameOnlyFormat, which this is a copy of. + private static readonly SymbolDisplayFormat s_metadataSymbolDisplayFormat = new SymbolDisplayFormat( + globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, + typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces); + private static readonly string PathSeparatorString = Path.DirectorySeparatorChar.ToString(); // Cache for any type forwards. Key is the dll being inspected. Value is a dictionary @@ -56,6 +62,7 @@ public bool TryFindImplementationAssemblyPath(string referencedDllPath, [NotNull // Only the top most containing type in the ExportedType table actually points to an assembly // so no point looking for nested types. var typeSymbol = MetadataAsSourceHelpers.GetTopLevelContainingNamedType(symbol); + var namespaceName = typeSymbol.ContainingNamespace.ToDisplayString(s_metadataSymbolDisplayFormat); try { @@ -66,7 +73,7 @@ public bool TryFindImplementationAssemblyPath(string referencedDllPath, [NotNull { // If there are no type forwards in this DLL, or not one for this type, then it means // we've found the right DLL - if (typeForwards?.TryGetValue((typeSymbol.ContainingNamespace.MetadataName, typeSymbol.MetadataName), out var assemblyName) != true) + if (typeForwards?.TryGetValue((namespaceName, typeSymbol.MetadataName), out var assemblyName) != true) { return dllPath; } diff --git a/src/Features/Core/Portable/PdbSourceDocument/PdbSourceDocumentMetadataAsSourceFileProvider.cs b/src/Features/Core/Portable/PdbSourceDocument/PdbSourceDocumentMetadataAsSourceFileProvider.cs index f9d75c28ed977..fa410592ec2a7 100644 --- a/src/Features/Core/Portable/PdbSourceDocument/PdbSourceDocumentMetadataAsSourceFileProvider.cs +++ b/src/Features/Core/Portable/PdbSourceDocument/PdbSourceDocumentMetadataAsSourceFileProvider.cs @@ -117,11 +117,11 @@ internal sealed class PdbSourceDocumentMetadataAsSourceFileProvider : IMetadataA var tmpCompilation = compilationFactory .CreateCompilation("tmp", compilationFactory.GetDefaultCompilationOptions()) - .AddReferences(project.MetadataReferences) .AddReferences(dllReference); var key = SymbolKey.Create(symbolToFind, cancellationToken); - var newSymbol = key.Resolve(tmpCompilation, ignoreAssemblyKey: true, cancellationToken).Symbol; + var resolution = key.Resolve(tmpCompilation, ignoreAssemblyKey: true, cancellationToken); + var newSymbol = resolution.Symbol; if (newSymbol is null) { _logger?.Log(FeaturesResources.Could_not_find_implementation_of_symbol_0, symbolToFind.MetadataName); From eb03fbbfffc5724edc44a540959420a37b823770 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 20 Jul 2022 12:13:23 -0700 Subject: [PATCH 65/66] Fix --- .../AbstractTypeParameterSymbolReferenceFinder.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractTypeParameterSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractTypeParameterSymbolReferenceFinder.cs index 4345d7b1653ed..120eeed538f26 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractTypeParameterSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractTypeParameterSymbolReferenceFinder.cs @@ -30,13 +30,13 @@ internal abstract class AbstractTypeParameterSymbolReferenceFinder : AbstractRef var tokens = await FindMatchingIdentifierTokensAsync(state, symbol.Name, cancellationToken).ConfigureAwait(false); - var normalTokens = tokens.WhereAsArray(static (token, state) => !IsObjectCreationToken(token, state), state); - var objectCreationTokens = tokens.WhereAsArray(static (token, state) => IsObjectCreationToken(token, state), state); - var normalReferences = await FindReferencesInTokensAsync( - symbol, state, objectCreationTokens, cancellationToken).ConfigureAwait(false); + symbol, state, + tokens.WhereAsArray(static (token, state) => !IsObjectCreationToken(token, state), state), + cancellationToken).ConfigureAwait(false); - var objectCreationReferences = GetObjectCreationReferences(objectCreationTokens); + var objectCreationReferences = GetObjectCreationReferences( + tokens.WhereAsArray(static (token, state) => IsObjectCreationToken(token, state), state)); return normalReferences.Concat(objectCreationReferences); From a3c05aba816d60ef300819268417860c8e21300e Mon Sep 17 00:00:00 2001 From: dotnet bot Date: Wed, 20 Jul 2022 15:09:46 -0700 Subject: [PATCH 66/66] Merge release/dev17.3 to main (#62573) --- .../CSharp/Portable/CSharpResources.resx | 6 + .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../CSharp/Portable/Errors/ErrorFacts.cs | 2 + .../CSharp/Portable/Errors/MessageProvider.cs | 1 + .../Generated/ErrorFacts.Generated.cs | 1 + .../Portable/xlf/CSharpResources.cs.xlf | 290 +++++++++--------- .../Portable/xlf/CSharpResources.de.xlf | 10 + .../Portable/xlf/CSharpResources.es.xlf | 10 + .../Portable/xlf/CSharpResources.fr.xlf | 10 + .../Portable/xlf/CSharpResources.it.xlf | 10 + .../Portable/xlf/CSharpResources.ja.xlf | 10 + .../Portable/xlf/CSharpResources.ko.xlf | 10 + .../Portable/xlf/CSharpResources.pl.xlf | 10 + .../Portable/xlf/CSharpResources.pt-BR.xlf | 10 + .../Portable/xlf/CSharpResources.ru.xlf | 10 + .../Portable/xlf/CSharpResources.tr.xlf | 10 + .../Portable/xlf/CSharpResources.zh-Hans.xlf | 10 + .../Portable/xlf/CSharpResources.zh-Hant.xlf | 10 + .../Test/Syntax/Diagnostics/DiagnosticTest.cs | 1 + .../Analyzers/AnalyzerFileReferenceTests.cs | 79 +++++ .../CommandLine/CommandLineArguments.cs | 3 + .../Diagnostic/CommonMessageProvider.cs | 1 + .../AnalyzerFileReference.cs | 23 +- .../AnalyzerLoadFailureEventArgs.cs | 10 +- .../Core/Portable/PublicAPI.Unshipped.txt | 2 + .../Test/Core/AssemblyLoadTestFixture.cs | 74 ++++- .../Test/Core/Mocks/TestMessageProvider.cs | 2 + .../VisualBasic/Portable/Errors/ErrorFacts.vb | 3 +- .../VisualBasic/Portable/Errors/Errors.vb | 2 + .../Portable/Errors/MessageProvider.vb | 6 + .../Generated/ErrorFacts.Generated.vb | 3 +- .../VisualBasic/Portable/VBResources.resx | 6 + .../Portable/xlf/VBResources.cs.xlf | 10 + .../Portable/xlf/VBResources.de.xlf | 10 + .../Portable/xlf/VBResources.es.xlf | 10 + .../Portable/xlf/VBResources.fr.xlf | 10 + .../Portable/xlf/VBResources.it.xlf | 10 + .../Portable/xlf/VBResources.ja.xlf | 10 + .../Portable/xlf/VBResources.ko.xlf | 10 + .../Portable/xlf/VBResources.pl.xlf | 10 + .../Portable/xlf/VBResources.pt-BR.xlf | 10 + .../Portable/xlf/VBResources.ru.xlf | 10 + .../Portable/xlf/VBResources.tr.xlf | 10 + .../Portable/xlf/VBResources.zh-Hans.xlf | 10 + .../Portable/xlf/VBResources.zh-Hant.xlf | 10 + .../Diagnostics/AnalyzerLoadFailureTests.cs | 1 + .../xlf/CSharpFeaturesResources.ru.xlf | 2 +- .../Core/Portable/FeaturesResources.resx | 3 + .../Portable/xlf/FeaturesResources.cs.xlf | 5 + .../Portable/xlf/FeaturesResources.de.xlf | 5 + .../Portable/xlf/FeaturesResources.es.xlf | 5 + .../Portable/xlf/FeaturesResources.fr.xlf | 5 + .../Portable/xlf/FeaturesResources.it.xlf | 5 + .../Portable/xlf/FeaturesResources.ja.xlf | 5 + .../Portable/xlf/FeaturesResources.ko.xlf | 5 + .../Portable/xlf/FeaturesResources.pl.xlf | 5 + .../Portable/xlf/FeaturesResources.pt-BR.xlf | 5 + .../Portable/xlf/FeaturesResources.ru.xlf | 5 + .../Portable/xlf/FeaturesResources.tr.xlf | 5 + .../xlf/FeaturesResources.zh-Hans.xlf | 5 + .../xlf/FeaturesResources.zh-Hant.xlf | 5 + .../DocumentAnalysisExecutor_Helpers.cs | 8 + .../Portable/xlf/VBFeaturesResources.ru.xlf | 2 +- .../Core/Def/xlf/ServicesVSResources.cs.xlf | 2 +- .../Core/Def/xlf/ServicesVSResources.fr.xlf | 2 +- .../Core/Def/xlf/ServicesVSResources.it.xlf | 2 +- .../Core/Def/xlf/ServicesVSResources.ko.xlf | 2 +- .../Core/Def/xlf/ServicesVSResources.pl.xlf | 2 +- .../Def/xlf/ServicesVSResources.pt-BR.xlf | 2 +- .../Core/Def/xlf/ServicesVSResources.tr.xlf | 2 +- .../Def/xlf/ServicesVSResources.zh-Hans.xlf | 2 +- 71 files changed, 702 insertions(+), 161 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 46f41d0e6cb39..18c2985c379d8 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6637,6 +6637,12 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The loaded assembly references .NET Framework, which is not supported. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The type '{0}' may not be used for a field of a record. diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 67a5a96e306e3..361dac4b52014 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2105,6 +2105,7 @@ internal enum ErrorCode ERR_FileTypeNested = 9054, ERR_GlobalUsingStaticFileType = 9055, ERR_FileTypeNameDisallowed = 9056, + WRN_AnalyzerReferencesNewerCompiler = 9057, ERR_FeatureNotAvailableInVersion11 = 9058, ERR_RefFieldInNonRefStruct = 9059, diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 9b49a406e2f91..087b043224ac4 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -500,6 +500,7 @@ internal static int GetWarningLevel(ErrorCode code) case ErrorCode.WRN_UnassignedThisAutoPropertySupportedVersion: case ErrorCode.WRN_UnassignedThisSupportedVersion: case ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired: + case ErrorCode.WRN_AnalyzerReferencesNewerCompiler: return 1; default: return 0; @@ -2206,6 +2207,7 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_FileTypeNameDisallowed: case ErrorCode.ERR_FeatureNotAvailableInVersion11: case ErrorCode.ERR_RefFieldInNonRefStruct: + case ErrorCode.WRN_AnalyzerReferencesNewerCompiler: return false; default: // NOTE: All error codes must be explicitly handled in this switch statement diff --git a/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs b/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs index ce1e63afcb4c0..5d387d84cc7e1 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs @@ -178,6 +178,7 @@ internal override bool ShouldAssertExpectedMessageArgumentsLength(int errorCode) public override int WRN_NoAnalyzerInAssembly => (int)ErrorCode.WRN_NoAnalyzerInAssembly; public override int WRN_UnableToLoadAnalyzer => (int)ErrorCode.WRN_UnableToLoadAnalyzer; public override int WRN_AnalyzerReferencesFramework => (int)ErrorCode.WRN_AnalyzerReferencesFramework; + public override int WRN_AnalyzerReferencesNewerCompiler => (int)ErrorCode.WRN_AnalyzerReferencesNewerCompiler; public override int INF_UnableToLoadSomeTypesInAnalyzer => (int)ErrorCode.INF_UnableToLoadSomeTypesInAnalyzer; public override int ERR_CantReadRulesetFile => (int)ErrorCode.ERR_CantReadRulesetFile; public override int ERR_CompileCancelled => (int)ErrorCode.ERR_CompileCancelled; diff --git a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs index f1c7d74365494..bfeeddf2c9fb3 100644 --- a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs @@ -288,6 +288,7 @@ public static bool IsWarning(ErrorCode code) case ErrorCode.WRN_UnassignedThisAutoPropertySupportedVersion: case ErrorCode.WRN_UnassignedThisSupportedVersion: case ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired: + case ErrorCode.WRN_AnalyzerReferencesNewerCompiler: return true; default: return false; diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 3183f5796bc1a..9a06122e5fad1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -1777,6 +1777,16 @@ Načtené sestavení se odkazuje na architekturu .NET Framework, což se nepodporuje + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. Typ {0} nelze v tomto kontextu použít, protože se nedá reprezentovat v metadatech. @@ -2230,160 +2240,160 @@ specified directory. - Parametry kompilátoru Visual C# + Parametry kompilátoru Visual C# - - VÝSTUPNÍ SOUBORY - --out:<file> Určuje název výstupního souboru (výchozí: základní název - souboru s hlavní třídou nebo prvního souboru) --target:exe Vytvoří spustitelný soubor konzoly (výchozí). (Krátký - formát: -t:exe) --target:winexe Vytvoří spustitelný soubor systému Windows. (Krátký formát: - -t:winexe) --target:library Vytvoří knihovnu. (Krátký formát: -t:library) --target:module Vytvoří modul, který se dá přidat do jiného - sestavení. (Krátký formát: -t:module) --target:appcontainerexe Sestaví spustitelný soubor kontejneru Appcontainer. (Krátký formát: - -t:appcontainerexe) --target:winmdobj Sestaví pomocný soubor modulu Windows Runtime, který - využívá knihovna WinMDExp. (Krátký formát: -t:winmdobj) --doc:<file> Soubor dokumentace XML, který má být vygenerován --refout:<file> Výstup referenčního sestavení, který má být vygenerován --platform:<string> Omezuje platformy, na kterých lze tento kód spustit: x86, - Itanium, x64, arm, arm64, anycpu32bitpreferred nebo - anycpu. Výchozí nastavení je anycpu. + - VÝSTUPNÍ SOUBORY - +-out:<file> Určuje název výstupního souboru (výchozí: základní název + souboru s hlavní třídou nebo prvního souboru) +-target:exe Vytvoří spustitelný soubor konzoly (výchozí). (Krátký + formát: -t:exe) +-target:winexe Vytvoří spustitelný soubor systému Windows. (Krátký formát: + -t:winexe) +-target:library Vytvoří knihovnu. (Krátký formát: -t:library) +-target:module Vytvoří modul, který se dá přidat do jiného + sestavení. (Krátký formát: -t:module) +-target:appcontainerexe Sestaví spustitelný soubor kontejneru Appcontainer. (Krátký formát: + -t:appcontainerexe) +-target:winmdobj Sestaví pomocný soubor modulu Windows Runtime, který + využívá knihovna WinMDExp. (Krátký formát: -t:winmdobj) +-doc:<file> Soubor dokumentace XML, který má být vygenerován +-refout:<file> Výstup referenčního sestavení, který má být vygenerován +-platform:<string> Omezuje platformy, na kterých lze tento kód spustit: x86, + Itanium, x64, arm, arm64, anycpu32bitpreferred nebo + anycpu. Výchozí nastavení je anycpu. - - VSTUPNÍ SOUBORY - --recurse:<wildcard> Zahrne všechny soubory v aktuálním adresáři - a jeho podadresářích podle zadaného - zástupného znaku. --reference:<alias>=<file> Odkazuje na metadata ze zadaného souboru sestavení - pomocí daného aliasu. (Krátký formát: -r) --reference:<file list> Odkazuje na metadata ze zadaných souborů - sestavení (Krátký formát: -r) --addmodule:<file list> Připojí zadané moduly k tomuto sestavení. --link:<file list> Vloží metadata ze zadaných souborů - sestavení spolupráce (Krátký formát: -l) --analyzer:<file list> Spustí analyzátory z tohoto sestavení. - (Krátký formát: -a) --additionalfile:<file list> Další soubory, které přímo neovlivňují generování - kódu, ale analyzátory můžou jejich pomocí - produkovat chyby nebo upozornění. --embed Vloží všechny zdrojové soubory do PDB. --embed:<file list> Vloží konkrétní soubory do PDB. + - VSTUPNÍ SOUBORY - +-recurse:<wildcard> Zahrne všechny soubory v aktuálním adresáři + a jeho podadresářích podle zadaného + zástupného znaku. +-reference:<alias>=<file> Odkazuje na metadata ze zadaného souboru sestavení + pomocí daného aliasu. (Krátký formát: -r) +-reference:<file list> Odkazuje na metadata ze zadaných souborů + sestavení (Krátký formát: -r) +-addmodule:<file list> Připojí zadané moduly k tomuto sestavení. +-link:<file list> Vloží metadata ze zadaných souborů + sestavení spolupráce (Krátký formát: -l) +-analyzer:<file list> Spustí analyzátory z tohoto sestavení. + (Krátký formát: -a) +-additionalfile:<file list> Další soubory, které přímo neovlivňují generování + kódu, ale analyzátory můžou jejich pomocí + produkovat chyby nebo upozornění. +-embed Vloží všechny zdrojové soubory do PDB. +-embed:<file list> Vloží konkrétní soubory do PDB. - - PROSTŘEDKY - --win32res:<file> Určuje soubor prostředků Win32 (.res). --win32icon:<file> Použije pro výstup zadanou ikonu. --win32manifest:<file> Určuje soubor manifestu Win32 (.xml). --nowin32manifest Nezahrne výchozí manifest Win32. --resource:<resinfo> Vloží zadaný prostředek. (Krátký formát: -res) --linkresource:<resinfo> Propojí zadaný prostředek s tímto sestavením. - (Krátký formát: -linkres) Prostředek má formát - is <file>[,<string name>[,public|private]]. + - PROSTŘEDKY - +-win32res:<file> Určuje soubor prostředků Win32 (.res). +-win32icon:<file> Použije pro výstup zadanou ikonu. +-win32manifest:<file> Určuje soubor manifestu Win32 (.xml). +-nowin32manifest Nezahrne výchozí manifest Win32. +-resource:<resinfo> Vloží zadaný prostředek. (Krátký formát: -res) +-linkresource:<resinfo> Propojí zadaný prostředek s tímto sestavením. + (Krátký formát: -linkres) Prostředek má formát + is <file>[,<string name>[,public|private]]. - - GENEROVÁNÍ KÓDU - --debug[+|-] Generuje ladicí informace. + - GENEROVÁNÍ KÓDU - +-debug[+|-] Generuje ladicí informace. -debug:{full|pdbonly|portable|embedded} - Určuje typ ladění (výchozí je možnost full, - portable je formát napříč platformami, - embedded je formát napříč platformami vložený do - cílového souboru .dll nebo .exe). --optimize[+|-] Povolí optimalizace. (Krátký formát: -o) --deterministic Vytvoří deterministické sestavení - (včetně GUID verze modulu a časového razítka). --refonly Vytvoří referenční sestavení na místě hlavního výstupu. --instrument:TestCoverage Vytvoří sestavení instrumentované ke shromažďování - informací o pokrytí. --sourcelink:<file> Informace o zdrojovém odkazu vkládané do souboru PDB.. + Určuje typ ladění (výchozí je možnost full, + portable je formát napříč platformami, + embedded je formát napříč platformami vložený do + cílového souboru .dll nebo .exe). +-optimize[+|-] Povolí optimalizace. (Krátký formát: -o) +-deterministic Vytvoří deterministické sestavení + (včetně GUID verze modulu a časového razítka). +-refonly Vytvoří referenční sestavení na místě hlavního výstupu. +-instrument:TestCoverage Vytvoří sestavení instrumentované ke shromažďování + informací o pokrytí. +-sourcelink:<file> Informace o zdrojovém odkazu vkládané do souboru PDB.. - - CHYBY A UPOZORNĚNÍ - --warnaserror[+|-] Hlásí všechna upozornění jako chyby. + - CHYBY A UPOZORNĚNÍ - +-warnaserror[+|-] Hlásí všechna upozornění jako chyby. -warnaserror[+|-]:<warn list> Hlásí zadaná upozornění jako chyby. - (Pro všechna upozornění na možnost použití hodnoty null použijte nullable.) --warn:<n> Nastaví úroveň pro upozornění (0 a více). (Krátký formát: -w) --nowarn:<warn list> Zakáže zadaná upozornění. - (Pro všechna upozornění na možnost použití hodnoty null použijte nullable.) --ruleset:<file> Určuje soubor sady pravidel, která zakazuje - specifickou diagnostiku. + (Pro všechna upozornění na možnost použití hodnoty null použijte nullable.) +-warn:<n> Nastaví úroveň pro upozornění (0 a více). (Krátký formát: -w) +-nowarn:<warn list> Zakáže zadaná upozornění. + (Pro všechna upozornění na možnost použití hodnoty null použijte nullable.) +-ruleset:<file> Určuje soubor sady pravidel, která zakazuje + specifickou diagnostiku. -errorlog:<file>[,version=<sarif_version>] - Určuje soubor pro protokolování veškeré - diagnostiky kompilátoru a analyzátoru. - verze_sarif:{1|2|2.1} Výchozí jsou 1. 2 a 2.1. - Obojí znamená SARIF verze 2.1.0. --reportanalyzer Hlásí další informace analyzátoru, např. - dobu spuštění. --skipanalyzers[+|-] Přeskočí spouštění diagnostických analyzátorů. + Určuje soubor pro protokolování veškeré + diagnostiky kompilátoru a analyzátoru. + verze_sarif:{1|2|2.1} Výchozí jsou 1. 2 a 2.1. + Obojí znamená SARIF verze 2.1.0. +-reportanalyzer Hlásí další informace analyzátoru, např. + dobu spuštění. +-skipanalyzers[+|-] Přeskočí spouštění diagnostických analyzátorů. - - JAZYK - --checked[+|-] Generuje kontroly přetečení. --unsafe[+|-] Povoluje nezabezpečený kód. --define:<symbol list> Definuje symboly podmíněné kompilace. (Krátký - formát: -d) --langversion:? Zobrazuje povolené hodnoty pro verzi jazyka. --langversion:<string> Určuje verzi jazyka, například: - latest (poslední verze včetně podverzí), - default (stejné jako latest), - latestmajor (poslední verze bez podverzí), - preview (poslední verze včetně funkcí v nepodporované verzi preview) - nebo konkrétní verze, například 6 nebo 7.1. --nullable[+|-] Určuje pro kontext s hodnotou null možnosti enable|disable. + - JAZYK - +-checked[+|-] Generuje kontroly přetečení. +-unsafe[+|-] Povoluje nezabezpečený kód. +-define:<symbol list> Definuje symboly podmíněné kompilace. (Krátký + formát: -d) +-langversion:? Zobrazuje povolené hodnoty pro verzi jazyka. +-langversion:<string> Určuje verzi jazyka, například: + latest (poslední verze včetně podverzí), + default (stejné jako latest), + latestmajor (poslední verze bez podverzí), + preview (poslední verze včetně funkcí v nepodporované verzi preview) + nebo konkrétní verze, například 6 nebo 7.1. +-nullable[+|-] Určuje pro kontext s hodnotou null možnosti enable|disable. -nullable:{enable|disable|warnings|annotations} - Určuje pro kontext s hodnotou null možnosti enable|disable|warnings|annotations. + Určuje pro kontext s hodnotou null možnosti enable|disable|warnings|annotations. - - ZABEZPEČENÍ - --delaysign[+|-] Vytvoří zpožděný podpis sestavení s využitím - jenom veřejné části klíče silného názvu. --publicsign[+|-] Vytvoří veřejný podpis sestavení s využitím jenom veřejné - části klíče silného názvu. --keyfile:<file> Určuje soubor klíče se silným názvem. --keycontainer:<string> Určuje kontejner klíče se silným názvem. --highentropyva[+|-] Povolí ASLR s vysokou entropií. + - ZABEZPEČENÍ - +-delaysign[+|-] Vytvoří zpožděný podpis sestavení s využitím + jenom veřejné části klíče silného názvu. +-publicsign[+|-] Vytvoří veřejný podpis sestavení s využitím jenom veřejné + části klíče silného názvu. +-keyfile:<file> Určuje soubor klíče se silným názvem. +-keycontainer:<string> Určuje kontejner klíče se silným názvem. +-highentropyva[+|-] Povolí ASLR s vysokou entropií. - - RŮZNÉ - -@<file> Načte další možnosti ze souboru odpovědí. --help Zobrazí tuto zprávu o použití. (Krátký formát: -?) --nologo Potlačí zprávu o autorských právech kompilátoru. --noconfig Nezahrnuje automaticky soubor CSC.RSP. --parallel[+|-] Souběžné sestavení. --version Zobrazí číslo verze kompilátoru a ukončí se. + - RŮZNÉ - +@<file> Načte další možnosti ze souboru odpovědí. +-help Zobrazí tuto zprávu o použití. (Krátký formát: -?) +-nologo Potlačí zprávu o autorských právech kompilátoru. +-noconfig Nezahrnuje automaticky soubor CSC.RSP. +-parallel[+|-] Souběžné sestavení. +-version Zobrazí číslo verze kompilátoru a ukončí se. - - POKROČILÉ - --baseaddress:<address> Základní adresa pro knihovnu, která se má sestavit. --checksumalgorithm:<alg> Určuje algoritmus pro výpočet kontrolního součtu - zdrojového souboru uloženého v PDB. Podporované hodnoty: - SHA1 nebo SHA256 (výchozí). --codepage:<n> Určuje znakovou stránku, která se má použít - při otevírání zdrojových souborů. --utf8output Určuje výstup zpráv kompilátoru v kódování UTF-8. --main:<typ> Určuje typ obsahující vstupní bod - (ignoruje všechny ostatní potenciální vstupní body). (Krátký - formát: -m) --fullpaths Kompilátor generuje úplné cesty. --filealign:<n> Určuje zarovnání použité pro oddíly výstupního - souboru. + - POKROČILÉ - +-baseaddress:<address> Základní adresa pro knihovnu, která se má sestavit. +-checksumalgorithm:<alg> Určuje algoritmus pro výpočet kontrolního součtu + zdrojového souboru uloženého v PDB. Podporované hodnoty: + SHA1 nebo SHA256 (výchozí). +-codepage:<n> Určuje znakovou stránku, která se má použít + při otevírání zdrojových souborů. +-utf8output Určuje výstup zpráv kompilátoru v kódování UTF-8. +-main:<typ> Určuje typ obsahující vstupní bod + (ignoruje všechny ostatní potenciální vstupní body). (Krátký + formát: -m) +-fullpaths Kompilátor generuje úplné cesty. +-filealign:<n> Určuje zarovnání použité pro oddíly výstupního + souboru. -pathmap:<K1>=<V1>,<K2>=<V2>,... - Určuje mapování pro výstup zdrojových názvů cest - kompilátorem. --pdb:<file> Určuje název souboru ladicích informací (výchozí: - název výstupního souboru s příponou .pdb). --errorendlocation Vypíše řádek a sloupec koncového umístění - jednotlivých chyb. --preferreduilang Určuje název upřednostňovaného výstupního jazyka. --nosdkpath Zakazuje hledání cesty k výchozí sadě SDK pro sestavení standardních knihoven. --nostdlib[+|-] Neodkazuje na standardní knihovnu (mscorlib.dll). --subsystemversion:<string> Určuje verzi subsystému tohoto sestavení. --lib:<file list> Určuje další adresáře, ve kterých se mají - hledat reference. --errorreport:<řetězec> Určuje způsob zpracování interních chyb kompilátoru: - prompt, send, queue nebo none. Výchozí možnost je - queue (zařadit do fronty). --appconfig:<file> Určuje konfigurační soubor aplikace, - který obsahuje nastavení vazby sestavení. --moduleassemblyname:<string> Určuje název sestavení, jehož součástí bude - tento modul. --modulename:<string> Určuje název zdrojového modulu. --generatedfilesout:<dir> Umístí soubory vygenerované během kompilace - do zadaného adresáře. + Určuje mapování pro výstup zdrojových názvů cest + kompilátorem. +-pdb:<file> Určuje název souboru ladicích informací (výchozí: + název výstupního souboru s příponou .pdb). +-errorendlocation Vypíše řádek a sloupec koncového umístění + jednotlivých chyb. +-preferreduilang Určuje název upřednostňovaného výstupního jazyka. +-nosdkpath Zakazuje hledání cesty k výchozí sadě SDK pro sestavení standardních knihoven. +-nostdlib[+|-] Neodkazuje na standardní knihovnu (mscorlib.dll). +-subsystemversion:<string> Určuje verzi subsystému tohoto sestavení. +-lib:<file list> Určuje další adresáře, ve kterých se mají + hledat reference. +-errorreport:<řetězec> Určuje způsob zpracování interních chyb kompilátoru: + prompt, send, queue nebo none. Výchozí možnost je + queue (zařadit do fronty). +-appconfig:<file> Určuje konfigurační soubor aplikace, + který obsahuje nastavení vazby sestavení. +-moduleassemblyname:<string> Určuje název sestavení, jehož součástí bude + tento modul. +-modulename:<string> Určuje název zdrojového modulu. +-generatedfilesout:<dir> Umístí soubory vygenerované během kompilace + do zadaného adresáře. Visual C# Compiler Options diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index a024ba23b0891..612388afaf72c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -1777,6 +1777,16 @@ Die geladene Assembly verweist auf das .NET Framework. Dies wird nicht unterstützt. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. Der Typ "{0}" kann in diesem Kontext nicht verwendet werden, da er nicht in Metadaten dargestellt werden kann. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index d74d8fd63824b..6811c80b0bef5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -1777,6 +1777,16 @@ El ensamblado que se ha cargado hace referencia a .NET Framework, lo cual no se admite. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. El tipo "{0}" no se puede usar en este contexto porque no se puede representar en metadatos. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 0ba241c903cc8..418facb9918b9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -1777,6 +1777,16 @@ L'assembly chargé référence le .NET Framework, ce qui n'est pas pris en charge. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. Le type « {0} » ne peut pas être utilisé dans ce contexte, car il ne peut pas être représenté dans les métadonnées. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 1d3d5a10ab689..ba419183967ee 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -1777,6 +1777,16 @@ L'assembly caricato fa riferimento a .NET Framework, che non è supportato. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. Non è possibile usare il tipo '{0}' in questo contesto perché non può essere rappresentato nei metadati. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 45f8a277d0508..c3b893f38f869 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -1777,6 +1777,16 @@ 読み込まれたアセンブリが .NET Framework を参照しています。これはサポートされていません。 + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. 型 '{0}' は、メタデータで表現できないため、このコンテキストでは使用できません。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 9570e4b0add75..c89dff459f03a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -1777,6 +1777,16 @@ 로드된 어셈블리가 지원되지 않는 .NET Framework를 참조합니다. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. 유형 ‘{0}’은(는) 메타데이터로 표현할 수 없기 때문에 이 컨텍스트에서 사용할 수 없습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index ed19c17259b77..c1c996b81fcd4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -1777,6 +1777,16 @@ Załadowany zestaw odwołuje się do platformy .NET Framework, co nie jest obsługiwane. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. Typ „{0}” nie może być używany w tym kontekście, ponieważ nie może być reprezentowany w metadanych. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index c6f2382dca260..441149d3dc25f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -1777,6 +1777,16 @@ O assembly carregado referencia o .NET Framework, mas não há suporte para isso. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. O tipo '{0}' não pode ser usado neste contexto porque ele não pode ser representado em metadados. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 85462424bd99a..15223ef937245 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -1777,6 +1777,16 @@ Загруженная сборка ссылается на платформу .NET Framework, которая не поддерживается. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. Тип "{0}" нельзя использовать в этом контексте, так как он не может быть представлен в метаданных. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 5390998e63d61..5685ac56d476a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -1777,6 +1777,16 @@ Yüklenen bütünleştirilmiş kod, desteklenmeyen .NET Framework'e başvuruyor. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. Tür '{0}', meta verilerde temsili olmadığından bu bağlamda kullanılamaz. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index a9667b5a3c756..ecba308627fb1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -1777,6 +1777,16 @@ 加载的程序集引用了 .NET Framework,而此操作不受支持。 + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. 类型“{0}”不能在此上下文中使用,因为它不能在元数据中表示。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 3f388a901cce0..91e7555f8d6ee 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -1777,6 +1777,16 @@ 載入的組件參考了 .NET Framework,此情形不受支援。 + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + Type '{0}' cannot be used in this context because it cannot be represented in metadata. 無法在此內容中使用類型 '{0}',因為它無法在中繼資料中表示。 diff --git a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs index d55c8f18240b5..4db9910725ac4 100644 --- a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs +++ b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs @@ -353,6 +353,7 @@ public void WarningLevel_2() case ErrorCode.WRN_UseDefViolationPropertySupportedVersion: case ErrorCode.WRN_UseDefViolationFieldSupportedVersion: case ErrorCode.WRN_UseDefViolationThisSupportedVersion: + case ErrorCode.WRN_AnalyzerReferencesNewerCompiler: Assert.Equal(1, ErrorFacts.GetWarningLevel(errorCode)); break; case ErrorCode.WRN_InvalidVersionFormat: diff --git a/src/Compilers/Core/CodeAnalysisTest/Analyzers/AnalyzerFileReferenceTests.cs b/src/Compilers/Core/CodeAnalysisTest/Analyzers/AnalyzerFileReferenceTests.cs index f28f09892b3c6..52645d1999638 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Analyzers/AnalyzerFileReferenceTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Analyzers/AnalyzerFileReferenceTests.cs @@ -244,6 +244,85 @@ public void TestFailedLoadDoesntCauseNoAnalyzersWarning() Assert.Equal(AnalyzerLoadFailureEventArgs.FailureErrorCode.UnableToCreateAnalyzer, errors.First().ErrorCode); } + [Fact] + [WorkItem(1032909, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1032909")] + public void TestReferencingFakeCompiler() + { + AnalyzerFileReference reference = CreateAnalyzerFileReference(_testFixture.AnalyzerWithFakeCompilerDependency.Path); + + List errors = new List(); + EventHandler errorHandler = (o, e) => errors.Add(e); + reference.AnalyzerLoadFailed += errorHandler; + var builder = ImmutableArray.CreateBuilder(); + reference.AddAnalyzers(builder, LanguageNames.CSharp); + var analyzers = builder.ToImmutable(); + reference.AnalyzerLoadFailed -= errorHandler; + + Assert.Equal(1, errors.Count); + var error = errors[0]; + + // failure is in the analyzer itself, i.e. abstract members on DiagnosticAnalyzer are not implemented. + Assert.Equal(AnalyzerLoadFailureEventArgs.FailureErrorCode.UnableToCreateAnalyzer, error.ErrorCode); + Assert.Equal("Analyzer", error.TypeName); + } + + [Fact] + [WorkItem(1032909, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1032909")] + public void TestReferencingLaterFakeCompiler() + { + AnalyzerFileReference reference = CreateAnalyzerFileReference(_testFixture.AnalyzerWithLaterFakeCompilerDependency.Path); + + List errors = new List(); + EventHandler errorHandler = (o, e) => errors.Add(e); + reference.AnalyzerLoadFailed += errorHandler; + var builder = ImmutableArray.CreateBuilder(); + reference.AddAnalyzers(builder, LanguageNames.CSharp); + var analyzers = builder.ToImmutable(); + reference.AnalyzerLoadFailed -= errorHandler; + + Assert.Equal(1, errors.Count); + var error = errors[0]; + Assert.Equal(AnalyzerLoadFailureEventArgs.FailureErrorCode.ReferencesNewerCompiler, error.ErrorCode); + Assert.Null(error.TypeName); + } + + private class AnalyzerLoaderMockCSharpCompiler : CSharpCompiler + { + public AnalyzerLoaderMockCSharpCompiler(CSharpCommandLineParser parser, string? responseFile, string[] args, BuildPaths buildPaths, string? additionalReferenceDirectories, IAnalyzerAssemblyLoader assemblyLoader, GeneratorDriverCache? driverCache = null, ICommonCompilerFileSystem? fileSystem = null) + : base(parser, responseFile, args, buildPaths, additionalReferenceDirectories, assemblyLoader, driverCache, fileSystem) + { + } + } + + [ConditionalFact(typeof(IsEnglishLocal))] + public void AssemblyLoading_ReferencesLaterFakeCompiler_EndToEnd_CSharp() + { + var directory = Temp.CreateDirectory(); + + TempFile corlib = directory.CreateFile("mscorlib.dll"); + corlib.WriteAllBytes(TestResources.NetFX.Minimal.mincorlib); + + TempFile source = directory.CreateFile("in.cs"); + source.WriteAllText("int x = 0;"); + + var compiler = new AnalyzerLoaderMockCSharpCompiler( + CSharpCommandLineParser.Default, + responseFile: null, + args: new[] { "/nologo", $@"/analyzer:""{_testFixture.AnalyzerWithLaterFakeCompilerDependency.Path}""", "/nostdlib", $@"/r:""{corlib.Path}""", "/out:something.dll", source.Path }, + new BuildPaths(clientDir: directory.Path, workingDir: directory.Path, sdkDir: null, tempDir: null), + additionalReferenceDirectories: null, + new DefaultAnalyzerAssemblyLoader()); + + var writer = new StringWriter(); + var result = compiler.Run(writer); + Assert.Equal(0, result); + AssertEx.Equal($""" + warning CS9057: The analyzer assembly '{_testFixture.AnalyzerWithLaterFakeCompilerDependency.Path}' references version '100.0.0.0' of the compiler, which is newer than the currently running version '{typeof(DefaultAnalyzerAssemblyLoader).Assembly.GetName().Version}'. + in.cs(1,5): warning CS0219: The variable 'x' is assigned but its value is never used + + """, writer.ToString()); + } + [ConditionalFact(typeof(CoreClrOnly), Reason = "Can't load a framework targeting generator, which these are in desktop")] public void TestLoadGenerators() { diff --git a/src/Compilers/Core/Portable/CommandLine/CommandLineArguments.cs b/src/Compilers/Core/Portable/CommandLine/CommandLineArguments.cs index 16388b49b1033..97d8125d4e6ee 100644 --- a/src/Compilers/Core/Portable/CommandLine/CommandLineArguments.cs +++ b/src/Compilers/Core/Portable/CommandLine/CommandLineArguments.cs @@ -493,6 +493,9 @@ public IEnumerable ResolveAnalyzerReferences(IAnalyzerAssembl case AnalyzerLoadFailureEventArgs.FailureErrorCode.ReferencesFramework: diagnostic = new DiagnosticInfo(messageProvider, messageProvider.WRN_AnalyzerReferencesFramework, analyzerReference.FullPath, e.TypeName!); break; + case AnalyzerLoadFailureEventArgs.FailureErrorCode.ReferencesNewerCompiler: + diagnostic = new DiagnosticInfo(messageProvider, messageProvider.WRN_AnalyzerReferencesNewerCompiler, analyzerReference.FullPath, e.ReferencedCompilerVersion!.ToString(), typeof(AnalyzerFileReference).Assembly.GetName().Version!.ToString()); + break; case AnalyzerLoadFailureEventArgs.FailureErrorCode.None: default: return; diff --git a/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs b/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs index bf19bca37db59..1f85e41c78dc5 100644 --- a/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs +++ b/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs @@ -175,6 +175,7 @@ public string GetIdForErrorCode(int errorCode) public abstract int WRN_AnalyzerCannotBeCreated { get; } public abstract int WRN_NoAnalyzerInAssembly { get; } public abstract int WRN_AnalyzerReferencesFramework { get; } + public abstract int WRN_AnalyzerReferencesNewerCompiler { get; } public abstract int ERR_CantReadRulesetFile { get; } public abstract int ERR_CompileCancelled { get; } diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerFileReference.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerFileReference.cs index 0f04d39809426..95b4e0484bf48 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerFileReference.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerFileReference.cs @@ -457,6 +457,10 @@ internal void AddExtensions(ImmutableSortedDictionary.Builder builder, string l } analyzerAssembly = _reference.GetAssembly(); - if (analyzerAssembly == null) + if (analyzerAssembly == null || CheckAssemblyReferencesNewerCompiler(analyzerAssembly)) { // This can be null if NoOpAnalyzerAssemblyLoader is used. return; @@ -536,6 +540,23 @@ internal void AddExtensions(ImmutableArray.Builder builder, string l } } + bool CheckAssemblyReferencesNewerCompiler(Assembly analyzerAssembly) + { + var runningCompilerAssemblyName = typeof(AnalyzerFileReference).Assembly.GetName(); + foreach (var referencedAssemblyName in analyzerAssembly.GetReferencedAssemblies()) + { + if (string.Equals(referencedAssemblyName.Name, runningCompilerAssemblyName.Name, StringComparison.OrdinalIgnoreCase) + && referencedAssemblyName.Version > runningCompilerAssemblyName.Version) + { + // note: we introduce an actual message for this scenario when handling the failed event. + _reference.AnalyzerLoadFailed?.Invoke(_reference, new AnalyzerLoadFailureEventArgs(AnalyzerLoadFailureEventArgs.FailureErrorCode.ReferencesNewerCompiler, message: "") { ReferencedCompilerVersion = referencedAssemblyName.Version }); + return true; + } + } + + return false; + } + private ImmutableArray GetLanguageSpecificAnalyzers(Assembly analyzerAssembly, ImmutableSortedDictionary> analyzerTypeNameMap, string language, ref bool reportedError) { ImmutableSortedSet? languageSpecificAnalyzerTypeNames; diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerLoadFailureEventArgs.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerLoadFailureEventArgs.cs index 07c4bbd4e972b..679a40fc2ecd1 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerLoadFailureEventArgs.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerLoadFailureEventArgs.cs @@ -14,7 +14,8 @@ public enum FailureErrorCode UnableToLoadAnalyzer = 1, UnableToCreateAnalyzer = 2, NoAnalyzers = 3, - ReferencesFramework = 4 + ReferencesFramework = 4, + ReferencesNewerCompiler = 5 } /// @@ -37,9 +38,14 @@ public enum FailureErrorCode /// public Exception? Exception { get; } + /// + /// If is , returns the compiler version referenced by the analyzer assembly. Otherwise, returns null. + /// + public Version? ReferencedCompilerVersion { get; internal init; } + public AnalyzerLoadFailureEventArgs(FailureErrorCode errorCode, string message, Exception? exceptionOpt = null, string? typeNameOpt = null) { - if (errorCode <= FailureErrorCode.None || errorCode > FailureErrorCode.ReferencesFramework) + if (errorCode <= FailureErrorCode.None || errorCode > FailureErrorCode.ReferencesNewerCompiler) { throw new ArgumentOutOfRangeException(nameof(errorCode)); } diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 5ff4e2f3841dd..668a8552ac91a 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -90,6 +90,8 @@ Microsoft.CodeAnalysis.OperationKind.Utf8String = 124 -> Microsoft.CodeAnalysis. Microsoft.CodeAnalysis.Operations.IUtf8StringOperation Microsoft.CodeAnalysis.Operations.IUtf8StringOperation.Value.get -> string! virtual Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions.Keys.get -> System.Collections.Generic.IEnumerable! +Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode.ReferencesNewerCompiler = 5 -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode +Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.ReferencedCompilerVersion.get -> System.Version? virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitUtf8String(Microsoft.CodeAnalysis.Operations.IUtf8StringOperation! operation) -> void virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitUtf8String(Microsoft.CodeAnalysis.Operations.IUtf8StringOperation! operation, TArgument argument) -> TResult? virtual Microsoft.CodeAnalysis.SymbolVisitor.DefaultVisit(Microsoft.CodeAnalysis.ISymbol! symbol, TArgument argument) -> TResult diff --git a/src/Compilers/Test/Core/AssemblyLoadTestFixture.cs b/src/Compilers/Test/Core/AssemblyLoadTestFixture.cs index 667cb2bedd3da..a01a348aec339 100644 --- a/src/Compilers/Test/Core/AssemblyLoadTestFixture.cs +++ b/src/Compilers/Test/Core/AssemblyLoadTestFixture.cs @@ -102,6 +102,10 @@ public sealed class AssemblyLoadTestFixture : IDisposable public TempFile AnalyzerWithNativeDependency { get; } + public TempFile AnalyzerWithFakeCompilerDependency { get; } + + public TempFile AnalyzerWithLaterFakeCompilerDependency { get; } + public AssemblyLoadTestFixture() { _temp = new TempRoot(); @@ -127,7 +131,7 @@ public void Write(StringBuilder sb, string s) Delta1 = GenerateDll("Delta", _directory, Delta1Source); var delta1Reference = MetadataReference.CreateFromFile(Delta1.Path); - DeltaPublicSigned1 = GenerateDll("DeltaPublicSigned", _directory.CreateDirectory("Delta1PublicSigned"), Delta1Source, publicSign: true); + DeltaPublicSigned1 = GenerateDll("DeltaPublicSigned", _directory.CreateDirectory("Delta1PublicSigned"), Delta1Source, publicKeyOpt: SigningTestHelpers.PublicKey); const string GammaSource = @" using System.Text; @@ -206,7 +210,7 @@ public void Write(StringBuilder sb, string s) var v2Directory = _directory.CreateDirectory("Version2"); Delta2 = GenerateDll("Delta", v2Directory, Delta2Source); var v2PublicSignedDirectory = _directory.CreateDirectory("Version2PublicSigned"); - DeltaPublicSigned2 = GenerateDll("DeltaPublicSigned", v2PublicSignedDirectory, Delta2Source, publicSign: true); + DeltaPublicSigned2 = GenerateDll("DeltaPublicSigned", v2PublicSignedDirectory, Delta2Source, publicKeyOpt: SigningTestHelpers.PublicKey); var delta2Reference = MetadataReference.CreateFromFile(Delta2.Path); @@ -385,20 +389,78 @@ public int GetFileAttributes(string path) } "); + + + var analyzerWithFakeCompilerDependencyDirectory = _directory.CreateDirectory("AnalyzerWithFakeCompilerDependency"); + var fakeCompilerAssembly = GenerateDll("Microsoft.CodeAnalysis", analyzerWithFakeCompilerDependencyDirectory, publicKeyOpt: typeof(SyntaxNode).Assembly.GetName().GetPublicKey()?.ToImmutableArray() ?? default, csSource: @" +using System; +using System.Reflection; + +[assembly: AssemblyVersionAttribute(""2.0.0.0"")] + +namespace Microsoft.CodeAnalysis.Diagnostics +{ + public class DiagnosticAnalyzerAttribute : Attribute + { + public DiagnosticAnalyzerAttribute(string firstLanguage, params string[] additionalLanguages) { } + } + + public class DiagnosticAnalyzer + { + } +} +"); + var fakeCompilerReference = MetadataReference.CreateFromFile(fakeCompilerAssembly.Path); + AnalyzerWithFakeCompilerDependency = GenerateDll("AnalyzerWithFakeCompilerDependency", analyzerWithFakeCompilerDependencyDirectory, @" +using Microsoft.CodeAnalysis.Diagnostics; + +[DiagnosticAnalyzer(""C#"")] +public class Analyzer : DiagnosticAnalyzer +{ +}", fakeCompilerReference); + + + var analyzerWithLaterFakeCompileDirectory = _directory.CreateDirectory("AnalyzerWithLaterFakeCompilerDependency"); + var laterFakeCompilerAssembly = GenerateDll("Microsoft.CodeAnalysis", analyzerWithLaterFakeCompileDirectory, publicKeyOpt: typeof(SyntaxNode).Assembly.GetName().GetPublicKey()?.ToImmutableArray() ?? default, csSource: @" +using System; +using System.Reflection; + +[assembly: AssemblyVersionAttribute(""100.0.0.0"")] + +namespace Microsoft.CodeAnalysis.Diagnostics +{ + public class DiagnosticAnalyzerAttribute : Attribute + { + public DiagnosticAnalyzerAttribute(string firstLanguage, params string[] additionalLanguages) { } + } + + public class DiagnosticAnalyzer + { + } +} +"); + var laterCompilerReference = MetadataReference.CreateFromFile(laterFakeCompilerAssembly.Path); + AnalyzerWithLaterFakeCompilerDependency = GenerateDll("AnalyzerWithLaterFakeCompilerDependency", analyzerWithLaterFakeCompileDirectory, @" +using Microsoft.CodeAnalysis.Diagnostics; + +[DiagnosticAnalyzer(""C#"")] +public class Analyzer : DiagnosticAnalyzer +{ +}", laterCompilerReference); } private static TempFile GenerateDll(string assemblyName, TempDirectory directory, string csSource, params MetadataReference[] additionalReferences) { - return GenerateDll(assemblyName, directory, csSource, publicSign: false, additionalReferences); + return GenerateDll(assemblyName, directory, csSource, publicKeyOpt: default, additionalReferences); } - private static TempFile GenerateDll(string assemblyName, TempDirectory directory, string csSource, bool publicSign, params MetadataReference[] additionalReferences) + private static TempFile GenerateDll(string assemblyName, TempDirectory directory, string csSource, ImmutableArray publicKeyOpt, params MetadataReference[] additionalReferences) { CSharpCompilationOptions options = new(OutputKind.DynamicallyLinkedLibrary, warningLevel: Diagnostic.MaxWarningLevel); - if (publicSign) + if (!publicKeyOpt.IsDefault) { - options = options.WithPublicSign(true).WithCryptoPublicKey(SigningTestHelpers.PublicKey); + options = options.WithPublicSign(true).WithCryptoPublicKey(publicKeyOpt); } var analyzerDependencyCompilation = CSharpCompilation.Create( diff --git a/src/Compilers/Test/Core/Mocks/TestMessageProvider.cs b/src/Compilers/Test/Core/Mocks/TestMessageProvider.cs index c75d1b7228a5e..199597b962a06 100644 --- a/src/Compilers/Test/Core/Mocks/TestMessageProvider.cs +++ b/src/Compilers/Test/Core/Mocks/TestMessageProvider.cs @@ -463,5 +463,7 @@ public override int ERR_InvalidDebugInfo public override int WRN_GeneratorFailedDuringInitialization => throw new NotImplementedException(); public override int WRN_AnalyzerReferencesFramework => throw new NotImplementedException(); + + public override int WRN_AnalyzerReferencesNewerCompiler => throw new NotImplementedException(); } } diff --git a/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb b/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb index 7fc8f25a9b996..2b43089ba88fa 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb @@ -1525,7 +1525,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ERRID.WRN_GeneratorFailedDuringGeneration, ERRID.WRN_AnalyzerReferencesFramework, ERRID.WRN_CallerArgumentExpressionAttributeSelfReferential, - ERRID.WRN_CallerArgumentExpressionAttributeHasInvalidParameterName + ERRID.WRN_CallerArgumentExpressionAttributeHasInvalidParameterName, + ERRID.WRN_AnalyzerReferencesNewerCompiler Return False Case Else ' NOTE: All error codes must be explicitly handled in the below select case statement diff --git a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb index 6ee391f206012..fdf78f60a2cce 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb @@ -1997,6 +1997,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic WRN_CallerArgumentExpressionAttributeSelfReferential = 42504 WRN_CallerArgumentExpressionAttributeHasInvalidParameterName = 42505 + WRN_AnalyzerReferencesNewerCompiler = 42506 + ' // AVAILABLE 42600 - 49998 WRN_NextAvailable = 42600 diff --git a/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb b/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb index 050ce25184283..ab4a1560ebebc 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb @@ -246,6 +246,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property + Public Overrides ReadOnly Property WRN_AnalyzerReferencesNewerCompiler As Integer + Get + Return ERRID.WRN_AnalyzerReferencesNewerCompiler + End Get + End Property + Public Overrides ReadOnly Property INF_UnableToLoadSomeTypesInAnalyzer As Integer Get Return ERRID.INF_UnableToLoadSomeTypesInAnalyzer diff --git a/src/Compilers/VisualBasic/Portable/Generated/ErrorFacts.Generated.vb b/src/Compilers/VisualBasic/Portable/Generated/ErrorFacts.Generated.vb index b32ca85040dd9..692bd1bc4c5d5 100644 --- a/src/Compilers/VisualBasic/Portable/Generated/ErrorFacts.Generated.vb +++ b/src/Compilers/VisualBasic/Portable/Generated/ErrorFacts.Generated.vb @@ -175,7 +175,8 @@ ERRID.WRN_GeneratorFailedDuringGeneration, ERRID.WRN_AnalyzerReferencesFramework, ERRID.WRN_CallerArgumentExpressionAttributeSelfReferential, - ERRID.WRN_CallerArgumentExpressionAttributeHasInvalidParameterName + ERRID.WRN_CallerArgumentExpressionAttributeHasInvalidParameterName, + ERRID.WRN_AnalyzerReferencesNewerCompiler Return True Case Else Return False diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx index 89b026a20b8b6..8ee01b4786c39 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.resx +++ b/src/Compilers/VisualBasic/Portable/VBResources.resx @@ -5614,6 +5614,12 @@ The loaded assembly references .NET Framework, which is not supported. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + The analyzer assembly references a newer version of the compiler than the currently running version. + assigning to or passing 'ByRef' properties with init-only setters diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf index 430808132023a..b3d7452a1e13b 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf @@ -528,6 +528,16 @@ Načtené sestavení se odkazuje na architekturu .NET Framework, což se nepodporuje + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. Atribut CallerArgumentExpressionAttribute použitý u parametru {0} nebude mít žádný účinek. Argument je použitý s neplatným názvem parametru. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf index 34e0bccc11b6e..0d022d3efc15f 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf @@ -528,6 +528,16 @@ Die geladene Assembly verweist auf das .NET Framework. Dies wird nicht unterstützt. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. Das auf den Parameter "{0}" angewendete CallerArgumentExpressionAttribute hat keine Auswirkungen. Es wird mit einem ungültigen Parameternamen angewendet. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf index ed258240c5fac..25281fe6fc096 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf @@ -528,6 +528,16 @@ El ensamblado que se ha cargado hace referencia a .NET Framework, lo cual no se admite. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. El atributo CallerArgumentExpressionAttribute aplicado al parámetro "{0}" no tendrá ningún efecto. Se ha aplicado con un nombre de parámetro no válido. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf index c7a3900f09dec..9127ce1c0284a 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf @@ -528,6 +528,16 @@ L'assembly chargé référence le .NET Framework, ce qui n'est pas pris en charge. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. Le CallerArgumentExpressionAttribute appliqué au paramètre « {0} » n’aura aucun effet. Il est appliqué avec un nom de paramètre non valide. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf index 1ec025c180f58..3489fa4c968a8 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf @@ -528,6 +528,16 @@ L'assembly caricato fa riferimento a .NET Framework, che non è supportato. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. CallerArgumentExpressionAttribute applicato al parametro '{0}' non avrà alcun effetto. È applicato con un nome di parametro non valido. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf index ccf86169be0dd..49bbd4fe2f60d 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf @@ -528,6 +528,16 @@ 読み込まれたアセンブリが .NET Framework を参照しています。これはサポートされていません。 + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. パラメーター '{0}' に適用された CallerArgumentExpressionAttribute は、無効なパラメーター名で適用されているため無効となります。 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf index 284792e06f251..504fb5ad54b5d 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf @@ -528,6 +528,16 @@ 로드된 어셈블리가 지원되지 않는 .NET Framework를 참조합니다. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. 매개 변수 '{0}'에 적용된 CallerArgumentExpressionAttribute는 효과가 없습니다. 잘못된 매개 변수 이름으로 적용되었습니다. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf index 3e8daacc551a7..fec494f8efc88 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf @@ -528,6 +528,16 @@ Załadowany zestaw odwołuje się do platformy .NET Framework, co nie jest obsługiwane. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. Atrybut CallerArgumentExpressionAttribute zastosowany do parametru „{0}” nie będzie działać. Jest on stosowany z nieprawidłową nazwą parametru. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf index e2c0d5370adb4..ad95c964e8256 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf @@ -528,6 +528,16 @@ O assembly carregado referencia o .NET Framework, mas não há suporte para isso. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. O CallerArgumentExpressionAttribute aplicado ao parâmetro '{0}' não terá efeito. Ele é aplicado com um nome de parâmetro inválido. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf index 9ec384dd4709c..3cbc4c84b160c 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf @@ -528,6 +528,16 @@ Загруженная сборка ссылается на платформу .NET Framework, которая не поддерживается. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. Применение класса CallerArgumentExpressionAttribute к параметру "{0}" не подействует, так как он применяется с недопустимым именем параметра. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf index e28dde0fbacf3..fec367a2b54a7 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf @@ -528,6 +528,16 @@ Yüklenen bütünleştirilmiş kod, desteklenmeyen .NET Framework'e başvuruyor. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. '{0}' parametresine uygulanan CallerArgumentExpressionAttribute hiçbir etkiye sahip olmaz. Geçersiz bir parametre adıyla uygulanır. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf index e15018eebbe20..8b0bfdf794da1 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf @@ -528,6 +528,16 @@ 加载的程序集引用了 .NET Framework,而此操作不受支持。 + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. 应用于参数“{0}”的 CallerArgumentExpressionAttribute 将不起任何作用。它采用了无效的参数名。 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf index f4c34ea2f7fc3..bbdc6aa66cfb4 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf @@ -528,6 +528,16 @@ 載入的組件參考了 .NET Framework,此情形不受支援。 + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + + + The analyzer assembly references a newer version of the compiler than the currently running version. + The analyzer assembly references a newer version of the compiler than the currently running version. + + The CallerArgumentExpressionAttribute applied to parameter '{0}' will have no effect. It is applied with an invalid parameter name. 套用到參數 '{0}' 的 CallerArgumentExpressionAttribute 將沒有效果。它套用了不正確的參數名稱。 diff --git a/src/EditorFeatures/Test/Diagnostics/AnalyzerLoadFailureTests.cs b/src/EditorFeatures/Test/Diagnostics/AnalyzerLoadFailureTests.cs index 9878355f848a3..66491e68e9625 100644 --- a/src/EditorFeatures/Test/Diagnostics/AnalyzerLoadFailureTests.cs +++ b/src/EditorFeatures/Test/Diagnostics/AnalyzerLoadFailureTests.cs @@ -4,6 +4,7 @@ #nullable enable +using System; using Microsoft.CodeAnalysis.Diagnostics; using Xunit; diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf index c22bfbff96466..e3bc7544a517d 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf @@ -189,7 +189,7 @@ Inline temporary variable - Встроенная временная переменная + Встроить временную переменную diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index 98f8aff7c83e6..47bb4a699a45c 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -2729,6 +2729,9 @@ Zero-width positive lookbehind assertions are typically used at the beginning of The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + Apply file header preferences diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf index 98ca114537c0f..edd55b51d1c7b 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -2650,6 +2650,11 @@ Pozitivní kontrolní výrazy zpětného vyhledávání s nulovou délkou se obv Sestavení {0}, které obsahuje typ {1}, se odkazuje na architekturu .NET Framework, což se nepodporuje. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. Výběr obsahuje volání lokální funkce, aniž by byla deklarovaná. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf index 1a18d48f7fd6f..36e0595fc4ae3 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf @@ -2650,6 +2650,11 @@ Positive Lookbehindassertionen mit Nullbreite werden normalerweise am Anfang reg Die Assembly "{0}" mit dem Typ "{1}" verweist auf das .NET Framework. Dies wird nicht unterstützt. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. Die Auswahl enthält einen lokalen Funktionsaufruf ohne Deklaration. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf index fd5b8253b37e0..56be25359b583 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf @@ -2650,6 +2650,11 @@ Las aserciones de búsqueda retrasada (lookbehind) positivas de ancho cero se us El ensamblado "{0}" que contiene el tipo "{1}" hace referencia a .NET Framework, lo cual no se admite. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. La selección contiene una llamada a una función local sin la declaración correspondiente. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf index 1060ca2e56faf..820a199516b45 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -2650,6 +2650,11 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée L'assembly '{0}' contenant le type '{1}' référence le .NET Framework, ce qui n'est pas pris en charge. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. La sélection contient un appel de fonction locale sans sa déclaration. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf index 1e28eaffcbadd..0ad6d14e77267 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf @@ -2650,6 +2650,11 @@ Le asserzioni lookbehind positive di larghezza zero vengono usate in genere all' L'assembly '{0}' che contiene il tipo '{1}' fa riferimento a .NET Framework, che non è supportato. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. La selezione contiene una chiamata di funzione locale senza la relativa dichiarazione. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf index 219fe86dedb1c..652a5d0e503d9 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -2650,6 +2650,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of 型 '{1}' を含むアセンブリ '{0}' が .NET Framework を参照しています。これはサポートされていません。 + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. 選択範囲に、宣言のないローカル関数呼び出しが含まれています。 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf index 2c1d9e3bae111..d02ff8d4e6c8d 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf @@ -2650,6 +2650,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of '{1}' 형식을 포함하는 '{0}' 어셈블리가 지원되지 않는 .NET Framework를 참조합니다. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. 선언이 없는 로컬 함수 호출이 선택 영역에 있습니다. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf index 19d1da19dc7c6..d5625a9be1931 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -2650,6 +2650,11 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk Zestaw „{0}” zawierający typ „{1}” odwołuje się do platformy .NET Framework, co nie jest obsługiwane. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. Zaznaczenie zawiera wywołanie funkcji lokalnej bez jego deklaracji. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf index f144264920ed9..32da7c3c0bd37 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -2650,6 +2650,11 @@ As declarações de lookbehind positivas de largura zero normalmente são usadas O assembly '{0}' contendo o tipo '{1}' referencia o .NET Framework, mas não há suporte para isso. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. A seleção contém uma chamada de função local sem sua declaração. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf index b8ca9cd2e41ad..8865cb50a6078 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf @@ -2650,6 +2650,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Сборка "{0}", содержащая тип "{1}", ссылается на платформу .NET Framework, которая не поддерживается. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. Выделенный фрагмент содержит вызов локальной функции без ее объявления. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf index d4ff250b089bf..7943a9eca564d 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -2650,6 +2650,11 @@ Sıfır genişlikli pozitif geri yönlü onaylamalar genellikle normal ifadeleri '{1}' türünü içeren '{0}' bütünleştirilmiş kodu, desteklenmeyen .NET Framework'e başvuruyor. + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. Seçim, bildirimi olmadan bir yerel işlev çağrısı içeriyor. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf index 56fbae53b4f62..664305c777cc4 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf @@ -2650,6 +2650,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of 包含类型“{1}”的程序集“{0}”引用了 .NET Framework,而此操作不受支持。 + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. 所选内容包含不带声明的本地函数调用。 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf index a001043cf4802..338d334e8c0e3 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -2650,6 +2650,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of 包含類型 '{1}' 的組件 '{0}' 參考了 .NET Framework,此情形不受支援。 + + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + The analyzer assembly '{0}' references version '{1}' of the compiler, which is newer than the currently running version '{2}'. + + The selection contains a local function call without its declaration. 選取範圍包含區域函式呼叫,但不含其宣告。 diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/DocumentAnalysisExecutor_Helpers.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/DocumentAnalysisExecutor_Helpers.cs index a3f27a9ffdfde..baeba5b96938b 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/DocumentAnalysisExecutor_Helpers.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/DocumentAnalysisExecutor_Helpers.cs @@ -33,6 +33,8 @@ internal sealed partial class DocumentAnalysisExecutor internal const string WRN_UnableToLoadAnalyzerIdVB = "BC42378"; internal const string WRN_AnalyzerReferencesNetFrameworkIdCS = "CS8850"; internal const string WRN_AnalyzerReferencesNetFrameworkIdVB = "BC42503"; + internal const string WRN_AnalyzerReferencesNewerCompilerIdCS = "CS9057"; + internal const string WRN_AnalyzerReferencesNewerCompilerIdVB = "BC42506"; // Shared with Compiler internal const string AnalyzerExceptionDiagnosticId = "AD0001"; @@ -43,6 +45,7 @@ internal sealed partial class DocumentAnalysisExecutor internal const string WRN_NoAnalyzerInAssemblyId = "AD1001"; internal const string WRN_UnableToLoadAnalyzerId = "AD1002"; internal const string WRN_AnalyzerReferencesNetFrameworkId = "AD1003"; + internal const string WRN_AnalyzerReferencesNewerCompilerId = "AD1004"; private const string AnalyzerExceptionDiagnosticCategory = "Intellisense"; @@ -100,6 +103,11 @@ static string GetLanguageSpecificId(string? language, string noLanguageId, strin message = string.Format(FeaturesResources.The_assembly_0_containing_type_1_references_NET_Framework, fullPath, e.TypeName); break; + case AnalyzerLoadFailureEventArgs.FailureErrorCode.ReferencesNewerCompiler: + id = GetLanguageSpecificId(language, WRN_AnalyzerReferencesNewerCompilerId, WRN_AnalyzerReferencesNewerCompilerIdCS, WRN_AnalyzerReferencesNewerCompilerIdVB); + message = string.Format(FeaturesResources.The_assembly_0_references_compiler_version_1_newer_than_2, fullPath, e.ReferencedCompilerVersion, typeof(AnalyzerLoadFailureEventArgs).Assembly.GetName().Version); + break; + default: throw ExceptionUtilities.UnexpectedValue(e.ErrorCode); } diff --git a/src/Features/VisualBasic/Portable/xlf/VBFeaturesResources.ru.xlf b/src/Features/VisualBasic/Portable/xlf/VBFeaturesResources.ru.xlf index 1cf940c4c390a..b9afb88ac2311 100644 --- a/src/Features/VisualBasic/Portable/xlf/VBFeaturesResources.ru.xlf +++ b/src/Features/VisualBasic/Portable/xlf/VBFeaturesResources.ru.xlf @@ -69,7 +69,7 @@ Inline temporary variable - Встроенная временная переменная + Встроить временную переменную diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf index fddf66a8dabba..bcc5b470a5098 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf @@ -254,7 +254,7 @@ Collapse Source Link, Embedded, and Decompiled source to definitions on file open - Sbalit zdrojový, vložený a dekompilovaný zdroj do definic při otevření souboru + Sbalit Source Link, vložený a dekompilovaný zdroj do definic při otevření souboru diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf index fc47f38d81b0b..8d56092ab4a73 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf @@ -254,7 +254,7 @@ Collapse Source Link, Embedded, and Decompiled source to definitions on file open - Réduire la source source, incorporée et décompilée aux définitions sur le fichier ouvert + Réduire Source Link, la source incorporée et décompilée aux définitions sur le fichier ouvert diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf index fc06647784ed0..22e27d1bd902b 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf @@ -254,7 +254,7 @@ Collapse Source Link, Embedded, and Decompiled source to definitions on file open - Comprimi collegamento di origine, origine incorporata e decompilata nelle definizioni all'apertura del file + Comprimi Source Link, origine incorporata e decompilata nelle definizioni all'apertura del file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf index fb30763eadfab..b29aeacde945f 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf @@ -254,7 +254,7 @@ Collapse Source Link, Embedded, and Decompiled source to definitions on file open - 원본 축소 파일을 열 때 정의에 대한 링크, 포함 및 디컴파일된 원본 + 파일을 열 때 소스 링크, 포함 및 디컴파일된 소스를 정의로 축소 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf index 0f1541856bbf8..8e11656f812fd 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf @@ -254,7 +254,7 @@ Collapse Source Link, Embedded, and Decompiled source to definitions on file open - Zwiń źródło linku źródłowego, osadzone i zdekompilowane źródło do definicji przy otwieraniu pliku + Zwiń źródło linku do źródła, osadzone i zdekompilowane źródło do definicji przy otwieraniu pliku diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf index 4ed8a787403a7..9fd532e04a3a1 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf @@ -254,7 +254,7 @@ Collapse Source Link, Embedded, and Decompiled source to definitions on file open - Recolher o Link da Fonte, a Fonte Integrada e Descompilada para definições no arquivo aberto + Recolher o Source Link, a Fonte Integrada e Descompilada para definições no arquivo aberto diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf index b5d1659f4c2e0..63c60d98e3c4b 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf @@ -254,7 +254,7 @@ Collapse Source Link, Embedded, and Decompiled source to definitions on file open - Dosya aılırken Kaynak Bağlantısı, Ekli ve Kaynak Koda Dönüştürülen kaynağı tanımlara daralt + Dosya açılırken Kaynak Bağlantısı, Ekli ve Kaynak Koda Dönüştürülen kaynağı tanımlara daralt diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf index 9d5b55101ab3b..e9e513dcba5a4 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf @@ -254,7 +254,7 @@ Collapse Source Link, Embedded, and Decompiled source to definitions on file open - 在打开文件时将源链接、嵌入源和反编译源折叠到定义 + 在文件打开时将源链接、嵌入和反编译的源折叠到定义