Skip to content

Commit

Permalink
Switches to official source generator
Browse files Browse the repository at this point in the history
  • Loading branch information
azeno committed Mar 5, 2022
1 parent c4e14bd commit d336828
Show file tree
Hide file tree
Showing 17 changed files with 241 additions and 226 deletions.
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ This project is actively developed using the following software.
It is highly recommended that anyone contributing to this library use the same
software.

1. [Visual Studio 2017][VS].
1. [Visual Studio 2022][VS].

All other dependencies are acquired via NuGet.

## Building

Everything in the repo may be built via building the solution file
either from Visual Studio 2017 or the command line:
either from Visual Studio 2022 or the command line:

msbuild /restore src\ImmutableObjectGraph.sln /t:pack

## Testing

The Visual Studio 2017 Test Explorer will list and execute all tests.
The Visual Studio 2022 Test Explorer will list and execute all tests.

## Pull requests

Expand Down
7 changes: 1 addition & 6 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<Authors>Andrew Arnott</Authors>
<Owners>Andrew Arnott</Owners>
<PackageProjectUrl>https://github.com/aarnott/immutableobjectgraph</PackageProjectUrl>
<LicenseUrl>https://raw.githubusercontent.com/AArnott/ImmutableObjectGraph/$GitCommitIdShort$/LICENSE.txt</LicenseUrl>
<PackageLicenseExpression>MS-PL</PackageLicenseExpression>
<Copyright>Copyright © Andrew Arnott</Copyright>
<PackageTags>immutable</PackageTags>
</PropertyGroup>
Expand All @@ -23,9 +23,4 @@
<ItemGroup>
<AdditionalFiles Include="$(MSBuildThisFileDirectory)stylecop.json" />
</ItemGroup>
<Target Name="SetNuSpecProperties" BeforeTargets="GenerateNuspec" DependsOnTargets="GetBuildVersion">
<PropertyGroup>
<PackageLicenseUrl>https://raw.githubusercontent.com/aarnott/ImmutableObjectGraph/$(GitCommitIdShort)/LICENSE.txt</PackageLicenseUrl>
</PropertyGroup>
</Target>
</Project>
23 changes: 9 additions & 14 deletions src/Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
<Project>
<PropertyGroup>
<CodeGenerationRoslynVersion>0.6.1</CodeGenerationRoslynVersion>
<CodeAnalysisVersion>4.1.0</CodeAnalysisVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Update="CodeGeneration.Roslyn.Attributes" Version="$(CodeGenerationRoslynVersion)" />
<PackageReference Update="CodeGeneration.Roslyn.BuildTime" Version="$(CodeGenerationRoslynVersion)" />
<PackageReference Update="CodeGeneration.Roslyn" Version="$(CodeGenerationRoslynVersion)" />
<PackageReference Update="CodeGeneration.Roslyn.Engine" Version="$(CodeGenerationRoslynVersion)" />
<PackageReference Update="Microsoft.Build" Version="14.3.0" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.1.0" />
<PackageReference Update="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Update="System.Collections.Immutable" Version="1.5.0" />
<PackageReference Update="Microsoft.Build" Version="17.0.0" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp" Version="$(CodeAnalysisVersion)" />
<PackageReference Update="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(CodeAnalysisVersion)" />
<PackageReference Update="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Update="System.Collections.Immutable" Version="5.0.0" />
<PackageReference Update="System.Diagnostics.Contracts" Version="4.3.0" />
<PackageReference Update="Validation" Version="2.4.22" />
<PackageReference Update="xunit.runner.visualstudio" Version="2.4.1" />
<PackageReference Update="Validation" Version="2.5.51" />
<PackageReference Update="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Update="xunit" Version="2.4.1" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Update="dotnet-codegen" Version="$(CodeGenerationRoslynVersion)" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
{
using System;
using System.Diagnostics;
using global::CodeGeneration.Roslyn;

[AttributeUsage(AttributeTargets.Class)]
[Conditional("CodeGeneration")]
[CodeGenerationAttribute("ImmutableObjectGraph.Generation.CodeGenerator, ImmutableObjectGraph.Generation, Version=" + ThisAssembly.AssemblyVersion + ", Culture=neutral, PublicKeyToken=" + ThisAssembly.PublicKeyToken)]
public class GenerateImmutableAttribute : Attribute
{
public GenerateImmutableAttribute()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@
<ItemGroup>
<PackageReference Include="Validation" PrivateAssets="compile" />
<PackageReference Include="System.Collections.Immutable" />
<PackageReference Include="CodeGeneration.Roslyn.Attributes" />
</ItemGroup>
</Project>
95 changes: 55 additions & 40 deletions src/ImmutableObjectGraph.Generation.Tests/CodeGenTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using CodeGeneration.Roslyn.Engine;
using global::CodeGeneration.Roslyn;
using ImmutableObjectGraph.Generation.Roslyn;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
Expand Down Expand Up @@ -38,7 +36,6 @@ public CodeGenTests(ITestOutputHelper logger)
.WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
.AddMetadataReferences(GetNetStandard20References())
.AddMetadataReference(MetadataReference.CreateFromFile(typeof(GenerateImmutableAttribute).Assembly.Location))
.AddMetadataReference(MetadataReference.CreateFromFile(typeof(CodeGenerationAttributeAttribute).Assembly.Location))
.AddMetadataReference(MetadataReference.CreateFromFile(typeof(Optional).Assembly.Location))
.AddMetadataReference(MetadataReference.CreateFromFile(typeof(ImmutableArray).Assembly.Location));
var inputDocument = project.AddDocument("input.cs", string.Empty);
Expand Down Expand Up @@ -265,40 +262,51 @@ protected async Task<GenerationResult> GenerateAsync(SourceText inputSource)
{
var solution = this.solution.WithDocumentText(this.inputDocumentId, inputSource);
var inputDocument = solution.GetDocument(this.inputDocumentId);
var generatorDiagnostics = new List<Diagnostic>();
var progress = new SynchronousProgress<Diagnostic>(generatorDiagnostics.Add);
var inputCompilation = (CSharpCompilation)await inputDocument.Project.GetCompilationAsync();
var inputSyntaxTree = await inputDocument.GetSyntaxTreeAsync();
var outputSyntaxTree = await DocumentTransform.TransformAsync(inputCompilation, inputSyntaxTree, null, Assembly.Load, progress);
var outputDocument = inputDocument.Project
.AddDocument("output.cs", outputSyntaxTree.GetRoot());

// Make sure the result compiles without errors or warnings.
var compilation = await outputDocument.Project.GetCompilationAsync();
var compilationDiagnostics = compilation.GetDiagnostics();
var driver = CSharpGeneratorDriver.Create(new CodeGenerator());
var runResult = driver.RunGenerators(inputCompilation).GetRunResult();
var outputSyntaxTree = runResult.GeneratedTrees[0];
var generatorDiagnostics = runResult.Diagnostics;
var project = inputDocument.Project;

var i = 0;
var syntaxTrees = ImmutableArray.CreateBuilder<SyntaxTree>();
foreach (var t in runResult.GeneratedTrees)
{
var document = project.AddDocument($"output{i++}.cs", t.GetRoot());

SourceText outputDocumentText = await outputDocument.GetTextAsync();
this.logger.WriteLine("{0}", outputDocumentText);
SourceText outputDocumentText = await document.GetTextAsync();
this.logger.WriteLine("{0}", outputDocumentText);

// Verify all line endings are consistent (otherwise VS can bug the heck out of the user if they have the generated file open).
string firstLineEnding = null;
foreach (var line in outputDocumentText.Lines)
{
string actualNewLine = line.Text.GetSubText(TextSpan.FromBounds(line.End, line.EndIncludingLineBreak)).ToString();
if (firstLineEnding == null)
{
firstLineEnding = actualNewLine;
}
else if (actualNewLine != firstLineEnding && actualNewLine.Length > 0)
// Verify all line endings are consistent (otherwise VS can bug the heck out of the user if they have the generated file open).
string firstLineEnding = null;
foreach (var line in outputDocumentText.Lines)
{
string expected = EscapeLineEndingCharacters(firstLineEnding);
string actual = EscapeLineEndingCharacters(actualNewLine);
Assert.True(false, $"Expected line ending characters '{expected}' but found '{actual}' on line {line.LineNumber + 1}.\nContent: {line}");
string actualNewLine = line.Text.GetSubText(TextSpan.FromBounds(line.End, line.EndIncludingLineBreak)).ToString();
if (firstLineEnding == null)
{
firstLineEnding = actualNewLine;
}
else if (actualNewLine != firstLineEnding && actualNewLine.Length > 0)
{
string expected = EscapeLineEndingCharacters(firstLineEnding);
string actual = EscapeLineEndingCharacters(actualNewLine);
Assert.True(false, $"Expected line ending characters '{expected}' but found '{actual}' on line {line.LineNumber + 1}.\nContent: {line}");
}
}

var syntaxTree = await document.GetSyntaxTreeAsync();
syntaxTrees.Add(syntaxTree);

project = document.Project;
}

var semanticModel = await outputDocument.GetSemanticModelAsync();
var result = new GenerationResult(outputDocument, semanticModel, generatorDiagnostics, compilationDiagnostics);
// Make sure the result compiles without errors or warnings.
var compilation = await project.GetCompilationAsync();
var compilationDiagnostics = compilation.GetDiagnostics();

var result = new GenerationResult(compilation, syntaxTrees.ToImmutable(), generatorDiagnostics, compilationDiagnostics);

foreach (var diagnostic in generatorDiagnostics)
{
Expand Down Expand Up @@ -338,32 +346,39 @@ private static string EscapeLineEndingCharacters(string whitespace)

private static IEnumerable<MetadataReference> GetNetStandard20References()
{
string nugetPackageRoot = Environment.GetEnvironmentVariable("NUGET_PACKAGES") ?? Environment.ExpandEnvironmentVariables(@"%USERPROFILE%\.nuget\packages");
string netstandardRoot = Path.Combine(nugetPackageRoot, @"netstandard.library\2.0.3\build\netstandard2.0\ref");
foreach (string assembly in Directory.GetFiles(netstandardRoot, "*.dll"))
var nugetPackageRoot = Environment.GetEnvironmentVariable("NUGET_PACKAGES") ?? Environment.ExpandEnvironmentVariables(@"%USERPROFILE%\.nuget\packages");
foreach (var dir in Directory.GetDirectories(Path.Combine(nugetPackageRoot, "netstandard.library"), "2.*"))
{
yield return MetadataReference.CreateFromFile(assembly);
var netstandardRoot = Path.Combine(dir, @"build\netstandard2.0\ref");
foreach (string assembly in Directory.GetFiles(netstandardRoot, "*.dll"))
{
yield return MetadataReference.CreateFromFile(assembly);
}
break;
}
}

protected class GenerationResult
{
public GenerationResult(
Document document,
SemanticModel semanticModel,
Compilation compilation,
ImmutableArray<SyntaxTree> syntaxTrees,
IReadOnlyList<Diagnostic> generatorDiagnostics,
IReadOnlyList<Diagnostic> compilationDiagnostics)
{
this.Document = document;
this.SemanticModel = semanticModel;
this.Declarations = CSharpDeclarationComputer.GetDeclarationsInSpan(semanticModel, TextSpan.FromBounds(0, semanticModel.SyntaxTree.Length), true, CancellationToken.None);
this.Compilation = compilation;
this.SyntaxTrees = syntaxTrees;
this.SemanticModels = syntaxTrees.Select(s => compilation.GetSemanticModel(s)).ToImmutableArray();
this.Declarations = SemanticModels.SelectMany(semanticModel => CSharpDeclarationComputer.GetDeclarationsInSpan(semanticModel, TextSpan.FromBounds(0, semanticModel.SyntaxTree.Length), true, CancellationToken.None)).ToImmutableArray();
this.GeneratorDiagnostics = generatorDiagnostics;
this.CompilationDiagnostics = compilationDiagnostics;
}

public Document Document { get; private set; }
public Compilation Compilation { get; }

public ImmutableArray<SemanticModel> SemanticModels { get; private set; }

public SemanticModel SemanticModel { get; private set; }
public ImmutableArray<SyntaxTree> SyntaxTrees { get; }

internal ImmutableArray<DeclarationInfo> Declarations { get; private set; }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,62 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472</TargetFrameworks>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
<ItemGroup>
<Compile Update="TestSources\AbstractClassMidTypeHierarchyWithRequiredField.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<EmbeddedResource Include="TestSources\AlmostRecursive.cs" />
<EmbeddedResource Include="TestSources\ByteArray.cs" />
<EmbeddedResource Include="TestSources\HierarchyLevels.cs" />
<EmbeddedResource Include="TestSources\IgnoreField.cs" />
<EmbeddedResource Include="TestSources\ImmutableArray.cs" />
<EmbeddedResource Include="TestSources\RootedStruct_Without_WithMethodsPerProperty.cs" />
<Compile Update="TestSources\Generations.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<EmbeddedResource Include="TestSources\DefineRootedStruct_NotApplicable.cs" />
<Compile Update="TestSources\ImmutableDictionaryHelpers.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Update="TestSources\ImmutableWithComplexStructField.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Update="TestSources\MSBuild.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Update="TestSources\Nested.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Update="TestSources\NonRecursive.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Update="TestSources\ProjectTree.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Update="TestSources\RequiresAndHierarchy.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Update="TestSources\Sealed.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Update="TestSources\TreeNode.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<EmbeddedResource Include="TestSources\UsingImmutableObjectGraph.cs" />
<Compile Update="TestSources\XmlNode.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<EmbeddedResource Include="TestSources\OneImmutableFieldToAnotherWithOneScalarField.cs" />
<Compile Update="TestSources\FileSystem.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Update="TestSources\AbstractClassFamilies.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Update="TestSources\DeepHierarchy.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<EmbeddedResource Include="TestSources\OneScalarFieldAndEmptyDerived.cs" />
<EmbeddedResource Include="TestSources\NoFieldsAndNoFieldsDerived.cs" />
<EmbeddedResource Include="TestSources\NoFieldsAndOneScalarFieldDerived.cs" />
Expand All @@ -65,12 +21,6 @@
<EmbeddedResource Include="TestSources\ClassDerivesFromAnotherWithFields.cs" />
<EmbeddedResource Include="TestSources\OneScalarFieldWithBuilder.cs" />
<EmbeddedResource Include="TestSources\OneScalarField.cs" />
<Compile Update="TestSources\Person.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Update="TestSources\Empty.cs">
<Generator>MSBuild:GenerateCodeFromAttributes</Generator>
</Compile>
<Compile Remove="@(EmbeddedResource)" />
<Compile Remove="TestSources\AlmostRecursive.cs" />
<Compile Remove="TestSources\HierarchyLevels.cs" />
Expand All @@ -84,15 +34,10 @@
<PackageReference Include="xunit.runner.visualstudio" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" PrivateAssets="all" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="CodeGeneration.Roslyn" PrivateAssets="all" />
<PackageReference Include="CodeGeneration.Roslyn.Engine" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="dotnet-codegen" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ImmutableObjectGraph.Generation.Attributes\ImmutableObjectGraph.Generation.Attributes.csproj" />
<ProjectReference Include="..\ImmutableObjectGraph.Generation\ImmutableObjectGraph.Generation.csproj" />
<ProjectReference Include="..\ImmutableObjectGraph.Generation\ImmutableObjectGraph.Generation.csproj" OutputItemType="Analyzer" />
<ProjectReference Include="..\ImmutableObjectGraph\ImmutableObjectGraph.csproj" />
</ItemGroup>
</Project>
</Project>
Loading

0 comments on commit d336828

Please sign in to comment.