Skip to content

Commit

Permalink
Merge pull request #3231 from sharwell/generate-lightup
Browse files Browse the repository at this point in the history
Use code generation for IOperation in the light-up layer
  • Loading branch information
sharwell authored Nov 11, 2020
2 parents d04c6cd + 1d35607 commit a283433
Show file tree
Hide file tree
Showing 143 changed files with 10,907 additions and 175 deletions.
11 changes: 8 additions & 3 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>8</LangVersion>
<Features>strict</Features>
<LangVersion>9</LangVersion>
<WarningLevel>5</WarningLevel>
</PropertyGroup>

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

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

<!-- Public API -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<file src="tools\uninstall.ps1" target="tools\" />

<!-- Source code -->
<file src="..\StyleCop.Analyzers\**\*.cs" exclude="..\StyleCop.Analyzers\obj\**\*.cs" target="src"/>
<file src="..\StyleCop.Analyzers\**\*.cs" exclude="..\StyleCop.Analyzers\obj\**\*.cs;..\StyleCop.Analyzers\Lightup\.generated\**\*.cs" target="src"/>
<file src="**\*.cs" exclude="obj\**\*.cs;Properties\AssemblyInfo.cs" target="src"/>

</files>
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: CLSCompliant(false)]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
</PropertyGroup>

<PropertyGroup>
<CodeAnalysisRuleSet>..\StyleCop.Analyzers.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>

<PropertyGroup>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\build\keys\StyleCopAnalyzers.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0-5.final" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

namespace StyleCop.Analyzers.Test.CSharp7.Lightup
{
using System.Collections.Generic;
using System.Reflection;
using Microsoft.CodeAnalysis;
using StyleCop.Analyzers.Lightup;
using Xunit;

public class OperationKindExTests
{
private static readonly Dictionary<OperationKind, string> OperationKindToName;
private static readonly Dictionary<string, OperationKind> NameToOperationKind;

static OperationKindExTests()
{
var renamedOperations =
new Dictionary<string, string>()
{
{ "BinaryOperator", "Binary" },
{ "ConstructorBodyOperation", "ConstructorBody" },
{ "MethodBodyOperation", "MethodBody" },
{ "TupleBinaryOperator", "TupleBinary" },
{ "UnaryOperator", "Unary" },
};

OperationKindToName = new Dictionary<OperationKind, string>();
NameToOperationKind = new Dictionary<string, OperationKind>();

foreach (var field in typeof(OperationKind).GetTypeInfo().DeclaredFields)
{
if (!field.IsStatic)
{
continue;
}

var value = (OperationKind)field.GetRawConstantValue();
var name = field.Name;
if (renamedOperations.TryGetValue(name, out var newName))
{
name = newName;
}

if (!OperationKindToName.ContainsKey(value))
{
OperationKindToName[value] = name;
}

if (!NameToOperationKind.ContainsKey(name))
{
NameToOperationKind.Add(name, value);
}
}
}

public static IEnumerable<object[]> OperationKinds
{
get
{
foreach (var field in typeof(OperationKindEx).GetTypeInfo().DeclaredFields)
{
yield return new object[] { field.Name, (OperationKind)field.GetRawConstantValue() };
}
}
}

[Theory]
[MemberData(nameof(OperationKinds))]
public void TestOperationKind(string name, OperationKind operationKind)
{
if (OperationKindToName.TryGetValue(operationKind, out var expectedName))
{
Assert.Equal(expectedName, name);
}
else
{
Assert.False(NameToOperationKind.TryGetValue(name, out _));
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

namespace StyleCop.Analyzers.Test.CSharp8.Lightup
{
using StyleCop.Analyzers.Test.CSharp7.Lightup;

public class OperationKindExTestsCSharp8 : OperationKindExTests
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ namespace StyleCop.Analyzers.Test.CSharp9.DocumentationRules

public class SA1600CSharp9UnitTests : SA1600CSharp8UnitTests
{
protected override DiagnosticResult[] GetExpectedResultTestRegressionMethodGlobalNamespace(string code, int column)
protected override DiagnosticResult[] GetExpectedResultTestRegressionMethodGlobalNamespace(string code)
{
if (code == "public void TestMember() { }" && column == 13)
if (code == "public void {|#0:TestMember|}() { }")
{
return new[]
{
Expand All @@ -20,12 +20,12 @@ protected override DiagnosticResult[] GetExpectedResultTestRegressionMethodGloba
// /0/Test0.cs(4,1): error CS0106: The modifier 'public' is not valid for this item
DiagnosticResult.CompilerError("CS0106").WithSpan(4, 1, 4, 7).WithArguments("public"),

// /0/Test0.cs(4,1): error CS8652: The feature 'top-level statements' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
DiagnosticResult.CompilerError("CS8652").WithSpan(4, 1, 4, 29).WithArguments("top-level statements"),
// /0/Test0.cs(4,1): error CS8320: Feature 'top-level statements' is not available in C# 7.2. Please use language version 9.0 or greater.
DiagnosticResult.CompilerError("CS8320").WithSpan(4, 1, 4, 29).WithArguments("top-level statements", "9.0"),
};
}

return base.GetExpectedResultTestRegressionMethodGlobalNamespace(code, column);
return base.GetExpectedResultTestRegressionMethodGlobalNamespace(code);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

namespace StyleCop.Analyzers.Test.CSharp9.Lightup
{
using StyleCop.Analyzers.Test.CSharp8.Lightup;

public class OperationKindExTestsCSharp9 : OperationKindExTestsCSharp8
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.8.0-2.20414.4" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.8.0-5.final" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" PrivateAssets="all" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ public class SA1600UnitTests
protected virtual LanguageVersion LanguageVersion => LanguageVersion.CSharp6;

[Theory]
[InlineData("public string TestMember;", 15)]
[InlineData("public string TestMember { get; set; }", 15)]
[InlineData("public void TestMember() { }", 13)]
[InlineData("public string this[int a] { get { return \"a\"; } set { } }", 15)]
[InlineData("public event EventHandler TestMember { add { } remove { } }", 27)]
public async Task TestRegressionMethodGlobalNamespaceAsync(string code, int column)
[InlineData("public string {|#0:TestMember|};")]
[InlineData("public string {|#0:TestMember|} { get; set; }")]
[InlineData("public void {|#0:TestMember|}() { }")]
[InlineData("public string {|#0:this|}[int a] { get { return \"a\"; } set { } }")]
[InlineData("public event EventHandler {|#0:TestMember|} { add { } remove { } }")]
public async Task TestRegressionMethodGlobalNamespaceAsync(string code)
{
// This test is a regression test for https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/1416
var testCode = $@"
using System;
{code}";

var expected = this.GetExpectedResultTestRegressionMethodGlobalNamespace(code, column);
var expected = this.GetExpectedResultTestRegressionMethodGlobalNamespace(code);
await VerifyCSharpDiagnosticAsync(this.LanguageVersion, testCode, expected, CancellationToken.None).ConfigureAwait(false);
}

Expand Down Expand Up @@ -1384,12 +1384,12 @@ public class OuterClass
await VerifyCSharpDiagnosticAsync(this.LanguageVersion, string.Format(hasDocumentation ? testCodeWithDocumentation : testCodeWithoutDocumentation, modifiers), requiresDiagnostic ? expected : DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}

protected virtual DiagnosticResult[] GetExpectedResultTestRegressionMethodGlobalNamespace(string code, int column)
protected virtual DiagnosticResult[] GetExpectedResultTestRegressionMethodGlobalNamespace(string code)
{
return new[]
{
DiagnosticResult.CompilerError("CS0116").WithMessage("A namespace cannot directly contain members such as fields or methods").WithLocation(4, column),
Diagnostic().WithLocation(4, column),
DiagnosticResult.CompilerError("CS0116").WithMessage("A namespace cannot directly contain members such as fields or methods").WithLocation(0),
Diagnostic().WithLocation(0),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="1.3.2" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.XUnit" Version="1.0.1-beta1.20478.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.XUnit" Version="1.0.1-beta1.20559.1" />
<PackageReference Include="Microsoft.VisualStudio.Composition" Version="16.1.8" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="xunit" Version="2.4.1" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

namespace StyleCop.Analyzers.Lightup
{
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;

internal readonly struct IAddressOfOperationWrapper : IOperationWrapper
{
internal const string WrappedTypeName = "Microsoft.CodeAnalysis.Operations.IAddressOfOperation";
private static readonly Type WrappedType;
private static readonly Func<IOperation, IOperation> ReferenceAccessor;
private readonly IOperation operation;
static IAddressOfOperationWrapper()
{
WrappedType = OperationWrapperHelper.GetWrappedType(typeof(IAddressOfOperationWrapper));
ReferenceAccessor = LightupHelpers.CreateOperationPropertyAccessor<IOperation, IOperation>(WrappedType, nameof(Reference));
}

private IAddressOfOperationWrapper(IOperation operation)
{
this.operation = operation;
}

public IOperation WrappedOperation => this.operation;
public ITypeSymbol Type => this.WrappedOperation.Type;
public IOperation Reference => ReferenceAccessor(this.WrappedOperation);
public static IAddressOfOperationWrapper FromOperation(IOperation operation)
{
if (operation == null)
{
return default;
}

if (!IsInstance(operation))
{
throw new InvalidCastException($"Cannot cast '{operation.GetType().FullName}' to '{WrappedTypeName}'");
}

return new IAddressOfOperationWrapper(operation);
}

public static bool IsInstance(IOperation operation)
{
return operation != null && LightupHelpers.CanWrapOperation(operation, WrappedType);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

namespace StyleCop.Analyzers.Lightup
{
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;

internal readonly struct IAnonymousFunctionOperationWrapper : IOperationWrapper
{
internal const string WrappedTypeName = "Microsoft.CodeAnalysis.Operations.IAnonymousFunctionOperation";
private static readonly Type WrappedType;
private static readonly Func<IOperation, IMethodSymbol> SymbolAccessor;
private static readonly Func<IOperation, IOperation> BodyAccessor;
private readonly IOperation operation;
static IAnonymousFunctionOperationWrapper()
{
WrappedType = OperationWrapperHelper.GetWrappedType(typeof(IAnonymousFunctionOperationWrapper));
SymbolAccessor = LightupHelpers.CreateOperationPropertyAccessor<IOperation, IMethodSymbol>(WrappedType, nameof(Symbol));
BodyAccessor = LightupHelpers.CreateOperationPropertyAccessor<IOperation, IOperation>(WrappedType, nameof(Body));
}

private IAnonymousFunctionOperationWrapper(IOperation operation)
{
this.operation = operation;
}

public IOperation WrappedOperation => this.operation;
public ITypeSymbol Type => this.WrappedOperation.Type;
public IMethodSymbol Symbol => SymbolAccessor(this.WrappedOperation);
public IBlockOperationWrapper Body => IBlockOperationWrapper.FromOperation(BodyAccessor(this.WrappedOperation));
public static IAnonymousFunctionOperationWrapper FromOperation(IOperation operation)
{
if (operation == null)
{
return default;
}

if (!IsInstance(operation))
{
throw new InvalidCastException($"Cannot cast '{operation.GetType().FullName}' to '{WrappedTypeName}'");
}

return new IAnonymousFunctionOperationWrapper(operation);
}

public static bool IsInstance(IOperation operation)
{
return operation != null && LightupHelpers.CanWrapOperation(operation, WrappedType);
}
}
}
Loading

0 comments on commit a283433

Please sign in to comment.