Skip to content

Commit

Permalink
Merge branch 'master' into feature/Issue3386CastInRange
Browse files Browse the repository at this point in the history
  • Loading branch information
sharwell committed Dec 9, 2021
2 parents 7754e6b + ca7ccd2 commit d2a3d2b
Show file tree
Hide file tree
Showing 30 changed files with 424 additions and 102 deletions.
8 changes: 4 additions & 4 deletions StyleCop.Analyzers/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
</PropertyGroup>

<PropertyGroup>
<LangVersion>9</LangVersion>
<WarningLevel>5</WarningLevel>
<LangVersion>10</LangVersion>
<WarningLevel>99</WarningLevel>
</PropertyGroup>

<PropertyGroup Condition="'$(BuildingInsideVisualStudio)' != 'true'">
Expand Down Expand Up @@ -47,12 +47,12 @@
<PackageReference Include="DotNetAnalyzers.DocumentationAnalyzers" Version="1.0.0-beta.46" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.304" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeStyle" Version="3.8.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeStyle" Version="4.0.1" PrivateAssets="all" />
</ItemGroup>

<!-- C# Compiler -->
<ItemGroup>
<PackageReference Include="Microsoft.Net.Compilers.Toolset" Version="3.8.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.Net.Compilers.Toolset" Version="4.0.1" PrivateAssets="all" />
</ItemGroup>

<!-- Public API -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@ namespace StyleCop.Analyzers.CodeGeneration
using Microsoft.CodeAnalysis.Text;

[Generator]
internal sealed class OperationLightupGenerator : ISourceGenerator
internal sealed class OperationLightupGenerator : IIncrementalGenerator
{
public void Initialize(GeneratorInitializationContext context)
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var operationInterfacesFiles = context.AdditionalTextsProvider.Where(static x => Path.GetFileName(x.Path) == "OperationInterfaces.xml");
context.RegisterSourceOutput(operationInterfacesFiles, this.Execute);
}

public void Execute(GeneratorExecutionContext context)
private void Execute(SourceProductionContext context, AdditionalText operationInterfacesFile)
{
var operationInterfacesFile = context.AdditionalFiles.Single(x => Path.GetFileName(x.Path) == "OperationInterfaces.xml");
var operationInterfacesText = operationInterfacesFile.GetText(context.CancellationToken);
if (operationInterfacesText is null)
{
Expand All @@ -38,7 +39,7 @@ public void Execute(GeneratorExecutionContext context)
this.GenerateOperationInterfaces(in context, operationInterfaces);
}

private void GenerateOperationInterfaces(in GeneratorExecutionContext context, XDocument operationInterfaces)
private void GenerateOperationInterfaces(in SourceProductionContext context, XDocument operationInterfaces)
{
var tree = operationInterfaces.XPathSelectElement("/Tree");
if (tree is null)
Expand All @@ -56,7 +57,7 @@ private void GenerateOperationInterfaces(in GeneratorExecutionContext context, X
this.GenerateOperationKindEx(in context, documentData.Interfaces.Values.ToImmutableArray());
}

private void GenerateOperationInterface(in GeneratorExecutionContext context, InterfaceData node)
private void GenerateOperationInterface(in SourceProductionContext context, InterfaceData node)
{
var members = SyntaxFactory.List<MemberDeclarationSyntax>();

Expand All @@ -69,7 +70,7 @@ private void GenerateOperationInterface(in GeneratorExecutionContext context, In
variables: SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(
identifier: SyntaxFactory.Identifier("WrappedTypeName"),
argumentList: null,
initializer: SyntaxFactory.EqualsValueClause(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal("Microsoft.CodeAnalysis.Operations." + node.InterfaceName))))))));
initializer: SyntaxFactory.EqualsValueClause(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal($"Microsoft.CodeAnalysis.{node.Namespace}.{node.InterfaceName}"))))))));

// private static readonly Type WrappedType;
members = members.Add(SyntaxFactory.FieldDeclaration(
Expand Down Expand Up @@ -581,7 +582,7 @@ private void GenerateOperationInterface(in GeneratorExecutionContext context, In
context.AddSource(node.WrapperName + ".g.cs", SourceText.From(wrapperNamespace.ToFullString(), Encoding.UTF8));
}

private void GenerateOperationWrapperHelper(in GeneratorExecutionContext context, ImmutableArray<InterfaceData> wrapperTypes)
private void GenerateOperationWrapperHelper(in SourceProductionContext context, ImmutableArray<InterfaceData> wrapperTypes)
{
// private static readonly ImmutableDictionary<Type, Type> WrappedTypes;
var wrappedTypes = SyntaxFactory.FieldDeclaration(
Expand Down Expand Up @@ -789,7 +790,7 @@ private void GenerateOperationWrapperHelper(in GeneratorExecutionContext context
context.AddSource("OperationWrapperHelper.g.cs", SourceText.From(wrapperNamespace.ToFullString(), Encoding.UTF8));
}

private void GenerateOperationKindEx(in GeneratorExecutionContext context, ImmutableArray<InterfaceData> wrapperTypes)
private void GenerateOperationKindEx(in SourceProductionContext context, ImmutableArray<InterfaceData> wrapperTypes)
{
var operationKinds = wrapperTypes
.SelectMany(type => type.OperationKinds)
Expand Down Expand Up @@ -988,6 +989,7 @@ public InterfaceData(DocumentData documentData, XElement node, ImmutableArray<(s

this.OperationKinds = operationKinds;
this.InterfaceName = node.Attribute("Name").Value;
this.Namespace = node.Attribute("Namespace")?.Value ?? "Operations";
this.Name = this.InterfaceName.Substring("I".Length, this.InterfaceName.Length - "I".Length - "Operation".Length);
this.WrapperName = this.InterfaceName + "Wrapper";
this.BaseInterfaceName = node.Attribute("Base").Value;
Expand All @@ -999,6 +1001,8 @@ public InterfaceData(DocumentData documentData, XElement node, ImmutableArray<(s

public string InterfaceName { get; }

public string Namespace { get; }

public string Name { get; }

public string WrapperName { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" />
<PackageReference Include="TunnelVisionLabs.ReferenceAssemblyAnnotator" Version="1.0.0-alpha.160" PrivateAssets="all" />
<PackageDownload Include="Microsoft.NETCore.App.Ref" Version="[3.1.0]" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace StyleCop.Analyzers.CodeGeneration
using Microsoft.CodeAnalysis.Text;

[Generator]
internal sealed class SyntaxLightupGenerator : ISourceGenerator
internal sealed class SyntaxLightupGenerator : IIncrementalGenerator
{
private enum NodeKind
{
Expand All @@ -28,33 +28,37 @@ private enum NodeKind
Concrete,
}

public void Initialize(GeneratorInitializationContext context)
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var compilation = context.CompilationProvider;
var syntaxFiles = context.AdditionalTextsProvider.Where(static x => Path.GetFileName(x.Path) == "Syntax.xml");
context.RegisterSourceOutput(
syntaxFiles.Combine(compilation),
(context, value) => this.Execute(in context, value.Right, value.Left));
}

public void Execute(GeneratorExecutionContext context)
private void Execute(in SourceProductionContext context, Compilation compilation, AdditionalText syntaxFile)
{
var syntaxFile = context.AdditionalFiles.Single(x => Path.GetFileName(x.Path) == "Syntax.xml");
var syntaxText = syntaxFile.GetText(context.CancellationToken);
if (syntaxText is null)
{
throw new InvalidOperationException("Failed to read Syntax.xml");
}

var syntaxData = new SyntaxData(in context, XDocument.Parse(syntaxText.ToString()));
var syntaxData = new SyntaxData(compilation, XDocument.Parse(syntaxText.ToString()));
this.GenerateSyntaxWrappers(in context, syntaxData);
this.GenerateSyntaxWrapperHelper(in context, syntaxData.Nodes);
}

private void GenerateSyntaxWrappers(in GeneratorExecutionContext context, SyntaxData syntaxData)
private void GenerateSyntaxWrappers(in SourceProductionContext context, SyntaxData syntaxData)
{
foreach (var node in syntaxData.Nodes)
{
this.GenerateSyntaxWrapper(in context, syntaxData, node);
}
}

private void GenerateSyntaxWrapper(in GeneratorExecutionContext context, SyntaxData syntaxData, NodeData nodeData)
private void GenerateSyntaxWrapper(in SourceProductionContext context, SyntaxData syntaxData, NodeData nodeData)
{
if (nodeData.WrapperName is null)
{
Expand Down Expand Up @@ -806,7 +810,7 @@ private void GenerateSyntaxWrapper(in GeneratorExecutionContext context, SyntaxD
context.AddSource(nodeData.WrapperName + ".g.cs", SourceText.From(wrapperNamespace.ToFullString(), Encoding.UTF8));
}

private void GenerateSyntaxWrapperHelper(in GeneratorExecutionContext context, ImmutableArray<NodeData> wrapperTypes)
private void GenerateSyntaxWrapperHelper(in SourceProductionContext context, ImmutableArray<NodeData> wrapperTypes)
{
// private static readonly ImmutableDictionary<Type, Type> WrappedTypes;
var wrappedTypes = SyntaxFactory.FieldDeclaration(
Expand Down Expand Up @@ -982,6 +986,65 @@ private void GenerateSyntaxWrapperHelper(in GeneratorExecutionContext context, I
continue;
}

if (node.Name == nameof(BaseNamespaceDeclarationSyntax))
{
// Prior to C# 10, NamespaceDeclarationSyntax was the base type for all namespace declarations.
// If the BaseNamespaceDeclarationSyntax type isn't found at runtime, we fall back
// to using this type instead.
//
// var baseNamespaceDeclarationSyntaxType = csharpCodeAnalysisAssembly.GetType(BaseNamespaceDeclarationSyntaxWrapper.WrappedTypeName)
// ?? csharpCodeAnalysisAssembly.GetType(BaseNamespaceDeclarationSyntaxWrapper.WrappedTypeName);
LocalDeclarationStatementSyntax localStatement =
SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(
type: SyntaxFactory.IdentifierName("var"),
variables: SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(
identifier: SyntaxFactory.Identifier("baseNamespaceDeclarationSyntaxType"),
argumentList: null,
initializer: SyntaxFactory.EqualsValueClause(
SyntaxFactory.BinaryExpression(
SyntaxKind.CoalesceExpression,
left: SyntaxFactory.InvocationExpression(
expression: SyntaxFactory.MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
expression: SyntaxFactory.IdentifierName("csharpCodeAnalysisAssembly"),
name: SyntaxFactory.IdentifierName("GetType")),
argumentList: SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(
SyntaxFactory.MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
expression: SyntaxFactory.IdentifierName(node.WrapperName),
name: SyntaxFactory.IdentifierName("WrappedTypeName")))))),
right: SyntaxFactory.InvocationExpression(
expression: SyntaxFactory.MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
expression: SyntaxFactory.IdentifierName("csharpCodeAnalysisAssembly"),
name: SyntaxFactory.IdentifierName("GetType")),
argumentList: SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(
SyntaxFactory.MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
expression: SyntaxFactory.IdentifierName(node.WrapperName),
name: SyntaxFactory.IdentifierName("FallbackWrappedTypeName"))))))))))));

// This is the first line of the statements that initialize 'builder', so start it with a blank line
staticCtorStatements = staticCtorStatements.Add(localStatement.WithLeadingBlankLine());

// builder.Add(typeof(BaseNamespaceDeclarationSyntaxWrapper), baseNamespaceDeclarationSyntaxType);
staticCtorStatements = staticCtorStatements.Add(SyntaxFactory.ExpressionStatement(
SyntaxFactory.InvocationExpression(
expression: SyntaxFactory.MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
expression: SyntaxFactory.IdentifierName("builder"),
name: SyntaxFactory.IdentifierName("Add")),
argumentList: SyntaxFactory.ArgumentList(
SyntaxFactory.SeparatedList(
new[]
{
SyntaxFactory.Argument(SyntaxFactory.TypeOfExpression(SyntaxFactory.IdentifierName(node.WrapperName))),
SyntaxFactory.Argument(SyntaxFactory.IdentifierName("baseNamespaceDeclarationSyntaxType")),
})))));

continue;
}

// builder.Add(typeof(ConstantPatternSyntaxWrapper), csharpCodeAnalysisAssembly.GetType(ConstantPatternSyntaxWrapper.WrappedTypeName));
staticCtorStatements = staticCtorStatements.Add(SyntaxFactory.ExpressionStatement(
SyntaxFactory.InvocationExpression(
Expand Down Expand Up @@ -1138,12 +1201,12 @@ private sealed class SyntaxData
{
private readonly Dictionary<string, NodeData> nameToNode;

public SyntaxData(in GeneratorExecutionContext context, XDocument document)
public SyntaxData(Compilation compilation, XDocument document)
{
var nodesBuilder = ImmutableArray.CreateBuilder<NodeData>();
foreach (var element in document.XPathSelectElement("/Tree[@Root='SyntaxNode']").XPathSelectElements("PredefinedNode|AbstractNode|Node"))
{
nodesBuilder.Add(new NodeData(in context, element));
nodesBuilder.Add(new NodeData(compilation, element));
}

this.Nodes = nodesBuilder.ToImmutable();
Expand Down Expand Up @@ -1180,7 +1243,7 @@ public SyntaxData(in GeneratorExecutionContext context, XDocument document)

private sealed class NodeData
{
public NodeData(in GeneratorExecutionContext context, XElement element)
public NodeData(Compilation compilation, XElement element)
{
this.Kind = element.Name.LocalName switch
{
Expand All @@ -1192,9 +1255,9 @@ public NodeData(in GeneratorExecutionContext context, XElement element)

this.Name = element.Attribute("Name").Value;

this.ExistingType = context.Compilation.GetTypeByMetadataName($"Microsoft.CodeAnalysis.CSharp.Syntax.{this.Name}")
?? context.Compilation.GetTypeByMetadataName($"Microsoft.CodeAnalysis.CSharp.{this.Name}")
?? context.Compilation.GetTypeByMetadataName($"Microsoft.CodeAnalysis.{this.Name}");
this.ExistingType = compilation.GetTypeByMetadataName($"Microsoft.CodeAnalysis.CSharp.Syntax.{this.Name}")
?? compilation.GetTypeByMetadataName($"Microsoft.CodeAnalysis.CSharp.{this.Name}")
?? compilation.GetTypeByMetadataName($"Microsoft.CodeAnalysis.{this.Name}");
if (this.ExistingType?.DeclaredAccessibility == Accessibility.Public)
{
this.WrapperName = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,53 @@

namespace StyleCop.Analyzers.Test.CSharp10.ReadabilityRules
{
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Testing;
using StyleCop.Analyzers.Test.CSharp9.ReadabilityRules;
using Xunit;
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
StyleCop.Analyzers.ReadabilityRules.SA1135UsingDirectivesMustBeQualified,
StyleCop.Analyzers.ReadabilityRules.SA1135CodeFixProvider>;

public class SA1135CSharp10UnitTests : SA1135CSharp9UnitTests
{
[Fact]
[WorkItem(3415, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3415")]
public async Task TestFileScopedNamespaceAsync()
{
var testCode = @"
namespace TestNamespace
{
using KeyValue = System.Collections.Generic.KeyValuePair<string, object?>;
}
";
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
await new CSharpTest
{
TestState =
{
Sources =
{
@"namespace A.B.C { }",
@"namespace A.B.D;
[|using C;|]
",
},
},
FixedState =
{
Sources =
{
@"namespace A.B.C { }",
@"namespace A.B.D;
using A.B.C;
",
},
},
}.RunAsync(CancellationToken.None).ConfigureAwait(false);
}
}
}
Loading

0 comments on commit d2a3d2b

Please sign in to comment.