提交 d57cc413 编写于 作者: J Jason Malinowski

Merge pull request #8362 from jasonmalinowski/new-compiler-flags-support-in-project-system

  Pass through features, publicsign, and deterministic flags to the IDE
......@@ -606,6 +606,8 @@ private bool InitializeHostCompiler(ICscHostObject cscHostObject)
}
}
InitializeHostObjectSupportForNewSwitches(cscHostObject, ref param);
// If we have been given a property value that the host compiler doesn't support
// then we need to state that we are falling back to the command line compiler.
// Null is supported because it means that option should be omitted, and compiler default used - obviously always valid.
......
// 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 System.Runtime.InteropServices;
namespace Microsoft.CodeAnalysis.BuildTasks
{
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("117CC9AD-299A-4898-AAFD-8ADE0FE0A1EF")]
public interface ICompilerOptionsHostObject
{
bool SetCompilerOptions([MarshalAs(UnmanagedType.BStr)] string compilerOptions);
}
}
......@@ -14,6 +14,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Csc.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Csi.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ErrorString.Designer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ICompilerOptionsHostObject.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ICscHostObject5.cs" />
<Compile Include="$(MSBuildThisFileDirectory)InteractiveCompiler.cs" />
<Compile Include="$(MSBuildThisFileDirectory)IVbcHostObject6.cs" />
......
......@@ -665,8 +665,6 @@ protected internal virtual void AddResponseFileCommands(CommandLineBuilderExtens
commandLine.AppendWhenTrue("/nologo", _store, nameof(NoLogo));
commandLine.AppendWhenTrue("/nowin32manifest", _store, nameof(NoWin32Manifest));
commandLine.AppendPlusOrMinusSwitch("/optimize", _store, nameof(Optimize));
commandLine.AppendPlusOrMinusSwitch("/deterministic", _store, nameof(Deterministic));
commandLine.AppendPlusOrMinusSwitch("/publicsign", _store, nameof(PublicSign));
commandLine.AppendSwitchIfNotNull("/pathmap:", PathMap);
commandLine.AppendSwitchIfNotNull("/out:", OutputAssembly);
commandLine.AppendSwitchIfNotNull("/ruleset:", CodeAnalysisRuleSet);
......@@ -681,7 +679,7 @@ protected internal virtual void AddResponseFileCommands(CommandLineBuilderExtens
commandLine.AppendSwitchIfNotNull("/win32icon:", Win32Icon);
commandLine.AppendSwitchIfNotNull("/win32manifest:", Win32Manifest);
AddFeatures(commandLine, Features);
AddResponseFileCommandsForSwitchesSinceInitialReleaseThatAreNeededByTheHost(commandLine);
AddAnalyzersToCommandLine(commandLine, Analyzers);
AddAdditionalFilesToCommandLine(commandLine);
......@@ -689,6 +687,14 @@ protected internal virtual void AddResponseFileCommands(CommandLineBuilderExtens
commandLine.AppendFileNamesIfNotNull(Sources, " ");
}
internal void AddResponseFileCommandsForSwitchesSinceInitialReleaseThatAreNeededByTheHost(CommandLineBuilderExtension commandLine)
{
commandLine.AppendPlusOrMinusSwitch("/deterministic", _store, nameof(Deterministic));
commandLine.AppendPlusOrMinusSwitch("/publicsign", _store, nameof(PublicSign));
AddFeatures(commandLine, Features);
}
/// <summary>
/// Adds a "/features:" switch to the command line for each provided feature.
/// </summary>
......@@ -922,6 +928,19 @@ bool resultFromHostObjectSetOperation
}
}
internal void InitializeHostObjectSupportForNewSwitches(ITaskHost hostObject, ref string param)
{
var compilerOptionsHostObject = hostObject as ICompilerOptionsHostObject;
if (compilerOptionsHostObject != null)
{
var commandLineBuilder = new CommandLineBuilderExtension();
AddResponseFileCommandsForSwitchesSinceInitialReleaseThatAreNeededByTheHost(commandLineBuilder);
param = "CompilerOptions";
CheckHostObjectSupport(param, compilerOptionsHostObject.SetCompilerOptions(commandLineBuilder.ToString()));
}
}
/// <summary>
/// Checks to see whether all of the passed-in references exist on disk before we launch the compiler.
/// </summary>
......
......@@ -953,6 +953,8 @@ private bool InitializeHostCompiler(IVbcHostObject vbcHostObject)
CheckHostObjectSupport(param = nameof(NoVBRuntimeReference), resultFromHostObjectSetOperation: false);
}
InitializeHostObjectSupportForNewSwitches(vbcHostObject, ref param);
// In general, we don't support preferreduilang with the in-proc compiler. It will always use the same locale as the
// host process, so in general, we have to fall back to the command line compiler if this option is specified.
// However, we explicitly allow two values (mostly for parity with C#):
......
......@@ -46,12 +46,12 @@ public void DeterministicFlag()
var csc = new Csc();
csc.Sources = MSBuildUtil.CreateTaskItems("test.cs");
csc.Deterministic = true;
Assert.Equal("/deterministic+ /out:test.exe test.cs", csc.GenerateResponseFileContents());
Assert.Equal("/out:test.exe /deterministic+ test.cs", csc.GenerateResponseFileContents());
csc = new Csc();
csc.Sources = MSBuildUtil.CreateTaskItems("test.cs");
csc.Deterministic = false;
Assert.Equal("/deterministic- /out:test.exe test.cs", csc.GenerateResponseFileContents());
Assert.Equal("/out:test.exe /deterministic- test.cs", csc.GenerateResponseFileContents());
csc = new Csc();
csc.Sources = MSBuildUtil.CreateTaskItems("test.cs");
......@@ -64,12 +64,12 @@ public void PublicSignFlag()
var csc = new Csc();
csc.Sources = MSBuildUtil.CreateTaskItems("test.cs");
csc.PublicSign = true;
Assert.Equal("/publicsign+ /out:test.exe test.cs", csc.GenerateResponseFileContents());
Assert.Equal("/out:test.exe /publicsign+ test.cs", csc.GenerateResponseFileContents());
csc = new Csc();
csc.Sources = MSBuildUtil.CreateTaskItems("test.cs");
csc.PublicSign = false;
Assert.Equal("/publicsign- /out:test.exe test.cs", csc.GenerateResponseFileContents());
Assert.Equal("/out:test.exe /publicsign- test.cs", csc.GenerateResponseFileContents());
csc = new Csc();
csc.Sources = MSBuildUtil.CreateTaskItems("test.cs");
......
......@@ -43,12 +43,12 @@ public void DeterministicFlag()
var vbc = new Vbc();
vbc.Sources = MSBuildUtil.CreateTaskItems("test.vb");
vbc.Deterministic = true;
Assert.Equal("/optionstrict:custom /deterministic+ /out:test.exe test.vb", vbc.GenerateResponseFileContents());
Assert.Equal("/optionstrict:custom /out:test.exe /deterministic+ test.vb", vbc.GenerateResponseFileContents());
vbc = new Vbc();
vbc.Sources = MSBuildUtil.CreateTaskItems("test.vb");
vbc.Deterministic = false;
Assert.Equal("/optionstrict:custom /deterministic- /out:test.exe test.vb", vbc.GenerateResponseFileContents());
Assert.Equal("/optionstrict:custom /out:test.exe /deterministic- test.vb", vbc.GenerateResponseFileContents());
vbc = new Vbc();
vbc.Sources = MSBuildUtil.CreateTaskItems("test.vb");
......@@ -61,12 +61,12 @@ public void PublicSignFlag()
var vbc = new Vbc();
vbc.Sources = MSBuildUtil.CreateTaskItems("test.vb");
vbc.PublicSign = true;
Assert.Equal("/optionstrict:custom /publicsign+ /out:test.exe test.vb", vbc.GenerateResponseFileContents());
Assert.Equal("/optionstrict:custom /out:test.exe /publicsign+ test.vb", vbc.GenerateResponseFileContents());
vbc = new Vbc();
vbc.Sources = MSBuildUtil.CreateTaskItems("test.vb");
vbc.PublicSign = false;
Assert.Equal("/optionstrict:custom /publicsign- /out:test.exe test.vb", vbc.GenerateResponseFileContents());
Assert.Equal("/optionstrict:custom /out:test.exe /publicsign- test.vb", vbc.GenerateResponseFileContents());
vbc = new Vbc();
vbc.Sources = MSBuildUtil.CreateTaskItems("test.vb");
......
......@@ -44,7 +44,7 @@ namespace Microsoft.VisualStudio.LanguageServices.CSharp.LanguageService
[ProvideAutomationProperties("TextEditor", "CSharp-Specific", packageGuid: Guids.CSharpPackageIdString, profileNodeLabelId: 104, profileNodeDescriptionId: 105)]
[ProvideService(typeof(CSharpLanguageService), ServiceName = "C# Language Service")]
[ProvideService(typeof(ICSharpTempPECompilerService), ServiceName = "C# TempPE Compiler Service")]
internal class CSharpPackage : AbstractPackage<CSharpPackage, CSharpLanguageService, CSharpProject>, IVsUserSettingsQuery
internal class CSharpPackage : AbstractPackage<CSharpPackage, CSharpLanguageService, CSharpProjectShim>, IVsUserSettingsQuery
{
private ObjectBrowserLibraryManager _libraryManager;
private uint _libraryManagerCookie;
......
......@@ -246,7 +246,6 @@
</Compile>
<Compile Include="Progression\CSharpGraphProvider.cs" />
<Compile Include="Progression\CSharpProgressionLanguageService.cs" />
<Compile Include="ProjectSystemShim\CSharpProject.cs" />
<Compile Include="ProjectSystemShim\CSharpProjectShim.cs" />
<Compile Include="ProjectSystemShim\CSharpProjectShim.ICSCompiler.cs" />
<Compile Include="ProjectSystemShim\CSharpProjectShim.ICSCompilerConfig.cs" />
......
......@@ -19,7 +19,7 @@ namespace Microsoft.VisualStudio.LanguageServices.CSharp.LanguageService
{
[ExcludeFromCodeCoverage]
[Guid(Guids.CSharpLanguageServiceIdString)]
internal partial class CSharpLanguageService : AbstractLanguageService<CSharpPackage, CSharpLanguageService, CSharpProject>
internal partial class CSharpLanguageService : AbstractLanguageService<CSharpPackage, CSharpLanguageService, CSharpProjectShim>
{
internal CSharpLanguageService(CSharpPackage package)
: base(package)
......
// 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 System.Collections.Concurrent;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.LanguageServices.Implementation.TaskList;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.TextManager.Interop;
namespace Microsoft.VisualStudio.LanguageServices.CSharp.ProjectSystemShim
{
/// <summary>
/// The representation of a project to both the project factory and workspace API.
/// </summary>
/// <remarks>
/// Due to the number of interfaces this object must implement, all interface implementations
/// are in a separate files. Methods that are shared across multiple interfaces (which are
/// effectively methods that just QI from one interface to another), are implemented here.
/// </remarks>
internal partial class CSharpProject : AbstractEncProject
{
private static readonly CSharpCompilationOptions s_defaultCompilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
private static readonly CSharpParseOptions s_defaultParseOptions = new CSharpParseOptions();
protected CSharpProject(
VisualStudioProjectTracker projectTracker,
Func<ProjectId, IVsReportExternalErrors> reportExternalErrorCreatorOpt,
string projectSystemName,
IVsHierarchy hierarchy,
IServiceProvider serviceProvider,
MiscellaneousFilesWorkspace miscellaneousFilesWorkspaceOpt,
VisualStudioWorkspaceImpl visualStudioWorkspaceOpt,
HostDiagnosticUpdateSource hostDiagnosticUpdateSourceOpt)
: base(projectTracker,
reportExternalErrorCreatorOpt,
projectSystemName,
hierarchy,
LanguageNames.CSharp,
serviceProvider,
miscellaneousFilesWorkspaceOpt,
visualStudioWorkspaceOpt,
hostDiagnosticUpdateSourceOpt)
{
InitializeOptions();
projectTracker.AddProject(this);
}
protected virtual void InitializeOptions()
{
this.SetOptions(this.CreateCompilationOptions(), this.CreateParseOptions());
}
protected virtual CSharpCompilationOptions CreateCompilationOptions()
{
return s_defaultCompilationOptions;
}
protected virtual CSharpParseOptions CreateParseOptions()
{
return s_defaultParseOptions;
}
protected override void UpdateAnalyzerRules()
{
base.UpdateAnalyzerRules();
this.SetOptions(this.CreateCompilationOptions(), this.CreateParseOptions());
}
internal void AddProjectReference(CSharpProject project)
{
base.AddProjectReference(new ProjectReference(project.Id));
}
}
}
......@@ -130,7 +130,7 @@ private void SetOption<T>(ref T value, T newValue)
if (!object.Equals(value, newValue))
{
value = newValue;
SetOptions(this.CreateCompilationOptions(), this.CreateParseOptions());
UpdateOptions();
}
}
}
......
......@@ -17,7 +17,7 @@ public void AddReferenceToCodeDirectory(string assemblyFileName, ICSharpProjectR
public void RemoveReferenceToCodeDirectory(string assemblyFileName, ICSharpProjectRoot project)
{
CSharpProject projectSite = GetProjectSite(project);
CSharpProjectShim projectSite = GetProjectSite(project);
if (!this.CurrentProjectReferencesContains(projectSite.Id))
{
......@@ -39,14 +39,14 @@ public void OnDiskFileUpdated(string filename, ref System.Runtime.InteropService
public void OnCodeDirectoryAliasesChanged(ICSharpProjectRoot project, int previousAliasesCount, string[] previousAliases, int currentAliasesCount, string[] currentAliases)
{
CSharpProject projectSite = GetProjectSite(project);
CSharpProjectShim projectSite = GetProjectSite(project);
UpdateProjectReferenceAliases(projectSite, ImmutableArray.Create(currentAliases));
}
public void AddReferenceToCodeDirectoryEx(string assemblyFileName, ICSharpProjectRoot project, CompilerOptions optionID)
{
CSharpProject projectSite = GetProjectSite(project);
CSharpProjectShim projectSite = GetProjectSite(project);
AddProjectReference(new ProjectReference(projectSite.Id));
}
......@@ -55,11 +55,11 @@ public void AddReferenceToCodeDirectoryEx(string assemblyFileName, ICSharpProjec
/// Given a ICSharpProjectRoot instance, it returns the ProjectSite instance, throwing if it
/// could not be obtained.
/// </summary>
private static CSharpProject GetProjectSite(ICSharpProjectRoot project)
private static CSharpProjectShim GetProjectSite(ICSharpProjectRoot project)
{
// Get the host back for the project
Guid projectSiteGuid = typeof(ICSharpProjectSite).GUID;
CSharpProject projectSite = project.GetProjectSite(ref projectSiteGuid) as CSharpProject;
CSharpProjectShim projectSite = project.GetProjectSite(ref projectSiteGuid) as CSharpProjectShim;
// We should have gotten a ProjectSite back. If we didn't, that means we're being given
// a project site that we didn't get BindToProject called on first which is a no-no by
......
......@@ -27,7 +27,7 @@ namespace Microsoft.VisualStudio.LanguageServices.CSharp.ProjectSystemShim
/// effectively methods that just QI from one interface to another), are implemented here.
/// </remarks>
[ExcludeFromCodeCoverage]
internal abstract partial class CSharpProjectShim : CSharpProject
internal abstract partial class CSharpProjectShim : AbstractRoslynProject
{
/// <summary>
/// This member is used to store a raw array of warning numbers, which is needed to properly implement
......@@ -56,6 +56,7 @@ internal abstract partial class CSharpProjectShim : CSharpProject
reportExternalErrorCreatorOpt,
projectSystemName,
hierarchy,
LanguageNames.CSharp,
serviceProvider,
miscellaneousFilesWorkspaceOpt,
visualStudioWorkspaceOpt,
......@@ -63,14 +64,22 @@ internal abstract partial class CSharpProjectShim : CSharpProject
{
_projectRoot = projectRoot;
_warningNumberArrayPointer = Marshal.AllocHGlobal(0);
InitializeOptions();
projectTracker.AddProject(this);
}
protected override void InitializeOptions()
private void InitializeOptions()
{
// Ensure the default options are set up
ResetAllOptions();
UpdateOptions();
}
base.InitializeOptions();
protected override void UpdateOptions()
{
this.SetOptions(this.CreateCompilationOptions(), this.CreateParseOptions());
}
public override void Disconnect()
......@@ -85,7 +94,7 @@ private string GetIdForErrorCode(int errorCode)
return "CS" + errorCode.ToString("0000");
}
protected override CSharpCompilationOptions CreateCompilationOptions()
protected CSharpCompilationOptions CreateCompilationOptions()
{
IDictionary<string, ReportDiagnostic> ruleSetSpecificDiagnosticOptions = null;
......@@ -213,7 +222,14 @@ protected override CSharpCompilationOptions CreateCompilationOptions()
sourceReferenceResolver: new SourceFileResolver(sourceSearchPaths, projectDirectory),
metadataReferenceResolver: referenceResolver,
assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default,
strongNameProvider: new DesktopStrongNameProvider(GetStrongNameKeyPaths()));
strongNameProvider: new DesktopStrongNameProvider(GetStrongNameKeyPaths()),
deterministic: GetParsedCommandLineArguments().CompilationOptions.Deterministic,
publicSign: GetParsedCommandLineArguments().CompilationOptions.PublicSign);
}
protected override CommandLineArguments ParseCommandLineArguments(IEnumerable<string> arguments)
{
return CSharpCommandLineParser.Default.Parse(arguments, this.ContainingDirectoryPathOpt, sdkDirectory: null);
}
private IEnumerable<string> ParseWarningCodes(CompilerOptions compilerOptions)
......@@ -275,7 +291,7 @@ private string GetStringOption(CompilerOptions optionID, string defaultValue)
}
}
protected override CSharpParseOptions CreateParseOptions()
protected CSharpParseOptions CreateParseOptions()
{
var symbols = GetStringOption(CompilerOptions.OPTID_CCSYMBOLS, defaultValue: "").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
......@@ -289,9 +305,11 @@ protected override CSharpParseOptions CreateParseOptions()
?? CSharpParseOptions.Default.LanguageVersion;
return new CSharpParseOptions(
kind: SourceCodeKind.Regular,
languageVersion: languageVersion,
preprocessorSymbols: symbols.AsImmutable(),
documentationMode: documentationMode);
documentationMode: documentationMode)
.WithFeatures(GetParsedCommandLineArguments().ParseOptions.Features);
}
~CSharpProjectShim()
......
......@@ -54,7 +54,7 @@ public void AddCyclicProjectMetadataReferences()
var project2 = CreateCSharpProject(environment, "project2");
environment.ProjectTracker.UpdateProjectBinPath(project2, null, @"c:\project2.dll");
project1.AddProjectReference(project2);
project1.AddProjectReference(new ProjectReference(project2.Id));
// normally this metadata reference would be elevated to a project reference, but fails because of cyclicness
project2.OnImportAdded(@"c:\project1.dll", "project1");
......@@ -76,8 +76,8 @@ public void AddCyclicProjectReferences()
var project1 = CreateCSharpProject(environment, "project1");
var project2 = CreateCSharpProject(environment, "project2");
project1.AddProjectReference(project2);
project2.AddProjectReference(project1);
project1.AddProjectReference(new ProjectReference(project2.Id));
project2.AddProjectReference(new ProjectReference(project1.Id));
Assert.Equal(true, project1.GetCurrentProjectReferences().Any(pr => pr.ProjectId == project2.Id));
Assert.Equal(false, project2.GetCurrentProjectReferences().Any(pr => pr.ProjectId == project1.Id));
......@@ -98,10 +98,10 @@ public void AddCyclicProjectReferencesDeep()
var project3 = CreateCSharpProject(environment, "project3");
var project4 = CreateCSharpProject(environment, "project4");
project1.AddProjectReference(project2);
project2.AddProjectReference(project3);
project3.AddProjectReference(project4);
project4.AddProjectReference(project1);
project1.AddProjectReference(new ProjectReference(project2.Id));
project2.AddProjectReference(new ProjectReference(project3.Id));
project3.AddProjectReference(new ProjectReference(project4.Id));
project4.AddProjectReference(new ProjectReference(project1.Id));
Assert.Equal(true, project1.GetCurrentProjectReferences().Any(pr => pr.ProjectId == project2.Id));
Assert.Equal(true, project2.GetCurrentProjectReferences().Any(pr => pr.ProjectId == project3.Id));
......
......@@ -110,7 +110,7 @@ int IVsReadOnlyViewNotification.OnDisabledEditingCommand(ref Guid pguidCmdGuid,
foreach (var documentId in vsWorkspace.GetRelatedDocumentIds(container))
{
var hostProject = vsWorkspace.GetHostProject(documentId.ProjectId) as AbstractEncProject;
var hostProject = vsWorkspace.GetHostProject(documentId.ProjectId) as AbstractRoslynProject;
if (hostProject?.EditAndContinueImplOpt != null)
{
if (hostProject.EditAndContinueImplOpt.OnEdit(documentId))
......
......@@ -143,7 +143,7 @@ internal bool OnEdit(DocumentId documentId)
return;
}
var hostProject = _vsProject.VisualStudioWorkspace.GetHostProject(documentId.ProjectId) as AbstractEncProject;
var hostProject = _vsProject.VisualStudioWorkspace.GetHostProject(documentId.ProjectId) as AbstractRoslynProject;
if (hostProject?.EditAndContinueImplOpt?._metadata != null)
{
var projectHierarchy = _vsProject.VisualStudioWorkspace.GetHierarchy(documentId.ProjectId);
......
......@@ -87,7 +87,7 @@ private void SetReadOnly(Document document)
{
// Only set documents read-only if they're part of a project that supports Enc.
var workspace = document.Project.Solution.Workspace as VisualStudioWorkspaceImpl;
var project = workspace?.ProjectTracker?.GetProject(document.Project.Id) as AbstractEncProject;
var project = workspace?.ProjectTracker?.GetProject(document.Project.Id) as AbstractRoslynProject;
if (project != null)
{
......
......@@ -540,7 +540,8 @@ private void OnAnalyzerChanged(object sender, EventArgs e)
AddAnalyzerAssembly(analyzer.FullPath);
}
protected void AddProjectReference(ProjectReference projectReference)
// Internal for unit testing
internal void AddProjectReference(ProjectReference projectReference)
{
// dev11 is sometimes calling us multiple times for the same data
if (!CanAddProjectReference(projectReference))
......@@ -1015,7 +1016,12 @@ protected virtual void OnDocumentRemoved(string filePath)
{
}
protected virtual void UpdateAnalyzerRules()
/// <summary>
/// Implemented by derived types to provide a way for <see cref="AbstractProject"/> to indicate that options will need to be refreshed.
/// It is expected that derived types will read in shared option state stored in this class, create new Compilation and Parse options,
/// and call <see cref="SetOptions"/> in response. The default implementation does nothing.
/// </summary>
protected virtual void UpdateOptions()
{
}
......
......@@ -133,7 +133,7 @@ private void ResetAnalyzerRuleSet(string ruleSetFileFullPath)
{
ClearAnalyzerRuleSet();
SetAnalyzerRuleSet(ruleSetFileFullPath);
UpdateAnalyzerRules();
UpdateOptions();
}
private void SetAnalyzerRuleSet(string ruleSetFileFullPath)
......
// 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 System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.VisualStudio.LanguageServices.Implementation.EditAndContinue;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.Interop;
using Microsoft.VisualStudio.LanguageServices.Implementation.TaskList;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.TextManager.Interop;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
{
internal abstract partial class AbstractEncProject : AbstractProject
internal abstract partial class AbstractRoslynProject : AbstractProject, ICompilerOptionsHostObject
{
internal VsENCRebuildableProjectImpl EditAndContinueImplOpt;
public AbstractEncProject(
public AbstractRoslynProject(
VisualStudioProjectTracker projectTracker,
Func<ProjectId, IVsReportExternalErrors> reportExternalErrorCreatorOpt,
string projectSystemName,
......@@ -38,5 +41,43 @@ public override void Disconnect()
base.Disconnect();
}
/// <summary>
/// Returns the parsed command line arguments (parsed by <see cref="ParseCommandLineArguments"/>) that were set by the project
/// system's call to <see cref="ICompilerOptionsHostObject.SetCompilerOptions(string, out bool)"/>.
/// </summary>
protected CommandLineArguments GetParsedCommandLineArguments()
{
if (_lastParsedCommandLineArguments == null)
{
// We don't have any yet, so let's parse nothing
_lastParsedCompilerOptions = "";
_lastParsedCommandLineArguments = ParseCommandLineArguments(SpecializedCollections.EmptyEnumerable<string>());
}
return _lastParsedCommandLineArguments;
}
private string _lastParsedCompilerOptions;
private CommandLineArguments _lastParsedCommandLineArguments;
protected abstract CommandLineArguments ParseCommandLineArguments(IEnumerable<string> arguments);
int ICompilerOptionsHostObject.SetCompilerOptions(string compilerOptions, out bool supported)
{
if (!string.Equals(_lastParsedCompilerOptions, compilerOptions))
{
var splitArguments = CommandLineParser.SplitCommandLineIntoArguments(compilerOptions, removeHashComments: false);
_lastParsedCommandLineArguments = ParseCommandLineArguments(splitArguments);
_lastParsedCompilerOptions = compilerOptions;
UpdateOptions();
}
supported = true;
return VSConstants.S_OK;
}
}
}
......@@ -9,7 +9,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
{
// Dev11 implementation: csharp\radmanaged\Features\EditAndContinue\EncProject.cs
internal partial class AbstractEncProject : EncInterop.IVsENCRebuildableProjectCfg2, EncInterop.IVsENCRebuildableProjectCfg4
internal partial class AbstractRoslynProject : EncInterop.IVsENCRebuildableProjectCfg2, EncInterop.IVsENCRebuildableProjectCfg4
{
public int HasCustomMetadataEmitter(out bool value)
{
......
// 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 System.Runtime.InteropServices;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.Interop
{
/// <summary>
/// An internal redefinition of ICompilerOptionsHostObject from Microsoft.CodeAnalysis.BuildTasks. We cannot take
/// a binary dependency on the build task because no component in Visual Studio may do so -- we cannot rely that any
/// specific version of the build task is present since the customer may have a NuGet package installed that contains
/// different versions. Since this a COM interface, it's easiest to redefine.
/// </summary>
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("117CC9AD-299A-4898-AAFD-8ADE0FE0A1EF")]
internal interface ICompilerOptionsHostObject
{
[PreserveSig]
int SetCompilerOptions([MarshalAs(UnmanagedType.BStr)] string compilerOptions, [MarshalAs(UnmanagedType.VariantBool)] out bool supported);
}
}
......@@ -63,7 +63,8 @@
<Compile Include="Implementation\Preview\ReferenceChange.AnalyzerReferenceChange.cs" />
<Compile Include="Implementation\Preview\ReferenceChange.ProjectReferenceChange.cs" />
<Compile Include="Implementation\Preview\ReferenceChange.cs" />
<Compile Include="Implementation\ProjectSystem\AbstractEncProject.cs" />
<Compile Include="Implementation\ProjectSystem\AbstractRoslynProject.cs" />
<Compile Include="Implementation\ProjectSystem\Interop\ICompilerOptionsHostObject.cs" />
<Compile Include="Implementation\ProjectSystem\IVisualStudioWorkingFolder.cs" />
<Compile Include="Implementation\ProjectSystem\MetadataReferences\VisualStudioAnalyzerAssemblyLoaderService.cs" />
<Compile Include="Implementation\ProjectSystem\RuleSets\RuleSetEventHandler.cs" />
......@@ -559,7 +560,7 @@
<Compile Include="Implementation\ProjectSystem\AbstractEntryPointFinder.cs" />
<Compile Include="Implementation\ProjectSystem\AbstractProject.cs" />
<Compile Include="Implementation\ProjectSystem\AbstractProject_IAnalyzerHost.cs" />
<Compile Include="Implementation\ProjectSystem\AbstractEncProject_IVsENCRebuildableProjectCfg.cs" />
<Compile Include="Implementation\ProjectSystem\AbstractRoslynProject_IVsENCRebuildableProjectCfg.cs" />
<Compile Include="Implementation\ProjectSystem\AbstractProject_IVsReportExternalErrors.cs" />
<Compile Include="Implementation\ProjectSystem\ComEventSink.cs" />
<Compile Include="Implementation\ProjectSystem\DocumentKey.cs" />
......
......@@ -53,7 +53,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim
RuntimeLibraries = SpecializedCollections.EmptyEnumerable(Of String)
End Sub
Public Sub New(options As VBCompilerOptions, compilerHost As IVbCompilerHost, globalImports As IEnumerable(Of GlobalImport), strongNameKeyPaths As ImmutableArray(Of String), projectDirectoryOpt As String, ruleSetOpt As IRuleSetFile)
Private Shared ReadOnly s_EmptyCommandLineArguments As VisualBasicCommandLineArguments = VisualBasicCommandLineParser.Default.Parse(SpecializedCollections.EmptyEnumerable(Of String)(), baseDirectory:="", sdkDirectory:=Nothing)
Public Sub New(options As VBCompilerOptions, compilerHost As IVbCompilerHost, globalImports As IEnumerable(Of GlobalImport), strongNameKeyPaths As ImmutableArray(Of String), projectDirectoryOpt As String, ruleSetOpt As IRuleSetFile, Optional parsedCommandLineArguments As CommandLineArguments = Nothing)
parsedCommandLineArguments = If(parsedCommandLineArguments, s_EmptyCommandLineArguments)
If options.wszOutputPath IsNot Nothing AndAlso options.wszExeName IsNot Nothing Then
OutputPath = PathUtilities.CombinePathsUnchecked(options.wszOutputPath, options.wszExeName)
Else
......@@ -99,7 +103,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim
' If they specified a fully qualified file, use it
If File.Exists(options.wszSpecifiedVBRuntime) Then
runtimes.Add(options.wszSpecifiedVBRuntime)
ElseIf sdkPath IsNot Nothing
ElseIf sdkPath IsNot Nothing Then
' If it's just a filename, try to find it in the SDK path.
If options.wszSpecifiedVBRuntime = PathUtilities.GetFileName(options.wszSpecifiedVBRuntime) Then
Dim runtimePath = PathUtilities.CombinePathsUnchecked(sdkPath, options.wszSpecifiedVBRuntime)
......@@ -133,7 +137,8 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim
ParseOptions = New VisualBasicParseOptions(
languageVersion:=options.langVersion,
preprocessorSymbols:=conditionalCompilationSymbols,
documentationMode:=If(Not String.IsNullOrEmpty(options.wszXMLDocName), DocumentationMode.Diagnose, DocumentationMode.Parse))
documentationMode:=If(Not String.IsNullOrEmpty(options.wszXMLDocName), DocumentationMode.Diagnose, DocumentationMode.Parse)) _
.WithFeatures(parsedCommandLineArguments.ParseOptions.Features)
Dim platform As Platform
If Not System.Enum.TryParse(options.wszPlatformType, ignoreCase:=True, result:=platform) Then
......@@ -160,6 +165,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim
cryptoKeyContainer:=options.wszStrongNameContainer,
cryptoKeyFile:=options.wszStrongNameKeyFile,
delaySign:=If(options.bDelaySign, CType(True, Boolean?), Nothing),
deterministic:=parsedCommandLineArguments.CompilationOptions.Deterministic,
embedVbCoreRuntime:=options.vbRuntimeKind = VBRuntimeKind.EmbeddedRuntime,
generalDiagnosticOption:=generalDiagnosticOption,
globalImports:=globalImports,
......@@ -171,6 +177,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim
optimizationLevel:=If(options.bOptimize, OptimizationLevel.Release, OptimizationLevel.Debug),
outputKind:=kind,
parseOptions:=ParseOptions,
publicSign:=parsedCommandLineArguments.CompilationOptions.PublicSign,
platform:=platform,
rootNamespace:=If(options.wszDefaultNamespace, ""),
specificDiagnosticOptions:=specificDiagnosticOptions,
......@@ -235,7 +242,8 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim
diagnosticOptions(pair.Key) = ReportDiagnostic.Error
End If
Next
ElseIf options.WarningLevel = WarningLevel.WARN_None
ElseIf options.WarningLevel = WarningLevel.WARN_None Then
For Each pair In ruleSetSpecificDiagnosticOptions
If pair.Value <> ReportDiagnostic.Error Then
diagnosticOptions(pair.Key) = ReportDiagnostic.Suppress
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Concurrent
Imports System.Runtime.InteropServices
Imports System.Runtime.InteropServices.ComTypes
Imports System.Threading
......@@ -16,7 +15,7 @@ Imports Microsoft.VisualStudio.TextManager.Interop
Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim
Partial Friend MustInherit Class VisualBasicProject
Inherits AbstractEncProject
Inherits AbstractRoslynProject
Implements IVbCompilerProject
Implements IVisualStudioHostProject
......@@ -381,8 +380,8 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim
End Try
End Sub
Private Sub UpdateOptions()
Dim newOptions = New ConvertedVisualBasicProjectOptions(_rawOptions, _compilerHost, _imports, GetStrongNameKeyPaths(), ContainingDirectoryPathOpt, Me.ruleSet)
Protected Overrides Sub UpdateOptions()
Dim newOptions = New ConvertedVisualBasicProjectOptions(_rawOptions, _compilerHost, _imports, GetStrongNameKeyPaths(), ContainingDirectoryPathOpt, Me.ruleSet, GetParsedCommandLineArguments())
UpdateRuleSetError(Me.ruleSet)
......@@ -424,6 +423,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim
_lastOptions = newOptions
End Sub
Protected Overrides Function ParseCommandLineArguments(arguments As IEnumerable(Of String)) As CommandLineArguments
Return VisualBasicCommandLineParser.Default.Parse(arguments, ContainingDirectoryPathOpt, sdkDirectory:=Nothing)
End Function
Public Sub SetModuleAssemblyName(wszName As String) Implements IVbCompilerProject.SetModuleAssemblyName
Throw New NotImplementedException()
End Sub
......@@ -483,12 +486,6 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.ProjectSystemShim
End If
End Sub
Protected Overrides Sub UpdateAnalyzerRules()
MyBase.UpdateAnalyzerRules()
UpdateOptions()
End Sub
#If DEBUG Then
Public Overrides ReadOnly Property Debug_VBEmbeddedCoreOptionOn As Boolean
Get
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册