Update to Microsoft.VisualStudio.Extensibility.Testing 0.1.135-beta
This commit is contained in:
Родитель
a42d204803
Коммит
1b795b8e6e
|
@ -21,6 +21,7 @@
|
|||
<MicrosoftCodeAnalysisPackagesVersion>4.0.0-1.21267.34</MicrosoftCodeAnalysisPackagesVersion>
|
||||
<MicrosoftVisualStudioShellPackagesVersion>17.0.0-previews-4-31709-430</MicrosoftVisualStudioShellPackagesVersion>
|
||||
<MicrosoftVisualStudioEditorPackagesVersion>17.0.391-preview-g5e248c9073</MicrosoftVisualStudioEditorPackagesVersion>
|
||||
<MicrosoftVisualStudioExtensibilityTestingVersion>0.1.135-beta</MicrosoftVisualStudioExtensibilityTestingVersion>
|
||||
<!-- Roslyn -->
|
||||
<MicrosoftCodeAnalysisAnalyzersVersion>3.3.2</MicrosoftCodeAnalysisAnalyzersVersion>
|
||||
<MicrosoftCodeAnalysisCommonVersion>$(MicrosoftCodeAnalysisPackagesVersion)</MicrosoftCodeAnalysisCommonVersion>
|
||||
|
@ -74,7 +75,8 @@
|
|||
<MicrosoftCodeAnalysisTestingVersion>1.0.1-beta1.20374.2</MicrosoftCodeAnalysisTestingVersion>
|
||||
<xunitassertVersion>$(xunitVersion)</xunitassertVersion>
|
||||
<XunitCombinatorialVersion>1.2.7</XunitCombinatorialVersion>
|
||||
<MicrosoftVisualStudioExtensibilityTestingXunitVersion>0.1.100-beta</MicrosoftVisualStudioExtensibilityTestingXunitVersion>
|
||||
<MicrosoftVisualStudioExtensibilityTestingSourceGeneratorVersion>$(MicrosoftVisualStudioExtensibilityTestingVersion)</MicrosoftVisualStudioExtensibilityTestingSourceGeneratorVersion>
|
||||
<MicrosoftVisualStudioExtensibilityTestingXunitVersion>$(MicrosoftVisualStudioExtensibilityTestingVersion)</MicrosoftVisualStudioExtensibilityTestingXunitVersion>
|
||||
<!-- Analyzers -->
|
||||
<RoslynDiagnosticsAnalyzersVersion>2.9.8</RoslynDiagnosticsAnalyzersVersion>
|
||||
<StyleCopAnalyzersVersion>1.2.0-beta.164</StyleCopAnalyzersVersion>
|
||||
|
|
|
@ -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.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using Microsoft.CodeAnalysis.Testing.InProcess;
|
||||
using Microsoft.VisualStudio.Shell;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Xunit;
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Testing
|
||||
{
|
||||
[IdeSettings(MinVersion = VisualStudioVersion.VS2022)]
|
||||
public abstract class AbstractIdeIntegrationTest : IAsyncLifetime, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// A long timeout used to avoid hangs in tests, where a test failure manifests as an operation never occurring.
|
||||
/// </summary>
|
||||
public static readonly TimeSpan HangMitigatingTimeout = TimeSpan.FromMinutes(4);
|
||||
|
||||
private JoinableTaskContext? _joinableTaskContext;
|
||||
private JoinableTaskCollection? _joinableTaskCollection;
|
||||
private JoinableTaskFactory? _joinableTaskFactory;
|
||||
|
||||
private TestServices? _testServices;
|
||||
|
||||
private CancellationTokenSource _hangMitigatingCancellationTokenSource;
|
||||
|
||||
protected AbstractIdeIntegrationTest()
|
||||
{
|
||||
Assert.True(Application.Current.Dispatcher.CheckAccess());
|
||||
|
||||
JoinableTaskContext = ThreadHelper.JoinableTaskContext;
|
||||
|
||||
_hangMitigatingCancellationTokenSource = new CancellationTokenSource(HangMitigatingTimeout);
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
protected JoinableTaskContext? JoinableTaskContext
|
||||
{
|
||||
get
|
||||
{
|
||||
return _joinableTaskContext ?? throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
private set
|
||||
{
|
||||
if (value == _joinableTaskContext)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (value is null)
|
||||
{
|
||||
_joinableTaskContext = null;
|
||||
_joinableTaskCollection = null;
|
||||
_joinableTaskFactory = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_joinableTaskContext = value;
|
||||
_joinableTaskCollection = value.CreateCollection();
|
||||
_joinableTaskFactory = value.CreateFactory(_joinableTaskCollection).WithPriority(Application.Current.Dispatcher, DispatcherPriority.Background);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
protected TestServices? TestServices
|
||||
{
|
||||
get
|
||||
{
|
||||
return _testServices ?? throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
private set
|
||||
{
|
||||
_testServices = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected JoinableTaskFactory JoinableTaskFactory
|
||||
=> _joinableTaskFactory ?? throw new InvalidOperationException();
|
||||
|
||||
protected CancellationToken HangMitigatingCancellationToken
|
||||
=> _hangMitigatingCancellationTokenSource.Token;
|
||||
|
||||
public virtual async Task InitializeAsync()
|
||||
{
|
||||
TestServices = await CreateTestServicesAsync();
|
||||
}
|
||||
|
||||
public virtual async Task DisposeAsync()
|
||||
{
|
||||
if (_joinableTaskCollection is object)
|
||||
{
|
||||
await _joinableTaskCollection.JoinTillEmptyAsync();
|
||||
}
|
||||
|
||||
JoinableTaskContext = null;
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual async Task<TestServices> CreateTestServicesAsync()
|
||||
=> await TestServices.CreateAsync(JoinableTaskFactory);
|
||||
}
|
||||
}
|
|
@ -2,13 +2,13 @@
|
|||
// 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.VisualStudio.Extensibility.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Testing
|
||||
{
|
||||
internal static class WellKnownCommandNames
|
||||
[IdeSettings(MinVersion = VisualStudioVersion.VS2022)]
|
||||
public abstract class AbstractIntegrationTest : AbstractIdeIntegrationTest
|
||||
{
|
||||
public static class Build
|
||||
{
|
||||
public const string BuildSolution = "Build.BuildSolution";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,150 +5,140 @@
|
|||
using System;
|
||||
using Microsoft.CodeAnalysis.Testing.Verifiers;
|
||||
using Microsoft.VisualStudio.Shell.Interop;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Xunit;
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Testing
|
||||
{
|
||||
public class CreateProjectTests : AbstractIdeIntegrationTest
|
||||
public class CreateProjectTests : AbstractIntegrationTest
|
||||
{
|
||||
public override async Task DisposeAsync()
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
|
||||
await TestServices.SolutionExplorer.CloseSolutionAsync();
|
||||
|
||||
await base.DisposeAsync();
|
||||
}
|
||||
|
||||
[IdeFact]
|
||||
public async Task CreateFromTemplateAsync()
|
||||
{
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests));
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", WellKnownProjectTemplates.CSharpNetCoreClassLibrary, languageName: LanguageNames.CSharp);
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests), HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", WellKnownProjectTemplates.CSharpNetCoreClassLibrary, languageName: LanguageNames.CSharp, HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(HangMitigatingCancellationToken);
|
||||
|
||||
await TestServices.Editor.SetTextAsync(@"using System");
|
||||
await TestServices.Editor.SetTextAsync(@"using System", HangMitigatingCancellationToken);
|
||||
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true);
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true, HangMitigatingCancellationToken);
|
||||
Assert.Equal("========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========", buildSummary);
|
||||
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync();
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync(HangMitigatingCancellationToken);
|
||||
|
||||
// Verify that intentional errors get validated by the test
|
||||
var errors = await TestServices.ErrorList.GetBuildErrorsAsync(__VSERRORCATEGORY.EC_ERROR);
|
||||
var errors = await TestServices.ErrorList.GetBuildErrorsAsync(__VSERRORCATEGORY.EC_ERROR, HangMitigatingCancellationToken);
|
||||
var expected = "(Compiler) Class1.cs(1, 13): error CS1002: ; expected";
|
||||
new XUnitVerifier().EqualOrDiff(expected, string.Join(Environment.NewLine, errors));
|
||||
Assert.Equal(1, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR));
|
||||
Assert.Equal(1, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR, HangMitigatingCancellationToken));
|
||||
}
|
||||
|
||||
[IdeFact]
|
||||
public async Task CreateAnalyzerFromCSharpTemplateAsync()
|
||||
{
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests));
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.CSharp.Analyzer", languageName: LanguageNames.CSharp);
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests), HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.CSharp.Analyzer", languageName: LanguageNames.CSharp, HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(HangMitigatingCancellationToken);
|
||||
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true);
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true, HangMitigatingCancellationToken);
|
||||
Assert.Equal("========== Build: 5 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========", buildSummary);
|
||||
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync();
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync(HangMitigatingCancellationToken);
|
||||
|
||||
var errors = await TestServices.ErrorList.GetBuildErrorsAsync(__VSERRORCATEGORY.EC_ERROR);
|
||||
var errors = await TestServices.ErrorList.GetBuildErrorsAsync(__VSERRORCATEGORY.EC_ERROR, HangMitigatingCancellationToken);
|
||||
new XUnitVerifier().EqualOrDiff(string.Empty, string.Join(Environment.NewLine, errors));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR, HangMitigatingCancellationToken));
|
||||
|
||||
// Currently have two analyzer warnings in the template.
|
||||
var warnings = await TestServices.ErrorList.GetBuildErrorsAsync(__VSERRORCATEGORY.EC_WARNING);
|
||||
var warnings = await TestServices.ErrorList.GetBuildErrorsAsync(__VSERRORCATEGORY.EC_WARNING, HangMitigatingCancellationToken);
|
||||
new XUnitVerifier().EqualOrDiff(string.Empty, string.Join(Environment.NewLine, warnings));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING, HangMitigatingCancellationToken));
|
||||
}
|
||||
|
||||
[IdeFact]
|
||||
public async Task CreateRefactoringFromCSharpTemplateAsync()
|
||||
{
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests));
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.CSharp.CodeRefactoring", languageName: LanguageNames.CSharp);
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests), HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.CSharp.CodeRefactoring", languageName: LanguageNames.CSharp, HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(HangMitigatingCancellationToken);
|
||||
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true);
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true, HangMitigatingCancellationToken);
|
||||
Assert.Equal("========== Build: 2 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========", buildSummary);
|
||||
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync();
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync(HangMitigatingCancellationToken);
|
||||
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR, HangMitigatingCancellationToken));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING, HangMitigatingCancellationToken));
|
||||
}
|
||||
|
||||
[IdeFact]
|
||||
public async Task CreateStandaloneToolFromCSharpTemplateAsync()
|
||||
{
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests));
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.CSharp.StandaloneCodeAnalysis", languageName: LanguageNames.CSharp);
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests), HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.CSharp.StandaloneCodeAnalysis", languageName: LanguageNames.CSharp, HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(HangMitigatingCancellationToken);
|
||||
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true);
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true, HangMitigatingCancellationToken);
|
||||
Assert.Equal("========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========", buildSummary);
|
||||
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync();
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync(HangMitigatingCancellationToken);
|
||||
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR, HangMitigatingCancellationToken));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING, HangMitigatingCancellationToken));
|
||||
}
|
||||
|
||||
[IdeFact]
|
||||
public async Task CreateAnalyzerFromVisualBasicTemplateAsync()
|
||||
{
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests));
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.VisualBasic.Analyzer", languageName: LanguageNames.VisualBasic);
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests), HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.VisualBasic.Analyzer", languageName: LanguageNames.VisualBasic, HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(HangMitigatingCancellationToken);
|
||||
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true);
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true, HangMitigatingCancellationToken);
|
||||
Assert.Equal("========== Build: 5 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========", buildSummary);
|
||||
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync();
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync(HangMitigatingCancellationToken);
|
||||
|
||||
var errors = await TestServices.ErrorList.GetBuildErrorsAsync(__VSERRORCATEGORY.EC_ERROR);
|
||||
var errors = await TestServices.ErrorList.GetBuildErrorsAsync(__VSERRORCATEGORY.EC_ERROR, HangMitigatingCancellationToken);
|
||||
new XUnitVerifier().EqualOrDiff(string.Empty, string.Join(Environment.NewLine, errors));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR, HangMitigatingCancellationToken));
|
||||
|
||||
// Currently have two analyzer warnings in the template.
|
||||
var warnings = await TestServices.ErrorList.GetBuildErrorsAsync(__VSERRORCATEGORY.EC_WARNING);
|
||||
var warnings = await TestServices.ErrorList.GetBuildErrorsAsync(__VSERRORCATEGORY.EC_WARNING, HangMitigatingCancellationToken);
|
||||
new XUnitVerifier().EqualOrDiff(string.Empty, string.Join(Environment.NewLine, warnings));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING, HangMitigatingCancellationToken));
|
||||
}
|
||||
|
||||
[IdeFact]
|
||||
public async Task CreateRefactoringFromVisualBasicTemplateAsync()
|
||||
{
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests));
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.VisualBasic.CodeRefactoring", languageName: LanguageNames.VisualBasic);
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests), HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.VisualBasic.CodeRefactoring", languageName: LanguageNames.VisualBasic, HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(HangMitigatingCancellationToken);
|
||||
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true);
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true, HangMitigatingCancellationToken);
|
||||
Assert.Equal("========== Build: 2 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========", buildSummary);
|
||||
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync();
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync(HangMitigatingCancellationToken);
|
||||
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR, HangMitigatingCancellationToken));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING, HangMitigatingCancellationToken));
|
||||
}
|
||||
|
||||
[IdeFact]
|
||||
public async Task CreateStandaloneToolFromVisualBasicTemplateAsync()
|
||||
{
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests));
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.VisualBasic.StandaloneCodeAnalysis", languageName: LanguageNames.VisualBasic);
|
||||
await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(CreateProjectTests), HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.AddProjectAsync("TestProj", "Microsoft.VisualBasic.StandaloneCodeAnalysis", languageName: LanguageNames.VisualBasic, HangMitigatingCancellationToken);
|
||||
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(HangMitigatingCancellationToken);
|
||||
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true);
|
||||
var buildSummary = await TestServices.SolutionExplorer.BuildSolutionAsync(waitForBuildToFinish: true, HangMitigatingCancellationToken);
|
||||
Assert.Equal("========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========", buildSummary);
|
||||
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync();
|
||||
await TestServices.ErrorList.ShowBuildErrorsAsync(HangMitigatingCancellationToken);
|
||||
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_ERROR, HangMitigatingCancellationToken));
|
||||
Assert.Equal(0, await TestServices.ErrorList.GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING, HangMitigatingCancellationToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,60 +2,19 @@
|
|||
// 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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
using Microsoft.VisualStudio.Text.Editor;
|
||||
using Microsoft.VisualStudio.TextManager.Interop;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Testing.InProcess
|
||||
namespace Microsoft.VisualStudio.Extensibility.Testing
|
||||
{
|
||||
public class EditorInProcess : InProcComponent
|
||||
internal partial class EditorInProcess
|
||||
{
|
||||
internal static readonly Guid IWpfTextViewId = new Guid("8C40265E-9FDB-4F54-A0FD-EBB72B7D0476");
|
||||
|
||||
public EditorInProcess(TestServices testServices)
|
||||
: base(testServices)
|
||||
public async Task SetTextAsync(string text, CancellationToken cancellationToken)
|
||||
{
|
||||
}
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
public async Task<IWpfTextView> GetActiveTextViewAsync()
|
||||
=> (await GetActiveTextViewHostAsync()).TextView;
|
||||
|
||||
private async Task<IVsTextView> GetActiveVsTextViewAsync()
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
|
||||
var vsTextManager = await GetRequiredGlobalServiceAsync<SVsTextManager, IVsTextManager>();
|
||||
|
||||
ErrorHandler.ThrowOnFailure(vsTextManager.GetActiveView(fMustHaveFocus: 1, pBuffer: null, ppView: out var vsTextView));
|
||||
|
||||
return vsTextView;
|
||||
}
|
||||
|
||||
private async Task<IWpfTextViewHost> GetActiveTextViewHostAsync()
|
||||
{
|
||||
// The active text view might not have finished composing yet, waiting for the application to 'idle'
|
||||
// means that it is done pumping messages (including WM_PAINT) and the window should return the correct text
|
||||
// view.
|
||||
await WaitForApplicationIdleAsync(CancellationToken.None);
|
||||
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
|
||||
var activeVsTextView = (IVsUserData)await GetActiveVsTextViewAsync();
|
||||
|
||||
ErrorHandler.ThrowOnFailure(activeVsTextView.GetData(IWpfTextViewId, out var wpfTextViewHost));
|
||||
|
||||
return (IWpfTextViewHost)wpfTextViewHost;
|
||||
}
|
||||
|
||||
public async Task SetTextAsync(string text)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
|
||||
var view = await GetActiveTextViewAsync();
|
||||
var view = await GetActiveTextViewAsync(cancellationToken);
|
||||
var textSnapshot = view.TextSnapshot;
|
||||
var replacementSpan = new SnapshotSpan(textSnapshot, 0, textSnapshot.Length);
|
||||
view.TextBuffer.Replace(replacementSpan, text);
|
||||
|
|
|
@ -7,7 +7,9 @@ using System.Collections.Generic;
|
|||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.Extensibility.Testing;
|
||||
using Microsoft.VisualStudio.Shell;
|
||||
using Microsoft.VisualStudio.Shell.Interop;
|
||||
using Microsoft.VisualStudio.Shell.TableControl;
|
||||
|
@ -16,18 +18,14 @@ using Task = System.Threading.Tasks.Task;
|
|||
|
||||
namespace Microsoft.CodeAnalysis.Testing.InProcess
|
||||
{
|
||||
public class ErrorListInProcess : InProcComponent
|
||||
[TestService]
|
||||
internal partial class ErrorListInProcess
|
||||
{
|
||||
public ErrorListInProcess(TestServices testServices)
|
||||
: base(testServices)
|
||||
public async Task ShowBuildErrorsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
}
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
public async Task ShowBuildErrorsAsync()
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
|
||||
var errorList = await GetRequiredGlobalServiceAsync<SVsErrorList, IErrorList>();
|
||||
var errorList = await GetRequiredGlobalServiceAsync<SVsErrorList, IErrorList>(cancellationToken);
|
||||
errorList.AreBuildErrorSourceEntriesShown = true;
|
||||
errorList.AreOtherErrorSourceEntriesShown = false;
|
||||
errorList.AreErrorsShown = true;
|
||||
|
@ -35,11 +33,16 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
errorList.AreWarningsShown = false;
|
||||
}
|
||||
|
||||
public async Task<ImmutableArray<string>> GetBuildErrorsAsync(__VSERRORCATEGORY minimumSeverity = __VSERRORCATEGORY.EC_WARNING)
|
||||
public Task<ImmutableArray<string>> GetBuildErrorsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
return GetBuildErrorsAsync(__VSERRORCATEGORY.EC_WARNING, cancellationToken);
|
||||
}
|
||||
|
||||
var errorItems = await GetErrorItemsAsync();
|
||||
public async Task<ImmutableArray<string>> GetBuildErrorsAsync(__VSERRORCATEGORY minimumSeverity, CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var errorItems = await GetErrorItemsAsync(cancellationToken);
|
||||
var list = new List<string>();
|
||||
|
||||
foreach (var item in errorItems)
|
||||
|
@ -79,19 +82,24 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
.ToImmutableArray();
|
||||
}
|
||||
|
||||
public async Task<int> GetErrorCountAsync(__VSERRORCATEGORY minimumSeverity = __VSERRORCATEGORY.EC_WARNING)
|
||||
public Task<int> GetErrorCountAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
return GetErrorCountAsync(__VSERRORCATEGORY.EC_WARNING, cancellationToken);
|
||||
}
|
||||
|
||||
var errorItems = await GetErrorItemsAsync();
|
||||
public async Task<int> GetErrorCountAsync(__VSERRORCATEGORY minimumSeverity, CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var errorItems = await GetErrorItemsAsync(cancellationToken);
|
||||
return errorItems.Count(e => e.GetCategory() <= minimumSeverity);
|
||||
}
|
||||
|
||||
private async Task<ImmutableArray<ITableEntryHandle>> GetErrorItemsAsync()
|
||||
private async Task<ImmutableArray<ITableEntryHandle>> GetErrorItemsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var errorList = await GetRequiredGlobalServiceAsync<SVsErrorList, IErrorList>();
|
||||
var errorList = await GetRequiredGlobalServiceAsync<SVsErrorList, IErrorList>(cancellationToken);
|
||||
var args = await errorList.TableControl.ForceUpdateAsync();
|
||||
return args.AllEntries.ToImmutableArray();
|
||||
}
|
||||
|
|
|
@ -1,76 +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 System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
using Microsoft.VisualStudio.ComponentModelHost;
|
||||
using Microsoft.VisualStudio.Shell;
|
||||
using Microsoft.VisualStudio.Shell.Interop;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Testing.InProcess
|
||||
{
|
||||
public abstract class InProcComponent
|
||||
{
|
||||
protected InProcComponent(TestServices testServices)
|
||||
{
|
||||
TestServices = testServices ?? throw new ArgumentNullException(nameof(testServices));
|
||||
}
|
||||
|
||||
public TestServices TestServices { get; }
|
||||
|
||||
protected JoinableTaskFactory JoinableTaskFactory => TestServices.JoinableTaskFactory;
|
||||
|
||||
protected async Task ExecuteCommandAsync(string commandName, string args = "")
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
|
||||
var dte = await GetRequiredGlobalServiceAsync<SDTE, EnvDTE.DTE>();
|
||||
dte.ExecuteCommand(commandName, args);
|
||||
}
|
||||
|
||||
protected async Task<TInterface> GetRequiredGlobalServiceAsync<TService, TInterface>()
|
||||
where TService : class
|
||||
where TInterface : class
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
|
||||
var serviceProvider = (IAsyncServiceProvider2?)await AsyncServiceProvider.GlobalProvider.GetServiceAsync(typeof(SAsyncServiceProvider));
|
||||
Assumes.Present(serviceProvider);
|
||||
|
||||
var @interface = (TInterface?)await serviceProvider.GetServiceAsync(typeof(TService));
|
||||
Assumes.Present(@interface);
|
||||
return @interface;
|
||||
}
|
||||
|
||||
protected async Task<TService> GetComponentModelServiceAsync<TService>()
|
||||
where TService : class
|
||||
{
|
||||
var componentModel = await GetRequiredGlobalServiceAsync<SComponentModel, IComponentModel>();
|
||||
return componentModel.GetService<TService>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waiting for the application to 'idle' means that it is done pumping messages (including WM_PAINT).
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token that the operation will observe.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
protected static async Task WaitForApplicationIdleAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var synchronizationContext = new DispatcherSynchronizationContext(Application.Current.Dispatcher, DispatcherPriority.ApplicationIdle);
|
||||
var taskScheduler = new SynchronizationContextTaskScheduler(synchronizationContext);
|
||||
await Task.Factory.StartNew(
|
||||
() => { },
|
||||
cancellationToken,
|
||||
TaskCreationOptions.None,
|
||||
taskScheduler);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,119 +8,42 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Testing;
|
||||
using Microsoft.VisualStudio.OperationProgress;
|
||||
using Microsoft.VisualStudio.Shell;
|
||||
using Microsoft.VisualStudio.Shell.Interop;
|
||||
using Microsoft.VisualStudio.Text.Editor;
|
||||
using Microsoft.VisualStudio.TextManager.Interop;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using NuGet.SolutionRestoreManager;
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Testing.InProcess
|
||||
namespace Microsoft.VisualStudio.Extensibility.Testing
|
||||
{
|
||||
public class SolutionExplorerInProcess : InProcComponent
|
||||
internal partial class SolutionExplorerInProcess
|
||||
{
|
||||
public SolutionExplorerInProcess(TestServices testServices)
|
||||
: base(testServices)
|
||||
public async Task CreateSolutionAsync(string solutionName, CancellationToken cancellationToken)
|
||||
{
|
||||
}
|
||||
|
||||
private async Task<bool> IsSolutionOpenAsync()
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
|
||||
var solution = await GetRequiredGlobalServiceAsync<SVsSolution, IVsSolution>();
|
||||
ErrorHandler.ThrowOnFailure(solution.GetProperty((int)__VSPROPID.VSPROPID_IsSolutionOpen, out var isOpen));
|
||||
return (bool)isOpen;
|
||||
}
|
||||
|
||||
public async Task CloseSolutionAsync(bool saveFirst = false)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
if (!await IsSolutionOpenAsync())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (saveFirst)
|
||||
{
|
||||
await SaveSolutionAsync();
|
||||
}
|
||||
|
||||
await CloseSolutionAsync();
|
||||
}
|
||||
|
||||
private async Task CloseSolutionAsync()
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
|
||||
var solution = await GetRequiredGlobalServiceAsync<SVsSolution, IVsSolution>();
|
||||
if (!await IsSolutionOpenAsync())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var semaphore = new SemaphoreSlim(1);
|
||||
using var solutionEvents = new SolutionEvents(JoinableTaskFactory, solution);
|
||||
|
||||
await semaphore.WaitAsync();
|
||||
|
||||
void HandleAfterCloseSolution(object sender, EventArgs e) => semaphore.Release();
|
||||
|
||||
solutionEvents.AfterCloseSolution += HandleAfterCloseSolution;
|
||||
try
|
||||
{
|
||||
ErrorHandler.ThrowOnFailure(solution.CloseSolutionElement((uint)__VSSLNCLOSEOPTIONS.SLNCLOSEOPT_DeleteProject | (uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_NoSave, null, 0));
|
||||
await semaphore.WaitAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
solutionEvents.AfterCloseSolution -= HandleAfterCloseSolution;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CreateSolutionAsync(string solutionName)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var solutionPath = CreateTemporaryPath();
|
||||
await CreateSolutionAsync(solutionPath, solutionName);
|
||||
await CreateSolutionAsync(solutionPath, solutionName, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task CreateSolutionAsync(string solutionPath, string solutionName)
|
||||
private async Task CreateSolutionAsync(string solutionPath, string solutionName, CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
await CloseSolutionAsync();
|
||||
await CloseSolutionAsync(cancellationToken);
|
||||
|
||||
var solutionFileName = Path.ChangeExtension(solutionName, ".sln");
|
||||
Directory.CreateDirectory(solutionPath);
|
||||
|
||||
var solution = await GetRequiredGlobalServiceAsync<SVsSolution, IVsSolution>();
|
||||
var solution = await GetRequiredGlobalServiceAsync<SVsSolution, IVsSolution>(cancellationToken);
|
||||
ErrorHandler.ThrowOnFailure(solution.CreateSolution(solutionPath, solutionFileName, (uint)__VSCREATESOLUTIONFLAGS.CSF_SILENT));
|
||||
ErrorHandler.ThrowOnFailure(solution.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, null, 0));
|
||||
}
|
||||
|
||||
public async Task SaveSolutionAsync()
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
|
||||
if (!await IsSolutionOpenAsync())
|
||||
{
|
||||
throw new InvalidOperationException("Cannot save solution when no solution is open.");
|
||||
}
|
||||
|
||||
var solution = await GetRequiredGlobalServiceAsync<SVsSolution, IVsSolution>();
|
||||
|
||||
// Make sure the directory exists so the Save dialog doesn't appear
|
||||
ErrorHandler.ThrowOnFailure(solution.GetSolutionInfo(out var solutionDirectory, out _, out _));
|
||||
Directory.CreateDirectory(solutionDirectory);
|
||||
|
||||
ErrorHandler.ThrowOnFailure(solution.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, null, 0));
|
||||
}
|
||||
|
||||
private static string ConvertLanguageName(string languageName)
|
||||
{
|
||||
return languageName switch
|
||||
|
@ -131,11 +54,11 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
};
|
||||
}
|
||||
|
||||
private async Task<string> GetDirectoryNameAsync()
|
||||
private async Task<string> GetDirectoryNameAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var solution = await GetRequiredGlobalServiceAsync<SVsSolution, IVsSolution>();
|
||||
var solution = await GetRequiredGlobalServiceAsync<SVsSolution, IVsSolution>(cancellationToken);
|
||||
ErrorHandler.ThrowOnFailure(solution.GetSolutionInfo(out _, out var solutionFileFullPath, out _));
|
||||
if (string.IsNullOrEmpty(solutionFileFullPath))
|
||||
{
|
||||
|
@ -145,11 +68,11 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
return Path.GetDirectoryName(solutionFileFullPath);
|
||||
}
|
||||
|
||||
private async Task<ImmutableDictionary<string, string>> GetCSharpProjectTemplatesAsync()
|
||||
private async Task<ImmutableDictionary<string, string>> GetCSharpProjectTemplatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var hostLocale = await GetRequiredGlobalServiceAsync<SUIHostLocale, IUIHostLocale>();
|
||||
var hostLocale = await GetRequiredGlobalServiceAsync<SUIHostLocale, IUIHostLocale>(cancellationToken);
|
||||
ErrorHandler.ThrowOnFailure(hostLocale.GetUILocale(out var localeID));
|
||||
|
||||
var builder = ImmutableDictionary.CreateBuilder<string, string>();
|
||||
|
@ -162,11 +85,11 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
return builder.ToImmutable();
|
||||
}
|
||||
|
||||
private async Task<ImmutableDictionary<string, string>> GetVisualBasicProjectTemplatesAsync()
|
||||
private async Task<ImmutableDictionary<string, string>> GetVisualBasicProjectTemplatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var hostLocale = await GetRequiredGlobalServiceAsync<SUIHostLocale, IUIHostLocale>();
|
||||
var hostLocale = await GetRequiredGlobalServiceAsync<SUIHostLocale, IUIHostLocale>(cancellationToken);
|
||||
ErrorHandler.ThrowOnFailure(hostLocale.GetUILocale(out var localeID));
|
||||
|
||||
var builder = ImmutableDictionary.CreateBuilder<string, string>();
|
||||
|
@ -179,31 +102,31 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
return builder.ToImmutable();
|
||||
}
|
||||
|
||||
public async Task AddProjectAsync(string projectName, string projectTemplate, string languageName)
|
||||
public async Task AddProjectAsync(string projectName, string projectTemplate, string languageName, CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var projectPath = Path.Combine(await GetDirectoryNameAsync(), projectName);
|
||||
var projectTemplatePath = await GetProjectTemplatePathAsync(projectTemplate, ConvertLanguageName(languageName));
|
||||
var solution = await GetRequiredGlobalServiceAsync<SVsSolution, IVsSolution6>();
|
||||
var projectPath = Path.Combine(await GetDirectoryNameAsync(cancellationToken), projectName);
|
||||
var projectTemplatePath = await GetProjectTemplatePathAsync(projectTemplate, ConvertLanguageName(languageName), cancellationToken);
|
||||
var solution = await GetRequiredGlobalServiceAsync<SVsSolution, IVsSolution6>(cancellationToken);
|
||||
ErrorHandler.ThrowOnFailure(solution.AddNewProjectFromTemplate(projectTemplatePath, null, null, projectPath, projectName, null, out _));
|
||||
}
|
||||
|
||||
private async Task<string> GetProjectTemplatePathAsync(string projectTemplate, string languageName)
|
||||
private async Task<string> GetProjectTemplatePathAsync(string projectTemplate, string languageName, CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var dte = await GetRequiredGlobalServiceAsync<SDTE, EnvDTE.DTE>();
|
||||
var dte = await GetRequiredGlobalServiceAsync<SDTE, EnvDTE.DTE>(cancellationToken);
|
||||
var solution = (EnvDTE80.Solution2)dte.Solution;
|
||||
|
||||
if (string.Equals(languageName, "csharp", StringComparison.OrdinalIgnoreCase)
|
||||
&& (await GetCSharpProjectTemplatesAsync()).TryGetValue(projectTemplate, out var csharpProjectTemplate))
|
||||
&& (await GetCSharpProjectTemplatesAsync(cancellationToken)).TryGetValue(projectTemplate, out var csharpProjectTemplate))
|
||||
{
|
||||
return solution.GetProjectTemplate(csharpProjectTemplate, languageName);
|
||||
}
|
||||
|
||||
if (string.Equals(languageName, "visualbasic", StringComparison.OrdinalIgnoreCase)
|
||||
&& (await GetVisualBasicProjectTemplatesAsync()).TryGetValue(projectTemplate, out var visualBasicProjectTemplate))
|
||||
&& (await GetVisualBasicProjectTemplatesAsync(cancellationToken)).TryGetValue(projectTemplate, out var visualBasicProjectTemplate))
|
||||
{
|
||||
return solution.GetProjectTemplate(visualBasicProjectTemplate, languageName);
|
||||
}
|
||||
|
@ -213,9 +136,9 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
|
||||
public async Task RestoreNuGetPackagesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var dte = await GetRequiredGlobalServiceAsync<SDTE, EnvDTE.DTE>();
|
||||
var dte = await GetRequiredGlobalServiceAsync<SDTE, EnvDTE.DTE>(cancellationToken);
|
||||
var solution = (EnvDTE80.Solution2)dte.Solution;
|
||||
foreach (var project in solution.Projects.OfType<EnvDTE.Project>())
|
||||
{
|
||||
|
@ -225,17 +148,17 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
|
||||
public async Task RestoreNuGetPackagesAsync(string projectName, CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var operationProgressStatus = await GetRequiredGlobalServiceAsync<SVsOperationProgress, IVsOperationProgressStatusService>();
|
||||
var operationProgressStatus = await GetRequiredGlobalServiceAsync<SVsOperationProgress, IVsOperationProgressStatusService>(cancellationToken);
|
||||
var stageStatus = operationProgressStatus.GetStageStatus(CommonOperationProgressStageIds.Intellisense);
|
||||
await stageStatus.WaitForCompletionAsync();
|
||||
|
||||
var solutionRestoreService = await GetComponentModelServiceAsync<IVsSolutionRestoreService>();
|
||||
var solutionRestoreService = await GetComponentModelServiceAsync<IVsSolutionRestoreService>(cancellationToken);
|
||||
await solutionRestoreService.CurrentRestoreOperation;
|
||||
|
||||
var projectFullPath = (await GetProjectAsync(projectName)).FullName;
|
||||
var solutionRestoreStatusProvider = await GetComponentModelServiceAsync<IVsSolutionRestoreStatusProvider>();
|
||||
var projectFullPath = (await GetProjectAsync(projectName, cancellationToken)).FullName;
|
||||
var solutionRestoreStatusProvider = await GetComponentModelServiceAsync<IVsSolutionRestoreStatusProvider>(cancellationToken);
|
||||
if (await solutionRestoreStatusProvider.IsRestoreCompleteAsync(cancellationToken))
|
||||
{
|
||||
return;
|
||||
|
@ -255,42 +178,42 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<string?> BuildSolutionAsync(bool waitForBuildToFinish)
|
||||
public async Task<string?> BuildSolutionAsync(bool waitForBuildToFinish, CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var buildOutputWindowPane = await GetBuildOutputWindowPaneAsync();
|
||||
var buildOutputWindowPane = await GetBuildOutputWindowPaneAsync(cancellationToken);
|
||||
buildOutputWindowPane.Clear();
|
||||
|
||||
await ExecuteCommandAsync(WellKnownCommandNames.Build.BuildSolution);
|
||||
await TestServices.Shell.ExecuteCommandAsync(VSConstants.VSStd97CmdID.BuildSln, cancellationToken);
|
||||
if (waitForBuildToFinish)
|
||||
{
|
||||
return await WaitForBuildToFinishAsync(buildOutputWindowPane);
|
||||
return await WaitForBuildToFinishAsync(buildOutputWindowPane, cancellationToken);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<string> WaitForBuildToFinishAsync()
|
||||
public async Task<string> WaitForBuildToFinishAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var buildOutputWindowPane = await GetBuildOutputWindowPaneAsync();
|
||||
return await WaitForBuildToFinishAsync(buildOutputWindowPane);
|
||||
var buildOutputWindowPane = await GetBuildOutputWindowPaneAsync(cancellationToken);
|
||||
return await WaitForBuildToFinishAsync(buildOutputWindowPane, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<IVsOutputWindowPane> GetBuildOutputWindowPaneAsync()
|
||||
public async Task<IVsOutputWindowPane> GetBuildOutputWindowPaneAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var outputWindow = await GetRequiredGlobalServiceAsync<SVsOutputWindow, IVsOutputWindow>();
|
||||
var outputWindow = await GetRequiredGlobalServiceAsync<SVsOutputWindow, IVsOutputWindow>(cancellationToken);
|
||||
ErrorHandler.ThrowOnFailure(outputWindow.GetPane(VSConstants.OutputWindowPaneGuid.BuildOutputPane_guid, out var pane));
|
||||
return pane;
|
||||
}
|
||||
|
||||
private async Task<string> WaitForBuildToFinishAsync(IVsOutputWindowPane buildOutputWindowPane)
|
||||
private async Task<string> WaitForBuildToFinishAsync(IVsOutputWindowPane buildOutputWindowPane, CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var buildManager = await GetRequiredGlobalServiceAsync<SVsSolutionBuildManager, IVsSolutionBuildManager2>();
|
||||
var buildManager = await GetRequiredGlobalServiceAsync<SVsSolutionBuildManager, IVsSolutionBuildManager2>(cancellationToken);
|
||||
using var semaphore = new SemaphoreSlim(1);
|
||||
using var solutionEvents = new UpdateSolutionEvents(buildManager);
|
||||
|
||||
|
@ -311,8 +234,8 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
ErrorHandler.ThrowOnFailure(buildOutputWindowPane.FlushToTaskList());
|
||||
|
||||
var textView = (IVsTextView)buildOutputWindowPane;
|
||||
ErrorHandler.ThrowOnFailure(((IVsUserData)textView).GetData(EditorInProcess.IWpfTextViewId, out var wpfTextViewHost));
|
||||
var lines = ((IWpfTextViewHost)wpfTextViewHost).TextView.TextViewLines;
|
||||
var wpfTextViewHost = await textView.GetTextViewHostAsync(JoinableTaskFactory, cancellationToken);
|
||||
var lines = wpfTextViewHost.TextView.TextViewLines;
|
||||
if (lines.Count < 1)
|
||||
{
|
||||
return string.Empty;
|
||||
|
@ -326,11 +249,11 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
return Path.Combine(Path.GetTempPath(), "roslyn-sdk-test", Path.GetRandomFileName());
|
||||
}
|
||||
|
||||
private async Task<EnvDTE.Project> GetProjectAsync(string nameOrFileName)
|
||||
private async Task<EnvDTE.Project> GetProjectAsync(string nameOrFileName, CancellationToken cancellationToken)
|
||||
{
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync();
|
||||
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
|
||||
|
||||
var dte = await GetRequiredGlobalServiceAsync<SDTE, EnvDTE.DTE>();
|
||||
var dte = await GetRequiredGlobalServiceAsync<SDTE, EnvDTE.DTE>(cancellationToken);
|
||||
var solution = (EnvDTE80.Solution2)dte.Solution;
|
||||
return solution.Projects.OfType<EnvDTE.Project>().First(
|
||||
project =>
|
||||
|
@ -341,84 +264,6 @@ namespace Microsoft.CodeAnalysis.Testing.InProcess
|
|||
});
|
||||
}
|
||||
|
||||
private sealed class SolutionEvents : IVsSolutionEvents, IDisposable
|
||||
{
|
||||
private readonly JoinableTaskFactory _joinableTaskFactory;
|
||||
private readonly IVsSolution _solution;
|
||||
private readonly uint _cookie;
|
||||
|
||||
public SolutionEvents(JoinableTaskFactory joinableTaskFactory, IVsSolution solution)
|
||||
{
|
||||
ThreadHelper.ThrowIfNotOnUIThread();
|
||||
|
||||
_joinableTaskFactory = joinableTaskFactory;
|
||||
_solution = solution;
|
||||
ErrorHandler.ThrowOnFailure(solution.AdviseSolutionEvents(this, out _cookie));
|
||||
}
|
||||
|
||||
public event EventHandler? AfterCloseSolution;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_joinableTaskFactory.Run(async () =>
|
||||
{
|
||||
await _joinableTaskFactory.SwitchToMainThreadAsync();
|
||||
ErrorHandler.ThrowOnFailure(_solution.UnadviseSolutionEvents(_cookie));
|
||||
});
|
||||
}
|
||||
|
||||
public int OnAfterOpenProject(IVsHierarchy pHierarchy, int fAdded)
|
||||
{
|
||||
return VSConstants.S_OK;
|
||||
}
|
||||
|
||||
public int OnQueryCloseProject(IVsHierarchy pHierarchy, int fRemoving, ref int pfCancel)
|
||||
{
|
||||
return VSConstants.S_OK;
|
||||
}
|
||||
|
||||
public int OnBeforeCloseProject(IVsHierarchy pHierarchy, int fRemoved)
|
||||
{
|
||||
return VSConstants.S_OK;
|
||||
}
|
||||
|
||||
public int OnAfterLoadProject(IVsHierarchy pStubHierarchy, IVsHierarchy pRealHierarchy)
|
||||
{
|
||||
return VSConstants.S_OK;
|
||||
}
|
||||
|
||||
public int OnQueryUnloadProject(IVsHierarchy pRealHierarchy, ref int pfCancel)
|
||||
{
|
||||
return VSConstants.S_OK;
|
||||
}
|
||||
|
||||
public int OnBeforeUnloadProject(IVsHierarchy pRealHierarchy, IVsHierarchy pStubHierarchy)
|
||||
{
|
||||
return VSConstants.S_OK;
|
||||
}
|
||||
|
||||
public int OnAfterOpenSolution(object pUnkReserved, int fNewSolution)
|
||||
{
|
||||
return VSConstants.S_OK;
|
||||
}
|
||||
|
||||
public int OnQueryCloseSolution(object pUnkReserved, ref int pfCancel)
|
||||
{
|
||||
return VSConstants.S_OK;
|
||||
}
|
||||
|
||||
public int OnBeforeCloseSolution(object pUnkReserved)
|
||||
{
|
||||
return VSConstants.S_OK;
|
||||
}
|
||||
|
||||
public int OnAfterCloseSolution(object pUnkReserved)
|
||||
{
|
||||
AfterCloseSolution?.Invoke(this, EventArgs.Empty);
|
||||
return VSConstants.S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class UpdateSolutionEvents : IVsUpdateSolutionEvents, IVsUpdateSolutionEvents2, IDisposable
|
||||
{
|
||||
private uint _cookie;
|
||||
|
|
|
@ -1,49 +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 System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Testing.InProcess
|
||||
{
|
||||
// Based on CoreCLR's implementation of the TaskScheduler they return from TaskScheduler.FromCurrentSynchronizationContext
|
||||
internal class SynchronizationContextTaskScheduler : TaskScheduler
|
||||
{
|
||||
private readonly SendOrPostCallback _postCallback;
|
||||
private readonly SynchronizationContext _synchronizationContext;
|
||||
|
||||
internal SynchronizationContextTaskScheduler(SynchronizationContext synchronizationContext)
|
||||
{
|
||||
_postCallback = new SendOrPostCallback(PostCallback);
|
||||
_synchronizationContext = synchronizationContext ?? throw new ArgumentNullException(nameof(synchronizationContext));
|
||||
}
|
||||
|
||||
public override int MaximumConcurrencyLevel => 1;
|
||||
|
||||
protected override void QueueTask(Task task)
|
||||
{
|
||||
#pragma warning disable VSTHRD001 // Avoid legacy thread switching APIs
|
||||
_synchronizationContext.Post(_postCallback, task);
|
||||
#pragma warning restore VSTHRD001 // Avoid legacy thread switching APIs
|
||||
}
|
||||
|
||||
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
|
||||
{
|
||||
if (SynchronizationContext.Current == _synchronizationContext)
|
||||
{
|
||||
return TryExecuteTask(task);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override IEnumerable<Task>? GetScheduledTasks()
|
||||
=> null;
|
||||
|
||||
private void PostCallback(object obj)
|
||||
=> TryExecuteTask((Task)obj);
|
||||
}
|
||||
}
|
|
@ -1,41 +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.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Testing.InProcess
|
||||
{
|
||||
public class TestServices
|
||||
{
|
||||
protected TestServices(JoinableTaskFactory joinableTaskFactory)
|
||||
{
|
||||
JoinableTaskFactory = joinableTaskFactory;
|
||||
|
||||
Editor = new EditorInProcess(this);
|
||||
ErrorList = new ErrorListInProcess(this);
|
||||
SolutionExplorer = new SolutionExplorerInProcess(this);
|
||||
}
|
||||
|
||||
public JoinableTaskFactory JoinableTaskFactory { get; }
|
||||
|
||||
public EditorInProcess Editor { get; }
|
||||
|
||||
public ErrorListInProcess ErrorList { get; }
|
||||
|
||||
public SolutionExplorerInProcess SolutionExplorer { get; }
|
||||
|
||||
internal static async Task<TestServices> CreateAsync(JoinableTaskFactory joinableTaskFactory)
|
||||
{
|
||||
var services = new TestServices(joinableTaskFactory);
|
||||
await services.InitializeAsync();
|
||||
return services;
|
||||
}
|
||||
|
||||
protected virtual Task InitializeAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
<PackageReference Include="DiffPlex" Version="$(DiffPlexVersion)" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.SDK.Analyzers" Version="$(MicrosoftVisualStudioSDKAnalyzersVersion)" PrivateAssets="all" />
|
||||
<PackageReference Include="NuGet.SolutionRestoreManager.Interop" Version="$(NuGetSolutionRestoreManagerInteropVersion)" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Testing.SourceGenerator" Version="$(MicrosoftVisualStudioExtensibilityTestingSourceGeneratorVersion)" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Testing.Xunit" Version="$(MicrosoftVisualStudioExtensibilityTestingXunitVersion)" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Interop" Version="$(MicrosoftVisualStudioInteropVersion)" />
|
||||
</ItemGroup>
|
||||
|
|
Загрузка…
Ссылка в новой задаче