Add support for 'additionalArguments' in compilationOptions

Rather than keep a map that will have to be constantly updated every time
a new argument gets added to a compiler, the 'additionalArguments' option
will allow users to directly add arguments to the underlying compiler.
This commit is contained in:
Andy Gocke 2016-01-31 01:25:01 -08:00
parent 44ac20a4ce
commit 6ba581fc17
8 changed files with 125 additions and 18 deletions

View file

@ -2,4 +2,5 @@ E2E
StreamForwarderTests
dotnet-publish.Tests
dotnet-compile.Tests
dotnet-build.Tests
dotnet-build.Tests
Compiler.Common.Tests

1 E2E
2 StreamForwarderTests
3 dotnet-publish.Tests
4 dotnet-compile.Tests
5 dotnet-build.Tests
6 Compiler.Common.Tests

View file

@ -36,6 +36,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
internal static readonly OptionTemplate s_generateXmlDocumentation = new OptionTemplate("generate-xml-documentation");
internal static readonly OptionTemplate s_additionalArgumentsTemplate = new OptionTemplate("additional-argument");
public static CommonCompilerOptions Parse(ArgumentSyntax syntax)
{
IReadOnlyList<string> defines = null;
@ -50,6 +52,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
bool? publicSign = null;
bool? emitEntryPoint = null;
bool? generateXmlDocumentation = null;
IReadOnlyList<string> additionalArguments = null;
Func<string, bool?> nullableBoolConverter = v => bool.Parse(v);
@ -57,6 +60,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
syntax.DefineOptionList(s_suppressWarningTemplate.LongName, ref suppressWarnings, "Suppresses the specified warning");
syntax.DefineOptionList(s_additionalArgumentsTemplate.LongName, ref additionalArguments, "Pass the additional argument directly to the compiler");
syntax.DefineOption(s_languageVersionTemplate.LongName, ref languageVersion,
"The version of the language used to compile");
@ -100,7 +105,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
DelaySign = delaySign,
PublicSign = publicSign,
EmitEntryPoint = emitEntryPoint,
GenerateXmlDocumentation = generateXmlDocumentation
GenerateXmlDocumentation = generateXmlDocumentation,
AdditionalArguments = additionalArguments
};
}
@ -118,6 +124,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
var publicSign = options.PublicSign;
var emitEntryPoint = options.EmitEntryPoint;
var generateXmlDocumentation = options.GenerateXmlDocumentation;
var additionalArguments = options.AdditionalArguments;
var args = new List<string>();
@ -131,6 +138,11 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
args.AddRange(suppressWarnings.Select(def => s_suppressWarningTemplate.ToLongArg(def)));
}
if (additionalArguments != null)
{
args.AddRange(additionalArguments.Select(arg => s_additionalArgumentsTemplate.ToLongArg(arg)));
}
if (languageVersion != null)
{
args.Add(s_languageVersionTemplate.ToLongArg(languageVersion));

View file

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
@ -34,6 +35,8 @@ namespace Microsoft.DotNet.ProjectModel
public IEnumerable<string> SuppressWarnings { get; set; }
public IEnumerable<string> AdditionalArguments { get; set; }
public override bool Equals(object obj)
{
var other = obj as CommonCompilerOptions;
@ -49,15 +52,29 @@ namespace Microsoft.DotNet.ProjectModel
EmitEntryPoint == other.EmitEntryPoint &&
GenerateXmlDocumentation == other.GenerateXmlDocumentation &&
PreserveCompilationContext == other.PreserveCompilationContext &&
Enumerable.SequenceEqual(Defines ?? Enumerable.Empty<string>(), other.Defines ?? Enumerable.Empty<string>()) &&
Enumerable.SequenceEqual(SuppressWarnings ?? Enumerable.Empty<string>(), other.SuppressWarnings ?? Enumerable.Empty<string>());
EnumerableEquals(Defines, other.Defines) &&
EnumerableEquals(SuppressWarnings, other.SuppressWarnings) &&
EnumerableEquals(AdditionalArguments, other.AdditionalArguments);
}
private static bool EnumerableEquals(IEnumerable<string> left, IEnumerable<string> right)
=> Enumerable.SequenceEqual(left ?? Array.Empty<string>(), right ?? Array.Empty<string>());
public override int GetHashCode()
{
return base.GetHashCode();
}
private static IEnumerable<string> Combine(IEnumerable<string> @new, IEnumerable<string> old)
{
if (@new != null)
{
old = old ?? Array.Empty<string>();
return old.Concat(@new).Distinct().ToArray();
}
return old;
}
public static CommonCompilerOptions Combine(params CommonCompilerOptions[] options)
{
var result = new CommonCompilerOptions();
@ -69,18 +86,10 @@ namespace Microsoft.DotNet.ProjectModel
continue;
}
// Defines and suppressions are always combined
if (option.Defines != null)
{
var existing = result.Defines ?? Enumerable.Empty<string>();
result.Defines = existing.Concat(option.Defines).Distinct();
}
if (option.SuppressWarnings != null)
{
var existing = result.SuppressWarnings ?? Enumerable.Empty<string>();
result.SuppressWarnings = existing.Concat(option.SuppressWarnings).Distinct();
}
// Defines, suppressions, and additional arguments are always combined
result.Defines = Combine(option.Defines, result.Defines);
result.SuppressWarnings = Combine(option.SuppressWarnings, result.SuppressWarnings);
result.AdditionalArguments = Combine(option.AdditionalArguments, result.AdditionalArguments);
if (option.LanguageVersion != null)
{

View file

@ -560,6 +560,7 @@ namespace Microsoft.DotNet.ProjectModel
{
Defines = rawOptions.ValueAsStringArray("define"),
SuppressWarnings = rawOptions.ValueAsStringArray("nowarn"),
AdditionalArguments = rawOptions.ValueAsStringArray("additionalArguments"),
LanguageVersion = rawOptions.ValueAsString("languageVersion"),
AllowUnsafe = rawOptions.ValueAsNullableBoolean("allowUnsafe"),
Platform = rawOptions.ValueAsString("platform"),

View file

@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Csc
syntax.DefineOption("out", ref outputName, "Name of the output assembly");
syntax.DefineOptionList("reference", ref references, "Path to a compiler metadata reference");
syntax.DefineOptionList("analyzer", ref analyzers, "Path to an analyzer assembly");
syntax.DefineOptionList("resource", ref resources, "Resources to embed");
@ -147,6 +147,12 @@ namespace Microsoft.DotNet.Tools.Compiler.Csc
commonArgs.AddRange(options.SuppressWarnings.Select(w => $"-nowarn:{w}"));
}
// Additional arguments are added verbatim
if (options.AdditionalArguments != null)
{
commonArgs.AddRange(options.AdditionalArguments);
}
if (options.LanguageVersion != null)
{
commonArgs.Add($"-langversion:{GetLanguageVersion(options.LanguageVersion)}");

View file

@ -0,0 +1,54 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.CommandLine;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
namespace Microsoft.DotNet.Cli.Compiler.Common
{
public class Tests : TestBase
{
private static void EqualAfterDeserialize(IEnumerable<string> args, CommonCompilerOptions original)
{
CommonCompilerOptions newOptions = null;
ArgumentSyntax.Parse(args, syntax =>
{
newOptions = CommonCompilerOptionsExtensions.Parse(syntax);
});
Assert.Equal(original, newOptions);
}
[Fact]
public void SimpleSerialize()
{
var options = new CommonCompilerOptions();
options.AdditionalArguments = new[] { "-highentropyva+" };
var args = options.SerializeToArgs();
Assert.Equal(new [] { "--additional-argument:-highentropyva+" }, args);
EqualAfterDeserialize(args, options);
}
[Fact]
public void WithSpaces()
{
var options = new CommonCompilerOptions();
options.AdditionalArguments = new[] { "-highentropyva+", "-addmodule:\"path with spaces\";\"after semicolon\"" };
var args = options.SerializeToArgs();
Assert.Equal(new [] {
"--additional-argument:-highentropyva+",
"--additional-argument:-addmodule:\"path with spaces\";\"after semicolon\""
}, args);
EqualAfterDeserialize(args, options);
}
}
}

View file

@ -0,0 +1,23 @@
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.0.0-rc2-23727",
"Microsoft.NETCore.TestHost" : "1.0.0-*",
"xunit": "2.1.0",
"xunit.console.netcore": "1.0.2-prerelease-00101",
"xunit.netcore.extensions": "1.0.0-prerelease-*",
"xunit.runner.utility": "2.1.0",
"Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" },
"Microsoft.DotNet.ProjectModel": { "target": "project" },
"Microsoft.DotNet.Compiler.Common": { "target": "project" }
},
"frameworks": {
"dnxcore50": {
"imports": "portable-net45+win8"
}
}
}

View file

@ -2,7 +2,8 @@
"version": "1.0.0-*",
"compilationOptions": {
"nowarn": [ "CS1591" ],
"xmlDoc": true
"xmlDoc": true,
"additionalArguments": [ "-highentropyva+" ]
},
"dependencies": {
"NETStandard.Library": "1.0.0-rc2-23727"