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

Switch to official source generator #121

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
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
12 changes: 5 additions & 7 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,18 @@
<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>

<!-- We forked the repo, don't create packages -->
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning" Version="2.1.23" PrivateAssets="all" />
<PackageReference Include="Nerdbank.GitVersioning" Version="3.6.133" PrivateAssets="all" />
<!-- <PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta006" PrivateAssets="all" /> -->
</ItemGroup>
<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.8.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.4" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(CodeAnalysisVersion)" />
<PackageReference Update="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Update="System.Collections.Immutable" Version="8.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: 54 additions & 41 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,49 @@ 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 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 +344,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