diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 000000000..a4b18fa7f --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "nbgv": { + "version": "3.1.71", + "commands": [ + "nbgv" + ] + } + } +} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a730152ec..539652ae0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,87 +12,49 @@ on: env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - build_configuration: Release + Configuration: Release jobs: - build-windows: - runs-on: windows-latest + build: + strategy: + matrix: + os: [ windows-latest, ubuntu-latest, macos-latest ] + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - - name: Install .NET Core - shell: pwsh - run: | - $info = dotnet --info - $isRuntime = $info -contains 'Microsoft.NETCore.App 2.1' - Push-Location src; dotnet --version > $null; Pop-Location; $isSdk = $LASTEXITCODE -eq 0; $LASTEXITCODE = 0 - if ($isSdk -and $isRuntime) { return } - [string]$dotnetroot = "~/.dotnet" | %{ if (-not (Test-Path $_)) { mkdir $_ > $null }; Resolve-Path $_ } - Invoke-WebRequest "https://dotnetwebsite.azurewebsites.net/download/dotnet-core/scripts/v1/dotnet-install.ps1" -OutFile ~/dotnet-install.ps1 - ~/dotnet-install.ps1 -JsonFile src/global.json -InstallDir $dotnetroot - ~/dotnet-install.ps1 -Channel 2.1 -Runtime dotnet -InstallDir $dotnetroot - Write-Output "::add-path::$dotnetroot" - Write-Output "::set-env name=DOTNET_ROOT::$dotnetroot" + - name: Setup .NET Core uses: actions/setup-dotnet@v1 + - run: dotnet --info - - name: Install and run nbgv - run: | - dotnet tool install --tool-path . nbgv - ./nbgv get-version -p src + + - run: dotnet tool restore + + - name: Run nbgv + run: dotnet nbgv get-version -p src + - name: Restore run: dotnet restore src -v normal + - name: Build - run: dotnet build src -t:build,pack --no-restore -m -c ${{ env.build_configuration }} -bl:obj/logs/build-windows.binlog + run: dotnet build src -t:build,pack --no-restore -m -bl:obj/logs/build-${{ matrix.os }}.binlog + - name: Test - run: dotnet test src --no-build -c ${{ env.build_configuration }} + run: dotnet test src --no-build + - name: Upload nugets - if: github.event_name == 'push' + if: github.event_name == 'push' && matrix.os == 'windows-latest' uses: actions/upload-artifact@v1 with: name: nugets - path: bin/Packages/${{ env.build_configuration }} - - name: Upload logs - uses: actions/upload-artifact@v1 - with: - name: logs-windows - path: obj/logs/ + path: bin/Packages/${{ env.Configuration }} - build-other: - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v1 - - name: Install .NET Core - shell: pwsh - run: | - $info = dotnet --info - $isRuntime = $info -contains 'Microsoft.NETCore.App 2.1' - Push-Location src; dotnet --version > $null; Pop-Location; $isSdk = $LASTEXITCODE -eq 0; $LASTEXITCODE = 0 - if ($isSdk -and $isRuntime) { return } - [string]$dotnetroot = "~/.dotnet" | %{ if (-not (Test-Path $_)) { mkdir $_ > $null }; Resolve-Path $_ } - Invoke-WebRequest "https://dotnetwebsite.azurewebsites.net/download/dotnet-core/scripts/v1/dotnet-install.sh" -OutFile ~/dotnet-install.sh - chmod +x ~/dotnet-install.sh - ~/dotnet-install.sh -JsonFile src/global.json -InstallDir $dotnetroot - ~/dotnet-install.sh -Channel 2.1 -Runtime dotnet -InstallDir $dotnetroot - Write-Output "::add-path::$dotnetroot" - Write-Output "::set-env name=DOTNET_ROOT::$dotnetroot" - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - - run: dotnet --info - - name: Install and run nbgv - run: | - dotnet tool install --tool-path . nbgv --version 3.0.28 - ./nbgv get-version -p src - - name: Restore - run: dotnet restore src -v normal - - name: Build - run: dotnet build src --no-restore -m -c ${{ env.build_configuration }} -bl:obj/logs/build-${{ matrix.os }}.binlog - - name: Test - run: dotnet test src --no-build -c ${{ env.build_configuration }} -f netcoreapp2.1 - name: Upload logs uses: actions/upload-artifact@v1 with: name: logs-${{ matrix.os }} path: obj/logs/ + + - name: Build samples + shell: pwsh + run: samples/build.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0956dc590..4a2438c2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,24 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +> ⚠ There are major changes, please look at [v0.7 migration guide]. + ### Added -* GeneratorInCustomerSolution sample in `samples` folder +* Various samples in `samples` folder * GitHub Actions CI * Support for plugin dependencies! 🎉 ([#156]). +* Plugins (generators) are now easier to build using `CodeGeneration.Roslyn.Plugin.Sdk` MSBuildSdk package ([#113]). ### Changed * .NET Core SDK version bumped to `3.1.100` ([#178]). * `Attributes` package now targets `net20;net40` in addition to `netstandard1.0` ([#178]). -* `dotnet-codegen` now has `RollForward=Major` policy to allow it to run on newer runtimes than 2.x, +* Tool now has `RollForward=Major` policy to allow it to run on newer runtimes than 2.x, e.g. .NET Core SDK v3.x *only* should suffice for most usage scenarios ([#178]). * MSBuild ItemGroup used for registration of plugin paths changed to `CodeGenerationRoslynPlugin` (was `GeneratorAssemblySearchPaths`). A warning for using old one is introduced (`CGR1002`). ([#156]) * ItemGroup now should contain full path to generator dll (previously it was a containing folder path) - * Old behavior has a compat-plug and the paths are searched for any dll, and those found are added to new ItemGroup. + * Old behavior has a compat-plug for now and the paths are searched for any dll, and those found are added to new ItemGroup. * When using P2P generator (same solution), a consuming project needs to add an attribute `OutputItemType="CodeGenerationRoslynPlugin"` to the `ProjectReference` of the generator project. See [v0.7 migration guide]. +* `dotnet-codegen` package is now `CodeGeneration.Roslyn.Tool` and is build very differently; + also it includes build assets from `BuildTime` package ([#198]). + +### Removed +* `CodeGeneration.Roslyn.BuildTime` package is now merged into `CodeGeneration.Roslyn.Tool` + (which is now the only package required to be referenced by generator consumers, aside from generators themselves) ([#198]). +[#113]: https://github.com/AArnott/CodeGeneration.Roslyn/issues/113 [#156]: https://github.com/AArnott/CodeGeneration.Roslyn/pull/156 [#178]: https://github.com/AArnott/CodeGeneration.Roslyn/pull/178 +[#198]: https://github.com/AArnott/CodeGeneration.Roslyn/pull/198 [v0.7 migration guide]: https://github.com/AArnott/CodeGeneration.Roslyn/wiki/Migrations#v07 diff --git a/README.md b/README.md index b6928acdb..38e7c9157 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ for it. That's because code generation runs *before* the consuming project is it Now we'll use an [MSBuild project SDK] `CodeGeneration.Roslyn.Plugin.Sdk` to speed up configuring our generator plugin. Edit your project file and add the `` element: ```xml + @@ -141,6 +142,7 @@ with a dependency on your code generation assembly. We'll consume our generator in a Reflector app: > `dotnet new console -f netcoreapp2.1 -o Reflector` +> > `dotnet add Reflector reference Duplicator` Let's write a simple program that prints all types in its assembly: @@ -183,14 +185,15 @@ namespace Reflector Right now `dotnet run -p Reflector` outputs: > `Reflector.Program` +> > `Reflector.Test` -Now all that's left is to plumb the build pipeline with code generation tool. You'll need to add the following two references to your Reflector project file: -* [`CodeGeneration.Roslyn.BuildTime`][BuildTimeNuPkg] -* [`dotnet-codegen`][ToolNuPkg] +Now all that's left is to plumb the build pipeline with code generation tool. +You'll need to add a reference to [`CodeGeneration.Roslyn.Tool`][ToolNuPkg] package: +> `dotnet add Reflector package CodeGeneration.Roslyn.Tool` Also, you need to add the following metadata to your generator project reference: -`OutputItemType="CodeGenerationRoslynPlugin"`. This will add the path to the `Duplicator.dll` to the list of plugins the tool uses. +`OutputItemType="CodeGenerationRoslynPlugin"`. This will add the path to the `Duplicator.dll` to the list of plugins the tool runs. This is how your project file can look like: @@ -200,31 +203,30 @@ This is how your project file can look like: Exe netcoreapp2.1 - {replace with actual version used} - - + - - ``` And if all steps were done correctly, `dotnet run -p Reflector` should print: > `Reflector.Program` +> > `Reflector.Test` +> > `Reflector.TestPassed` -> ➡ Notice that there is a `TestPassed` type in the assembly now. +> 💡 Notice that there is a `TestPassed` type in the assembly now. What's even better is that you should see that new type in IntelliSense as well! Try executing Go to Definition (F12) on it - your IDE (VS/VS Code) should open the generated file for you (it'll be located in `IntermediateOutputPath` - most commonly `obj/`). @@ -264,18 +266,27 @@ So, the consuming project will have a simple ProjectReference to the `Duplicator.Attributes` project, and the generator project will not have any attribute defined. With that done, we can move to the next section. -> 📋 Side note: if you use generator only in a single TFM-incompatible project, +> 📋 Side note: if there's only one consumer project for your generator, > you can define the triggering attribute in the consuming project as well. +> In our case, this would bean moving the `DuplicateWithSuffixAttribute.cs` +> from `Duplicator` to `Reflector`, and adding a reference to the +> [`CodeGeneration.Roslyn.Attributes`][AttrNuPkg] in Reflector: +> > `dotnet add Reflector package CodeGeneration.Roslyn.Attributes` +> > +> > `mv Duplicator/DuplicateWithSuffixAttribute.cs Reflector` +> +> For simplicity, we'll assume this is the case in the following sections. ### Customize generator reference With the attribute available to consuming code, we don't need a reference to the generator project, right? Well, not quite. The magic OutputItemType metadata is important - it adds a path to the generator dll to the list of plugins known -to the `dotnet-codegen` tool. Additionally, we want to specify that there's a build -dependency of the consuming project on the generator. So we modify the reference: +to the `CodeGeneration.Roslyn.Tool` tool. Additionally, we want to specify that there's a build dependency of the consuming project on the generator. So we modify +the reference: ```xml + netcoreapp2.1;netcoreapp3.0 + + + + netcoreapp2.1;netcoreapp3.1 + + + ``` -You could want to do that to use C#8's Nullable Reference Types feature. - -This won't work now, because the generator's Build target output will contain two references. To fix that you can use `SetTargetFramework` metadata: +There'll be a build error, because the consumer (Reflector) doesn't know which +output to use (and assign to the CodeGenerationRoslynPlugin Item). To fix that +we have to use `SetTargetFramework` metadata. Setting it implies +`SkipGetTargetFrameworkProperties="true"` so we can replace it. ```xml + ``` -Non-empty `SetTargetFramework` automatically implies `SkipGetTargetFrameworkProperties="true"` so we can omit that. - -We also need to add a condition on `TargetFrameworks` element so that we skip -setting it at all when a singular property is set. - -```xml - - netcoreapp2.1; - netcoreapp3.0 - -``` - ### Package your code generator You can also package up your code generator as a NuGet package for others to install @@ -331,35 +341,29 @@ and use. A project using `CodeGeneration.Roslyn.Plugin.Sdk` is automatically configured to produce a correct Plugin nuget package. Your consumers will have to depend on the following: -- [`dotnet-codegen`][ToolNuPkg] tool -- [`CodeGeneration.Roslyn.BuildTime`][BuildTimeNuPkg] +- [`CodeGeneration.Roslyn.Tool`][ToolNuPkg] tool - `Duplicator.Attributes` (your attributes package) - `Duplicator` (your generator/plugin package) An example consuming project file should contain: ```xml + - - ``` -where `CodeGenerationRoslynVersion` is a correctly defined Property. - > 📋 You can also attempt to craft a self-contained package that will -> flow all the needed dependencies and assets into the consuming project, -> but the `DotNetCliToolReference` has to be in the consumer's project file -> no matter what. Just a friendly reminder. Also, such a scenario is definitely -> outside this project's scope. +> flow all the needed dependencies and assets into the consuming project. +> For a sample implementation, see [MetapackageSample](samples/MetapackageSample/). [NuPkg]: https://nuget.org/packages/CodeGeneration.Roslyn [BuildTimeNuPkg]: https://nuget.org/packages/CodeGeneration.Roslyn.BuildTime [AttrNuPkg]: https://nuget.org/packages/CodeGeneration.Roslyn.Attributes -[ToolNuPkg]: https://nuget.org/packages/dotnet-codegen +[ToolNuPkg]: https://nuget.org/packages/CodeGeneration.Roslyn.Tool [netstandard-table]: https://docs.microsoft.com/dotnet/standard/net-standard#net-implementation-support [MSBuild project SDK]: https://docs.microsoft.com/visualstudio/msbuild/how-to-use-project-sdk diff --git a/azure-pipeline.yml b/azure-pipeline.yml index 8c4abd5dd..f3f1f8d0a 100644 --- a/azure-pipeline.yml +++ b/azure-pipeline.yml @@ -33,8 +33,8 @@ jobs: workingDirectory: src - script: | - dotnet tool install --tool-path . nbgv --version 3.0.28 - .\nbgv cloud -p src + dotnet tool restore + dotnet nbgv cloud -p src displayName: Set build number condition: ne(variables['system.pullrequest.isfork'], true) diff --git a/samples/.gitignore b/samples/.gitignore new file mode 100644 index 000000000..024021fd4 --- /dev/null +++ b/samples/.gitignore @@ -0,0 +1 @@ +.nuget \ No newline at end of file diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props new file mode 100644 index 000000000..f81f0442a --- /dev/null +++ b/samples/Directory.Build.props @@ -0,0 +1,28 @@ + + + + Debug + $(MSBuildThisFileDirectory)obj/$(MSBuildProjectName)/ + $(MSBuildThisFileDirectory)bin/$(MSBuildProjectName)/$(Configuration)/ + $(MSBuildThisFileDirectory)bin/Packages/$(Configuration)/ + + * + + $(LocalNuGetVersion) + $(MSBuildThisFileDirectory)/.nuget/ + + <_MainPackagesDebug>$(MSBuildThisFileDirectory)../bin/Packages/Debug/ + <_MainPackagesRelease>$(MSBuildThisFileDirectory)../bin/Packages/Release/ + <_SamplePackages>$(MSBuildThisFileDirectory)bin/Packages/$(Configuration)/ + @(CustomLocalFeed);$(RestoreAdditionalProjectSources) + + $(MSBuildThisFileDirectory)../src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/ + + + + + + + + + \ No newline at end of file diff --git a/samples/GeneratorInConsumerSolution/Directory.Build.props b/samples/GeneratorInConsumerSolution/Directory.Build.props deleted file mode 100644 index f337ec2be..000000000 --- a/samples/GeneratorInConsumerSolution/Directory.Build.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - * - - - \ No newline at end of file diff --git a/samples/GeneratorInConsumerSolution/Sample.Consumer/Sample.Consumer.csproj b/samples/GeneratorInConsumerSolution/Sample.Consumer/Sample.Consumer.csproj index 3514babca..b629e803d 100644 --- a/samples/GeneratorInConsumerSolution/Sample.Consumer/Sample.Consumer.csproj +++ b/samples/GeneratorInConsumerSolution/Sample.Consumer/Sample.Consumer.csproj @@ -5,8 +5,7 @@ - - + diff --git a/samples/GeneratorInConsumerSolution/Sample.Generator/Sample.Generator.csproj b/samples/GeneratorInConsumerSolution/Sample.Generator/Sample.Generator.csproj index 4466c7c61..2f908575d 100644 --- a/samples/GeneratorInConsumerSolution/Sample.Generator/Sample.Generator.csproj +++ b/samples/GeneratorInConsumerSolution/Sample.Generator/Sample.Generator.csproj @@ -1,11 +1,11 @@ + + netstandard2.0 - - - + diff --git a/samples/GeneratorInConsumerSolution/nuget.config b/samples/GeneratorInConsumerSolution/nuget.config deleted file mode 100644 index 4314c7a4b..000000000 --- a/samples/GeneratorInConsumerSolution/nuget.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/samples/JsonConsumer/JsonConsumer.csproj b/samples/JsonConsumer/JsonConsumer.csproj new file mode 100644 index 000000000..9597f4260 --- /dev/null +++ b/samples/JsonConsumer/JsonConsumer.csproj @@ -0,0 +1,17 @@ + + + + Exe + netcoreapp3.1 + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + \ No newline at end of file diff --git a/samples/JsonConsumer/Program.cs b/samples/JsonConsumer/Program.cs new file mode 100644 index 000000000..e585600b7 --- /dev/null +++ b/samples/JsonConsumer/Program.cs @@ -0,0 +1,18 @@ +using System; +using CodeGeneration.Roslyn; + +namespace JsonConsumer +{ + [CodeGenerationAttribute("JsonGenerator.JsonGenerator, JsonGenerator")] + class JsonAttribute : Attribute { } + + [Json] + partial class Program + { + static void Main(string[] args) + { + Console.WriteLine("Json of generator assembly full name:"); + Console.WriteLine(Json); + } + } +} diff --git a/samples/JsonGenerator/JsonGenerator.cs b/samples/JsonGenerator/JsonGenerator.cs new file mode 100644 index 000000000..4263e611a --- /dev/null +++ b/samples/JsonGenerator/JsonGenerator.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using CodeGeneration.Roslyn; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace JsonGenerator +{ + public class JsonGenerator : ICodeGenerator + { + public JsonGenerator(AttributeData attributeData) + { + } + + public Task> GenerateAsync(TransformationContext context, IProgress progress, CancellationToken cancellationToken) + { + var partialType = CreatePartialType(); + return Task.FromResult(SyntaxFactory.List(partialType)); + + IEnumerable CreatePartialType() + { + var newPartialType = + context.ProcessingNode is ClassDeclarationSyntax classDeclaration + ? SyntaxFactory.ClassDeclaration(classDeclaration.Identifier.ValueText) + : context.ProcessingNode is StructDeclarationSyntax structDeclaration + ? SyntaxFactory.StructDeclaration(structDeclaration.Identifier.ValueText) + : default(TypeDeclarationSyntax); + if (newPartialType is null) + yield break; + yield return newPartialType + ?.AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword)) + .AddMembers(CreateIdProperty()); + } + MemberDeclarationSyntax CreateIdProperty() + { + var json = Newtonsoft.Json.JsonConvert.SerializeObject( + new { GeneratorAssembly = typeof(JsonGenerator).Assembly.FullName } + ); + return + PropertyDeclaration( + PredefinedType( + Token(SyntaxKind.StringKeyword)), + Identifier("Json")) + .WithModifiers( + TokenList( + Token(SyntaxKind.StaticKeyword))) + .WithExpressionBody( + ArrowExpressionClause( + LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal(json)))) + .WithSemicolonToken( + Token(SyntaxKind.SemicolonToken)); + } + } + } +} diff --git a/samples/JsonGenerator/JsonGenerator.csproj b/samples/JsonGenerator/JsonGenerator.csproj new file mode 100644 index 000000000..bb8c048ab --- /dev/null +++ b/samples/JsonGenerator/JsonGenerator.csproj @@ -0,0 +1,16 @@ + + + + + + netcoreapp2.1;netcoreapp3.1 + $(TargetFramework.Equals('netcoreapp2.1')) + + + + + + + + + \ No newline at end of file diff --git a/samples/MetapackageSample/MetapackageConsumer/MetapackageConsumer.csproj b/samples/MetapackageSample/MetapackageConsumer/MetapackageConsumer.csproj new file mode 100644 index 000000000..45cfbab52 --- /dev/null +++ b/samples/MetapackageSample/MetapackageConsumer/MetapackageConsumer.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/samples/MetapackageSample/MetapackageConsumer/Program.cs b/samples/MetapackageSample/MetapackageConsumer/Program.cs new file mode 100644 index 000000000..89a8c5ea2 --- /dev/null +++ b/samples/MetapackageSample/MetapackageConsumer/Program.cs @@ -0,0 +1,19 @@ +using System; +using MetapackageSample; + +namespace MetapackageConsumer +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine(TestGenerated.Text()); + } + + } + + [DuplicateWithSuffix("Generated")] + class Test { + public static string Text() => "Success!"; + } +} diff --git a/samples/MetapackageSample/MetapackageSample.Attributes/DuplicateWithSuffixAttribute.cs b/samples/MetapackageSample/MetapackageSample.Attributes/DuplicateWithSuffixAttribute.cs new file mode 100644 index 000000000..994f733ad --- /dev/null +++ b/samples/MetapackageSample/MetapackageSample.Attributes/DuplicateWithSuffixAttribute.cs @@ -0,0 +1,19 @@ +using System; +using System.Diagnostics; +using CodeGeneration.Roslyn; + +namespace MetapackageSample +{ + [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] + [CodeGenerationAttribute("MetapackageSample.Generators.DuplicateWithSuffixGenerator, MetapackageSample.Generators")] + [Conditional("CodeGeneration")] + public class DuplicateWithSuffixAttribute : Attribute + { + public DuplicateWithSuffixAttribute(string suffix) + { + Suffix = suffix; + } + + public string Suffix { get; } + } +} diff --git a/samples/MetapackageSample/MetapackageSample.Attributes/MetapackageSample.Attributes.csproj b/samples/MetapackageSample/MetapackageSample.Attributes/MetapackageSample.Attributes.csproj new file mode 100644 index 000000000..f486fec61 --- /dev/null +++ b/samples/MetapackageSample/MetapackageSample.Attributes/MetapackageSample.Attributes.csproj @@ -0,0 +1,12 @@ + + + + netstandard1.0 + MetapackageSample + + + + + + + diff --git a/samples/MetapackageSample/MetapackageSample.Generators/DuplicateWithSuffixGenerator.cs b/samples/MetapackageSample/MetapackageSample.Generators/DuplicateWithSuffixGenerator.cs new file mode 100644 index 000000000..9231e38c9 --- /dev/null +++ b/samples/MetapackageSample/MetapackageSample.Generators/DuplicateWithSuffixGenerator.cs @@ -0,0 +1,33 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using CodeGeneration.Roslyn; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace MetapackageSample.Generators +{ + public class DuplicateWithSuffixGenerator : ICodeGenerator + { + private readonly string suffix; + + public DuplicateWithSuffixGenerator(AttributeData attributeData) + { + suffix = (string)attributeData.ConstructorArguments[0].Value; + } + + public Task> GenerateAsync(TransformationContext context, IProgress progress, CancellationToken cancellationToken) + { + // Our generator is applied to any class that our attribute is applied to. + var applyToClass = (ClassDeclarationSyntax)context.ProcessingNode; + + // Apply a suffix to the name of a copy of the class. + var copy = applyToClass.WithIdentifier(SyntaxFactory.Identifier(applyToClass.Identifier.ValueText + suffix)); + + // Return our modified copy. It will be added to the user's project for compilation. + var results = SyntaxFactory.SingletonList(copy); + return Task.FromResult(results); + } + } +} diff --git a/samples/MetapackageSample/MetapackageSample.Generators/MetapackageSample.Generators.csproj b/samples/MetapackageSample/MetapackageSample.Generators/MetapackageSample.Generators.csproj new file mode 100644 index 000000000..23c432864 --- /dev/null +++ b/samples/MetapackageSample/MetapackageSample.Generators/MetapackageSample.Generators.csproj @@ -0,0 +1,9 @@ + + + + + netcoreapp2.1 + + + + diff --git a/samples/MetapackageSample/MetapackageSample.sln b/samples/MetapackageSample/MetapackageSample.sln new file mode 100644 index 000000000..d63456179 --- /dev/null +++ b/samples/MetapackageSample/MetapackageSample.sln @@ -0,0 +1,48 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetapackageSample.Attributes", "MetapackageSample.Attributes\MetapackageSample.Attributes.csproj", "{6D458348-E045-4E8A-B133-0B05E7CA9465}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetapackageSample.Generators", "MetapackageSample.Generators\MetapackageSample.Generators.csproj", "{6B5DBA1C-1FE6-4211-819D-1CD520B143F8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Debug|x64.ActiveCfg = Debug|Any CPU + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Debug|x64.Build.0 = Debug|Any CPU + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Debug|x86.ActiveCfg = Debug|Any CPU + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Debug|x86.Build.0 = Debug|Any CPU + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Release|Any CPU.Build.0 = Release|Any CPU + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Release|x64.ActiveCfg = Release|Any CPU + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Release|x64.Build.0 = Release|Any CPU + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Release|x86.ActiveCfg = Release|Any CPU + {6D458348-E045-4E8A-B133-0B05E7CA9465}.Release|x86.Build.0 = Release|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Debug|x64.ActiveCfg = Debug|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Debug|x64.Build.0 = Debug|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Debug|x86.ActiveCfg = Debug|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Debug|x86.Build.0 = Debug|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Release|Any CPU.Build.0 = Release|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Release|x64.ActiveCfg = Release|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Release|x64.Build.0 = Release|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Release|x86.ActiveCfg = Release|Any CPU + {6B5DBA1C-1FE6-4211-819D-1CD520B143F8}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/samples/MetapackageSample/MetapackageSample/MetapackageSample.csproj b/samples/MetapackageSample/MetapackageSample/MetapackageSample.csproj new file mode 100644 index 000000000..fa02c3c80 --- /dev/null +++ b/samples/MetapackageSample/MetapackageSample/MetapackageSample.csproj @@ -0,0 +1,23 @@ + + + + + netstandard1.0 + + true + + false + + + + + + + + + + + + + + diff --git a/samples/MetapackageSample/MetapackageSample/_._ b/samples/MetapackageSample/MetapackageSample/_._ new file mode 100644 index 000000000..e69de29bb diff --git a/samples/MetapackageSample/README.md b/samples/MetapackageSample/README.md new file mode 100644 index 000000000..b64904a49 --- /dev/null +++ b/samples/MetapackageSample/README.md @@ -0,0 +1,25 @@ +# MetapackageSample + +This sample demonstrates an approach to providing a nice UX for our generator consumers. + +The `MetapackageSample.sln` solution builds and packs `Attributes` and `Generators` packages, +and then using those packages from local folder feed, `MetapackageSample` project +is packed and creates a new NuGet package that just references those packages, +as well as the `CodeGeneration.Roslyn.Tool` package. + +This allows your consumers to simply +> `dotnet add package MetapackageSample` +and have the source generator working immediately. + +Important aspects of the `Metapackage/Metapackage.csproj`: +* it's not built at the same time as Attributes and Generators because it needs + their NuGets to be in the folder feed it uses. +* it's not producing any dll, and so should be only `pack`ed +* there are important comments for every element, please read them +* variables used (`$(PackageVersion)`, `$(LocalNuGetVersion)`) should be replaced + with whatever you use in your setup. `LocalNuGetVersion` is the version of CG.R + used across samples - you should use the same version as other CG.R packages you + reference. `Directory.Build.props` is a good place to define that once. + +`MetapackageConsumer` is an example consumer project that references just +our single `MetapackageSample` package, and successfully runs the generator. \ No newline at end of file diff --git a/samples/MetapackageSample/build.ps1 b/samples/MetapackageSample/build.ps1 new file mode 100644 index 000000000..4adb0b578 --- /dev/null +++ b/samples/MetapackageSample/build.ps1 @@ -0,0 +1,26 @@ +#!/usr/bin/env pwsh + +Write-Host "Running in $PSScriptRoot" -ForegroundColor Cyan +Push-Location $PSScriptRoot +try { + $env:Configuration ??= 'Debug' + + # clean up all restore and build artifacts: + Remove-Item .nuget, bin, obj -Recurse -Force -ErrorAction Ignore + + # set env variable to use local CG.R packages + $env:LocalNuGetVersion = dotnet nbgv get-version --variable NuGetPackageVersion --project ../../src + + Write-Host "Using CG.R package version: $env:LocalNuGetVersion" -ForegroundColor Cyan + + # pack directory (solution), then pack Metapackage + '.','MetapackageSample' | ForEach-Object { + Write-Host "dotnet pack $_" -ForegroundColor Green + dotnet pack $_ + } + Write-Host "dotnet run MetapackageConsumer" -ForegroundColor Green + dotnet run -p MetapackageConsumer +} +finally { + Pop-Location +} \ No newline at end of file diff --git a/samples/PackageConsumer/PackageConsumer.csproj b/samples/PackageConsumer/PackageConsumer.csproj new file mode 100644 index 000000000..edc79116f --- /dev/null +++ b/samples/PackageConsumer/PackageConsumer.csproj @@ -0,0 +1,17 @@ + + + + Exe + netcoreapp3.1 + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + \ No newline at end of file diff --git a/samples/PackageConsumer/Program.cs b/samples/PackageConsumer/Program.cs new file mode 100644 index 000000000..df4ae3288 --- /dev/null +++ b/samples/PackageConsumer/Program.cs @@ -0,0 +1,17 @@ +using System; +using CodeGeneration.Roslyn; + +namespace PackageConsumer +{ + [CodeGenerationAttribute("Sample.Generator.IdGenerator, PackagedGenerator")] + class IdAttribute : Attribute { } + + [Id] + partial class Program + { + static void Main(string[] args) + { + Console.WriteLine("Generated 'Id' property value: " + new Program().Id); + } + } +} diff --git a/samples/PackagedGenerator/IdGenerator.cs b/samples/PackagedGenerator/IdGenerator.cs new file mode 100644 index 000000000..4b8a4b133 --- /dev/null +++ b/samples/PackagedGenerator/IdGenerator.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using CodeGeneration.Roslyn; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Sample.Generator +{ + public class IdGenerator : ICodeGenerator + { + public IdGenerator(AttributeData attributeData) + { + } + + public Task> GenerateAsync(TransformationContext context, IProgress progress, CancellationToken cancellationToken) + { + var partialType = CreatePartialType(); + return Task.FromResult(SyntaxFactory.List(partialType)); + + IEnumerable CreatePartialType() + { + var newPartialType = + context.ProcessingNode is ClassDeclarationSyntax classDeclaration + ? SyntaxFactory.ClassDeclaration(classDeclaration.Identifier.ValueText) + : context.ProcessingNode is StructDeclarationSyntax structDeclaration + ? SyntaxFactory.StructDeclaration(structDeclaration.Identifier.ValueText) + : default(TypeDeclarationSyntax); + if (newPartialType is null) + yield break; + yield return newPartialType + ?.AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword)) + .AddMembers(CreateIdProperty()); + } + MemberDeclarationSyntax CreateIdProperty() + { + return SyntaxFactory.ParseMemberDeclaration("public System.Guid Id { get; } = System.Guid.NewGuid();"); + } + } + } +} \ No newline at end of file diff --git a/samples/PackagedGenerator/PackagedGenerator.csproj b/samples/PackagedGenerator/PackagedGenerator.csproj new file mode 100644 index 000000000..fcb74e67b --- /dev/null +++ b/samples/PackagedGenerator/PackagedGenerator.csproj @@ -0,0 +1,11 @@ + + + + + + netcoreapp2.1 + + + + + \ No newline at end of file diff --git a/samples/README.md b/samples/README.md new file mode 100644 index 000000000..002f29190 --- /dev/null +++ b/samples/README.md @@ -0,0 +1,20 @@ +# Samples + +## Usage + +If you want to use samples, they'll build against **latest stable** `CodeGeneration.Roslyn` packages from NuGet. + +To build against locally built packages, specify `LocalNuGetVersion`. The easiest +way is to save the result of `CodeGeneration.Roslyn> nbgv get-version -p src` into +`LocalNuGetVersion` environment variable in the terminal from which you'll then +`dotnet run` or build specific samples. + +From PowerShell, for example: +```powershell +pwsh> $env:LocalNuGetVersion = nbgv get-version -v NuGetPackageVersion -p src +pwsh> dotnet pack samples/PackagedGenerator +pwsh> dotnet run samples/PackageConsumer +``` + +After you've rebuilt any packages, simply delete the `samples/.nuget` folder +and new packages should restore. \ No newline at end of file diff --git a/samples/build.ps1 b/samples/build.ps1 new file mode 100644 index 000000000..a95b620d3 --- /dev/null +++ b/samples/build.ps1 @@ -0,0 +1,44 @@ +#!/usr/bin/env pwsh + +param ( + [string[]] + $Projects +) + +Write-Host "Running in $PSScriptRoot" -ForegroundColor Cyan +Push-Location $PSScriptRoot +try { + $env:Configuration ??= 'Debug' + + # clean up all restore and build artifacts: + Remove-Item .nuget, bin, obj -Recurse -Force -ErrorAction Ignore + + # set env variable to use local CG.R packages + $env:LocalNuGetVersion = dotnet nbgv get-version --variable NuGetPackageVersion --project ../src + + Write-Host "Using CG.R package version: $env:LocalNuGetVersion" -ForegroundColor Cyan + + # get generator project folders + $generators = Get-ChildItem -Directory -Name | Where-Object { $_ -match 'Generator$' } + + # pack generators to make them available in folder feed + $generators | Where-Object { $Projects -eq $null -or $Projects -contains $_} | ForEach-Object { + Write-Host "dotnet pack $_" -ForegroundColor Green + dotnet pack $_ + } + + # build all other projects/solutions + Get-ChildItem -Directory -Name -Exclude $generators | Where-Object { $Projects -eq $null -or $Projects -contains $_} | ForEach-Object { + if (Get-ChildItem $_/* -File -Include 'build.ps1') { + Write-Host "$_/build.ps1" -ForegroundColor Green + & "$_/build.ps1" + } + elseif (Get-ChildItem $_/* -File -Include *.csproj, *.sln) { + Write-Host "dotnet build $_" -ForegroundColor Green + dotnet build $_ + } + } +} +finally { + Pop-Location +} \ No newline at end of file diff --git a/src/CodeGeneration.Roslyn.BuildTime/build/CodeGeneration.Roslyn.BuildTime.targets b/src/CodeGeneration.Roslyn.BuildTime/build/CodeGeneration.Roslyn.BuildTime.targets index 7d833da86..719272f5b 100644 --- a/src/CodeGeneration.Roslyn.BuildTime/build/CodeGeneration.Roslyn.BuildTime.targets +++ b/src/CodeGeneration.Roslyn.BuildTime/build/CodeGeneration.Roslyn.BuildTime.targets @@ -41,8 +41,9 @@ Text="Using GeneratorAssemblySearchPaths is deprecated, please use CodeGenerationRoslynPlugin ItemGroup. See $(CgrUrl) for more info. Suppress this warning by adding CGR1002 to MSBuildWarningsAsMessages PropertyGroup." Condition=" '@(GeneratorAssemblySearchPaths)' != '' " /> - codegen + $(GenerateCodeFromAttributesToolPathOverride) + $(CodeGenerationRoslynToolPath.Trim()) <_CodeGenToolOutputBasePath>$(IntermediateOutputPath)$(MSBuildProjectFile).dotnet-codegen <_CodeGenToolResponseFileFullPath>$(_CodeGenToolOutputBasePath).rsp <_CodeGenToolGeneratedFileListFullPath>$(_CodeGenToolOutputBasePath).GeneratedFileList.txt @@ -73,7 +74,7 @@ WriteOnlyWhenDifferent="true" /> @@ -105,7 +106,7 @@ Outputs="$(_CodeGenToolGeneratedFileListFullPath)"> + + + + + $(GenerateCodeFromAttributesDependsOn); + ResolveReferences; + PrepareGenerateCodeFromAttributes; + GenerateCodeFromAttributesCore; + ReadGenerateCodeFromAttributesResults + + https://github.com/AArnott/CodeGeneration.Roslyn + + + + + + + + <_CodeGenToolInputs_Compile + Include="@(Compile)" + Condition=" '%(Compile.Generator)' == 'MSBuild:GenerateCodeFromAttributes' " /> + <_CodeGenToolInputs_DefineConstants Include="$(DefineConstants)" /> + + + <_GeneratorAssemblySearchPathsResolved + Include="%(GeneratorAssemblySearchPaths.PathWithTrailingSlash)*.dll" /> + + + + + + + $(GenerateCodeFromAttributesToolPathOverride) + $(CodeGenerationRoslynToolPath.Trim()) + <_CodeGenToolOutputBasePath>$(IntermediateOutputPath)$(MSBuildProjectFile).dotnet-codegen + <_CodeGenToolResponseFileFullPath>$(_CodeGenToolOutputBasePath).rsp + <_CodeGenToolGeneratedFileListFullPath>$(_CodeGenToolOutputBasePath).GeneratedFileList.txt + <_CodeGenToolResponseFileLines> + @(ReferencePath->'-r;%(Identity)'); + @(_CodeGenToolInputs_DefineConstants->'-d;%(Identity)'); + @(CodeGenerationRoslynPlugin->'--plugin;%(Identity)'); + --out; + $(IntermediateOutputPath); + --projectDir; + $(MSBuildProjectDirectory); + --generatedFilesList; + $(_CodeGenToolGeneratedFileListFullPath); + --; + @(_CodeGenToolInputs_Compile) + + <_CodeGenToolVersionOutput>(n/a) + <_CodeGenToolVersionExitCode> + + + <_CodeGenToolResponseFileContent Include="$(_CodeGenToolResponseFileLines)" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/CodeGeneration.Roslyn.Engine/CodeGeneration.Roslyn.Engine.csproj b/src/CodeGeneration.Roslyn.Engine/CodeGeneration.Roslyn.Engine.csproj index c23ba0575..f85aac57a 100644 --- a/src/CodeGeneration.Roslyn.Engine/CodeGeneration.Roslyn.Engine.csproj +++ b/src/CodeGeneration.Roslyn.Engine/CodeGeneration.Roslyn.Engine.csproj @@ -2,7 +2,7 @@ netcoreapp2.0 - The engine of source code generation used by `dotnet-codegen` tool. + The engine of source code generation used by CodeGeneration.Roslyn.Tool. diff --git a/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/BuildPluginPackage.props b/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/BuildPluginPackage.props index 66c44867f..02006a438 100644 --- a/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/BuildPluginPackage.props +++ b/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/BuildPluginPackage.props @@ -1,17 +1,23 @@ - - - true - - + true + - true - - true + true + + 2.5 + + false + + true \ No newline at end of file diff --git a/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/BuildPluginPackage.targets b/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/BuildPluginPackage.targets index 6f8f3bb04..b5d072ed9 100644 --- a/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/BuildPluginPackage.targets +++ b/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/BuildPluginPackage.targets @@ -1,7 +1,16 @@ - + + + true + + + + $(TargetsForTfmSpecificContentInPackage); - CreatePluginPackageBuildProps + PackCodeGenerationRoslynPlugin + + + $(PackCodeGenerationRoslynPluginDependsOn); + DefinePluginPackagePath; + CreatePluginPackageBuildProps; + Publish; + + + ValidatePluginPackageBuildProps;$(BeforePack) + + + tools/$(TargetFramework)/any + + + - + - - + ]]> @@ -36,23 +62,51 @@ - + + + + + + + + + + + - - + + + <_PackAsCgrPluginRequiresSingleTargetFrameworkMessage> + %24(TargetFramework.Equals('netcoreapp2.1')) + ]]> + + + \ No newline at end of file diff --git a/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/CodeGenerationRoslynReferences.props b/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/CodeGenerationRoslynReferences.props deleted file mode 100644 index ebb8aa6d0..000000000 --- a/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/CodeGenerationRoslynReferences.props +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/Sdk.props b/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/Sdk.props index d0f2d8415..a3da24110 100644 --- a/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/Sdk.props +++ b/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/Sdk.props @@ -4,22 +4,15 @@ true - - - true - - - $(MSBuildThisFileDirectory)CodeGenerationRoslynReferences.props - - + + - - - + \ No newline at end of file diff --git a/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/Sdk.targets b/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/Sdk.targets index 15affc0ba..3ce9423c7 100644 --- a/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/Sdk.targets +++ b/src/CodeGeneration.Roslyn.Plugin.Sdk/Sdk/Sdk.targets @@ -1,6 +1,22 @@ - + + + + + + + \ No newline at end of file diff --git a/src/CodeGeneration.Roslyn.Tests/CodeGeneration.Roslyn.Tests.csproj b/src/CodeGeneration.Roslyn.Tests/CodeGeneration.Roslyn.Tests.csproj index 17f957737..b8cca48e1 100644 --- a/src/CodeGeneration.Roslyn.Tests/CodeGeneration.Roslyn.Tests.csproj +++ b/src/CodeGeneration.Roslyn.Tests/CodeGeneration.Roslyn.Tests.csproj @@ -1,12 +1,12 @@  - + - netcoreapp2.1 - $(OutputPath)..\..\CodeGeneration.Roslyn.Tool\$(Configuration)\netcoreapp2.1\dotnet-codegen.dll + netcoreapp3.1 $(MSBuildWarningsAsMessages);CGR1002 + OverrideCodeGenToolPath;$(GenerateCodeFromAttributesDependsOn) @@ -28,10 +28,17 @@ OutputItemType="CodeGenerationRoslynPlugin" /> + + + + @(CodeGeneratorToolPathItem) + + - + diff --git a/src/CodeGeneration.Roslyn.Tool/CodeGeneration.Roslyn.Tool.csproj b/src/CodeGeneration.Roslyn.Tool/CodeGeneration.Roslyn.Tool.csproj index ec88a36b1..4d35aadbd 100644 --- a/src/CodeGeneration.Roslyn.Tool/CodeGeneration.Roslyn.Tool.csproj +++ b/src/CodeGeneration.Roslyn.Tool/CodeGeneration.Roslyn.Tool.csproj @@ -1,18 +1,43 @@  - DotnetCliTool Exe netcoreapp2.1 - dotnet-codegen The dotnet code generation tool that works with the CodeGeneration.Roslyn nuget package. CodeGeneration.Roslyn.Tool.ruleset - $(NoWarn);CS1591 + Major + + $(NoWarn);CS1591 + + $(NoWarn);NU5129 + + true + + 2.5 + + false + + true + + + PackCustomTool;$(TargetsForTfmSpecificContentInPackage) + + tools/any - + + true + build/ + PreserveNewest + True True @@ -32,4 +57,50 @@ + + + + + + + + + + + + + + + + + + + %24(MSBuildThisFileDirectory)../$(PackPublishedContentPath)/$(TargetFileName) + + + +]]> + + $(IntermediateOutputPath)ToolPath.props + + + + + + + + \ No newline at end of file diff --git a/src/CodeGeneration.Roslyn.Tool/build/CodeGeneration.Roslyn.Tool.props b/src/CodeGeneration.Roslyn.Tool/build/CodeGeneration.Roslyn.Tool.props new file mode 100644 index 000000000..6972a5f7e --- /dev/null +++ b/src/CodeGeneration.Roslyn.Tool/build/CodeGeneration.Roslyn.Tool.props @@ -0,0 +1,12 @@ + + + + + + MSBuild:GenerateCodeFromAttributes + + + + + + \ No newline at end of file diff --git a/src/CodeGeneration.Roslyn.Tool/build/CodeGeneration.Roslyn.Tool.targets b/src/CodeGeneration.Roslyn.Tool/build/CodeGeneration.Roslyn.Tool.targets new file mode 100644 index 000000000..34a6855d8 --- /dev/null +++ b/src/CodeGeneration.Roslyn.Tool/build/CodeGeneration.Roslyn.Tool.targets @@ -0,0 +1,130 @@ + + + + + + $(GenerateCodeFromAttributesDependsOn); + ResolveReferences; + PrepareGenerateCodeFromAttributes; + GenerateCodeFromAttributesCore; + ReadGenerateCodeFromAttributesResults + + https://github.com/AArnott/CodeGeneration.Roslyn + + + + + + + + <_CodeGenToolInputs_Compile + Include="@(Compile)" + Condition=" '%(Compile.Generator)' == 'MSBuild:GenerateCodeFromAttributes' " /> + <_CodeGenToolInputs_DefineConstants Include="$(DefineConstants)" /> + + + <_GeneratorAssemblySearchPathsResolved + Include="%(GeneratorAssemblySearchPaths.PathWithTrailingSlash)*.dll" /> + + + + + + + $(GenerateCodeFromAttributesToolPathOverride) + $(CodeGenerationRoslynToolPath.Trim()) + <_CodeGenToolOutputBasePath>$(IntermediateOutputPath)$(MSBuildProjectFile).dotnet-codegen + <_CodeGenToolResponseFileFullPath>$(_CodeGenToolOutputBasePath).rsp + <_CodeGenToolGeneratedFileListFullPath>$(_CodeGenToolOutputBasePath).GeneratedFileList.txt + <_CodeGenToolResponseFileLines> + @(ReferencePath->'-r;%(Identity)'); + @(_CodeGenToolInputs_DefineConstants->'-d;%(Identity)'); + @(CodeGenerationRoslynPlugin->'--plugin;%(Identity)'); + --out; + $(IntermediateOutputPath); + --projectDir; + $(MSBuildProjectDirectory); + --generatedFilesList; + $(_CodeGenToolGeneratedFileListFullPath); + --; + @(_CodeGenToolInputs_Compile) + + <_CodeGenToolVersionOutput>(n/a) + <_CodeGenToolVersionExitCode> + + + <_CodeGenToolResponseFileContent Include="$(_CodeGenToolResponseFileLines)" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/CodeGeneration.Roslyn.Tool/prefercliruntime b/src/CodeGeneration.Roslyn.Tool/prefercliruntime deleted file mode 100644 index 5f282702b..000000000 --- a/src/CodeGeneration.Roslyn.Tool/prefercliruntime +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/CodeGeneration.Roslyn.sln b/src/CodeGeneration.Roslyn.sln index d1d7459b3..501a30a1e 100644 --- a/src/CodeGeneration.Roslyn.sln +++ b/src/CodeGeneration.Roslyn.sln @@ -22,8 +22,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeGeneration.Roslyn.Attri EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeGeneration.Roslyn", "CodeGeneration.Roslyn\CodeGeneration.Roslyn.csproj", "{09465031-08F8-4632-9C26-AC561B6E3538}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeGeneration.Roslyn.BuildTime", "CodeGeneration.Roslyn.BuildTime\CodeGeneration.Roslyn.BuildTime.csproj", "{D5240C82-6F90-48F8-9192-DA53EE1B0355}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeGeneration.Roslyn.Tests", "CodeGeneration.Roslyn.Tests\CodeGeneration.Roslyn.Tests.csproj", "{D8E7323F-6721-42A5-BADA-496A63DB0A88}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeGeneration.Roslyn.Tests.Generators", "CodeGeneration.Roslyn.Tests.Generators\CodeGeneration.Roslyn.Tests.Generators.csproj", "{8B57E557-EF79-47E4-9396-135850304990}" @@ -56,10 +54,6 @@ Global {09465031-08F8-4632-9C26-AC561B6E3538}.Debug|Any CPU.Build.0 = Debug|Any CPU {09465031-08F8-4632-9C26-AC561B6E3538}.Release|Any CPU.ActiveCfg = Release|Any CPU {09465031-08F8-4632-9C26-AC561B6E3538}.Release|Any CPU.Build.0 = Release|Any CPU - {D5240C82-6F90-48F8-9192-DA53EE1B0355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D5240C82-6F90-48F8-9192-DA53EE1B0355}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D5240C82-6F90-48F8-9192-DA53EE1B0355}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D5240C82-6F90-48F8-9192-DA53EE1B0355}.Release|Any CPU.Build.0 = Release|Any CPU {D8E7323F-6721-42A5-BADA-496A63DB0A88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D8E7323F-6721-42A5-BADA-496A63DB0A88}.Debug|Any CPU.Build.0 = Debug|Any CPU {D8E7323F-6721-42A5-BADA-496A63DB0A88}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -95,7 +89,6 @@ Global GlobalSection(NestedProjects) = preSolution {0E3F218E-0B47-4925-8FDB-8A8BC4C01DCD} = {654F1532-27EE-4854-B0EC-45F9075FF968} {09465031-08F8-4632-9C26-AC561B6E3538} = {654F1532-27EE-4854-B0EC-45F9075FF968} - {D5240C82-6F90-48F8-9192-DA53EE1B0355} = {654F1532-27EE-4854-B0EC-45F9075FF968} {D8E7323F-6721-42A5-BADA-496A63DB0A88} = {D753E49D-90A8-40AF-918F-21BCDB296D1D} {8B57E557-EF79-47E4-9396-135850304990} = {D753E49D-90A8-40AF-918F-21BCDB296D1D} {3162A2B3-5FEF-454C-AB50-A103883CC2F4} = {D753E49D-90A8-40AF-918F-21BCDB296D1D}