提交 5566daaf 编写于 作者: M manishv

Fix for bug 1094337: Remove /option switch in command line compilers and...

Fix for bug 1094337: Remove /option switch in command line compilers and remove global options and culture on AnalyzerOptions

Remove "/option" command line switch added for custom key-value pair analyzer options. There is no way to specify these options in the msbuild project file, so we will just revert the command line support and add it back once the end-to-end scenario is implemented for analyzer options.

Additionally, also remove the Culture passed into the analyzer options. Diagnostic analyzer authors need not report localized diagnostics, just localizable diagnostics, which can be localized for any given culture by the analyzer host (IDE/command line compiler). (changeset 1384781)
上级 12fdf4dd
......@@ -75,7 +75,6 @@ public new CSharpCommandLineArguments Parse(IEnumerable<string> args, string bas
List<ResourceDescription> managedResources = new List<ResourceDescription>();
List<CommandLineSourceFile> sourceFiles = new List<CommandLineSourceFile>();
List<AdditionalStream> additionalFiles = new List<AdditionalStream>();
Dictionary<string, string> additionalOptions = new Dictionary<string, string>();
bool sourceFilesSpecified = false;
bool resourcesOrModulesSpecified = false;
Encoding codepage = null;
......@@ -916,33 +915,6 @@ public new CSharpCommandLineArguments Parse(IEnumerable<string> args, string bas
additionalFiles.AddRange(ParseAdditionalFiles(value, baseDirectory, diagnostics));
continue;
case "option":
unquoted = RemoveAllQuotes(value);
if (string.IsNullOrEmpty(unquoted))
{
AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<name>=<value>", name);
continue;
}
var parts = unquoted.Split(new[] { '=' }, 2, StringSplitOptions.None);
if (parts.Length != 2 || string.IsNullOrEmpty(parts[0]) || string.IsNullOrEmpty(parts[1]))
{
AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<name>=<value>", name);
continue;
}
if (additionalOptions.ContainsKey(parts[0]))
{
additionalOptions[parts[0]] = parts[1];
}
else
{
additionalOptions.Add(parts[0], parts[1]);
}
continue;
}
}
......@@ -1074,7 +1046,6 @@ public new CSharpCommandLineArguments Parse(IEnumerable<string> args, string bas
MetadataReferences = metadataReferences.AsImmutable(),
AnalyzerReferences = analyzers.AsImmutable(),
AdditionalStreams = additionalFiles.AsImmutable(),
AdditionalOptions = additionalOptions.ToImmutableDictionary(),
ReferencePaths = referencePaths,
KeyFileSearchPaths = keyFileSearchPaths.AsImmutable(),
Win32ResourceFile = win32ResourceFile,
......
......@@ -3838,7 +3838,6 @@
/nowarn:&lt;warn list&gt; Disable specific warning messages
/ruleset:&lt;file&gt; Specify a ruleset file that disables specific
diagnostics.
/option:&lt;name&gt;=&lt;value&gt; Specify an option that can be passed to analyzers.
- LANGUAGE -
/checked[+|-] Generate overflow checks
......
......@@ -6498,64 +6498,6 @@ public void ParseAdditionalFile()
Assert.Equal(0, args.AdditionalStreams.Length);
}
[Fact]
public void ParseOptions()
{
var args = CSharpCommandLineParser.Default.Parse(new[] { "/option:a=b", "a.cs" }, baseDirectory);
args.Errors.Verify();
Assert.Equal("a", args.AdditionalOptions.Keys.Single());
Assert.Equal("b", args.AdditionalOptions.Values.Single());
args = CSharpCommandLineParser.Default.Parse(new[] { "/option:a=b", "/option:d=e", "a.cs" }, baseDirectory);
args.Errors.Verify();
Assert.Equal("b", args.AdditionalOptions["a"]);
Assert.Equal("e", args.AdditionalOptions["d"]);
args = CSharpCommandLineParser.Default.Parse(new[] { "/option", "a.cs" }, baseDirectory);
args.Errors.Verify(Diagnostic(ErrorCode.ERR_SwitchNeedsString).WithArguments("<name>=<value>", "option"));
Assert.Equal(0, args.AdditionalOptions.Count);
args = CSharpCommandLineParser.Default.Parse(new[] { "/option:", "a.cs" }, baseDirectory);
args.Errors.Verify(Diagnostic(ErrorCode.ERR_SwitchNeedsString).WithArguments("<name>=<value>", "option"));
Assert.Equal(0, args.AdditionalOptions.Count);
args = CSharpCommandLineParser.Default.Parse(new[] { "/option:a", "a.cs" }, baseDirectory);
args.Errors.Verify(Diagnostic(ErrorCode.ERR_SwitchNeedsString).WithArguments("<name>=<value>", "option"));
Assert.Equal(0, args.AdditionalOptions.Count);
args = CSharpCommandLineParser.Default.Parse(new[] { "/option:a=", "a.cs" }, baseDirectory);
args.Errors.Verify(Diagnostic(ErrorCode.ERR_SwitchNeedsString).WithArguments("<name>=<value>", "option"));
Assert.Equal(0, args.AdditionalOptions.Count);
args = CSharpCommandLineParser.Default.Parse(new[] { "/option:a:b", "a.cs" }, baseDirectory);
args.Errors.Verify(Diagnostic(ErrorCode.ERR_SwitchNeedsString).WithArguments("<name>=<value>", "option"));
Assert.Equal(0, args.AdditionalOptions.Count);
args = CSharpCommandLineParser.Default.Parse(new[] { "/option:=b", "a.cs" }, baseDirectory);
args.Errors.Verify(Diagnostic(ErrorCode.ERR_SwitchNeedsString).WithArguments("<name>=<value>", "option"));
Assert.Equal(0, args.AdditionalOptions.Count);
args = CSharpCommandLineParser.Default.Parse(new[] { "/option:a=b=c", "a.cs" }, baseDirectory);
args.Errors.Verify();
Assert.Equal("b=c", args.AdditionalOptions["a"]);
args = CSharpCommandLineParser.Default.Parse(new[] { "/option:a==b", "a.cs" }, baseDirectory);
args.Errors.Verify();
Assert.Equal("=b", args.AdditionalOptions["a"]);
args = CSharpCommandLineParser.Default.Parse(new[] { "/option:\"a b\"=\"c d\"", "a.cs" }, baseDirectory);
args.Errors.Verify();
Assert.Equal("c d", args.AdditionalOptions["a b"]);
args = CSharpCommandLineParser.Default.Parse(new[] { "/option:\"a b=c d\"", "a.cs" }, baseDirectory);
args.Errors.Verify();
Assert.Equal("c d", args.AdditionalOptions["a b"]);
args = CSharpCommandLineParser.Default.Parse(new[] { "/option:a=b", "/option:a=c", "a.cs" }, baseDirectory);
args.Errors.Verify();
Assert.Equal("c", args.AdditionalOptions["a"]);
}
private static int OccurenceCount(string source, string word)
{
var n = 0;
......
......@@ -95,8 +95,7 @@ public void AnalyzerOptionsArePassedToAllAnalyzers()
{
AnalyzerOptions options = new AnalyzerOptions
(
new[] { new AdditionalFileStream("myfilepath") }.ToImmutableArray<AdditionalStream>(),
new Dictionary<string, string> { { "optionName", "optionValue" } }.ToImmutableDictionary()
new[] { new AdditionalFileStream("myfilepath") }.ToImmutableArray<AdditionalStream>()
);
var compilation = CreateCompilationWithMscorlib45(TestResource.AllInOneCSharpCode, parseOptions: TestOptions.Regular);
......
......@@ -111,11 +111,6 @@ public abstract class CommandLineArguments
/// </summary>
public ImmutableArray<AdditionalStream> AdditionalStreams { get; internal set; }
/// <summary>
/// A set of additional options passed in from the /option switch that can be used by analyzers.
/// </summary>
public ImmutableDictionary<string, string> AdditionalOptions { get; internal set; }
/// <summary>
/// If true, prepend the command line header logo during
/// <see cref="CommonCompiler.Run"/>.
......
......@@ -287,7 +287,7 @@ public virtual int Run(TextWriter consoleOutput, CancellationToken cancellationT
cancellationToken.ThrowIfCancellationRequested();
var analyzerOptions = new AnalyzerOptions(Arguments.AdditionalStreams, Arguments.AdditionalOptions, Culture);
var analyzerOptions = new AnalyzerOptions(Arguments.AdditionalStreams);
AnalyzerDriver analyzerDriver = null;
if (!analyzers.IsDefaultOrEmpty)
......
......@@ -11,34 +11,20 @@ namespace Microsoft.CodeAnalysis.Diagnostics
/// </summary>
public class AnalyzerOptions
{
internal static readonly AnalyzerOptions Empty = new AnalyzerOptions(ImmutableArray<AdditionalStream>.Empty, ImmutableDictionary<string, string>.Empty);
internal static readonly AnalyzerOptions Empty = new AnalyzerOptions(ImmutableArray<AdditionalStream>.Empty);
/// <summary>
/// A set of additional non-code streams that can be used by analyzers.
/// </summary>
public ImmutableArray<AdditionalStream> AdditionalStreams { get; internal set; }
/// <summary>
/// A set of global options for analyzers.
/// </summary>
public ImmutableDictionary<string, string> GlobalOptions { get; internal set; }
/// <summary>
/// CultureInfo to be used for localizing diagnostics.
/// </summary>
public CultureInfo Culture { get; internal set; }
/// <summary>
/// Creates analyzer options to be passed to <see cref="DiagnosticAnalyzer"/>.
/// </summary>
/// <param name="additionalStreams">A set of additional non-code streams that can be used by analyzers.</param>
/// <param name="globalOptions">A set of global options for analyzers.</param>
/// <param name="culture">Optional CultureInfo to be used for localizing diagnostics.</param>
public AnalyzerOptions(ImmutableArray<AdditionalStream> additionalStreams, ImmutableDictionary<string, string> globalOptions, CultureInfo culture = null)
public AnalyzerOptions(ImmutableArray<AdditionalStream> additionalStreams)
{
this.AdditionalStreams = additionalStreams.IsDefault ? ImmutableArray<AdditionalStream>.Empty : additionalStreams;
this.GlobalOptions = globalOptions ?? ImmutableDictionary<string, string>.Empty;
this.Culture = culture ?? CultureInfo.CurrentCulture;
}
/// <summary>
......@@ -51,33 +37,7 @@ public AnalyzerOptions WithAdditionalStreams(ImmutableArray<AdditionalStream> ad
return this;
}
return new AnalyzerOptions(additionalStreams, this.GlobalOptions, this.Culture);
}
/// <summary>
/// Returns analyzer options with the given globalOptions.
/// </summary>
public AnalyzerOptions WithGlobalOptions(ImmutableDictionary<string, string> globalOptions)
{
if (this.GlobalOptions == globalOptions)
{
return this;
}
return new AnalyzerOptions(this.AdditionalStreams, globalOptions, this.Culture);
}
/// <summary>
/// Returns analyzer options with the given culture.
/// </summary>
public AnalyzerOptions WithCulture(CultureInfo culture)
{
if (this.Culture == culture)
{
return this;
}
return new AnalyzerOptions(this.AdditionalStreams, this.GlobalOptions, culture);
return new AnalyzerOptions(additionalStreams);
}
}
}
......@@ -42,8 +42,7 @@ protected override void OnOptions(AnalyzerOptions options, [CallerMemberName]str
private bool AreEqual(AnalyzerOptions actual, AnalyzerOptions expected)
{
if (actual.AdditionalStreams.Length != expected.AdditionalStreams.Length ||
actual.GlobalOptions.Count != expected.GlobalOptions.Count)
if (actual.AdditionalStreams.Length != expected.AdditionalStreams.Length)
{
return false;
}
......@@ -56,15 +55,6 @@ private bool AreEqual(AnalyzerOptions actual, AnalyzerOptions expected)
}
}
for (int i = 0; i < actual.GlobalOptions.Count; i++)
{
if (actual.GlobalOptions.Keys.ElementAt(i) != expected.GlobalOptions.Keys.ElementAt(i) ||
actual.GlobalOptions.Values.ElementAt(i) != expected.GlobalOptions.Values.ElementAt(i))
{
return false;
}
}
return true;
}
......
......@@ -109,7 +109,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim sourceFiles = New List(Of CommandLineSourceFile)()
Dim hasSourceFiles = False
Dim additionalFiles = New List(Of AdditionalStream)()
Dim additionalOptions = New Dictionary(Of String, String)()
Dim codepage As Encoding = Nothing
Dim checksumAlgorithm = SourceHashAlgorithm.Sha1
Dim defines As IReadOnlyDictionary(Of String, Object) = Nothing
......@@ -978,28 +977,6 @@ lVbRuntimePlus:
additionalFiles.AddRange(ParseAdditionalFiles(value, baseDirectory, diagnostics))
Continue For
Case "option"
Dim unquoted = RemoveAllQuotes(value)
If String.IsNullOrEmpty(unquoted) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":<name>=<value>")
Continue For
End If
Dim parts = unquoted.Split({"="}, 2, StringSplitOptions.None)
If parts.Length <> 2 OrElse String.IsNullOrEmpty(parts(0)) OrElse String.IsNullOrEmpty(parts(1)) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":<name>=<value>")
Continue For
End If
If (additionalOptions.ContainsKey(parts(0))) Then
additionalOptions(parts(0)) = parts(1)
Else
additionalOptions.Add(parts(0), parts(1))
End If
Continue For
End Select
End If
......@@ -1156,7 +1133,6 @@ lVbRuntimePlus:
.MetadataReferences = metadataReferences.AsImmutable(),
.AnalyzerReferences = analyzers.AsImmutable(),
.AdditionalStreams = additionalFiles.AsImmutable(),
.AdditionalOptions = additionalOptions.ToImmutableDictionary(),
.ReferencePaths = searchPaths,
.KeyFileSearchPaths = keyFileSearchPaths.AsImmutable(),
.Win32ResourceFile = win32ResourceFile,
......
......@@ -4568,7 +4568,6 @@
/warnaserror[+|-]:&lt;number_list&gt; Treat a list of warnings as errors.
/ruleset:&lt;file&gt; Specify a ruleset file that disables specific
diagnostics.
/option:&lt;name&gt;=&lt;value&gt; Specify an option that can be passed to analyzers.
- LANGUAGE -
/define:&lt;symbol_list&gt; Declare global conditional compilation
......
......@@ -6102,63 +6102,6 @@ C:\*.vb(100) : error BC30451: 'Foo' is not declared. It may be inaccessible due
Assert.Equal(0, args.AdditionalStreams.Length)
End Sub
<Fact>
Public Sub ParseOptions()
Dim args = VisualBasicCommandLineParser.Default.Parse({"/option:a=b", "a.vb"}, _baseDirectory)
args.Errors.Verify()
Assert.Equal("a", args.AdditionalOptions.Keys.Single())
Assert.Equal("b", args.AdditionalOptions.Values.Single())
args = VisualBasicCommandLineParser.Default.Parse({"/option:a=b", "/option:d=e", "a.vb"}, _baseDirectory)
args.Errors.Verify()
Assert.Equal("b", args.AdditionalOptions("a"))
Assert.Equal("e", args.AdditionalOptions("d"))
args = VisualBasicCommandLineParser.Default.Parse({"/option", "a.vb"}, _baseDirectory)
args.Errors.Verify(Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("option", ":<name>=<value>"))
Assert.Equal(0, args.AdditionalOptions.Count)
args = VisualBasicCommandLineParser.Default.Parse({"/option:", "a.vb"}, _baseDirectory)
args.Errors.Verify(Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("option", ":<name>=<value>"))
Assert.Equal(0, args.AdditionalOptions.Count)
args = VisualBasicCommandLineParser.Default.Parse({"/option:a", "a.vb"}, _baseDirectory)
args.Errors.Verify(Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("option", ":<name>=<value>"))
Assert.Equal(0, args.AdditionalOptions.Count)
args = VisualBasicCommandLineParser.Default.Parse({"/option:a=", "a.vb"}, _baseDirectory)
args.Errors.Verify(Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("option", ":<name>=<value>"))
Assert.Equal(0, args.AdditionalOptions.Count)
args = VisualBasicCommandLineParser.Default.Parse({"/option:a:b", "a.vb"}, _baseDirectory)
args.Errors.Verify(Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("option", ":<name>=<value>"))
Assert.Equal(0, args.AdditionalOptions.Count)
args = VisualBasicCommandLineParser.Default.Parse({"/option:=b", "a.vb"}, _baseDirectory)
args.Errors.Verify(Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("option", ":<name>=<value>"))
Assert.Equal(0, args.AdditionalOptions.Count)
args = VisualBasicCommandLineParser.Default.Parse({"/option:a=b=c", "a.vb"}, _baseDirectory)
args.Errors.Verify()
Assert.Equal("b=c", args.AdditionalOptions("a"))
args = VisualBasicCommandLineParser.Default.Parse({"/option:a==b", "a.vb"}, _baseDirectory)
args.Errors.Verify()
Assert.Equal("=b", args.AdditionalOptions("a"))
args = VisualBasicCommandLineParser.Default.Parse({"/option:""a b""=""c d""", "a.vb"}, _baseDirectory)
args.Errors.Verify()
Assert.Equal("c d", args.AdditionalOptions("a b"))
args = VisualBasicCommandLineParser.Default.Parse({"/option:""a b=c d""", "a.cs"}, _baseDirectory)
args.Errors.Verify()
Assert.Equal("c d", args.AdditionalOptions("a b"))
args = VisualBasicCommandLineParser.Default.Parse({"/option:a=b", "/option:a=c", "a.vb"}, _baseDirectory)
args.Errors.Verify()
Assert.Equal("c", args.AdditionalOptions("a"))
End Sub
Private Shared Sub Verify(actual As IEnumerable(Of Diagnostic), ParamArray expected As DiagnosticDescription())
actual.Verify(expected)
End Sub
......
......@@ -48,8 +48,7 @@ End Enum
<Fact>
Public Sub AnalyzerOptionsArePassedToAllAnalyzers()
Dim additionalStreams As AdditionalStream() = {New AdditionalFileStream("myfilepath")}
Dim options = New AnalyzerOptions(additionalStreams.ToImmutableArray(),
New Dictionary(Of String, String) From {{"optionName", "optionValue"}}.ToImmutableDictionary())
Dim options = New AnalyzerOptions(additionalStreams.ToImmutableArray())
Dim compilation = CreateCompilationWithMscorlib({TestResource.AllInOneVisualBasicCode})
Dim analyzer = New OptionsDiagnosticAnalyzer(Of SyntaxKind)(options)
......
......@@ -233,7 +233,7 @@ public AnalyzerOptions AnalyzerOptions
{
if (analyzerOptions == null)
{
this.analyzerOptions = new AnalyzerOptions(this.additionalDocumentStates.Values.Select(d => new AdditionalDocumentStream(d)).ToImmutableArray<AdditionalStream>(), globalOptions: null);
this.analyzerOptions = new AnalyzerOptions(this.additionalDocumentStates.Values.Select(d => new AdditionalDocumentStream(d)).ToImmutableArray<AdditionalStream>());
}
return analyzerOptions;
......@@ -242,7 +242,7 @@ public AnalyzerOptions AnalyzerOptions
private static AnalyzerOptions CreateAnalyzerOptions(ImmutableDictionary<DocumentId, TextDocumentState> additionalDocStates)
{
return new AnalyzerOptions(additionalDocStates.Values.Select(d => new AdditionalDocumentStream(d)).ToImmutableArray<AdditionalStream>(), globalOptions: null);
return new AnalyzerOptions(additionalDocStates.Values.Select(d => new AdditionalDocumentStream(d)).ToImmutableArray<AdditionalStream>());
}
public Task<VersionStamp> GetLatestDocumentVersionAsync(CancellationToken cancellationToken)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册