From edd54dd3001a1d78643bade4be4b5a6cff66faf8 Mon Sep 17 00:00:00 2001 From: Chris Sienkiewicz Date: Mon, 22 Feb 2021 18:14:45 -0800 Subject: [PATCH 1/7] Remove capability provider --- .../ComponentDebugger/CapabilityProvider.cs | 43 ------------------- 1 file changed, 43 deletions(-) delete mode 100644 src/VisualStudio.Roslyn.SDK/ComponentDebugger/CapabilityProvider.cs diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CapabilityProvider.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CapabilityProvider.cs deleted file mode 100644 index b24b37ca4..000000000 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CapabilityProvider.cs +++ /dev/null @@ -1,43 +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.Immutable; -using System.ComponentModel.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.VisualStudio.ProjectSystem; - -namespace Roslyn.ComponentDebugger -{ - [Export(ExportContractNames.Scopes.ConfiguredProject, typeof(IProjectCapabilitiesProvider))] - [AppliesTo(ProjectCapabilities.CSharp + " | " + ProjectCapabilities.VB)] - public class CapabilityProvider : ConfiguredProjectCapabilitiesProviderBase - { - private readonly IProjectSnapshotService snapshotService; - - [ImportingConstructor] - [System.Obsolete("This exported object must be obtained through the MEF export provider.", error: true)] - public CapabilityProvider(ConfiguredProject configuredProject, IProjectSnapshotService snapshotService) - : base(nameof(CapabilityProvider), configuredProject) - { - this.snapshotService = snapshotService; - } - - protected override async Task> GetCapabilitiesAsync(CancellationToken cancellationToken) - { - // an alternative design could be to have 'IsRoslynComponent' just define the Date: Tue, 23 Feb 2021 17:11:32 -0800 Subject: [PATCH 2/7] Add command line data source: - add data source to obtain command line args - use data source in extension method - extract out shared logic into launchsettingsmanager - clean up VM code --- .../CommandLineArgumentsDataSource.cs | 64 +++++++++++++++ .../ComponentDebugger/Constants.cs | 4 +- .../ComponentDebugger/DebugProfileProvider.cs | 52 ++++--------- .../DebuggerOptionsViewModel.cs | 58 +++++--------- .../LaunchSettingsManager.cs | 49 ++++++++++++ .../LaunchSettingsProvider.cs | 77 +++++++++++-------- .../ComponentDebugger/ProjectUtilities.cs | 22 ++---- 7 files changed, 199 insertions(+), 127 deletions(-) create mode 100644 src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs create mode 100644 src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs new file mode 100644 index 000000000..af2ff204f --- /dev/null +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs @@ -0,0 +1,64 @@ +// 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.Immutable; +using System.ComponentModel.Composition; +using System.Threading; +using System.Threading.Tasks; +using System.Threading.Tasks.Dataflow; +using Microsoft.VisualStudio.ProjectSystem; +using Microsoft.VisualStudio.ProjectSystem.VS; + +namespace Roslyn.ComponentDebugger +{ + [Export] + [AppliesTo("(" + ProjectCapabilities.CSharp + " | " + ProjectCapabilities.VB + ") & !" + ProjectCapabilities.SharedAssetsProject)] + public class CommandLineArgumentsDataSource : UnconfiguredProjectHostBridge, IProjectVersionedValue>, IProjectVersionedValue>> + { + private readonly IActiveConfiguredProjectSubscriptionService activeProjectSubscriptionService; + + [ImportingConstructor] + public CommandLineArgumentsDataSource(IProjectThreadingService projectThreadingService, IActiveConfiguredProjectSubscriptionService activeProjectSubscriptionService) + : base(projectThreadingService.JoinableTaskContext) + { + this.activeProjectSubscriptionService = activeProjectSubscriptionService; + } + + public async Task> GetArgsAsync() + { + using (JoinableCollection.Join()) + { + await this.InitializeAsync(); + return this.AppliedValue?.Value ?? ImmutableArray.Empty; + } + } + + protected override bool BlockInitializeOnFirstAppliedValue => true; + + protected override Task InitializeInnerCoreAsync(CancellationToken cancellationToken) => Task.CompletedTask; + + protected override IDisposable LinkExternalInput(ITargetBlock> targetBlock) + { + JoinUpstreamDataSources(this.activeProjectSubscriptionService.ProjectBuildRuleSource); + return activeProjectSubscriptionService.ProjectBuildRuleSource.SourceBlock.LinkTo(target: targetBlock, + linkOptions: new DataflowLinkOptions { PropagateCompletion = true }, + initialDataAsNew: true, + suppressVersionOnlyUpdates: true, + ruleNames: Constants.CommandLineArgsRuleName); + } + + protected override Task>> PreprocessAsync(IProjectVersionedValue input, IProjectVersionedValue>? previousOutput) + { + var description = input.Value.ProjectChanges[Constants.CommandLineArgsRuleName]; + return Task.FromResult>>(new ProjectVersionedValue>(description.After.Items.Keys.ToImmutableArray(), input.DataSourceVersions)); + } + + protected override Task ApplyAsync(IProjectVersionedValue> value) + { + AppliedValue = value; + return Task.CompletedTask; + } + } +} diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/Constants.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/Constants.cs index c4654f185..9181bd754 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/Constants.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/Constants.cs @@ -6,12 +6,12 @@ namespace Roslyn.ComponentDebugger { internal static class Constants { - public const string RoslynComponentPropertyName = "IsRoslynComponent"; - public const string RoslynComponentCapability = "RoslynComponent"; public const string CommandName = "DebugRoslynComponent"; public const string TargetProjectPropertyName = "targetProject"; + + public const string CommandLineArgsRuleName = "CompilerCommandLineArgs"; } } diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs index 69d720d2b..d58b05066 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs @@ -24,16 +24,19 @@ namespace Roslyn.ComponentDebugger public class DebugProfileProvider : IDebugProfileLaunchTargetsProvider { private readonly ConfiguredProject _configuredProject; - private readonly IDebugTokenReplacer _tokenReplacer; + private readonly LaunchSettingsManager _launchSettingsManager; + private readonly IProjectThreadingService _threadingService; private readonly AsyncLazy _compilerRoot; [ImportingConstructor] [Obsolete("This exported object must be obtained through the MEF export provider.", error: true)] - public DebugProfileProvider(ConfiguredProject configuredProject, IDebugTokenReplacer tokenReplacer, SVsServiceProvider? serviceProvider) + public DebugProfileProvider(ConfiguredProject configuredProject, LaunchSettingsManager launchSettingsManager, SVsServiceProvider? serviceProvider, IProjectThreadingService threadingService) { _configuredProject = configuredProject; - _tokenReplacer = tokenReplacer; - _compilerRoot = new AsyncLazy(() => GetCompilerRootAsync(serviceProvider), ThreadHelper.JoinableTaskFactory); + _launchSettingsManager = launchSettingsManager; + _threadingService = threadingService; + + _compilerRoot = new AsyncLazy(() => GetCompilerRootAsync(serviceProvider), _threadingService.JoinableTaskFactory); } public Task OnAfterLaunchAsync(DebugLaunchOptions launchOptions, ILaunchProfile profile) => Task.CompletedTask; @@ -53,57 +56,34 @@ public async Task> QueryDebugTargetsAsync(De }; // try and get the target project - var targetProjectUnconfigured = await TryGetTargetProjectAsync(profile).ConfigureAwait(false); + var targetProjectUnconfigured = await _launchSettingsManager.TryGetProjectForLaunchAsync(profile); if (targetProjectUnconfigured is object) { settings.CurrentDirectory = Path.GetDirectoryName(targetProjectUnconfigured.FullPath); var compiler = _configuredProject.Capabilities.Contains(ProjectCapabilities.VB) ? "vbc.exe" : "csc.exe"; - var compilerRoot = await _compilerRoot.GetValueAsync().ConfigureAwait(false); + var compilerRoot = await _compilerRoot.GetValueAsync(); settings.Executable = Path.Combine(compilerRoot, compiler); - // try and get the configured version of the target project - var targetProject = await targetProjectUnconfigured.GetSuggestedConfiguredProjectAsync().ConfigureAwait(false); - if (targetProject is object) - { - // get its compilation args - var args = await targetProject.GetCompilationArgumentsAsync().ConfigureAwait(false); + // get its compilation args + var args = await targetProjectUnconfigured.GetCompilationArgumentsAsync(); - // append the command line args to the debugger launch - settings.Arguments = string.Join(" ", args); - } + // append the command line args to the debugger launch + settings.Arguments = string.Join(" ", args); } // https://github.com/dotnet/roslyn-sdk/issues/728 : better error handling return new IDebugLaunchSettings[] { settings }; } - private static async Task GetCompilerRootAsync(SVsServiceProvider? serviceProvider) + private async Task GetCompilerRootAsync(SVsServiceProvider? serviceProvider) { - await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + await _threadingService.SwitchToUIThread(); - // https://github.com/dotnet/roslyn-sdk/issues/729 + // https://github.com/dotnet/roslyn-sdk/issues/729 : don't hardcode net fx compiler object rootDir = string.Empty; var shell = (IVsShell?)serviceProvider?.GetService(typeof(SVsShell)); shell?.GetProperty((int)__VSSPROPID2.VSSPROPID_InstallRootDir, out rootDir); return Path.Combine((string)rootDir, "MSBuild", "Current", "Bin", "Roslyn"); } - - private async Task TryGetTargetProjectAsync(ILaunchProfile? profile) - { - UnconfiguredProject? targetProject = null; - object? value = null; - profile?.OtherSettings?.TryGetValue(Constants.TargetProjectPropertyName, out value); - - if (value is string targetProjectPath) - { - // expand any variables in the path, and root it based on this project - var replacedProjectPath = await _tokenReplacer.ReplaceTokensInStringAsync(targetProjectPath, true).ConfigureAwait(false); - replacedProjectPath = _configuredProject.UnconfiguredProject.MakeRooted(replacedProjectPath); - - targetProject = _configuredProject.Services.ProjectService.LoadedUnconfiguredProjects.SingleOrDefault(p => p.FullPath == replacedProjectPath); - } - - return targetProject; - } } } diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptionsViewModel.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptionsViewModel.cs index 00dae05fc..481c5779c 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptionsViewModel.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptionsViewModel.cs @@ -6,69 +6,49 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.ComponentModel; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.VisualStudio.ProjectSystem; -using Microsoft.VisualStudio.ProjectSystem.Debug; +using System.Runtime.CompilerServices; namespace Roslyn.ComponentDebugger { internal class DebuggerOptionsViewModel : INotifyPropertyChanged { - private IWritableLaunchProfile? _launchProfile; + private readonly Action indexChanged; - private readonly ImmutableArray _targetProjects; + private IEnumerable _projectNames = ImmutableArray.Empty; - private readonly IEnumerable _targetProjectNames; + private int _selectedProjectIndex = -1; public event PropertyChangedEventHandler? PropertyChanged; - public DebuggerOptionsViewModel(ImmutableArray targetProjects) + public DebuggerOptionsViewModel(Action indexChanged) { - _targetProjects = targetProjects; - _targetProjectNames = _targetProjects.Select(t => Path.GetFileNameWithoutExtension(t.UnconfiguredProject.FullPath)); + this.indexChanged = indexChanged; } - public IEnumerable ProjectNames { get => _targetProjectNames; } - - public IWritableLaunchProfile? LaunchProfile + public IEnumerable ProjectNames { - get => _launchProfile; + get => _projectNames; set { - _launchProfile = value; - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedProjectIndex))); + _projectNames = value; + NotifyPropertyChanged(); } } public int SelectedProjectIndex { - get - { - if (LaunchProfile?.OtherSettings.ContainsKey(Constants.TargetProjectPropertyName) == true) - { - var target = LaunchProfile.OtherSettings[Constants.TargetProjectPropertyName].ToString(); - for (var i = 0; i < _targetProjects.Length; i++) - { - if (_targetProjects[i].UnconfiguredProject.FullPath.Equals(target, StringComparison.OrdinalIgnoreCase)) - { - return i; - } - } - } - return -1; - } + get => _selectedProjectIndex; set { - if (LaunchProfile is object) - { - var newTargetProject = _targetProjects[value].UnconfiguredProject; - LaunchProfile.OtherSettings[Constants.TargetProjectPropertyName] = newTargetProject.FullPath; - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedProjectIndex))); - } + _selectedProjectIndex = value; + NotifyPropertyChanged(); + indexChanged(value); } } + + private void NotifyPropertyChanged([CallerMemberName]string propertyName = "") + { + this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } } } diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs new file mode 100644 index 000000000..ee7e3097b --- /dev/null +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs @@ -0,0 +1,49 @@ +// 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.ComponentModel.Composition; +using System.Threading.Tasks; +using Microsoft.VisualStudio.ProjectSystem; +using Microsoft.VisualStudio.ProjectSystem.Debug; + +namespace Roslyn.ComponentDebugger +{ + [Export] + public class LaunchSettingsManager + { + private readonly UnconfiguredProject owningProject; + private readonly IDebugTokenReplacer tokenReplacer; + + [ImportingConstructor] + public LaunchSettingsManager(UnconfiguredProject owningProject, IDebugTokenReplacer tokenReplacer) + { + this.owningProject = owningProject; + this.tokenReplacer = tokenReplacer; + } + + public async Task TryGetProjectForLaunchAsync(ILaunchProfile? profile) + { + UnconfiguredProject? targetProject = null; + object? value = null; + profile?.OtherSettings?.TryGetValue(Constants.TargetProjectPropertyName, out value); + + if (value is string targetProjectPath) + { + // expand any variables in the path, and root it based on this project + var replacedProjectPath = await tokenReplacer.ReplaceTokensInStringAsync(targetProjectPath, true); + replacedProjectPath = owningProject.MakeRooted(replacedProjectPath); + + targetProject = ((IProjectService2)owningProject.Services.ProjectService).GetLoadedProject(replacedProjectPath); + } + return targetProject; + } + + public void WriteProjectForLaunch(IWritableLaunchProfile profile, UnconfiguredProject targetProject) + { + var rootedPath = this.owningProject.MakeRelative(targetProject.FullPath); + profile.OtherSettings[Constants.TargetProjectPropertyName] = rootedPath; + } + + } +} diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs index 7e10b807a..238692807 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs @@ -3,16 +3,15 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Immutable; using System.ComponentModel.Composition; using System.IO; using System.Linq; -using System.Threading.Tasks; using System.Windows.Controls; using Microsoft.VisualStudio.ProjectSystem; using Microsoft.VisualStudio.ProjectSystem.Debug; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Threading; using Microsoft.VisualStudio.Utilities; +using Task = System.Threading.Tasks.Task; namespace Roslyn.ComponentDebugger { @@ -20,15 +19,22 @@ namespace Roslyn.ComponentDebugger [AppliesTo(Constants.RoslynComponentCapability)] public class LaunchSettingsProvider : ILaunchSettingsUIProvider { + private readonly IProjectThreadingService _threadingService; private readonly UnconfiguredProject _unconfiguredProject; - private readonly AsyncLazy _viewModel; + private readonly LaunchSettingsManager _launchSettingsManager; + private readonly DebuggerOptionsViewModel _viewModel; + + private ImmutableArray _projects; + private IWritableLaunchProfile? _launchProfile; [ImportingConstructor] [Obsolete("This exported object must be obtained through the MEF export provider.", error: true)] - public LaunchSettingsProvider(UnconfiguredProject unconfiguredProject) + public LaunchSettingsProvider(IProjectThreadingService threadingService, UnconfiguredProject unconfiguredProject, LaunchSettingsManager launchSettingsManager) { + _threadingService = threadingService; _unconfiguredProject = unconfiguredProject; - _viewModel = new AsyncLazy(GetViewModelAsync, ThreadHelper.JoinableTaskFactory); + _launchSettingsManager = launchSettingsManager; + _viewModel = new DebuggerOptionsViewModel(IndexChanged); } public string CommandName { get => Constants.CommandName; } @@ -36,12 +42,12 @@ public LaunchSettingsProvider(UnconfiguredProject unconfiguredProject) // https://github.com/dotnet/roslyn-sdk/issues/730 : localization public string FriendlyName { get => "Roslyn Component"; } - public UserControl? CustomUI { get => new DebuggerOptions() { DataContext = _viewModel.GetValue() }; } + public UserControl? CustomUI { get => new DebuggerOptions() { DataContext = _viewModel }; } public void ProfileSelected(IWritableLaunchSettings curSettings) { - // Update the viewmodel's current profile. - this._viewModel.GetValue().LaunchProfile = curSettings?.ActiveProfile; + _launchProfile = curSettings?.ActiveProfile; + _threadingService.ExecuteSynchronously(UpdateViewModelAsync); } public bool ShouldEnableProperty(string propertyName) @@ -52,39 +58,44 @@ public bool ShouldEnableProperty(string propertyName) return false; } - private async Task GetViewModelAsync() + private async Task UpdateViewModelAsync() { - var targetProjects = ArrayBuilder.GetInstance(); + var targetProjects = ArrayBuilder.GetInstance(); - // NOTE: we assume the target projects are in the same configuration as this one (can they be different?) - var configuredProject = await _unconfiguredProject.GetSuggestedConfiguredProjectAsync().ConfigureAwait(false); - if (configuredProject is object) - { - // get the output assembly for this project - var projectArgs = await configuredProject.GetCompilationArgumentsAsync().ConfigureAwait(false); - var targetArg = projectArgs.LastOrDefault(a => a.StartsWith("/out:", StringComparison.OrdinalIgnoreCase)); - var target = Path.GetFileName(targetArg); + // get the output assembly for this project + var projectArgs = await _unconfiguredProject.GetCompilationArgumentsAsync().ConfigureAwait(false); + var targetArg = projectArgs.LastOrDefault(a => a.StartsWith("/out:", StringComparison.OrdinalIgnoreCase)); + var target = Path.GetFileName(targetArg); - var projectService = configuredProject.Services.ProjectService; - foreach (var targetProjectUnconfigured in projectService.LoadedUnconfiguredProjects) + var projectService = _unconfiguredProject.Services.ProjectService; + foreach (var targetProjectUnconfigured in projectService.LoadedUnconfiguredProjects) + { + // check if the args contain the project as an analyzer ref + foreach (var arg in await targetProjectUnconfigured.GetCompilationArgumentsAsync().ConfigureAwait(false)) { - var targetProject = await targetProjectUnconfigured.LoadConfiguredProjectAsync(configuredProject.ProjectConfiguration).ConfigureAwait(false); - if (targetProject is object) + if (arg.StartsWith("/analyzer", StringComparison.OrdinalIgnoreCase) + && arg.EndsWith(target, StringComparison.OrdinalIgnoreCase)) { - // check if the args contain the project as an analyzer ref - foreach (var arg in await targetProject.GetCompilationArgumentsAsync().ConfigureAwait(false)) - { - if (arg.StartsWith("/analyzer", StringComparison.OrdinalIgnoreCase) - && arg.EndsWith(target, StringComparison.OrdinalIgnoreCase)) - { - targetProjects.Add(targetProject); - } - } + targetProjects.Add(targetProjectUnconfigured); } } } + _projects = targetProjects.ToImmutableAndFree(); - return new DebuggerOptionsViewModel(targetProjects.ToImmutableAndFree()); + var launchTargetProject = await _launchSettingsManager.TryGetProjectForLaunchAsync(_launchProfile?.ToLaunchProfile()); + var index = _projects.IndexOf(launchTargetProject!); + + _viewModel.ProjectNames = _projects.Select(p => Path.GetFileNameWithoutExtension(p.FullPath)); + _viewModel.SelectedProjectIndex = index; + } + + private void IndexChanged(int newIndex) + { + if (_launchProfile is object && !_projects.IsDefaultOrEmpty && newIndex >= 0 && newIndex < _projects.Length) + { + var project = _projects[newIndex]; + _launchSettingsManager.WriteProjectForLaunch(_launchProfile, project); + } } } } diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/ProjectUtilities.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/ProjectUtilities.cs index ad40f94e4..b20cc3115 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/ProjectUtilities.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/ProjectUtilities.cs @@ -3,9 +3,7 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; using System.Threading.Tasks; using Microsoft.VisualStudio.ProjectSystem; @@ -13,30 +11,20 @@ namespace Roslyn.ComponentDebugger { public static class ProjectUtilities { - // PROTOTYPE: is there a way to get this other than hardcoding it? - static readonly string[] CommandLineSchemaRuleNames = new[] { "CompilerCommandLineArgs" }; - - public static async Task> GetCompilationArgumentsAsync(this ConfiguredProject project) + public static Task> GetCompilationArgumentsAsync(this UnconfiguredProject project) { if (project is null) { throw new ArgumentNullException(nameof(project)); } - var args = ImmutableArray.Empty; - - var subscriptionService = project.Services.ProjectSubscription; - if (subscriptionService is object) + var dataSource = project.Services.ExportProvider.GetExportedValueOrDefault(); + if (dataSource is object) { - // get the latest snapshot of the command line args rules - var snapshots = await subscriptionService.JointRuleSource.GetLatestVersionAsync(project, CommandLineSchemaRuleNames).ConfigureAwait(false); - var latest = snapshots.Values.FirstOrDefault(); - - // extract the actual command line arguments - args = latest?.Items.Keys.ToImmutableArray() ?? args; + return dataSource.GetArgsAsync(); } - return args; + return Task.FromResult(ImmutableArray.Empty); } } } From 0fff2414c63ac93f478d7857e40c21f15c55c1a8 Mon Sep 17 00:00:00 2001 From: Chris Sienkiewicz Date: Thu, 25 Feb 2021 11:08:34 -0800 Subject: [PATCH 3/7] Fix bad merge --- Roslyn-SDK.sln | 7 ++++ .../ComponentDebugger/DebuggerOptions.xaml | 19 +++++++++ .../Roslyn.ComponentDebugger.csproj | 40 +++++++++++++++++++ .../Roslyn.SDK/Roslyn.SDK.csproj | 10 +++++ .../Roslyn.SDK/source.extension.vsixmanifest | 1 + 5 files changed, 77 insertions(+) create mode 100644 src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptions.xaml create mode 100644 src/VisualStudio.Roslyn.SDK/ComponentDebugger/Roslyn.ComponentDebugger.csproj diff --git a/Roslyn-SDK.sln b/Roslyn-SDK.sln index 2715ebfa9..ef1484fb0 100644 --- a/Roslyn-SDK.sln +++ b/Roslyn-SDK.sln @@ -189,6 +189,8 @@ Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Microsoft.CodeAnalysis.Visu EndProject Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.XUnit.UnitTests", "tests\Microsoft.CodeAnalysis.Testing\Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.XUnit.UnitTests\Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.XUnit.UnitTests.vbproj", "{92BD1781-5DB4-4F72-BCCB-0D64C0790A2B}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roslyn.ComponentDebugger", "src\VisualStudio.Roslyn.SDK\ComponentDebugger\Roslyn.ComponentDebugger.csproj", "{421DE59C-8246-4679-9D69-79F16A7187BE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -539,6 +541,10 @@ Global {92BD1781-5DB4-4F72-BCCB-0D64C0790A2B}.Debug|Any CPU.Build.0 = Debug|Any CPU {92BD1781-5DB4-4F72-BCCB-0D64C0790A2B}.Release|Any CPU.ActiveCfg = Release|Any CPU {92BD1781-5DB4-4F72-BCCB-0D64C0790A2B}.Release|Any CPU.Build.0 = Release|Any CPU + {421DE59C-8246-4679-9D69-79F16A7187BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {421DE59C-8246-4679-9D69-79F16A7187BE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {421DE59C-8246-4679-9D69-79F16A7187BE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {421DE59C-8246-4679-9D69-79F16A7187BE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -635,6 +641,7 @@ Global {7D9C0EF5-7383-4E35-811B-3288B3C806F3} = {9905147E-CC1F-42A0-BD27-05586C583DF7} {7C3FE60E-055B-4E0C-BB85-C7E94A640074} = {9905147E-CC1F-42A0-BD27-05586C583DF7} {92BD1781-5DB4-4F72-BCCB-0D64C0790A2B} = {9905147E-CC1F-42A0-BD27-05586C583DF7} + {421DE59C-8246-4679-9D69-79F16A7187BE} = {F9B73995-76C6-4056-ADA9-18342F951361} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {56695AA9-EA80-47A7-8562-E51285906C54} diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptions.xaml b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptions.xaml new file mode 100644 index 000000000..b431658e4 --- /dev/null +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptions.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/Roslyn.ComponentDebugger.csproj b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/Roslyn.ComponentDebugger.csproj new file mode 100644 index 000000000..37bb4c8b9 --- /dev/null +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/Roslyn.ComponentDebugger.csproj @@ -0,0 +1,40 @@ + + + + + Library + Roslyn.ComponentDebugger + net472 + enable + NU1603;NU1605 + + + + + + + + + + + + + + + + + + + + + + + + + + + + MSBuild:Compile + + + diff --git a/src/VisualStudio.Roslyn.SDK/Roslyn.SDK/Roslyn.SDK.csproj b/src/VisualStudio.Roslyn.SDK/Roslyn.SDK/Roslyn.SDK.csproj index b04a9074b..370c4ea74 100644 --- a/src/VisualStudio.Roslyn.SDK/Roslyn.SDK/Roslyn.SDK.csproj +++ b/src/VisualStudio.Roslyn.SDK/Roslyn.SDK/Roslyn.SDK.csproj @@ -120,5 +120,15 @@ true false + + Roslyn.ComponentDebugger + BuiltProjectOutputGroup%3bGetCopyToOutputDirectoryItems%3b + DebugSymbolsProjectOutputGroup%3b + true + false + + + + diff --git a/src/VisualStudio.Roslyn.SDK/Roslyn.SDK/source.extension.vsixmanifest b/src/VisualStudio.Roslyn.SDK/Roslyn.SDK/source.extension.vsixmanifest index 8d8661a4e..a091d5313 100644 --- a/src/VisualStudio.Roslyn.SDK/Roslyn.SDK/source.extension.vsixmanifest +++ b/src/VisualStudio.Roslyn.SDK/Roslyn.SDK/source.extension.vsixmanifest @@ -30,6 +30,7 @@ + From c3ac5f88c63f328fb0ca340f9f195dc3655c0635 Mon Sep 17 00:00:00 2001 From: Chris Sienkiewicz Date: Thu, 25 Feb 2021 11:33:08 -0800 Subject: [PATCH 4/7] Fix merge --- NuGet.config | 1 + eng/Versions.props | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NuGet.config b/NuGet.config index e0e61bbbf..687b1bf8e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -6,6 +6,7 @@ + diff --git a/eng/Versions.props b/eng/Versions.props index 2976df46c..e84c615fa 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -10,7 +10,7 @@ true true true - 3.8.0-4.20464.1 + 3.8.0-5.final 16.1.1 From 5f100730b7f32b0dec40a571d5708498c374f254 Mon Sep 17 00:00:00 2001 From: Chris Sienkiewicz Date: Thu, 25 Feb 2021 11:46:56 -0800 Subject: [PATCH 5/7] PR feedback --- .../ComponentDebugger/DebugProfileProvider.cs | 46 +++++++++++-------- .../DebuggerOptionsViewModel.cs | 23 ++++++---- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs index d58b05066..e0162cb2c 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs @@ -9,6 +9,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using Microsoft.VisualStudio; using Microsoft.VisualStudio.ProjectSystem; using Microsoft.VisualStudio.ProjectSystem.Debug; using Microsoft.VisualStudio.ProjectSystem.VS.Debug; @@ -26,7 +27,7 @@ public class DebugProfileProvider : IDebugProfileLaunchTargetsProvider private readonly ConfiguredProject _configuredProject; private readonly LaunchSettingsManager _launchSettingsManager; private readonly IProjectThreadingService _threadingService; - private readonly AsyncLazy _compilerRoot; + private readonly AsyncLazy _compilerRoot; [ImportingConstructor] [Obsolete("This exported object must be obtained through the MEF export provider.", error: true)] @@ -36,7 +37,7 @@ public DebugProfileProvider(ConfiguredProject configuredProject, LaunchSettingsM _launchSettingsManager = launchSettingsManager; _threadingService = threadingService; - _compilerRoot = new AsyncLazy(() => GetCompilerRootAsync(serviceProvider), _threadingService.JoinableTaskFactory); + _compilerRoot = new AsyncLazy(() => GetCompilerRootAsync(serviceProvider), _threadingService.JoinableTaskFactory); } public Task OnAfterLaunchAsync(DebugLaunchOptions launchOptions, ILaunchProfile profile) => Task.CompletedTask; @@ -54,36 +55,43 @@ public async Task> QueryDebugTargetsAsync(De LaunchDebugEngineGuid = Microsoft.VisualStudio.ProjectSystem.Debug.DebuggerEngines.ManagedOnlyEngine, LaunchOperation = DebugLaunchOperation.CreateProcess }; - - // try and get the target project - var targetProjectUnconfigured = await _launchSettingsManager.TryGetProjectForLaunchAsync(profile); - if (targetProjectUnconfigured is object) + + var compilerRoot = await _compilerRoot.GetValueAsync(); + if (compilerRoot is object) { - settings.CurrentDirectory = Path.GetDirectoryName(targetProjectUnconfigured.FullPath); - var compiler = _configuredProject.Capabilities.Contains(ProjectCapabilities.VB) ? "vbc.exe" : "csc.exe"; - var compilerRoot = await _compilerRoot.GetValueAsync(); - settings.Executable = Path.Combine(compilerRoot, compiler); + // try and get the target project + var targetProjectUnconfigured = await _launchSettingsManager.TryGetProjectForLaunchAsync(profile); + if (targetProjectUnconfigured is object) + { + settings.CurrentDirectory = Path.GetDirectoryName(targetProjectUnconfigured.FullPath); + var compiler = _configuredProject.Capabilities.Contains(ProjectCapabilities.VB) ? "vbc.exe" : "csc.exe"; + settings.Executable = Path.Combine(compilerRoot, compiler); - // get its compilation args - var args = await targetProjectUnconfigured.GetCompilationArgumentsAsync(); + // get its compilation args + var args = await targetProjectUnconfigured.GetCompilationArgumentsAsync(); - // append the command line args to the debugger launch - settings.Arguments = string.Join(" ", args); + // append the command line args to the debugger launch + settings.Arguments = string.Join(" ", args); + } } - // https://github.com/dotnet/roslyn-sdk/issues/728 : better error handling return new IDebugLaunchSettings[] { settings }; } - private async Task GetCompilerRootAsync(SVsServiceProvider? serviceProvider) + private async Task GetCompilerRootAsync(SVsServiceProvider? serviceProvider) { await _threadingService.SwitchToUIThread(); // https://github.com/dotnet/roslyn-sdk/issues/729 : don't hardcode net fx compiler - object rootDir = string.Empty; var shell = (IVsShell?)serviceProvider?.GetService(typeof(SVsShell)); - shell?.GetProperty((int)__VSSPROPID2.VSSPROPID_InstallRootDir, out rootDir); - return Path.Combine((string)rootDir, "MSBuild", "Current", "Bin", "Roslyn"); + if (shell is object + && shell.GetProperty((int)__VSSPROPID2.VSSPROPID_InstallRootDir, out var rootDirObj) == VSConstants.S_OK + && rootDirObj is string rootDir) + { + return Path.Combine(rootDir, "MSBuild", "Current", "Bin", "Roslyn"); + } + + return null; } } } diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptionsViewModel.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptionsViewModel.cs index 481c5779c..180012a97 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptionsViewModel.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebuggerOptionsViewModel.cs @@ -6,13 +6,14 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.ComponentModel; +using System.Linq; using System.Runtime.CompilerServices; namespace Roslyn.ComponentDebugger { - internal class DebuggerOptionsViewModel : INotifyPropertyChanged + internal sealed class DebuggerOptionsViewModel : INotifyPropertyChanged { - private readonly Action indexChanged; + private readonly Action _indexChanged; private IEnumerable _projectNames = ImmutableArray.Empty; @@ -22,7 +23,7 @@ internal class DebuggerOptionsViewModel : INotifyPropertyChanged public DebuggerOptionsViewModel(Action indexChanged) { - this.indexChanged = indexChanged; + _indexChanged = indexChanged; } public IEnumerable ProjectNames @@ -30,8 +31,11 @@ public IEnumerable ProjectNames get => _projectNames; set { - _projectNames = value; - NotifyPropertyChanged(); + if (!_projectNames.SequenceEqual(value)) + { + _projectNames = value; + NotifyPropertyChanged(); + } } } @@ -40,9 +44,12 @@ public int SelectedProjectIndex get => _selectedProjectIndex; set { - _selectedProjectIndex = value; - NotifyPropertyChanged(); - indexChanged(value); + if (_selectedProjectIndex != value) + { + _selectedProjectIndex = value; + NotifyPropertyChanged(); + _indexChanged?.Invoke(value); + } } } From 287dab4dce4a6999213518d57b69acc66606a2df Mon Sep 17 00:00:00 2001 From: Chris Sienkiewicz Date: Thu, 25 Feb 2021 11:57:37 -0800 Subject: [PATCH 6/7] Fix warnings --- .../CommandLineArgumentsDataSource.cs | 9 +++++++-- .../ComponentDebugger/DebugProfileProvider.cs | 8 ++++---- .../ComponentDebugger/LaunchSettingsManager.cs | 12 +++++++++++- .../ComponentDebugger/LaunchSettingsProvider.cs | 2 +- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs index af2ff204f..4f58c692f 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs @@ -21,7 +21,7 @@ public class CommandLineArgumentsDataSource : UnconfiguredProjectHostBridge> GetArgsAsync() { using (JoinableCollection.Join()) { - await this.InitializeAsync(); + await this.InitializeAsync().ConfigureAwait(true); return this.AppliedValue?.Value ?? ImmutableArray.Empty; } } @@ -51,6 +51,11 @@ protected override IDisposable LinkExternalInput(ITargetBlock>> PreprocessAsync(IProjectVersionedValue input, IProjectVersionedValue>? previousOutput) { + if (input is null) + { + throw new ArgumentNullException(nameof(input)); + } + var description = input.Value.ProjectChanges[Constants.CommandLineArgsRuleName]; return Task.FromResult>>(new ProjectVersionedValue>(description.After.Items.Keys.ToImmutableArray(), input.DataSourceVersions)); } diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs index e0162cb2c..5f2ca2b3e 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/DebugProfileProvider.cs @@ -55,12 +55,12 @@ public async Task> QueryDebugTargetsAsync(De LaunchDebugEngineGuid = Microsoft.VisualStudio.ProjectSystem.Debug.DebuggerEngines.ManagedOnlyEngine, LaunchOperation = DebugLaunchOperation.CreateProcess }; - - var compilerRoot = await _compilerRoot.GetValueAsync(); + + var compilerRoot = await _compilerRoot.GetValueAsync().ConfigureAwait(true); if (compilerRoot is object) { // try and get the target project - var targetProjectUnconfigured = await _launchSettingsManager.TryGetProjectForLaunchAsync(profile); + var targetProjectUnconfigured = await _launchSettingsManager.TryGetProjectForLaunchAsync(profile).ConfigureAwait(true); if (targetProjectUnconfigured is object) { settings.CurrentDirectory = Path.GetDirectoryName(targetProjectUnconfigured.FullPath); @@ -68,7 +68,7 @@ public async Task> QueryDebugTargetsAsync(De settings.Executable = Path.Combine(compilerRoot, compiler); // get its compilation args - var args = await targetProjectUnconfigured.GetCompilationArgumentsAsync(); + var args = await targetProjectUnconfigured.GetCompilationArgumentsAsync().ConfigureAwait(true); // append the command line args to the debugger launch settings.Arguments = string.Join(" ", args); diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs index ee7e3097b..d9eab52c6 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs @@ -31,7 +31,7 @@ public LaunchSettingsManager(UnconfiguredProject owningProject, IDebugTokenRepla if (value is string targetProjectPath) { // expand any variables in the path, and root it based on this project - var replacedProjectPath = await tokenReplacer.ReplaceTokensInStringAsync(targetProjectPath, true); + var replacedProjectPath = await tokenReplacer.ReplaceTokensInStringAsync(targetProjectPath, true).ConfigureAwait(true); replacedProjectPath = owningProject.MakeRooted(replacedProjectPath); targetProject = ((IProjectService2)owningProject.Services.ProjectService).GetLoadedProject(replacedProjectPath); @@ -41,6 +41,16 @@ public LaunchSettingsManager(UnconfiguredProject owningProject, IDebugTokenRepla public void WriteProjectForLaunch(IWritableLaunchProfile profile, UnconfiguredProject targetProject) { + if (profile is null) + { + throw new System.ArgumentNullException(nameof(profile)); + } + + if (targetProject is null) + { + throw new System.ArgumentNullException(nameof(targetProject)); + } + var rootedPath = this.owningProject.MakeRelative(targetProject.FullPath); profile.OtherSettings[Constants.TargetProjectPropertyName] = rootedPath; } diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs index 238692807..7df0bc776 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs @@ -82,7 +82,7 @@ private async Task UpdateViewModelAsync() } _projects = targetProjects.ToImmutableAndFree(); - var launchTargetProject = await _launchSettingsManager.TryGetProjectForLaunchAsync(_launchProfile?.ToLaunchProfile()); + var launchTargetProject = await _launchSettingsManager.TryGetProjectForLaunchAsync(_launchProfile?.ToLaunchProfile()).ConfigureAwait(true); var index = _projects.IndexOf(launchTargetProject!); _viewModel.ProjectNames = _projects.Select(p => Path.GetFileNameWithoutExtension(p.FullPath)); From 92b76ee578639f1c6de0bf90ab08cdf220e21657 Mon Sep 17 00:00:00 2001 From: Chris Sienkiewicz Date: Thu, 25 Feb 2021 15:25:52 -0800 Subject: [PATCH 7/7] PR Feedback --- .../CommandLineArgumentsDataSource.cs | 11 +++++----- .../ComponentDebugger/Constants.cs | 2 +- .../LaunchSettingsManager.cs | 20 +++++++++---------- .../LaunchSettingsProvider.cs | 2 +- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs index 4f58c692f..64174d3a2 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/CommandLineArgumentsDataSource.cs @@ -17,13 +17,14 @@ namespace Roslyn.ComponentDebugger [AppliesTo("(" + ProjectCapabilities.CSharp + " | " + ProjectCapabilities.VB + ") & !" + ProjectCapabilities.SharedAssetsProject)] public class CommandLineArgumentsDataSource : UnconfiguredProjectHostBridge, IProjectVersionedValue>, IProjectVersionedValue>> { - private readonly IActiveConfiguredProjectSubscriptionService activeProjectSubscriptionService; + private readonly IActiveConfiguredProjectSubscriptionService _activeProjectSubscriptionService; [ImportingConstructor] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "MEF ensures not null")] public CommandLineArgumentsDataSource(IProjectThreadingService projectThreadingService, IActiveConfiguredProjectSubscriptionService activeProjectSubscriptionService) - : base(projectThreadingService?.JoinableTaskContext) + : base(projectThreadingService.JoinableTaskContext) { - this.activeProjectSubscriptionService = activeProjectSubscriptionService; + _activeProjectSubscriptionService = activeProjectSubscriptionService; } public async Task> GetArgsAsync() @@ -41,8 +42,8 @@ public async Task> GetArgsAsync() protected override IDisposable LinkExternalInput(ITargetBlock> targetBlock) { - JoinUpstreamDataSources(this.activeProjectSubscriptionService.ProjectBuildRuleSource); - return activeProjectSubscriptionService.ProjectBuildRuleSource.SourceBlock.LinkTo(target: targetBlock, + JoinUpstreamDataSources(_activeProjectSubscriptionService.ProjectBuildRuleSource); + return _activeProjectSubscriptionService.ProjectBuildRuleSource.SourceBlock.LinkTo(target: targetBlock, linkOptions: new DataflowLinkOptions { PropagateCompletion = true }, initialDataAsNew: true, suppressVersionOnlyUpdates: true, diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/Constants.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/Constants.cs index 9181bd754..3c8bb093d 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/Constants.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/Constants.cs @@ -10,7 +10,7 @@ internal static class Constants public const string CommandName = "DebugRoslynComponent"; - public const string TargetProjectPropertyName = "targetProject"; + public const string TargetProjectKeyName = "targetProject"; public const string CommandLineArgsRuleName = "CompilerCommandLineArgs"; } diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs index d9eab52c6..6d9c97236 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsManager.cs @@ -12,29 +12,29 @@ namespace Roslyn.ComponentDebugger [Export] public class LaunchSettingsManager { - private readonly UnconfiguredProject owningProject; - private readonly IDebugTokenReplacer tokenReplacer; + private readonly UnconfiguredProject _owningProject; + private readonly IDebugTokenReplacer _tokenReplacer; [ImportingConstructor] public LaunchSettingsManager(UnconfiguredProject owningProject, IDebugTokenReplacer tokenReplacer) { - this.owningProject = owningProject; - this.tokenReplacer = tokenReplacer; + _owningProject = owningProject; + _tokenReplacer = tokenReplacer; } public async Task TryGetProjectForLaunchAsync(ILaunchProfile? profile) { UnconfiguredProject? targetProject = null; object? value = null; - profile?.OtherSettings?.TryGetValue(Constants.TargetProjectPropertyName, out value); + profile?.OtherSettings?.TryGetValue(Constants.TargetProjectKeyName, out value); if (value is string targetProjectPath) { // expand any variables in the path, and root it based on this project - var replacedProjectPath = await tokenReplacer.ReplaceTokensInStringAsync(targetProjectPath, true).ConfigureAwait(true); - replacedProjectPath = owningProject.MakeRooted(replacedProjectPath); + var replacedProjectPath = await _tokenReplacer.ReplaceTokensInStringAsync(targetProjectPath, true).ConfigureAwait(true); + replacedProjectPath = _owningProject.MakeRooted(replacedProjectPath); - targetProject = ((IProjectService2)owningProject.Services.ProjectService).GetLoadedProject(replacedProjectPath); + targetProject = ((IProjectService2)_owningProject.Services.ProjectService).GetLoadedProject(replacedProjectPath); } return targetProject; } @@ -51,8 +51,8 @@ public void WriteProjectForLaunch(IWritableLaunchProfile profile, UnconfiguredPr throw new System.ArgumentNullException(nameof(targetProject)); } - var rootedPath = this.owningProject.MakeRelative(targetProject.FullPath); - profile.OtherSettings[Constants.TargetProjectPropertyName] = rootedPath; + var rootedPath = _owningProject.MakeRelative(targetProject.FullPath); + profile.OtherSettings[Constants.TargetProjectKeyName] = rootedPath; } } diff --git a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs index 7df0bc776..43b54a2d7 100644 --- a/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs +++ b/src/VisualStudio.Roslyn.SDK/ComponentDebugger/LaunchSettingsProvider.cs @@ -73,7 +73,7 @@ private async Task UpdateViewModelAsync() // check if the args contain the project as an analyzer ref foreach (var arg in await targetProjectUnconfigured.GetCompilationArgumentsAsync().ConfigureAwait(false)) { - if (arg.StartsWith("/analyzer", StringComparison.OrdinalIgnoreCase) + if (arg.StartsWith("/analyzer:", StringComparison.OrdinalIgnoreCase) && arg.EndsWith(target, StringComparison.OrdinalIgnoreCase)) { targetProjects.Add(targetProjectUnconfigured);