diff --git a/src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/EditAndContinueTests.cs b/src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/EditAndContinueTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..1d47d56fba0a1641fc2d62c5312262de51a2e68f --- /dev/null +++ b/src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/EditAndContinueTests.cs @@ -0,0 +1,24 @@ +using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.VisualStudio.LanguageServices.Implementation.EditAndContinue.Interop; +using Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Framework; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Roslyn.VisualStudio.CSharp.UnitTests.ProjectSystemShim.CPS +{ + [UseExportProvider] + public class EditAndContinueTests + { + [WpfFact, WorkItem(31034, "https://github.com/dotnet/roslyn/issues/31034")] + [Trait(Traits.Feature, Traits.Features.ProjectSystemShims)] + public void EditAndContinueInterfacesAreImplemented() + { + using (var environment = new TestEnvironment()) + using (var project = CSharpHelpers.CreateCSharpCPSProject(environment, "Test", binOutputPath: null)) + { + Assert.IsAssignableFrom(project); + Assert.IsAssignableFrom(project); + } + } + } +} diff --git a/src/VisualStudio/Core/Impl/ProjectSystem/CPS/CPSProject_IVsENCRebuildableProjectCfg.cs b/src/VisualStudio/Core/Impl/ProjectSystem/CPS/CPSProject_IVsENCRebuildableProjectCfg.cs new file mode 100644 index 0000000000000000000000000000000000000000..93bf703dc86c07aee199ad3bda79d65402063e1f --- /dev/null +++ b/src/VisualStudio/Core/Impl/ProjectSystem/CPS/CPSProject_IVsENCRebuildableProjectCfg.cs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using EncInterop = Microsoft.VisualStudio.LanguageServices.Implementation.EditAndContinue.Interop; +using ShellInterop = Microsoft.VisualStudio.Shell.Interop; +using VsTextSpan = Microsoft.VisualStudio.TextManager.Interop.TextSpan; + +namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.CPS +{ + internal partial class CPSProject : EncInterop.IVsENCRebuildableProjectCfg2, EncInterop.IVsENCRebuildableProjectCfg4 + { + public int HasCustomMetadataEmitter(out bool value) + { + value = true; + return VSConstants.S_OK; + } + + public int StartDebuggingPE() + { + return _editAndContinueProject.StartDebuggingPE(); + } + + public int StopDebuggingPE() + { + return _editAndContinueProject.StopDebuggingPE(); + } + + public int GetPEidentity(Guid[] pMVID, string[] pbstrPEName) + { + return _editAndContinueProject.GetPEidentity(pMVID, pbstrPEName); + } + + public int EnterBreakStateOnPE(EncInterop.ENC_BREAKSTATE_REASON encBreakReason, ShellInterop.ENC_ACTIVE_STATEMENT[] pActiveStatements, uint cActiveStatements) + { + return _editAndContinueProject.EnterBreakStateOnPE(encBreakReason, pActiveStatements, cActiveStatements); + } + + public int GetExceptionSpanCount(out uint pcExceptionSpan) + { + pcExceptionSpan = default; + return _editAndContinueProject.GetExceptionSpanCount(out pcExceptionSpan); + } + + public int GetExceptionSpans(uint celt, ShellInterop.ENC_EXCEPTION_SPAN[] rgelt, ref uint pceltFetched) + { + return _editAndContinueProject.GetExceptionSpans(celt, rgelt, ref pceltFetched); + } + + public int GetCurrentExceptionSpanPosition(uint id, VsTextSpan[] ptsNewPosition) + { + return _editAndContinueProject.GetCurrentExceptionSpanPosition(id, ptsNewPosition); + } + + public int GetENCBuildState(ShellInterop.ENC_BUILD_STATE[] pENCBuildState) + { + return _editAndContinueProject.GetENCBuildState(pENCBuildState); + } + + public int ExitBreakStateOnPE() + { + return _editAndContinueProject.ExitBreakStateOnPE(); + } + + public int GetCurrentActiveStatementPosition(uint id, VsTextSpan[] ptsNewPosition) + { + return _editAndContinueProject.GetCurrentActiveStatementPosition(id, ptsNewPosition); + } + + public int EncApplySucceeded(int hrApplyResult) + { + return _editAndContinueProject.EncApplySucceeded(hrApplyResult); + } + + public int GetPEBuildTimeStamp(Microsoft.VisualStudio.OLE.Interop.FILETIME[] pTimeStamp) + { + return VSConstants.E_NOTIMPL; + } + + public int BuildForEnc(object pUpdatePE) + { + return _editAndContinueProject.BuildForEnc(pUpdatePE); + } + } +} diff --git a/src/VisualStudio/Core/Impl/ProjectSystem/CPS/CPSProject_IWorkspaceProjectContext.cs b/src/VisualStudio/Core/Impl/ProjectSystem/CPS/CPSProject_IWorkspaceProjectContext.cs index 9ea80f2d5c3592be491ced347a4848cca98b746b..ba4682a0013c43a495063f89ea2aab600a122d15 100644 --- a/src/VisualStudio/Core/Impl/ProjectSystem/CPS/CPSProject_IWorkspaceProjectContext.cs +++ b/src/VisualStudio/Core/Impl/ProjectSystem/CPS/CPSProject_IWorkspaceProjectContext.cs @@ -10,6 +10,7 @@ using Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel; using Microsoft.VisualStudio.LanguageServices.Implementation.TaskList; using Microsoft.VisualStudio.LanguageServices.ProjectSystem; +using Microsoft.VisualStudio.Shell.Interop; using Roslyn.Utilities; namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.CPS @@ -27,6 +28,7 @@ internal sealed partial class CPSProject : IWorkspaceProjectContext private readonly VisualStudioWorkspaceImpl _visualStudioWorkspace; private readonly IProjectCodeModel _projectCodeModel; private readonly ProjectExternalErrorReporter _externalErrorReporterOpt; + private readonly EditAndContinue.VsENCRebuildableProjectImpl _editAndContinueProject; public string DisplayName { @@ -66,6 +68,14 @@ public CPSProject(VisualStudioProject visualStudioProject, VisualStudioWorkspace _visualStudioProjectOptionsProcessor = new VisualStudioProjectOptionsProcessor(_visualStudioProject, visualStudioWorkspace.Services); } + // We don't have a SVsShellDebugger service in unit tests, in that case we can't implement ENC. We're OK + // leaving the field null in that case. + if (Shell.ServiceProvider.GlobalProvider.GetService(typeof(SVsShellDebugger)) != null) + { + // TODO: make this lazier, as fetching all the services up front during load shoudn't be necessary + _editAndContinueProject = new EditAndContinue.VsENCRebuildableProjectImpl(_visualStudioWorkspace, _visualStudioProject, Shell.ServiceProvider.GlobalProvider); + } + Guid = projectGuid; BinOutputPath = binOutputPath; }