diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3a1524f..81dc8b5 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -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
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index e42c586..6c4ed28 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -12,7 +12,7 @@
Andrew Arnott
Andrew Arnott
https://github.com/aarnott/immutableobjectgraph
- https://raw.githubusercontent.com/AArnott/ImmutableObjectGraph/$GitCommitIdShort$/LICENSE.txt
+ MS-PL
Copyright © Andrew Arnott
immutable
@@ -23,9 +23,4 @@
-
-
- https://raw.githubusercontent.com/aarnott/ImmutableObjectGraph/$(GitCommitIdShort)/LICENSE.txt
-
-
diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets
index 1286826..aebcec3 100644
--- a/src/Directory.Build.targets
+++ b/src/Directory.Build.targets
@@ -1,22 +1,17 @@
- 0.6.1
+ 4.1.0
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
-
diff --git a/src/ImmutableObjectGraph.Generation.Attributes/GenerateImmutableAttribute.cs b/src/ImmutableObjectGraph.Generation.Attributes/GenerateImmutableAttribute.cs
index d651913..de814b2 100644
--- a/src/ImmutableObjectGraph.Generation.Attributes/GenerateImmutableAttribute.cs
+++ b/src/ImmutableObjectGraph.Generation.Attributes/GenerateImmutableAttribute.cs
@@ -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()
diff --git a/src/ImmutableObjectGraph.Generation.Attributes/ImmutableObjectGraph.Generation.Attributes.csproj b/src/ImmutableObjectGraph.Generation.Attributes/ImmutableObjectGraph.Generation.Attributes.csproj
index 315dbfc..6f58f42 100644
--- a/src/ImmutableObjectGraph.Generation.Attributes/ImmutableObjectGraph.Generation.Attributes.csproj
+++ b/src/ImmutableObjectGraph.Generation.Attributes/ImmutableObjectGraph.Generation.Attributes.csproj
@@ -10,6 +10,5 @@
-
diff --git a/src/ImmutableObjectGraph.Generation.Tests/CodeGenTests.cs b/src/ImmutableObjectGraph.Generation.Tests/CodeGenTests.cs
index afb53bf..ff135bd 100644
--- a/src/ImmutableObjectGraph.Generation.Tests/CodeGenTests.cs
+++ b/src/ImmutableObjectGraph.Generation.Tests/CodeGenTests.cs
@@ -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;
@@ -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);
@@ -265,40 +262,49 @@ protected async Task GenerateAsync(SourceText inputSource)
{
var solution = this.solution.WithDocumentText(this.inputDocumentId, inputSource);
var inputDocument = solution.GetDocument(this.inputDocumentId);
- var generatorDiagnostics = new List();
- var progress = new SynchronousProgress(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();
+ 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)
{
@@ -338,32 +344,39 @@ private static string EscapeLineEndingCharacters(string whitespace)
private static IEnumerable 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 syntaxTrees,
IReadOnlyList generatorDiagnostics,
IReadOnlyList 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 SemanticModels { get; private set; }
- public SemanticModel SemanticModel { get; private set; }
+ public ImmutableArray SyntaxTrees { get; }
internal ImmutableArray Declarations { get; private set; }
diff --git a/src/ImmutableObjectGraph.Generation.Tests/ImmutableObjectGraph.Generation.Tests.csproj b/src/ImmutableObjectGraph.Generation.Tests/ImmutableObjectGraph.Generation.Tests.csproj
index 6d9cd56..bdc463f 100644
--- a/src/ImmutableObjectGraph.Generation.Tests/ImmutableObjectGraph.Generation.Tests.csproj
+++ b/src/ImmutableObjectGraph.Generation.Tests/ImmutableObjectGraph.Generation.Tests.csproj
@@ -1,62 +1,18 @@
net472
+ true
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
@@ -65,12 +21,6 @@
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
@@ -84,15 +34,10 @@
-
-
-
-
-
-
+
-
+
\ No newline at end of file
diff --git a/src/ImmutableObjectGraph.Generation/CodeGen.cs b/src/ImmutableObjectGraph.Generation/CodeGen.cs
index 7082d82..0afc8c8 100644
--- a/src/ImmutableObjectGraph.Generation/CodeGen.cs
+++ b/src/ImmutableObjectGraph.Generation/CodeGen.cs
@@ -11,7 +11,6 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
- using global::CodeGeneration.Roslyn;
using ImmutableObjectGraph.Generation.Roslyn;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
@@ -262,7 +261,7 @@ private static bool HasEqualityOperators(ITypeSymbol symbol)
var equalityOperators = from method in symbol.GetMembers().OfType()
where method.MethodKind == MethodKind.BuiltinOperator || method.MethodKind == MethodKind.UserDefinedOperator
- where method.Parameters.Length == 2 && method.Parameters.All(p => p.Type.Equals(symbol))
+ where method.Parameters.Length == 2 && method.Parameters.All(p => p.Type.Equals(symbol, SymbolEqualityComparer.Default))
where method.Name == "op_Equality"
select method;
return equalityOperators.Any();
@@ -1240,9 +1239,9 @@ public IEnumerable Descendents
var that = this;
return from type in this.generator.TypesInInputDocument
- where type != that.TypeSymbol
+ where !SymbolEqualityComparer.Default.Equals(type, that.TypeSymbol)
let metaType = new MetaType(that.generator, type)
- where metaType.Ancestors.Any(a => a.TypeSymbol == that.TypeSymbol)
+ where metaType.Ancestors.Any(a => SymbolEqualityComparer.Default.Equals(a.TypeSymbol, that.TypeSymbol))
select metaType;
}
}
@@ -1252,7 +1251,7 @@ public MetaField RecursiveField
get
{
var allowedElementTypes = this.ThisTypeAndAncestors;
- var matches = this.LocalFields.Where(f => f.IsCollection && !f.IsDefinitelyNotRecursive && allowedElementTypes.Any(t => t.TypeSymbol.Equals(f.ElementType))).ToList();
+ var matches = this.LocalFields.Where(f => f.IsCollection && !f.IsDefinitelyNotRecursive && allowedElementTypes.Any(t => t.TypeSymbol.Equals(f.ElementType, SymbolEqualityComparer.Default))).ToList();
return matches.Count == 1 ? matches.First() : default(MetaField);
}
}
@@ -1343,7 +1342,7 @@ public bool ChildrenAreOrdered
public IEnumerable GetFieldsBeyond(MetaType ancestor)
{
- if (ancestor.TypeSymbol == this.TypeSymbol)
+ if (SymbolEqualityComparer.Default.Equals(ancestor.TypeSymbol, this.TypeSymbol))
{
return ImmutableList.Create();
}
@@ -1359,7 +1358,7 @@ public bool IsAssignableFrom(ITypeSymbol type)
return false;
}
- return type == this.TypeSymbol
+ return SymbolEqualityComparer.Default.Equals(type, this.TypeSymbol)
|| this.IsAssignableFrom(type.BaseType);
}
@@ -1407,12 +1406,12 @@ public override bool Equals(object obj)
public bool Equals(MetaType other)
{
return this.generator == other.generator
- && this.TypeSymbol == other.TypeSymbol;
+ && SymbolEqualityComparer.Default.Equals(this.TypeSymbol, other.TypeSymbol);
}
public override int GetHashCode()
{
- return this.TypeSymbol?.GetHashCode() ?? 0;
+ return SymbolEqualityComparer.Default.GetHashCode(this.TypeSymbol);
}
private MetaType FindMetaType(INamedTypeSymbol type)
@@ -1475,7 +1474,7 @@ public MetaType DeclaringType
public bool IsRecursiveCollection
{
- get { return this.IsCollection && !this.DeclaringType.RecursiveType.IsDefault && this.ElementType == this.DeclaringType.RecursiveType.TypeSymbol; }
+ get { return this.IsCollection && !this.DeclaringType.RecursiveType.IsDefault && SymbolEqualityComparer.Default.Equals(this.ElementType, this.DeclaringType.RecursiveType.TypeSymbol); }
}
public bool IsDefinitelyNotRecursive => IsAttributeApplied(this.Symbol);
@@ -1486,7 +1485,7 @@ public bool IsRecursiveCollection
///
public bool IsLocallyDefined
{
- get { return this.Symbol.ContainingType == this.metaType.Generator.applyToSymbol; }
+ get { return SymbolEqualityComparer.Default.Equals(this.Symbol.ContainingType, this.metaType.Generator.applyToSymbol); }
}
public IFieldSymbol Symbol { get; }
@@ -1514,7 +1513,7 @@ public bool IsAssignableFrom(ITypeSymbol type)
}
var that = this;
- return type == this.Symbol.Type
+ return SymbolEqualityComparer.Default.Equals(type, this.Symbol.Type)
|| this.IsAssignableFrom(type.BaseType)
|| type.Interfaces.Any(i => that.IsAssignableFrom(i));
}
diff --git a/src/ImmutableObjectGraph.Generation/CodeGenerator.cs b/src/ImmutableObjectGraph.Generation/CodeGenerator.cs
index 9828368..fb82ee2 100644
--- a/src/ImmutableObjectGraph.Generation/CodeGenerator.cs
+++ b/src/ImmutableObjectGraph.Generation/CodeGenerator.cs
@@ -3,47 +3,141 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
+ using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
- using CodeGeneration.Roslyn;
using Microsoft.CodeAnalysis;
+ using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Validation;
+ using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
- public class CodeGenerator : ICodeGenerator
+ [Generator]
+ public class CodeGenerator : IIncrementalGenerator
{
- private readonly AttributeData attributeData;
- private readonly ImmutableDictionary data;
+ private const string GenerateImmutableAttributeMetadataName = "ImmutableObjectGraph.Generation.GenerateImmutableAttribute";
- public CodeGenerator(AttributeData attributeData)
+ public void Initialize(IncrementalGeneratorInitializationContext context)
{
- Requires.NotNull(attributeData, nameof(attributeData));
+ var classes = context.SyntaxProvider.CreateSyntaxProvider(
+ predicate: (node, token) => node is ClassDeclarationSyntax @class && @class.AttributeLists.Count > 0,
+ transform: (ctx, token) => GetSemanticTargetForGeneration(ctx, token))
+ .Where(c => c != null);
- this.attributeData = attributeData;
- this.data = this.attributeData.NamedArguments.ToImmutableDictionary(kv => kv.Key, kv => kv.Value);
+ var compilationAndClasses = context.CompilationProvider.Combine(classes.Collect());
+
+ context.RegisterSourceOutput(compilationAndClasses, (spc, source) => Execute(source.Left, source.Right, spc));
}
- public Task> GenerateAsync(TransformationContext context, IProgress progress, CancellationToken cancellationToken)
+ private static ClassDeclarationSyntax GetSemanticTargetForGeneration(GeneratorSyntaxContext context, CancellationToken token)
{
- Requires.NotNull(context, nameof(context));
+ var classSyntax = (ClassDeclarationSyntax)context.Node;
- var options = new CodeGen.Options(this.attributeData)
+ foreach (var attributeListSyntax in classSyntax.AttributeLists)
{
- GenerateBuilder = this.GetBoolData(nameof(GenerateImmutableAttribute.GenerateBuilder)),
- Delta = this.GetBoolData(nameof(GenerateImmutableAttribute.Delta)),
- DefineInterface = this.GetBoolData(nameof(GenerateImmutableAttribute.DefineInterface)),
- DefineRootedStruct = this.GetBoolData(nameof(GenerateImmutableAttribute.DefineRootedStruct)),
- DefineWithMethodsPerProperty = this.GetBoolData(nameof(GenerateImmutableAttribute.DefineWithMethodsPerProperty)),
- };
-
- return CodeGen.GenerateAsync((ClassDeclarationSyntax)context.ProcessingNode, context.SemanticModel, progress, options, cancellationToken);
+ foreach (var attributeSyntax in attributeListSyntax.Attributes)
+ {
+ var attributeSymbol = context.SemanticModel.GetSymbolInfo(attributeSyntax, token).Symbol as IMethodSymbol;
+ if (attributeSymbol is null)
+ continue;
+
+ var attributeContainingTypeSymbol = attributeSymbol.ContainingType;
+ var fullName = attributeContainingTypeSymbol.ToDisplayString();
+
+ if (fullName == GenerateImmutableAttributeMetadataName)
+ return classSyntax;
+ }
+ }
+
+ return null;
}
- private bool GetBoolData(string name)
+ private static void Execute(Compilation compilation, ImmutableArray classes, SourceProductionContext context)
{
- return (bool)(this.data.GetValueOrDefault(name).Value ?? false);
+ if (classes.IsDefaultOrEmpty)
+ return;
+
+ var attributeSymbol = compilation.GetTypeByMetadataName(GenerateImmutableAttributeMetadataName)
+ ?? throw new InvalidOperationException("Symbol not found: " + GenerateImmutableAttributeMetadataName);
+
+ foreach (var syntax in classes.Distinct())
+ {
+ var semanticModel = compilation.GetSemanticModel(syntax.SyntaxTree);
+ var classSymbol = semanticModel.GetDeclaredSymbol(syntax);
+ var attributeData = classSymbol?.GetAttributes().FirstOrDefault(d => d.AttributeClass?.Equals(attributeSymbol, SymbolEqualityComparer.Default) == true);
+ var data = attributeData.NamedArguments.ToImmutableDictionary(kv => kv.Key, kv => kv.Value);
+ var options = new CodeGen.Options(attributeData)
+ {
+ GenerateBuilder = GetBoolData(data, nameof(GenerateImmutableAttribute.GenerateBuilder)),
+ Delta = GetBoolData(data, nameof(GenerateImmutableAttribute.Delta)),
+ DefineInterface = GetBoolData(data, nameof(GenerateImmutableAttribute.DefineInterface)),
+ DefineRootedStruct = GetBoolData(data, nameof(GenerateImmutableAttribute.DefineRootedStruct)),
+ DefineWithMethodsPerProperty = GetBoolData(data, nameof(GenerateImmutableAttribute.DefineWithMethodsPerProperty)),
+ };
+
+ var compilationUnit = CreateSource(context, syntax, semanticModel, classSymbol, options);
+ var sourceText = SyntaxTree(compilationUnit, encoding: Encoding.UTF8).GetText();
+ context.AddSource($"{syntax.Identifier}.g.cs", sourceText);
+ }
+ }
+
+ private static bool GetBoolData(ImmutableDictionary data, string name)
+ {
+ return (bool)(data.GetValueOrDefault(name).Value ?? false);
+ }
+
+ private static CompilationUnitSyntax CreateSource(SourceProductionContext context, ClassDeclarationSyntax declarationSyntax, SemanticModel semanticModel, INamedTypeSymbol typeSymbol, CodeGen.Options options)
+ {
+ var root = declarationSyntax.SyntaxTree.GetCompilationUnitRoot();
+ var declaredUsings = root.Usings;
+ foreach (var ns in root.Members.OfType())
+ declaredUsings = declaredUsings.AddRange(ns.Usings);
+
+ var usings = List(declaredUsings);
+
+ var generatedMembers = CodeGen.GenerateAsync(declarationSyntax, semanticModel, progress: new Progress(context), options, context.CancellationToken).Result;
+
+ var containingType = typeSymbol;
+ while (containingType.ContainingType != null)
+ {
+ containingType = containingType.ContainingType;
+
+ generatedMembers = SingletonList(
+ ClassDeclaration(containingType.Name)
+ .WithModifiers(TokenList(Token(SyntaxKind.PartialKeyword)))
+ .WithMembers(generatedMembers));
+ }
+
+ if (!containingType.ContainingNamespace.IsGlobalNamespace)
+ {
+ generatedMembers = SingletonList(
+ NamespaceDeclaration(
+ ParseName(typeSymbol.ContainingNamespace.ToDisplayString()))
+ .WithMembers(generatedMembers));
+ }
+
+ return
+ CompilationUnit()
+ .WithUsings(usings)
+ .WithMembers(generatedMembers)
+ .NormalizeWhitespace();
+ }
+
+ private class Progress : IProgress
+ {
+ private readonly SourceProductionContext context;
+
+ public Progress(SourceProductionContext context)
+ {
+ this.context = context;
+ }
+
+ public void Report(Diagnostic value)
+ {
+ context.ReportDiagnostic(value);
+ }
}
}
}
diff --git a/src/ImmutableObjectGraph.Generation/ImmutableObjectGraph.Generation.csproj b/src/ImmutableObjectGraph.Generation/ImmutableObjectGraph.Generation.csproj
index b01d157..872a958 100644
--- a/src/ImmutableObjectGraph.Generation/ImmutableObjectGraph.Generation.csproj
+++ b/src/ImmutableObjectGraph.Generation/ImmutableObjectGraph.Generation.csproj
@@ -4,14 +4,11 @@
netstandard2.0
MSBuild-based code generator to transform simple mutable type definitions into fully functional immutable types with persistent characteristics.
- true
- true
-
- $(GenerateNuspecDependsOn);SetNuSpecPropertiesForHost
- $(MSBuildProjectName).nuspec
false
+ $(GetTargetPathDependsOn);GetDependencyTargetPaths
$(TargetsForTfmSpecificContentInPackage);PackBuildOutputs
+
True
@@ -19,9 +16,6 @@
DiagnosticsStrings.resx
-
-
-
ResXFileCodeGenerator
@@ -33,29 +27,47 @@
-
-
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
-
-
-
-
+
..\..\lib\netstandard1.0\CG.Pluralization.dll
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
- id=$(PackageId);version=$(NuGetPackageVersion);authors=$(Authors);copyright=$(Copyright);tags=$(PackageTags);requireLicenseAcceptance=$(PackageRequireLicenseAcceptance);licenseUrl=$(PackageLicenseUrl);description=$(Description);CodeGenerationRoslynVersion=$(CodeGenerationRoslynVersion);Configuration=$(Configuration);OutDir=$(OutDir)
-
+
+
+
+
+
+
+
+
diff --git a/src/ImmutableObjectGraph.Generation/ImmutableObjectGraph.Generation.nuspec b/src/ImmutableObjectGraph.Generation/ImmutableObjectGraph.Generation.nuspec
index 81e8819..474147a 100644
--- a/src/ImmutableObjectGraph.Generation/ImmutableObjectGraph.Generation.nuspec
+++ b/src/ImmutableObjectGraph.Generation/ImmutableObjectGraph.Generation.nuspec
@@ -12,19 +12,17 @@
$PackageTags$
-
-
-
-
-
-
+
+
+
+
+
-
diff --git a/src/ImmutableObjectGraph.Generation/Readme.txt b/src/ImmutableObjectGraph.Generation/Readme.txt
index b65e676..1f7aa74 100644
--- a/src/ImmutableObjectGraph.Generation/Readme.txt
+++ b/src/ImmutableObjectGraph.Generation/Readme.txt
@@ -14,16 +14,10 @@
readonly string lastName;
}
-2. On each source file that contains the [GenerateImmutable] attribute, set the file's
- Custom Tool property to "MSBuild:GenerateCodeFromAttributes".
-
-3. You may need to close and reopen the project/solution after first setting the
- Custom Tool property before IntelliSense includes the generated members.
-
-4. Create a Person in another of your code files using the generated factory method:
+2. Create a Person in another of your code files using the generated factory method:
var author = Person.Create(firstName: "Andrew", lastName: "Arnott");
-5. Now add more types, add arguments to the [GenerateImmutable(...)] attribute, etc.
+3. Now add more types, add arguments to the [GenerateImmutable(...)] attribute, etc.
Send issues to https://github.com/aarnott/immutableobjectgraph/issues
diff --git a/src/ImmutableObjectGraph.Generation/build/ImmutableObjectGraph.Generation.targets b/src/ImmutableObjectGraph.Generation/build/ImmutableObjectGraph.Generation.targets
deleted file mode 100644
index 5a91b7d..0000000
--- a/src/ImmutableObjectGraph.Generation/build/ImmutableObjectGraph.Generation.targets
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/src/ImmutableObjectGraph.sln b/src/ImmutableObjectGraph.sln
index bde0def..17546c6 100644
--- a/src/ImmutableObjectGraph.sln
+++ b/src/ImmutableObjectGraph.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28010.2036
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32210.238
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImmutableObjectGraph", "ImmutableObjectGraph\ImmutableObjectGraph.csproj", "{63930555-500F-4E7B-9F24-3D5C3D4F0573}"
EndProject
@@ -12,7 +12,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
..\CONTRIBUTING.md = ..\CONTRIBUTING.md
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
- global.json = global.json
..\LICENSE.txt = ..\LICENSE.txt
NuGet.Config = NuGet.Config
..\README.md = ..\README.md
diff --git a/src/ImmutableObjectGraph/ImmutableObjectGraph.csproj b/src/ImmutableObjectGraph/ImmutableObjectGraph.csproj
index 41e881d..ed86784 100644
--- a/src/ImmutableObjectGraph/ImmutableObjectGraph.csproj
+++ b/src/ImmutableObjectGraph/ImmutableObjectGraph.csproj
@@ -4,7 +4,6 @@
-
diff --git a/src/RoslynDemo/RoslynDemo.csproj b/src/RoslynDemo/RoslynDemo.csproj
index 639c146..4700d96 100644
--- a/src/RoslynDemo/RoslynDemo.csproj
+++ b/src/RoslynDemo/RoslynDemo.csproj
@@ -4,25 +4,9 @@
Exe
false
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
- MSBuild:GenerateCodeFromAttributes
-
-
-
-
- false
-
-
-
-
-
-
+
diff --git a/src/global.json b/src/global.json
deleted file mode 100644
index 3d26ee6..0000000
--- a/src/global.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "sdk": {
- "version": "2.2.401"
- }
-}