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

Few analyzer bug fixes in presence of top level programs #4066

Merged
merged 2 commits into from
Aug 26, 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
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,12 @@ public static bool IsOkToBeUnused(
return true;
}

// Ignore type generated for holding top level statements
if (type.IsTopLevelStatementsEntryPointType())
{
return true;
}

// The type containing the assembly's entry point is OK.
if (ContainsEntryPoint(type, compilation))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,12 @@ private static bool ShouldAnalyzeMethod(
return false;
}

// Ignore generated method for top level statements
if (method.IsTopLevelStatementsEntryPointMethod())
{
return false;
}

return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,25 @@ public void MyMethod(object obj) {}
}");
}

[Fact, WorkItem(4052, "https://github.com/dotnet/roslyn-analyzers/issues/4052")]
public async Task CA1720_TopLevelStatements_NoDiagnostic()
{
await new VerifyCS.Test()
{
TestCode = @"int x = 0;",
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp9,
SolutionTransforms =
{
(solution, projectId) =>
{
var project = solution.GetProject(projectId);
project = project.WithCompilationOptions(project.CompilationOptions.WithOutputKind(CodeAnalysis.OutputKind.ConsoleApplication));
return project.Solution;
},
}
}.RunAsync();
}

#region Helpers

private static DiagnosticResult GetCA1720CSharpResultAt(int line, int column, string identifierName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,25 @@ End Function
End Class");
}

[Fact, WorkItem(4052, "https://github.com/dotnet/roslyn-analyzers/issues/4052")]
public async Task CA1812_CSharp_TopLevelStatements_NoDiagnostic()
{
await new VerifyCS.Test()
{
TestCode = @"int x = 0;",
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp9,
SolutionTransforms =
{
(solution, projectId) =>
{
var project = solution.GetProject(projectId);
project = project.WithCompilationOptions(project.CompilationOptions.WithOutputKind(OutputKind.ConsoleApplication));
return project.Solution;
},
}
}.RunAsync();
}

private static DiagnosticResult GetCSharpResultAt(int line, int column, string className)
=> VerifyCS.Diagnostic()
.WithLocation(line, column)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,25 @@ public class Class1
");
}

[Fact, WorkItem(4052, "https://github.com/dotnet/roslyn-analyzers/issues/4052")]
public async Task CA1801_TopLevelStatements_NoDiagnostic()
{
await new VerifyCS.Test()
{
TestCode = @"int x = 0;",
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp9,
SolutionTransforms =
{
(solution, projectId) =>
{
var project = solution.GetProject(projectId);
project = project.WithCompilationOptions(project.CompilationOptions.WithOutputKind(OutputKind.ConsoleApplication));
return project.Solution;
},
}
}.RunAsync();
}

#endregion

#region Unit tests for analyzer diagnostic(s)
Expand Down
13 changes: 13 additions & 0 deletions src/Utilities/Compiler/Extensions/IMethodSymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -680,5 +680,18 @@ public static bool IsAutoPropertyAccessor(this IMethodSymbol methodSymbol)
=> methodSymbol.IsPropertyAccessor()
&& methodSymbol.AssociatedSymbol is IPropertySymbol propertySymbol
&& propertySymbol.IsAutoProperty();

/// <summary>
/// Check if the given <paramref name="methodSymbol"/> is an implicitly generated method for top level statements.
/// </summary>
public static bool IsTopLevelStatementsEntryPointMethod([NotNullWhen(true)] this IMethodSymbol? methodSymbol)
=> methodSymbol?.ContainingType.IsTopLevelStatementsEntryPointType() == true &&
methodSymbol.IsStatic &&
methodSymbol.Name switch
{
"$Main" => true,
"<$Main>$" => true,
_ => false
};
}
}
12 changes: 12 additions & 0 deletions src/Utilities/Compiler/Extensions/INamedTypeSymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis;

Expand Down Expand Up @@ -269,5 +270,16 @@ public static bool IsXUnitTestAttribute(this INamedTypeSymbol attributeClass, Co

return knownTestAttributes.GetOrAdd(attributeClass, attributeClass.DerivesFrom(xunitFactAttribute));
}

/// <summary>
/// Check if the given <paramref name="typeSymbol"/> is an implicitly generated type for top level statements.
/// </summary>
public static bool IsTopLevelStatementsEntryPointType([NotNullWhen(true)] this INamedTypeSymbol? typeSymbol)
=> typeSymbol?.IsStatic == true && typeSymbol.Name switch
{
"$Program" => true,
"<Program>$" => true,
_ => false
};
}
}
2 changes: 2 additions & 0 deletions src/Utilities/Compiler/Options/AnalyzerOptionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ private static bool TryGetSyntaxTreeForOption(ISymbol symbol, [NotNullWhen(retur
case SymbolKind.Namespace when ((INamespaceSymbol)symbol).IsGlobalNamespace:
tree = null;
return false;
case SymbolKind.Parameter:
return TryGetSyntaxTreeForOption(symbol.ContainingSymbol, out tree);
default:
tree = symbol.Locations[0].SourceTree;
return tree != null;
Expand Down