Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new command line switch to skip analyzer execution #46669

Merged
3 commits merged into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -4680,6 +4680,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable<string> ar
string? runtimeMetadataVersion = null;
bool errorEndLocation = false;
bool reportAnalyzer = false;
bool skipAnalyzers = false;
ArrayBuilder<InstrumentationKind> instrumentationKinds = ArrayBuilder<InstrumentationKind>.GetInstance();
CultureInfo? preferredUILang = null;
string? touchedFilesPath = null;
Expand Down Expand Up @@ -1179,6 +1180,21 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable<string> ar
reportAnalyzer = true;
continue;

case "skipanalyzers":
case "skipanalyzers+":
if (value != null)
break;

skipAnalyzers = true;
continue;

case "skipanalyzers-":
if (value != null)
break;

skipAnalyzers = false;
continue;

case "nostdlib":
case "nostdlib+":
if (value != null)
Expand Down Expand Up @@ -1503,6 +1519,7 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable<string> ar
ShouldIncludeErrorEndLocation = errorEndLocation,
PreferredUILang = preferredUILang,
ReportAnalyzer = reportAnalyzer,
SkipAnalyzers = skipAnalyzers,
EmbeddedFiles = embeddedFiles.AsImmutable()
};
}
Expand Down
3 changes: 2 additions & 1 deletion src/Compilers/CSharp/Portable/CommandLine/CSharpCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -361,10 +361,11 @@ protected override bool TryGetCompilerDiagnosticCode(string diagnosticId, out ui
protected override void ResolveAnalyzersFromArguments(
List<DiagnosticInfo> diagnostics,
CommonMessageProvider messageProvider,
bool skipAnalyzers,
out ImmutableArray<DiagnosticAnalyzer> analyzers,
out ImmutableArray<ISourceGenerator> generators)
{
Arguments.ResolveAnalyzersFromArguments(LanguageNames.CSharp, diagnostics, messageProvider, AssemblyLoader, out analyzers, out generators);
Arguments.ResolveAnalyzersFromArguments(LanguageNames.CSharp, diagnostics, messageProvider, AssemblyLoader, skipAnalyzers, out analyzers, out generators);
}

protected override void ResolveEmbeddedFilesFromExternalSourceDirectives(
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@
both mean SARIF version 2.1.0.
-reportanalyzer Report additional analyzer information, such as
execution time.
-skipanalyzers[+|-] Skip execution of diagnostic analyzers.

- LANGUAGE -
-checked[+|-] Generate overflow checks
Expand Down
109 changes: 109 additions & 0 deletions src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9129,6 +9129,66 @@ public void ReportAnalyzerOutput()
CleanupAllGeneratedFiles(srcFile.Path);
}

[Fact]
[WorkItem(40926, "https://github.com/dotnet/roslyn/issues/40926")]
public void SkipAnalyzersParse()
{
var parsedArgs = DefaultParse(new[] { "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.False(parsedArgs.SkipAnalyzers);

parsedArgs = DefaultParse(new[] { "/skipanalyzers+", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.True(parsedArgs.SkipAnalyzers);

parsedArgs = DefaultParse(new[] { "/skipanalyzers", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.True(parsedArgs.SkipAnalyzers);

parsedArgs = DefaultParse(new[] { "/SKIPANALYZERS+", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.True(parsedArgs.SkipAnalyzers);

parsedArgs = DefaultParse(new[] { "/skipanalyzers-", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.False(parsedArgs.SkipAnalyzers);

parsedArgs = DefaultParse(new[] { "/skipanalyzers-", "/skipanalyzers+", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.True(parsedArgs.SkipAnalyzers);

parsedArgs = DefaultParse(new[] { "/skipanalyzers", "/skipanalyzers-", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.False(parsedArgs.SkipAnalyzers);
}

[Theory, CombinatorialData]
[WorkItem(40926, "https://github.com/dotnet/roslyn/issues/40926")]
public void SkipAnalyzersSemantics(bool skipAnalyzers)
{
var srcFile = Temp.CreateFile().WriteAllText(@"class C {}");
var srcDirectory = Path.GetDirectoryName(srcFile.Path);

var outWriter = new StringWriter(CultureInfo.InvariantCulture);
var skipAnalyzersFlag = "/skipanalyzers" + (skipAnalyzers ? "+" : "-");
var csc = CreateCSharpCompiler(null, srcDirectory, new[] { skipAnalyzersFlag, "/reportanalyzer", "/t:library", "/a:" + Assembly.GetExecutingAssembly().Location, srcFile.Path });
var exitCode = csc.Run(outWriter);
Assert.Equal(0, exitCode);
var output = outWriter.ToString();
if (skipAnalyzers)
{
Assert.DoesNotContain(CodeAnalysisResources.AnalyzerExecutionTimeColumnHeader, output, StringComparison.Ordinal);
Assert.DoesNotContain(new WarningDiagnosticAnalyzer().ToString(), output, StringComparison.Ordinal);
}
else
{
Assert.Contains(CodeAnalysisResources.AnalyzerExecutionTimeColumnHeader, output, StringComparison.Ordinal);
Assert.Contains(new WarningDiagnosticAnalyzer().ToString(), output, StringComparison.Ordinal);
}

CleanupAllGeneratedFiles(srcFile.Path);
}

[Fact]
[WorkItem(24835, "https://github.com/dotnet/roslyn/issues/24835")]
public void TestCompilationSuccessIfOnlySuppressedDiagnostics()
Expand Down Expand Up @@ -12249,6 +12309,55 @@ class C
CleanupAllGeneratedFiles(src.Path);
}

[Theory, CombinatorialData]
[WorkItem(40926, "https://github.com/dotnet/roslyn/issues/40926")]
public void TestSourceGeneratorsWithAnalyzers(bool includeCurrentAssemblyAsAnalyzerReference, bool skipAnalyzers)
{
var dir = Temp.CreateDirectory();
var src = dir.CreateFile("temp.cs").WriteAllText(@"
class C
{
}");

var generatedSource = "public class D { }";
var generator = new SingleFileTestGenerator(generatedSource, "generatedSource.cs");

// 'skipAnalyzers' should have no impact on source generator execution, but should prevent analyzer execution.
var skipAnalyzersFlag = "/skipAnalyzers" + (skipAnalyzers ? "+" : "-");

// Verify analyzers were executed only if both the following conditions were satisfied:
// 1. Current assembly was added as an analyzer reference, i.e. "includeCurrentAssemblyAsAnalyzerReference = true" and
// 2. We did not explicitly request skipping analyzers, i.e. "skipAnalyzers = false".
var expectedAnalayzerExecution = includeCurrentAssemblyAsAnalyzerReference && !skipAnalyzers;

// 'WarningDiagnosticAnalyzer' generates a warning for each named type.
// We expect two warnings for this test: type "C" defined in source and the source generator defined type.
// Additionally, we also have an analyzer that generates "warning CS8032: An instance of analyzer cannot be created"
var expectedWarningCount = expectedAnalayzerExecution ? 3 : 0;

var output = VerifyOutput(dir, src, includeCurrentAssemblyAsAnalyzerReference,
expectedWarningCount: expectedWarningCount,
additionalFlags: new[] { "/langversion:preview", "/debug:embedded", "/out:embed.exe", skipAnalyzersFlag },
generators: new[] { generator });

// Verify source generator was executed, regardless of the value of 'skipAnalyzers'.
var generatorPrefix = $"{generator.GetType().Module.ModuleVersionId}_{generator.GetType().FullName}";
ValidateEmbeddedSources_Portable(new Dictionary<string, string> { { Path.Combine(dir.Path, $"{generatorPrefix}_generatedSource.cs"), generatedSource } }, dir, true);

if (expectedAnalayzerExecution)
{
Assert.Contains("warning Warning01", output, StringComparison.Ordinal);
Assert.Contains("warning CS8032", output, StringComparison.Ordinal);
}
else
{
Assert.Empty(output);
}

// Clean up temp files
CleanupAllGeneratedFiles(src.Path);
}

[Theory]
[InlineData("partial class D {}", "file1.cs", "partial class E {}", "file2.cs")] // different files, different names
[InlineData("partial class D {}", "file1.cs", "partial class E {}", "file1.cs")] // different files, same names
Expand Down
7 changes: 7 additions & 0 deletions src/Compilers/Core/MSBuildTask/ManagedCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,12 @@ public string? SharedCompilationId
get { return (string?)_store[nameof(SharedCompilationId)]; }
}

public bool SkipAnalyzers
{
set { _store[nameof(SkipAnalyzers)] = value; }
get { return _store.GetOrDefault(nameof(SkipAnalyzers), false); }
}

public bool SkipCompilerExecution
{
set { _store[nameof(SkipCompilerExecution)] = value; }
Expand Down Expand Up @@ -830,6 +836,7 @@ internal void AddResponseFileCommandsForSwitchesSinceInitialReleaseThatAreNeeded
commandLine.AppendSwitchWithSplitting("/instrument:", Instrument, ",", ';', ',');
commandLine.AppendSwitchIfNotNull("/sourcelink:", SourceLink);
commandLine.AppendSwitchIfNotNull("/langversion:", LangVersion);
commandLine.AppendPlusOrMinusSwitch("/skipanalyzers", _store, nameof(SkipAnalyzers));

AddFeatures(commandLine, Features);
AddEmbeddedFilesToCommandLine(commandLine);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
ResponseFiles="$(CompilerResponseFile)"
RuntimeMetadataVersion="$(RuntimeMetadataVersion)"
SharedCompilationId="$(SharedCompilationId)"
SkipAnalyzers="$(_SkipAnalyzers)"
SkipCompilerExecution="$(SkipCompilerExecution)"
Sources="@(Compile)"
SubsystemVersion="$(SubsystemVersion)"
Expand Down
22 changes: 22 additions & 0 deletions src/Compilers/Core/MSBuildTask/Microsoft.Managed.Core.targets
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,28 @@
</PropertyGroup>
</Target>

<Target Name="_ComputeSkipAnalyzers" BeforeTargets="CoreCompile">
<!-- First, force clear non-user facing property '_SkipAnalyzers'. -->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trust no one ;)

image

<PropertyGroup>
<_SkipAnalyzers></_SkipAnalyzers>
</PropertyGroup>

<!--
Then, determine if '_SkipAnalyzers' needs to be 'true' based on user facing property 'RunAnalyzers'.
If 'RunAnalyzers' is not set, then fallback to user facing property 'RunAnalyzersDuringBuild'.
Latter property allows users to disable analyzers only for non-design time builds.
Design time builds are background builds inside Visual Studio,
see details here: https://github.com/dotnet/project-system/blob/master/docs/design-time-builds.md.
Setting 'RunAnalyzersDuringBuild' to false, without setting 'RunAnalyzers', allows users to
continue running analyzers in the background in Visual Studio while typing (i.e. intellisense),
while disabling analyzer execution on explicitly invoked non-design time builds.
-->
<PropertyGroup Condition="'$(RunAnalyzers)' == 'false' or
('$(RunAnalyzers)' == '' and '$(RunAnalyzersDuringBuild)' == 'false')">
<_SkipAnalyzers>true</_SkipAnalyzers>
</PropertyGroup>
</Target>

<!--
========================
.editorconfig Support
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
RuntimeMetadataVersion="$(RuntimeMetadataVersion)"
SdkPath="$(FrameworkPathOverride)"
SharedCompilationId="$(SharedCompilationId)"
SkipAnalyzers="$(_SkipAnalyzers)"
SkipCompilerExecution="$(SkipCompilerExecution)"
Sources="@(Compile)"
SubsystemVersion="$(SubsystemVersion)"
Expand Down
19 changes: 19 additions & 0 deletions src/Compilers/Core/MSBuildTaskTests/CscTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -481,5 +481,24 @@ public void EditorConfig()
csc.AnalyzerConfigFiles = MSBuildUtil.CreateTaskItems("..\\.editorconfig", "sub dir\\.editorconfig");
Assert.Equal(@"/out:test.exe /analyzerconfig:..\.editorconfig /analyzerconfig:""sub dir\.editorconfig"" test.cs", csc.GenerateResponseFileContents());
}

[Fact]
[WorkItem(40926, "https://github.com/dotnet/roslyn/issues/40926")]
public void SkipAnalyzersFlag()
{
var csc = new Csc();
csc.Sources = MSBuildUtil.CreateTaskItems("test.cs");
csc.SkipAnalyzers = true;
Assert.Equal("/out:test.exe /skipanalyzers+ test.cs", csc.GenerateResponseFileContents());

csc = new Csc();
csc.Sources = MSBuildUtil.CreateTaskItems("test.cs");
csc.SkipAnalyzers = false;
Assert.Equal("/out:test.exe /skipanalyzers- test.cs", csc.GenerateResponseFileContents());

csc = new Csc();
csc.Sources = MSBuildUtil.CreateTaskItems("test.cs");
Assert.Equal("/out:test.exe test.cs", csc.GenerateResponseFileContents());
}
}
}
Loading