Skip to content
Merged
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
25 changes: 0 additions & 25 deletions src/GeneratorExtension.cs

This file was deleted.

17 changes: 0 additions & 17 deletions src/IsExternalInit.cs

This file was deleted.

69 changes: 48 additions & 21 deletions src/ThisAssembly.AssemblyInfo/AssemblyInfoGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Scriban;

namespace ThisAssembly
{
[Generator]
public class AssemblyInfoGenerator : ISourceGenerator
public class AssemblyInfoGenerator : IIncrementalGenerator
{
readonly HashSet<string> attributes = new HashSet<string>(new[]
static readonly HashSet<string> attributes = new()
{
nameof(AssemblyConfigurationAttribute),
nameof(AssemblyCompanyAttribute),
Expand All @@ -21,35 +25,58 @@ public class AssemblyInfoGenerator : ISourceGenerator
nameof(AssemblyVersionAttribute),
nameof(AssemblyInformationalVersionAttribute),
nameof(AssemblyFileVersionAttribute),
});
};

public void Initialize(GeneratorInitializationContext context) { }
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var metadata = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (s, _) => s is AttributeSyntax,
transform: static (ctx, token) => GetSemanticTargetForGeneration(ctx, token))
.Where(static m => m is not null)
.Select(static (m, _) => m!.Value)
.Collect();

context.RegisterSourceOutput(
metadata.Combine(context.CompilationProvider.Select((s, _) => s.Language)),
GenerateSource);
}

public void Execute(GeneratorExecutionContext context)
static KeyValuePair<string, string>? GetSemanticTargetForGeneration(GeneratorSyntaxContext ctx, CancellationToken token)
{
context.CheckDebugger("ThisAssemblyAssemblyInfo");
var attributeNode = (AttributeSyntax)ctx.Node;

var metadata = context.Compilation.Assembly.GetAttributes()
.Where(x => !string.IsNullOrEmpty(x.AttributeClass?.Name) && attributes.Contains(x.AttributeClass!.Name))
.Where(x => x.ConstructorArguments.Length == 1)
.Select(x => new KeyValuePair<string, string?>(x.AttributeClass!.Name.Substring(8).Replace("Attribute", ""), (string?)x.ConstructorArguments[0].Value))
.Distinct(new KeyPairComparer())
.ToDictionary(x => x.Key, x => x.Value ?? "");
if (attributeNode.ArgumentList?.Arguments.Count != 1)
return null;

var model = new Model(metadata);
var language = context.ParseOptions.Language;
var file = language.Replace("#", "Sharp") + ".sbntxt";
var template = Template.Parse(EmbeddedResource.GetContent(file), file);
var output = template.Render(model, member => member.Name);
if (ctx.SemanticModel.GetSymbolInfo(attributeNode, token).Symbol is not IMethodSymbol ctor)
return null;

context.AddSource("ThisAssembly.Info", SourceText.From(output, Encoding.UTF8));
var attributeType = ctor.ContainingType;
if (attributeType == null)
return null;

if (!attributes.Contains(attributeType.Name))
return null;

var key = attributeType.Name[8..^9];
var expr = attributeNode.ArgumentList!.Arguments[0].Expression;
var value = ctx.SemanticModel.GetConstantValue(expr, token).ToString();
return new KeyValuePair<string, string>(key, value);
}

class KeyPairComparer : IEqualityComparer<KeyValuePair<string, string?>>
static void GenerateSource(SourceProductionContext spc, (ImmutableArray<KeyValuePair<string, string>> attributes, string language) arg2)
{
public bool Equals(KeyValuePair<string, string?> x, KeyValuePair<string, string?> y) => x.Key == y.Key;
var (attributes, language) = arg2;

var model = new Model(attributes.ToList());
var file = language.Replace("#", "Sharp") + ".sbntxt";
var template = Template.Parse(EmbeddedResource.GetContent(file), file);
var output = template.Render(model, member => member.Name);

public int GetHashCode(KeyValuePair<string, string?> obj) => obj.Key.GetHashCode();
spc.AddSource(
"ThisAssembly.AssemblyInfo.g.cs",
SourceText.From(output, Encoding.UTF8));
}
}
}
24 changes: 0 additions & 24 deletions src/ThisAssembly.AssemblyInfo/FSharp.sbntxt

This file was deleted.

8 changes: 8 additions & 0 deletions src/ThisAssembly.AssemblyInfo/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"profiles": {
"ThisAssembly.AssemblyInfo": {
"commandName": "DebugRoslynComponent",
"targetProject": "..\\ThisAssembly.Tests\\ThisAssembly.Tests.csproj"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<IsRoslynComponent>true</IsRoslynComponent>
</PropertyGroup>

<PropertyGroup>
<PackageId>ThisAssembly.AssemblyInfo</PackageId>
<Description>** C# 9.0 ONLY **
<Description>** C# 9.0+ ONLY **
This package generates a static `ThisAssembly.Info` class with public
constants exposing the following attribute values generated by default for SDK style projects:

Expand All @@ -29,10 +31,11 @@ on the `ThisAssembly.Info` class.
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />

<PackageReference Include="Scriban" Version="5.5.0" Pack="false" IncludeAssets="build" />
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />

<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" Pack="false" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" Pack="false" />
<PackageReference Include="PolySharp" Version="1.7.1" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
Expand Down
49 changes: 27 additions & 22 deletions src/ThisAssembly.Constants/ConstantsGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
Expand All @@ -9,32 +10,35 @@
namespace ThisAssembly
{
[Generator]
public class ConstantsGenerator : ISourceGenerator
public class ConstantsGenerator : IIncrementalGenerator
{
public void Initialize(GeneratorInitializationContext context) { }

public void Execute(GeneratorExecutionContext context)
public void Initialize(IncrementalGeneratorInitializationContext context)
{
context.CheckDebugger("ThisAssemblyConstants");
var files = context.AdditionalTextsProvider
.Combine(context.AnalyzerConfigOptionsProvider)
.Where(x =>
x.Right.GetOptions(x.Left).TryGetValue("build_metadata.AdditionalFiles.SourceItemType", out var itemType)
&& itemType == "Constant")
.Where(x => x.Right.GetOptions(x.Left).TryGetValue("build_metadata.Constant.Value", out var value) && value != null)
.Select((x, ct) =>
{
x.Right.GetOptions(x.Left).TryGetValue("build_metadata.Constant.Value", out var value);
x.Right.GetOptions(x.Left).TryGetValue("build_metadata.Constant.Comment", out var comment);
return (name: Path.GetFileName(x.Left.Path), value: value!, comment: string.IsNullOrWhiteSpace(comment) ? null : comment);
})
.Combine(context.CompilationProvider.Select((p, _) => p.Language));

var constantFiles = context.AdditionalFiles
.Where(f => context.AnalyzerConfigOptions
.GetOptions(f)
.TryGetValue("build_metadata.AdditionalFiles.SourceItemType", out var itemType)
&& itemType == "Constant");
context.RegisterSourceOutput(
files,
GenerateConstant);

if (!constantFiles.Any())
return;
}

var pairs = constantFiles.Select(f =>
{
context.AnalyzerConfigOptions.GetOptions(f).TryGetValue("build_metadata.Constant.Value", out var value);
context.AnalyzerConfigOptions.GetOptions(f).TryGetValue("build_metadata.Constant.Comment", out var comment);
return new Constant(Path.GetFileName(f.Path), value, string.IsNullOrWhiteSpace(comment) ? null : comment);
}).Where(x => x.Value != null).ToList();
void GenerateConstant(SourceProductionContext spc, ((string name, string value, string? comment), string language) arg2)
{
var ((name, value, comment), language) = arg2;

var root = Area.Load(pairs);
var language = context.ParseOptions.Language;
var root = Area.Load(new List<Constant> { new Constant(name, value, comment), });
var file = language.Replace("#", "Sharp") + ".sbntxt";
var template = Template.Parse(EmbeddedResource.GetContent(file), file);
var output = template.Render(new Model(root), member => member.Name);
Expand All @@ -56,7 +60,8 @@ public void Execute(GeneratorExecutionContext context)
// .ToString();
//}

context.AddSource("ThisAssembly.Constants", SourceText.From(output, Encoding.UTF8));
spc.AddSource($"{name}.g.cs", SourceText.From(output, Encoding.UTF8));

}
}
}
8 changes: 8 additions & 0 deletions src/ThisAssembly.Constants/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"profiles": {
"ThisAssembly.Constants": {
"commandName": "DebugRoslynComponent",
"targetProject": "..\\ThisAssembly.Tests\\ThisAssembly.Tests.csproj"
}
}
}
9 changes: 6 additions & 3 deletions src/ThisAssembly.Constants/ThisAssembly.Constants.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<IsRoslynComponent>true</IsRoslynComponent>
</PropertyGroup>

<PropertyGroup>
<PackageId>ThisAssembly.Constants</PackageId>
<Description>** C# 9.0 ONLY **
<Description>** C# 9.0+ ONLY **
This package generates a static `ThisAssembly.Constants` class with public
constants for each Constant MSBuild item in the project.

Expand Down Expand Up @@ -49,10 +51,11 @@ C#:
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />

<PackageReference Include="Scriban" Version="5.5.0" Pack="false" IncludeAssets="build" />
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />

<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" Pack="false" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" Pack="false" />
<PackageReference Include="PolySharp" Version="1.7.1" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
Expand Down
24 changes: 0 additions & 24 deletions src/ThisAssembly.Metadata/FSharp.sbntxt

This file was deleted.

Loading