提交 81a26537 编写于 作者: T Tanner Gooding

Adding the Csi task to MSBuild.

上级 571ea520
......@@ -208,44 +208,44 @@ protected override string GenerateFullPathToTool()
/// </summary>
protected internal override void AddResponseFileCommands(CommandLineBuilderExtension commandLine)
{
commandLine.AppendSwitchIfNotNull("/lib:", this.AdditionalLibPaths, ",");
commandLine.AppendPlusOrMinusSwitch("/unsafe", this._store, "AllowUnsafeBlocks");
commandLine.AppendPlusOrMinusSwitch("/checked", this._store, "CheckForOverflowUnderflow");
commandLine.AppendSwitchWithSplitting("/nowarn:", this.DisabledWarnings, ",", ';', ',');
commandLine.AppendWhenTrue("/fullpaths", this._store, "GenerateFullPaths");
commandLine.AppendSwitchIfNotNull("/langversion:", this.LangVersion);
commandLine.AppendSwitchIfNotNull("/moduleassemblyname:", this.ModuleAssemblyName);
commandLine.AppendSwitchIfNotNull("/pdb:", this.PdbFile);
commandLine.AppendPlusOrMinusSwitch("/nostdlib", this._store, "NoStandardLib");
commandLine.AppendSwitchIfNotNull("/platform:", this.PlatformWith32BitPreference);
commandLine.AppendSwitchIfNotNull("/errorreport:", this.ErrorReport);
commandLine.AppendSwitchWithInteger("/warn:", this._store, "WarningLevel");
commandLine.AppendSwitchIfNotNull("/doc:", this.DocumentationFile);
commandLine.AppendSwitchIfNotNull("/baseaddress:", this.BaseAddress);
commandLine.AppendSwitchUnquotedIfNotNull("/define:", this.GetDefineConstantsSwitch(this.DefineConstants));
commandLine.AppendSwitchIfNotNull("/win32res:", this.Win32Resource);
commandLine.AppendSwitchIfNotNull("/main:", this.MainEntryPoint);
commandLine.AppendSwitchIfNotNull("/appconfig:", this.ApplicationConfiguration);
commandLine.AppendWhenTrue("/errorendlocation", this._store, "ErrorEndLocation");
commandLine.AppendSwitchIfNotNull("/preferreduilang:", this.PreferredUILang);
commandLine.AppendPlusOrMinusSwitch("/highentropyva", this._store, "HighEntropyVA");
commandLine.AppendSwitchIfNotNull("/lib:", AdditionalLibPaths, ",");
commandLine.AppendPlusOrMinusSwitch("/unsafe", _store, nameof(AllowUnsafeBlocks));
commandLine.AppendPlusOrMinusSwitch("/checked", _store, nameof(CheckForOverflowUnderflow));
commandLine.AppendSwitchWithSplitting("/nowarn:", DisabledWarnings, ",", ';', ',');
commandLine.AppendWhenTrue("/fullpaths", _store, nameof(GenerateFullPaths));
commandLine.AppendSwitchIfNotNull("/langversion:", LangVersion);
commandLine.AppendSwitchIfNotNull("/moduleassemblyname:", ModuleAssemblyName);
commandLine.AppendSwitchIfNotNull("/pdb:", PdbFile);
commandLine.AppendPlusOrMinusSwitch("/nostdlib", _store, nameof(NoStandardLib));
commandLine.AppendSwitchIfNotNull("/platform:", PlatformWith32BitPreference);
commandLine.AppendSwitchIfNotNull("/errorreport:", ErrorReport);
commandLine.AppendSwitchWithInteger("/warn:", _store, nameof(WarningLevel));
commandLine.AppendSwitchIfNotNull("/doc:", DocumentationFile);
commandLine.AppendSwitchIfNotNull("/baseaddress:", BaseAddress);
commandLine.AppendSwitchUnquotedIfNotNull("/define:", GetDefineConstantsSwitch(DefineConstants, Log));
commandLine.AppendSwitchIfNotNull("/win32res:", Win32Resource);
commandLine.AppendSwitchIfNotNull("/main:", MainEntryPoint);
commandLine.AppendSwitchIfNotNull("/appconfig:", ApplicationConfiguration);
commandLine.AppendWhenTrue("/errorendlocation", _store, nameof(ErrorEndLocation));
commandLine.AppendSwitchIfNotNull("/preferreduilang:", PreferredUILang);
commandLine.AppendPlusOrMinusSwitch("/highentropyva", _store, nameof(HighEntropyVA));
// If not design time build and the globalSessionGuid property was set then add a -globalsessionguid:<guid>
bool designTime = false;
if (this.HostObject != null)
if (HostObject != null)
{
var csHost = this.HostObject as ICscHostObject;
var csHost = HostObject as ICscHostObject;
designTime = csHost.IsDesignTime();
}
if (!designTime)
{
if (!string.IsNullOrWhiteSpace(this.VsSessionGuid))
if (!string.IsNullOrWhiteSpace(VsSessionGuid))
{
commandLine.AppendSwitchIfNotNull("/sqmsessionguid:", this.VsSessionGuid);
commandLine.AppendSwitchIfNotNull("/sqmsessionguid:", VsSessionGuid);
}
}
this.AddReferencesToCommandLine(commandLine);
AddReferencesToCommandLine(commandLine, References);
base.AddResponseFileCommands(commandLine);
......@@ -264,16 +264,16 @@ protected internal override void AddResponseFileCommands(CommandLineBuilderExten
// /warnaserror-
// is just shorthand for:
// /warnaserror-:<all possible warnings>
commandLine.AppendSwitchWithSplitting("/warnaserror+:", this.WarningsAsErrors, ",", ';', ',');
commandLine.AppendSwitchWithSplitting("/warnaserror-:", this.WarningsNotAsErrors, ",", ';', ',');
commandLine.AppendSwitchWithSplitting("/warnaserror+:", WarningsAsErrors, ",", ';', ',');
commandLine.AppendSwitchWithSplitting("/warnaserror-:", WarningsNotAsErrors, ",", ';', ',');
// It's a good idea for the response file to be the very last switch passed, just
// from a predictability perspective. It also solves the problem that a dogfooder
// ran into, which is described in an email thread attached to bug VSWhidbey 146883.
// See also bugs 177762 and 118307 for additional bugs related to response file position.
if (this.ResponseFiles != null)
if (ResponseFiles != null)
{
foreach (ITaskItem response in this.ResponseFiles)
foreach (ITaskItem response in ResponseFiles)
{
commandLine.AppendSwitchIfNotNull("@", response.ItemSpec);
}
......@@ -294,14 +294,14 @@ protected internal override void AddResponseFileCommands(CommandLineBuilderExten
/// list of aliases, and if any of the aliases specified is the string "global",
/// then we add that reference to the command-line without an alias.
/// </summary>
private void AddReferencesToCommandLine
(
CommandLineBuilderExtension commandLine
)
internal static void AddReferencesToCommandLine(
CommandLineBuilderExtension commandLine,
ITaskItem[] references,
bool isInteractive = false)
{
// If there were no references passed in, don't add any /reference: switches
// on the command-line.
if ((this.References == null) || (this.References.Length == 0))
if (references == null)
{
return;
}
......@@ -309,22 +309,24 @@ CommandLineBuilderExtension commandLine
// Loop through all the references passed in. We'll be adding separate
// /reference: switches for each reference, and in some cases even multiple
// /reference: switches per reference.
foreach (ITaskItem reference in this.References)
foreach (ITaskItem reference in references)
{
// See if there was an "Alias" attribute on the reference.
string aliasString = reference.GetMetadata("Aliases");
string switchName = "/reference:";
bool embed = Utilities.TryConvertItemMetadataToBool(reference,
"EmbedInteropTypes");
if (embed == true)
if (!isInteractive)
{
switchName = "/link:";
}
bool embed = Utilities.TryConvertItemMetadataToBool(reference,
"EmbedInteropTypes");
if ((aliasString == null) || (aliasString.Length == 0))
if (embed)
{
switchName = "/link:";
}
}
if (string.IsNullOrEmpty(aliasString))
{
// If there was no "Alias" attribute, just add this as a global reference.
commandLine.AppendSwitchIfNotNull(switchName, reference.ItemSpec);
......@@ -365,7 +367,7 @@ CommandLineBuilderExtension commandLine
// The alias called "global" is special. It means that we don't
// give it an alias on the command-line.
if (String.Compare("global", trimmedAlias, StringComparison.OrdinalIgnoreCase) == 0)
if (string.Compare("global", trimmedAlias, StringComparison.OrdinalIgnoreCase) == 0)
{
commandLine.AppendSwitchIfNotNull(switchName, reference.ItemSpec);
}
......@@ -395,7 +397,7 @@ CommandLineBuilderExtension commandLine
/// other words, a constant is either defined or not defined ... it can't have
/// an actual value.
/// </summary>
internal string GetDefineConstantsSwitch(string originalDefineConstants)
internal static string GetDefineConstantsSwitch(string originalDefineConstants, TaskLoggingHelper log)
{
if (originalDefineConstants == null)
{
......@@ -424,7 +426,7 @@ internal string GetDefineConstantsSwitch(string originalDefineConstants)
}
else if (singleIdentifier.Length > 0)
{
Log.LogWarningWithCodeFromResources("Csc_InvalidParameterWarning", "/define:", singleIdentifier);
log.LogWarningWithCodeFromResources("Csc_InvalidParameterWarning", "/define:", singleIdentifier);
}
}
......@@ -465,7 +467,7 @@ internal string GetDefineConstantsSwitch(string originalDefineConstants)
private bool InitializeHostCompiler(ICscHostObject cscHostObject)
{
bool success;
this.HostCompilerSupportsAllParameters = this.UseHostCompilerIfAvailable;
HostCompilerSupportsAllParameters = UseHostCompilerIfAvailable;
string param = "Unknown";
try
......@@ -485,7 +487,7 @@ private bool InitializeHostCompiler(ICscHostObject cscHostObject)
}
catch (Exception e) when (!Utilities.IsCriticalException(e))
{
if (this.HostCompilerSupportsAllParameters)
if (HostCompilerSupportsAllParameters)
{
// If the host compiler doesn't support everything we need, we're going to end up
// shelling out to the command-line compiler anyway. That means the command-line
......@@ -513,7 +515,7 @@ private bool InitializeHostCompiler(ICscHostObject cscHostObject)
CheckHostObjectSupport(param = nameof(EmitDebugInformation), cscHostObject.SetEmitDebugInformation(EmitDebugInformation));
CheckHostObjectSupport(param = nameof(DebugType), cscHostObject.SetDebugType(DebugType));
CheckHostObjectSupport(param = nameof(DefineConstants), cscHostObject.SetDefineConstants(GetDefineConstantsSwitch(DefineConstants)));
CheckHostObjectSupport(param = nameof(DefineConstants), cscHostObject.SetDefineConstants(GetDefineConstantsSwitch(DefineConstants, Log)));
CheckHostObjectSupport(param = nameof(DelaySign), cscHostObject.SetDelaySign((_store["DelaySign"] != null), DelaySign));
CheckHostObjectSupport(param = nameof(DisabledWarnings), cscHostObject.SetDisabledWarnings(DisabledWarnings));
CheckHostObjectSupport(param = nameof(DocumentationFile), cscHostObject.SetDocumentationFile(DocumentationFile));
......@@ -581,7 +583,7 @@ private bool InitializeHostCompiler(ICscHostObject cscHostObject)
{
// If we have been given a property that the host compiler doesn't support
// then we need to state that we are falling back to the command line compiler
if (!String.IsNullOrEmpty(Win32Manifest))
if (!string.IsNullOrEmpty(Win32Manifest))
{
CheckHostObjectSupport(param = nameof(Win32Manifest), resultFromHostObjectSetOperation: false);
}
......@@ -599,7 +601,7 @@ private bool InitializeHostCompiler(ICscHostObject cscHostObject)
{
// If we have been given a property that the host compiler doesn't support
// then we need to state that we are falling back to the command line compiler
if (!String.IsNullOrEmpty(ApplicationConfiguration))
if (!string.IsNullOrEmpty(ApplicationConfiguration))
{
CheckHostObjectSupport(nameof(ApplicationConfiguration), resultFromHostObjectSetOperation: false);
}
......@@ -610,14 +612,14 @@ private bool InitializeHostCompiler(ICscHostObject cscHostObject)
// Null is supported because it means that option should be omitted, and compiler default used - obviously always valid.
// Explicitly specified name of current locale is also supported, since it is effectively a no-op.
// Other options are not supported since in-proc compiler always uses current locale.
if (!String.IsNullOrEmpty(PreferredUILang) && !String.Equals(PreferredUILang, System.Globalization.CultureInfo.CurrentUICulture.Name, StringComparison.OrdinalIgnoreCase))
if (!string.IsNullOrEmpty(PreferredUILang) && !string.Equals(PreferredUILang, System.Globalization.CultureInfo.CurrentUICulture.Name, StringComparison.OrdinalIgnoreCase))
{
CheckHostObjectSupport(nameof(PreferredUILang), resultFromHostObjectSetOperation: false);
}
}
catch (Exception e) when (!Utilities.IsCriticalException(e))
{
if (this.HostCompilerSupportsAllParameters)
if (HostCompilerSupportsAllParameters)
{
// If the host compiler doesn't support everything we need, we're going to end up
// shelling out to the command-line compiler anyway. That means the command-line
......@@ -634,7 +636,7 @@ private bool InitializeHostCompiler(ICscHostObject cscHostObject)
success = cscHostObject.EndInitialization(out errorMessage, out errorCode);
if (this.HostCompilerSupportsAllParameters)
if (HostCompilerSupportsAllParameters)
{
// If the host compiler doesn't support everything we need, we're going to end up
// shelling out to the command-line compiler anyway. That means the command-line
......@@ -669,7 +671,7 @@ private bool InitializeHostCompiler(ICscHostObject cscHostObject)
/// <owner>RGoel</owner>
protected override HostObjectInitializationStatus InitializeHostObject()
{
if (this.HostObject != null)
if (HostObject != null)
{
// When the host object was passed into the task, it was passed in as a generic
// "Object" (because ITask interface obviously can't have any Csc-specific stuff
......@@ -680,7 +682,7 @@ protected override HostObjectInitializationStatus InitializeHostObject()
// NOTE: For compat reasons this must remain ICscHostObject
// we can dynamically test for smarter interfaces later..
using (RCWForCurrentContext<ICscHostObject> hostObject = new RCWForCurrentContext<ICscHostObject>(this.HostObject as ICscHostObject))
using (RCWForCurrentContext<ICscHostObject> hostObject = new RCWForCurrentContext<ICscHostObject>(HostObject as ICscHostObject))
{
ICscHostObject cscHostObject = hostObject.RCW;
......@@ -738,9 +740,9 @@ protected override HostObjectInitializationStatus InitializeHostObject()
/// <owner>RGoel</owner>
protected override bool CallHostObjectToExecute()
{
Debug.Assert(this.HostObject != null, "We should not be here if the host object has not been set.");
Debug.Assert(HostObject != null, "We should not be here if the host object has not been set.");
ICscHostObject cscHostObject = this.HostObject as ICscHostObject;
ICscHostObject cscHostObject = HostObject as ICscHostObject;
Debug.Assert(cscHostObject != null, "Wrong kind of host object passed in!");
return cscHostObject.Compile();
}
......
// 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.Text;
using Microsoft.Build.Framework;
using Microsoft.CodeAnalysis.CSharp;
namespace Microsoft.CodeAnalysis.BuildTasks
{
public class Csi : InteractiveCompiler
{
#region Properties - Please keep these alphabetized.
// These are the parameters specific to Csi.
// The ones shared between Csi and Vbi are defined in InteractiveCompiler.cs, which is the base class.
#endregion
#region Tool Members
/// <summary>
/// Return the name of the tool to execute.
/// </summary>
protected override string ToolName => "csi.exe";
#endregion
#region Interactive Compiler Members
protected override void AddResponseFileCommands(CommandLineBuilderExtension commandLine)
{
commandLine.AppendSwitchIfNotNull("/lib:", AdditionalLibPaths, ",");
commandLine.AppendSwitchIfNotNull("/loadpaths:", AdditionalLoadPaths, ",");
commandLine.AppendSwitchIfNotNull("/imports:", Imports, ";");
Csc.AddReferencesToCommandLine(commandLine, References, isInteractive: true);
base.AddResponseFileCommands(commandLine);
}
#endregion
}
}
// 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;
using System.Linq;
using Roslyn.Utilities;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.CodeAnalysis.BuildTasks
{
/// <summary>
/// This class defines all of the common stuff that is shared between the Vbc and Csc tasks.
/// This class is not instantiatable as a Task just by itself.
/// </summary>
public abstract class InteractiveCompiler : ToolTask
{
internal readonly PropertyDictionary _store = new PropertyDictionary();
public InteractiveCompiler()
{
TaskResources = ErrorString.ResourceManager;
}
#region Properties - Please keep these alphabetized.
public string[] AdditionalLibPaths
{
set
{
_store[nameof(AdditionalLibPaths)] = value;
}
get
{
return (string[])_store[nameof(AdditionalLibPaths)];
}
}
public string[] AdditionalLoadPaths
{
set
{
_store[nameof(AdditionalLoadPaths)] = value;
}
get
{
return (string[])_store[nameof(AdditionalLoadPaths)];
}
}
[Output]
public ITaskItem[] CommandLineArgs
{
set
{
_store[nameof(CommandLineArgs)] = value;
}
get
{
return (ITaskItem[])_store[nameof(CommandLineArgs)];
}
}
public string Features
{
set
{
_store[nameof(Features)] = value;
}
get
{
return (string)_store[nameof(Features)];
}
}
public ITaskItem[] Imports
{
set
{
_store[nameof(Imports)] = value;
}
get
{
return (ITaskItem[])_store[nameof(Imports)];
}
}
public bool ProvideCommandLineArgs
{
set
{
_store[nameof(ProvideCommandLineArgs)] = value;
}
get
{
return _store.GetOrDefault(nameof(ProvideCommandLineArgs), false);
}
}
public ITaskItem[] References
{
set
{
_store[nameof(References)] = value;
}
get
{
return (ITaskItem[])_store[nameof(References)];
}
}
public ITaskItem[] ResponseFiles
{
set
{
_store[nameof(ResponseFiles)] = value;
}
get
{
return (ITaskItem[])_store[nameof(ResponseFiles)];
}
}
public string[] ScriptArguments
{
set
{
_store[nameof(ScriptArguments)] = value;
}
get
{
return (string[])_store[nameof(ScriptArguments)];
}
}
public ITaskItem[] ScriptResponseFiles
{
set
{
_store[nameof(ScriptResponseFiles)] = value;
}
get
{
return (ITaskItem[])_store[nameof(ScriptResponseFiles)];
}
}
public bool SkipInteractiveExecution
{
set
{
_store[nameof(SkipInteractiveExecution)] = value;
}
get
{
return _store.GetOrDefault(nameof(SkipInteractiveExecution), false);
}
}
public ITaskItem Source
{
set
{
_store[nameof(Source)] = value;
}
get
{
return (ITaskItem)_store[nameof(Source)];
}
}
#endregion
#region Tool Members
protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
{
if (ProvideCommandLineArgs)
{
CommandLineArgs = GetArguments(commandLineCommands, responseFileCommands).Select(arg => new TaskItem(arg)).ToArray();
}
return (SkipInteractiveExecution) ? 0 : base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
}
public string GenerateCommandLineContents() => GenerateCommandLineCommands();
protected override string GenerateCommandLineCommands()
{
var commandLineBuilder = new CommandLineBuilderExtension();
AddCommandLineCommands(commandLineBuilder);
return commandLineBuilder.ToString();
}
/// <summary>
/// Return the path to the tool to execute.
/// </summary>
protected override string GenerateFullPathToTool()
{
string pathToTool = ToolLocationHelper.GetPathToBuildToolsFile(ToolName, ToolLocationHelper.CurrentToolsVersion);
if (pathToTool == null)
{
pathToTool = ToolLocationHelper.GetPathToDotNetFrameworkFile(ToolName, TargetDotNetFrameworkVersion.VersionLatest);
if (pathToTool == null)
{
Log.LogErrorWithCodeFromResources("General_FrameworksFileNotFound", ToolName, ToolLocationHelper.GetDotNetFrameworkVersionFolderPrefix(TargetDotNetFrameworkVersion.VersionLatest));
}
}
return pathToTool;
}
public string GenerateResponseFileContents() => GenerateResponseFileCommands();
protected override string GenerateResponseFileCommands()
{
var commandLineBuilder = new CommandLineBuilderExtension();
AddResponseFileCommands(commandLineBuilder);
return commandLineBuilder.ToString();
}
protected override bool ValidateParameters() => ManagedCompiler.ListHasNoDuplicateItems(Sources, nameof(Sources), Log);
#endregion
/// <summary>
/// Fills the provided CommandLineBuilderExtension with those switches and other information that can't go into a response file and
/// must go directly onto the command line.
/// </summary>
protected virtual void AddCommandLineCommands(CommandLineBuilderExtension commandLine)
{
}
/// <summary>
/// Fills the provided CommandLineBuilderExtension with those switches and other information that can go into a response file.
/// </summary>
protected virtual void AddResponseFileCommands(CommandLineBuilderExtension commandLine)
{
commandLine.AppendSwitch("/i-");
ManagedCompiler.AddFeatures(commandLine, Features);
if (ResponseFiles != null)
{
foreach (var response in ResponseFiles)
{
commandLine.AppendSwitchIfNotNull("@", response.ItemSpec);
}
}
commandLine.AppendFileNameIfNotNull(Source);
foreach (var scriptArgument in ScriptArguments)
{
commandLine.AppendTextUnquoted(scriptArgument);
}
if (ResponseFiles != null)
{
foreach (var scriptResponse in ScriptResponseFiles)
{
commandLine.AppendSwitchIfNotNull("@", scriptResponse.ItemSpec);
}
}
}
/// <summary>
/// Get the command line arguments to pass to the compiler.
/// </summary>
private string[] GetArguments(string commandLineCommands, string responseFileCommands)
{
var commandLineArguments = CommandLineParser.SplitCommandLineIntoArguments(commandLineCommands, removeHashComments: true);
var responseFileArguments = CommandLineParser.SplitCommandLineIntoArguments(responseFileCommands, removeHashComments: true);
return commandLineArguments.Concat(responseFileArguments).ToArray();
}
}
}
......@@ -53,12 +53,14 @@
<Compile Include="CanonicalError.cs" />
<Compile Include="CommandLineBuilderExtension.cs" />
<Compile Include="Csc.cs" />
<Compile Include="Csi.cs" />
<Compile Include="ErrorString.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>ErrorString.resx</DependentUpon>
</Compile>
<Compile Include="ICscHostObject5.cs" />
<Compile Include="InteractiveCompiler.cs" />
<Compile Include="IVbcHostObject6.cs" />
<Compile Include="ManagedCompiler.cs" />
<Compile Include="NativeMethods.cs" />
......
......@@ -27,7 +27,7 @@ public abstract class ManagedCompiler : ToolTask
public ManagedCompiler()
{
this.TaskResources = ErrorString.ResourceManager;
TaskResources = ErrorString.ResourceManager;
}
#region Properties
......@@ -311,8 +311,8 @@ internal string PlatformWith32BitPreference
{
get
{
string platform = this.Platform;
if ((String.IsNullOrEmpty(platform) || platform.Equals("anycpu", StringComparison.OrdinalIgnoreCase)) && this.Prefer32Bit)
string platform = Platform;
if ((string.IsNullOrEmpty(platform) || platform.Equals("anycpu", StringComparison.OrdinalIgnoreCase)) && Prefer32Bit)
{
platform = "anycpu32bitpreferred";
}
......@@ -348,7 +348,7 @@ protected override int ExecuteTool(string pathToTool, string responseFileCommand
return 0;
}
if (!UseSharedCompilation || !String.IsNullOrEmpty(this.ToolPath))
if (!UseSharedCompilation || !string.IsNullOrEmpty(ToolPath))
{
return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
}
......@@ -446,10 +446,10 @@ private string LibDirectoryToUse()
string libDirectory = Environment.GetEnvironmentVariable("LIB");
// Now go through additional environment variables.
string[] additionalVariables = this.EnvironmentVariables;
string[] additionalVariables = EnvironmentVariables;
if (additionalVariables != null)
{
foreach (string var in this.EnvironmentVariables)
foreach (string var in EnvironmentVariables)
{
if (var.StartsWith("LIB=", StringComparison.OrdinalIgnoreCase))
{
......@@ -482,7 +482,7 @@ private int HandleResponse(BuildResponse response, string pathToTool, string res
case BuildResponse.ResponseType.Completed:
var completedResponse = (CompletedBuildResponse)response;
LogMessages(completedResponse.Output, this.StandardOutputImportanceToUse);
LogMessages(completedResponse.Output, StandardOutputImportanceToUse);
if (LogStandardErrorAsError)
{
......@@ -490,7 +490,7 @@ private int HandleResponse(BuildResponse response, string pathToTool, string res
}
else
{
LogMessages(completedResponse.ErrorOutput, this.StandardErrorImportanceToUse);
LogMessages(completedResponse.ErrorOutput, StandardErrorImportanceToUse);
}
return completedResponse.ReturnCode;
......@@ -567,7 +567,7 @@ protected override string GenerateCommandLineCommands()
/// </summary>
protected internal virtual void AddCommandLineCommands(CommandLineBuilderExtension commandLine)
{
commandLine.AppendWhenTrue("/noconfig", this._store, "NoConfig");
commandLine.AppendWhenTrue("/noconfig", _store, nameof(NoConfig));
}
/// <summary>
......@@ -582,7 +582,7 @@ protected internal virtual void AddResponseFileCommands(CommandLineBuilderExtens
(OutputAssembly == null) &&
(Sources != null) &&
(Sources.Length > 0) &&
(this.ResponseFiles == null) // The response file may already have a /out: switch in it, so don't try to be smart here.
(ResponseFiles == null) // The response file may already have a /out: switch in it, so don't try to be smart here.
)
{
try
......@@ -593,11 +593,11 @@ protected internal virtual void AddResponseFileCommands(CommandLineBuilderExtens
{
throw new ArgumentException(e.Message, "Sources");
}
if (String.Compare(TargetType, "library", StringComparison.OrdinalIgnoreCase) == 0)
if (string.Compare(TargetType, "library", StringComparison.OrdinalIgnoreCase) == 0)
{
OutputAssembly.ItemSpec += ".dll";
}
else if (String.Compare(TargetType, "module", StringComparison.OrdinalIgnoreCase) == 0)
else if (string.Compare(TargetType, "module", StringComparison.OrdinalIgnoreCase) == 0)
{
OutputAssembly.ItemSpec += ".netmodule";
}
......@@ -607,8 +607,8 @@ protected internal virtual void AddResponseFileCommands(CommandLineBuilderExtens
}
}
commandLine.AppendSwitchIfNotNull("/addmodule:", this.AddModules, ",");
commandLine.AppendSwitchWithInteger("/codepage:", this._store, "CodePage");
commandLine.AppendSwitchIfNotNull("/addmodule:", AddModules, ",");
commandLine.AppendSwitchWithInteger("/codepage:", _store, nameof(CodePage));
ConfigureDebugProperties();
......@@ -616,36 +616,36 @@ protected internal virtual void AddResponseFileCommands(CommandLineBuilderExtens
// because it's more specific. Order matters on the command-line, and the last one wins.
// /debug+ is just a shorthand for /debug:full. And /debug- is just a shorthand for /debug:none.
commandLine.AppendPlusOrMinusSwitch("/debug", this._store, "EmitDebugInformation");
commandLine.AppendSwitchIfNotNull("/debug:", this.DebugType);
commandLine.AppendPlusOrMinusSwitch("/debug", _store, nameof(EmitDebugInformation));
commandLine.AppendSwitchIfNotNull("/debug:", DebugType);
commandLine.AppendPlusOrMinusSwitch("/delaysign", this._store, "DelaySign");
commandLine.AppendPlusOrMinusSwitch("/delaysign", _store, nameof(DelaySign));
commandLine.AppendSwitchWithInteger("/filealign:", this._store, "FileAlignment");
commandLine.AppendSwitchIfNotNull("/keycontainer:", this.KeyContainer);
commandLine.AppendSwitchIfNotNull("/keyfile:", this.KeyFile);
commandLine.AppendSwitchWithInteger("/filealign:", _store, nameof(FileAlignment));
commandLine.AppendSwitchIfNotNull("/keycontainer:", KeyContainer);
commandLine.AppendSwitchIfNotNull("/keyfile:", KeyFile);
// If the strings "LogicalName" or "Access" ever change, make sure to search/replace everywhere in vsproject.
commandLine.AppendSwitchIfNotNull("/linkresource:", this.LinkResources, new string[] { "LogicalName", "Access" });
commandLine.AppendWhenTrue("/nologo", this._store, "NoLogo");
commandLine.AppendWhenTrue("/nowin32manifest", this._store, "NoWin32Manifest");
commandLine.AppendPlusOrMinusSwitch("/optimize", this._store, "Optimize");
commandLine.AppendPlusOrMinusSwitch("/deterministic", this._store, "Deterministic");
commandLine.AppendSwitchIfNotNull("/out:", this.OutputAssembly);
commandLine.AppendSwitchIfNotNull("/ruleset:", this.CodeAnalysisRuleSet);
commandLine.AppendSwitchIfNotNull("/errorlog:", this.ErrorLog);
commandLine.AppendSwitchIfNotNull("/subsystemversion:", this.SubsystemVersion);
commandLine.AppendWhenTrue("/reportanalyzer", this._store, "ReportAnalyzer");
commandLine.AppendSwitchIfNotNull("/linkresource:", LinkResources, new string[] { "LogicalName", "Access" });
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.AppendSwitchIfNotNull("/out:", OutputAssembly);
commandLine.AppendSwitchIfNotNull("/ruleset:", CodeAnalysisRuleSet);
commandLine.AppendSwitchIfNotNull("/errorlog:", ErrorLog);
commandLine.AppendSwitchIfNotNull("/subsystemversion:", SubsystemVersion);
commandLine.AppendWhenTrue("/reportanalyzer", _store, nameof(ReportAnalyzer));
// If the strings "LogicalName" or "Access" ever change, make sure to search/replace everywhere in vsproject.
commandLine.AppendSwitchIfNotNull("/resource:", this.Resources, new string[] { "LogicalName", "Access" });
commandLine.AppendSwitchIfNotNull("/target:", this.TargetType);
commandLine.AppendPlusOrMinusSwitch("/warnaserror", this._store, "TreatWarningsAsErrors");
commandLine.AppendWhenTrue("/utf8output", this._store, "Utf8Output");
commandLine.AppendSwitchIfNotNull("/win32icon:", this.Win32Icon);
commandLine.AppendSwitchIfNotNull("/win32manifest:", this.Win32Manifest);
commandLine.AppendSwitchIfNotNull("/resource:", Resources, new string[] { "LogicalName", "Access" });
commandLine.AppendSwitchIfNotNull("/target:", TargetType);
commandLine.AppendPlusOrMinusSwitch("/warnaserror", _store, nameof(TreatWarningsAsErrors));
commandLine.AppendWhenTrue("/utf8output", _store, nameof(Utf8Output));
commandLine.AppendSwitchIfNotNull("/win32icon:", Win32Icon);
commandLine.AppendSwitchIfNotNull("/win32manifest:", Win32Manifest);
this.AddFeatures(commandLine);
this.AddAnalyzersToCommandLine(commandLine);
this.AddAdditionalFilesToCommandLine(commandLine);
AddFeatures(commandLine, Features);
AddAnalyzersToCommandLine(commandLine, Analyzers);
AddAdditionalFilesToCommandLine(commandLine);
// Append the sources.
commandLine.AppendFileNamesIfNotNull(Sources, " ");
......@@ -654,10 +654,8 @@ protected internal virtual void AddResponseFileCommands(CommandLineBuilderExtens
/// <summary>
/// Adds a "/features:" switch to the command line for each provided feature.
/// </summary>
/// <param name="commandLine"></param>
private void AddFeatures(CommandLineBuilderExtension commandLine)
internal static void AddFeatures(CommandLineBuilderExtension commandLine, string features)
{
var features = Features;
if (string.IsNullOrEmpty(features))
{
return;
......@@ -672,16 +670,16 @@ private void AddFeatures(CommandLineBuilderExtension commandLine)
/// <summary>
/// Adds a "/analyzer:" switch to the command line for each provided analyzer.
/// </summary>
private void AddAnalyzersToCommandLine(CommandLineBuilderExtension commandLine)
internal static void AddAnalyzersToCommandLine(CommandLineBuilderExtension commandLine, ITaskItem[] analyzers)
{
// If there were no analyzers passed in, don't add any /analyzer: switches
// on the command-line.
if ((this.Analyzers == null) || (this.Analyzers.Length == 0))
if (analyzers == null)
{
return;
}
foreach (ITaskItem analyzer in this.Analyzers)
foreach (ITaskItem analyzer in analyzers)
{
commandLine.AppendSwitchIfNotNull("/analyzer:", analyzer.ItemSpec);
}
......@@ -694,12 +692,12 @@ private void AddAdditionalFilesToCommandLine(CommandLineBuilderExtension command
{
// If there were no additional files passed in, don't add any /additionalfile: switches
// on the command-line.
if ((this.AdditionalFiles == null) || (this.AdditionalFiles.Length == 0))
if (AdditionalFiles == null)
{
return;
}
foreach (ITaskItem additionalFile in this.AdditionalFiles)
foreach (ITaskItem additionalFile in AdditionalFiles)
{
commandLine.AppendSwitchIfNotNull("/additionalfile:", additionalFile.ItemSpec);
}
......@@ -733,13 +731,13 @@ private void ConfigureDebugProperties()
{
// If debug type is set we need to take some action depending on the value. If debugtype is not set
// We don't need to modify the EmitDebugInformation switch as its value will be used as is.
if (_store["DebugType"] != null)
if (_store[nameof(DebugType)] != null)
{
// If debugtype is none then only show debug- else use the debug type and the debugsymbols as is.
if (string.Compare((string)_store["DebugType"], "none", StringComparison.OrdinalIgnoreCase) == 0)
if (string.Compare((string)_store[nameof(DebugType)], "none", StringComparison.OrdinalIgnoreCase) == 0)
{
_store["DebugType"] = null;
_store["EmitDebugInformation"] = false;
_store[nameof(DebugType)] = null;
_store[nameof(EmitDebugInformation)] = false;
}
}
}
......@@ -750,15 +748,15 @@ private void ConfigureDebugProperties()
/// </summary>
protected override bool ValidateParameters()
{
return ListHasNoDuplicateItems(this.Resources, "Resources", "LogicalName") && ListHasNoDuplicateItems(this.Sources, "Sources");
return ListHasNoDuplicateItems(Resources, nameof(Resources), "LogicalName", Log) && ListHasNoDuplicateItems(Sources, nameof(Sources), Log);
}
/// <summary>
/// Returns true if the provided item list contains duplicate items, false otherwise.
/// </summary>
protected bool ListHasNoDuplicateItems(ITaskItem[] itemList, string parameterName)
internal static bool ListHasNoDuplicateItems(ITaskItem[] itemList, string parameterName, TaskLoggingHelper log)
{
return ListHasNoDuplicateItems(itemList, parameterName, null);
return ListHasNoDuplicateItems(itemList, parameterName, null, log);
}
/// <summary>
......@@ -767,7 +765,8 @@ protected bool ListHasNoDuplicateItems(ITaskItem[] itemList, string parameterNam
/// <param name="itemList"></param>
/// <param name="disambiguatingMetadataName">Optional name of metadata that may legitimately disambiguate items. May be null.</param>
/// <param name="parameterName"></param>
private bool ListHasNoDuplicateItems(ITaskItem[] itemList, string parameterName, string disambiguatingMetadataName)
/// <param name="log"></param>
private static bool ListHasNoDuplicateItems(ITaskItem[] itemList, string parameterName, string disambiguatingMetadataName, TaskLoggingHelper log)
{
if (itemList == null || itemList.Length == 0)
{
......@@ -784,7 +783,7 @@ private bool ListHasNoDuplicateItems(ITaskItem[] itemList, string parameterName,
disambiguatingMetadataValue = item.GetMetadata(disambiguatingMetadataName);
}
if (disambiguatingMetadataName == null || String.IsNullOrEmpty(disambiguatingMetadataValue))
if (disambiguatingMetadataName == null || string.IsNullOrEmpty(disambiguatingMetadataValue))
{
key = item.ItemSpec;
}
......@@ -795,19 +794,19 @@ private bool ListHasNoDuplicateItems(ITaskItem[] itemList, string parameterName,
if (alreadySeen.ContainsKey(key))
{
if (disambiguatingMetadataName == null || String.IsNullOrEmpty(disambiguatingMetadataValue))
if (disambiguatingMetadataName == null || string.IsNullOrEmpty(disambiguatingMetadataValue))
{
Log.LogErrorWithCodeFromResources("General_DuplicateItemsNotSupported", item.ItemSpec, parameterName);
log.LogErrorWithCodeFromResources("General_DuplicateItemsNotSupported", item.ItemSpec, parameterName);
}
else
{
Log.LogErrorWithCodeFromResources("General_DuplicateItemsNotSupportedWithMetadata", item.ItemSpec, parameterName, disambiguatingMetadataValue, disambiguatingMetadataName);
log.LogErrorWithCodeFromResources("General_DuplicateItemsNotSupportedWithMetadata", item.ItemSpec, parameterName, disambiguatingMetadataValue, disambiguatingMetadataName);
}
return false;
}
else
{
alreadySeen[key] = String.Empty;
alreadySeen[key] = string.Empty;
}
}
......@@ -891,7 +890,7 @@ bool resultFromHostObjectSetOperation
/// <owner>RGoel</owner>
protected bool CheckAllReferencesExistOnDisk()
{
if (null == this.References)
if (null == References)
{
// No references
return true;
......@@ -899,7 +898,7 @@ protected bool CheckAllReferencesExistOnDisk()
bool success = true;
foreach (ITaskItem reference in this.References)
foreach (ITaskItem reference in References)
{
if (!File.Exists(reference.ItemSpec))
{
......@@ -937,11 +936,11 @@ string win32Manifest
{
if (!noDefaultWin32Manifest)
{
if (String.IsNullOrEmpty(win32Manifest) && String.IsNullOrEmpty(this.Win32Resource))
if (string.IsNullOrEmpty(win32Manifest) && string.IsNullOrEmpty(Win32Resource))
{
// We only want to consider the default.win32manifest if this is an executable
if (!String.Equals(TargetType, "library", StringComparison.OrdinalIgnoreCase)
&& !String.Equals(TargetType, "module", StringComparison.OrdinalIgnoreCase))
if (!string.Equals(TargetType, "library", StringComparison.OrdinalIgnoreCase)
&& !string.Equals(TargetType, "module", StringComparison.OrdinalIgnoreCase))
{
// We need to compute the path to the default win32 manifest
string pathToDefaultManifest = ToolLocationHelper.GetPathToDotNetFrameworkFile
......
// 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 Xunit;
namespace Microsoft.CodeAnalysis.BuildTasks.UnitTests
{
public sealed class CsiTests
{
[Fact]
public void SingleSource()
{
var csi = new Csi();
csi.Source = MSBuildUtil.CreateTaskItem("test.csx");
Assert.Equal("test.csx", csi.GenerateResponseFileContents());
}
[Fact]
public void Features()
{
Action<string> test = (s) =>
{
var csi = new Csi();
csi.Features = s;
csi.Source = MSBuildUtil.CreateTaskItem("test.csx");
Assert.Equal("/features:a /features:b test.csx", csi.GenerateResponseFileContents());
};
test("a;b");
test("a,b");
test("a b");
test(",a;b ");
test(";a;;b;");
test(",a,,b,");
}
[Fact]
public void FeaturesEmpty()
{
foreach (var cur in new[] { "", null })
{
var csi = new Csi();
csi.Features = cur;
csi.Sources = MSBuildUtil.CreateTaskItems("test.csx");
Assert.Equal("test.csx", csi.GenerateResponseFileContents());
}
}
}
}
......@@ -89,6 +89,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CscTests.cs" />
<Compile Include="CsiTests.cs" />
<Compile Include="MSBuildUtil.cs" />
<Compile Include="VbcTests.cs" />
</ItemGroup>
......@@ -102,4 +103,4 @@
<ImportGroup Label="Targets">
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册