diff --git a/src/VisualStudio/CSharp/Impl/LanguageService/CSharpLanguageService_ICSharpProjectHost.cs b/src/VisualStudio/CSharp/Impl/LanguageService/CSharpLanguageService_ICSharpProjectHost.cs index ff449c9957a1037017317735ddf08a13e0b8ea3a..79331a1b93e5f027e863d2aad2c8080638b533b6 100644 --- a/src/VisualStudio/CSharp/Impl/LanguageService/CSharpLanguageService_ICSharpProjectHost.cs +++ b/src/VisualStudio/CSharp/Impl/LanguageService/CSharpLanguageService_ICSharpProjectHost.cs @@ -24,9 +24,7 @@ public void BindToProject(ICSharpProjectRoot projectRoot, IVsHierarchy hierarchy projectName, hierarchy, this.SystemServiceProvider, - this.Package.ComponentModel.GetService(), - this.HostDiagnosticUpdateSource, - this.Workspace.Services.GetLanguageServices(LanguageNames.CSharp).GetService()); + this.Package.ComponentModel.GetService()); projectRoot.SetProjectSite(project); } diff --git a/src/VisualStudio/CSharp/Impl/ProjectSystemShim/CSharpProjectShim.cs b/src/VisualStudio/CSharp/Impl/ProjectSystemShim/CSharpProjectShim.cs index dcecfa40c4fa5296ec794e9fccf5ebd82c4b754e..3c589e03d68b1f7946ff440339e408a526f63667 100644 --- a/src/VisualStudio/CSharp/Impl/ProjectSystemShim/CSharpProjectShim.cs +++ b/src/VisualStudio/CSharp/Impl/ProjectSystemShim/CSharpProjectShim.cs @@ -6,13 +6,11 @@ using System.Runtime.InteropServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; -using Microsoft.CodeAnalysis.Host; using Microsoft.VisualStudio.ComponentModelHost; using Microsoft.VisualStudio.LanguageServices.CSharp.ProjectSystemShim.Interop; using Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel; using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem; using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.Legacy; -using Microsoft.VisualStudio.LanguageServices.Implementation.TaskList; using Microsoft.VisualStudio.Shell.Interop; namespace Microsoft.VisualStudio.LanguageServices.CSharp.ProjectSystemShim @@ -51,17 +49,14 @@ private new OptionsProcessor VisualStudioProjectOptionsProcessor string projectSystemName, IVsHierarchy hierarchy, IServiceProvider serviceProvider, - IThreadingContext threadingContext, - HostDiagnosticUpdateSource hostDiagnosticUpdateSourceOpt, - ICommandLineParserService commandLineParserServiceOpt) + IThreadingContext threadingContext) : base(projectSystemName, hierarchy, LanguageNames.CSharp, + isVsIntellisenseProject: projectRoot is IVsIntellisenseProject, serviceProvider, threadingContext, - externalErrorReportingPrefix: "CS", - hostDiagnosticUpdateSourceOpt: hostDiagnosticUpdateSourceOpt, - commandLineParserServiceOpt: commandLineParserServiceOpt) + externalErrorReportingPrefix: "CS") { _projectRoot = projectRoot; _serviceProvider = serviceProvider; diff --git a/src/VisualStudio/CSharp/Test/ProjectSystemShim/CSharpHelpers.cs b/src/VisualStudio/CSharp/Test/ProjectSystemShim/CSharpHelpers.cs index 7a9c1e7dd37e31d9e1fa8909c4c6ddcba704f0b2..f4e9bfa7336f1c5388088f91243a40536aa8630e 100644 --- a/src/VisualStudio/CSharp/Test/ProjectSystemShim/CSharpHelpers.cs +++ b/src/VisualStudio/CSharp/Test/ProjectSystemShim/CSharpHelpers.cs @@ -8,7 +8,6 @@ using System.Runtime.InteropServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.UnitTests; using Microsoft.VisualStudio; @@ -39,9 +38,7 @@ public static CSharpProjectShim CreateCSharpProject(TestEnvironment environment, projectSystemName: projectName, hierarchy: hierarchy, serviceProvider: environment.ServiceProvider, - threadingContext: environment.ThreadingContext, - hostDiagnosticUpdateSourceOpt: null, - commandLineParserServiceOpt: new CSharpCommandLineParserService()); + threadingContext: environment.ThreadingContext); } public static CPSProject CreateCSharpCPSProject(TestEnvironment environment, string projectName, params string[] commandLineArguments) diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Legacy/AbstractLegacyProject.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Legacy/AbstractLegacyProject.cs index d94c91f4737716efde3a9ef445bb91daa6895653..a6b4e3b3e3aed65fd3597a3a4c11f4c58dbf4aa8 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Legacy/AbstractLegacyProject.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Legacy/AbstractLegacyProject.cs @@ -9,10 +9,8 @@ using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; -using Microsoft.CodeAnalysis.Host; using Microsoft.VisualStudio.ComponentModelHost; using Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel; -using Microsoft.VisualStudio.LanguageServices.Implementation.EditAndContinue; using Microsoft.VisualStudio.LanguageServices.Implementation.TaskList; using Microsoft.VisualStudio.LanguageServices.ProjectSystem; using Microsoft.VisualStudio.Shell; @@ -42,6 +40,11 @@ internal abstract partial class AbstractLegacyProject : ForegroundThreadAffiniti /// private readonly string _projectDirectory = null; + /// + /// Whether we should ignore the output path for this project because it's a special project. + /// + private readonly bool _ignoreOutputPath; + private static readonly char[] PathSeparatorCharacters = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }; #region Mutable fields that should only be used from the UI thread @@ -54,11 +57,10 @@ internal abstract partial class AbstractLegacyProject : ForegroundThreadAffiniti string projectSystemName, IVsHierarchy hierarchy, string language, + bool isVsIntellisenseProject, IServiceProvider serviceProvider, IThreadingContext threadingContext, - string externalErrorReportingPrefix, - HostDiagnosticUpdateSource hostDiagnosticUpdateSourceOpt, - ICommandLineParserService commandLineParserServiceOpt) + string externalErrorReportingPrefix) : base(threadingContext, assertIsForeground: true) { Contract.ThrowIfNull(hierarchy); @@ -79,6 +81,23 @@ internal abstract partial class AbstractLegacyProject : ForegroundThreadAffiniti _projectDirectory = Path.GetDirectoryName(projectFilePath); } + if (isVsIntellisenseProject) + { + // IVsIntellisenseProjects are usually used for contained language cases, which means these projects don't have any real + // output path that we should consider. Since those point to the same IVsHierarchy as another project, we end up with two projects + // with the same output path, which potentially breaks conversion of metadata references to project references. However they're + // also used for database projects and a few other cases where there there isn't a "primary" IVsHierarchy. + // As a heuristic here we'll ignore the output path if we already have another project tied to the IVsHierarchy. + foreach (var projectId in Workspace.CurrentSolution.ProjectIds) + { + if (Workspace.GetHierarchy(projectId) == hierarchy) + { + _ignoreOutputPath = true; + break; + } + } + } + var projectFactory = componentModel.GetService(); VisualStudioProject = projectFactory.CreateAndAddToWorkspace( projectSystemName, @@ -217,6 +236,15 @@ protected void RemoveFile(string filename) protected void RefreshBinOutputPath() { + // These projects are created against the same hierarchy as the "main" project that + // hosts the rest of the code; if we query the IVsHierarchy for the output path + // we'll end up with duplicate output paths which can break P2P referencing. Since the output + // path doesn't make sense for these, we'll ignore them. + if (_ignoreOutputPath) + { + return; + } + if (!(Hierarchy is IVsBuildPropertyStorage storage)) { return; @@ -271,22 +299,6 @@ private static Guid GetProjectIDGuid(IVsHierarchy hierarchy) return Guid.Empty; } - private static bool GetIsWebsiteProject(IVsHierarchy hierarchy) - { - try - { - if (hierarchy.TryGetProject(out var project)) - { - return project.Kind == VsWebSite.PrjKind.prjKindVenusProject; - } - } - catch (Exception) - { - } - - return false; - } - /// /// Map of folder item IDs in the workspace to the string version of their path. /// diff --git a/src/VisualStudio/TestUtilities2/ProjectSystemShim/VisualBasicHelpers/VisualBasicHelpers.vb b/src/VisualStudio/TestUtilities2/ProjectSystemShim/VisualBasicHelpers/VisualBasicHelpers.vb index 1f7b5c5e03918c279f548baadc75aad169237aa5..00b75b5407d17ca6bb1d2ee6864640dd2ad94014 100644 --- a/src/VisualStudio/TestUtilities2/ProjectSystemShim/VisualBasicHelpers/VisualBasicHelpers.vb +++ b/src/VisualStudio/TestUtilities2/ProjectSystemShim/VisualBasicHelpers/VisualBasicHelpers.vb @@ -3,7 +3,6 @@ ' See the LICENSE file in the project root for more information. Imports System.IO -Imports Microsoft.CodeAnalysis.VisualBasic Imports Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Framework Imports Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim Imports Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim.Interop @@ -15,9 +14,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Vi Return New VisualBasicProject(projectName, If(compilerHost, MockCompilerHost.FullFrameworkCompilerHost), environment.CreateHierarchy(projectName, projectBinPath, projectRefPath:=Nothing, "VB"), + isIntellisenseProject:=False, environment.ServiceProvider, - environment.ThreadingContext, - commandLineParserServiceOpt:=New VisualBasicCommandLineParserService()) + environment.ThreadingContext) End Function Public Function CreateMinimalCompilerOptions(project As VisualBasicProject) As VBCompilerOptions diff --git a/src/VisualStudio/VisualBasic/Impl/LanguageService/VisualBasicPackage.IVbCompiler.vb b/src/VisualStudio/VisualBasic/Impl/LanguageService/VisualBasicPackage.IVbCompiler.vb index 905326b6d085ec34be4a2aa58aecc6f974f46435..c54bbda72b14a4c9be2fa2e433c369b0f0ef6fe6 100644 --- a/src/VisualStudio/VisualBasic/Impl/LanguageService/VisualBasicPackage.IVbCompiler.vb +++ b/src/VisualStudio/VisualBasic/Impl/LanguageService/VisualBasicPackage.IVbCompiler.vb @@ -2,9 +2,7 @@ ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. -Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities -Imports Microsoft.CodeAnalysis.Host Imports Microsoft.CodeAnalysis.VisualBasic Imports Microsoft.VisualStudio.LanguageServices.Implementation.TaskList Imports Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim @@ -27,10 +25,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic wszName, pVbCompilerHost, pProjHier, + TypeOf punkProject Is IVsIntellisenseProject, Me, - ComponentModel.GetService(Of IThreadingContext), - hostDiagnosticUpdateSource, - commandLineParserServiceOpt:=Workspace.Services.GetLanguageServices(LanguageNames.VisualBasic).GetService(Of ICommandLineParserService)) + ComponentModel.GetService(Of IThreadingContext)) End Function Public Function IsValidIdentifier(wszIdentifier As String) As Boolean Implements IVbCompiler.IsValidIdentifier diff --git a/src/VisualStudio/VisualBasic/Impl/ProjectSystemShim/VisualBasicProject.vb b/src/VisualStudio/VisualBasic/Impl/ProjectSystemShim/VisualBasicProject.vb index 67c566ea15c895395d08d50af5b741016f0a0a86..d15f148f17e355f7c3521ca53b31bc59751d2872 100644 --- a/src/VisualStudio/VisualBasic/Impl/ProjectSystemShim/VisualBasicProject.vb +++ b/src/VisualStudio/VisualBasic/Impl/ProjectSystemShim/VisualBasicProject.vb @@ -39,12 +39,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim Friend Sub New(projectSystemName As String, compilerHost As IVbCompilerHost, hierarchy As IVsHierarchy, + isIntellisenseProject As Boolean, serviceProvider As IServiceProvider, - threadingContext As IThreadingContext, - Optional hostDiagnosticUpdateSourceOpt As HostDiagnosticUpdateSource = Nothing, - Optional commandLineParserServiceOpt As ICommandLineParserService = Nothing) - MyBase.New(projectSystemName, hierarchy, LanguageNames.VisualBasic, - serviceProvider, threadingContext, "VB", hostDiagnosticUpdateSourceOpt, commandLineParserServiceOpt) + threadingContext As IThreadingContext) + MyBase.New(projectSystemName, hierarchy, LanguageNames.VisualBasic, isIntellisenseProject, serviceProvider, threadingContext, "VB") _compilerHost = compilerHost