Skip to content

Commit

Permalink
Use global usings and file scoped namespaces.
Browse files Browse the repository at this point in the history
  • Loading branch information
AraHaan committed Jan 13, 2022
1 parent de25f59 commit d5beac0
Show file tree
Hide file tree
Showing 14 changed files with 453 additions and 486 deletions.
11 changes: 10 additions & 1 deletion src/GitBuildInfo.SourceGenerator/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>true</IsPackable>
<Version>1.0.15</Version>
<PackageReleaseNotes>Fixed bug where the git information is not properly obtained and the head information was not properly dumped to the right file name.</PackageReleaseNotes>
<Copyright>Copyright (c) 2021</Copyright>
<Copyright>Copyright (c) 2021-2022</Copyright>
<!-- Suppresses the warnings about the package not having assemblies in lib/*/.dll.-->
<NoPackageAnalysis>true</NoPackageAnalysis>
<!-- Special properties for analyzer packages. -->
Expand All @@ -14,6 +15,7 @@
<NoWarn>$(NoWarn);NU5128;NU5127</NoWarn>
<NuSpecFile>GitBuildInfo.SourceGenerator.nuspec</NuSpecFile>
<IsRoslynComponent>true</IsRoslynComponent>
<NoWarn>RS2003</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand All @@ -26,6 +28,13 @@
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>$(AssemblyName).Tests</_Parameter1> <!-- We use the value of AssemblyName to declare the value of the attribute -->
</AssemblyAttribute>
<Using Include="System.Runtime.CompilerServices" />
<Using Include="System.Text" />
<!-- Required dotnet/roslyn usings. -->
<Using Include="Microsoft.CodeAnalysis" />
<Using Include="Microsoft.CodeAnalysis.CSharp" />
<Using Include="Microsoft.CodeAnalysis.CSharp.Syntax" />
<Using Include="Microsoft.CodeAnalysis.Text" />
</ItemGroup>

<Import Project="../../Directory.Build.props" />
Expand Down
1 change: 0 additions & 1 deletion src/GitBuildInfo.SourceGenerator/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="*-*" />
<PackageReference Include="IsExternalInit" Version="*-*" />
</ItemGroup>

</Project>
285 changes: 139 additions & 146 deletions src/GitBuildInfo.SourceGenerator/Generator.cs
Original file line number Diff line number Diff line change
@@ -1,86 +1,52 @@
namespace GitBuildInfo.SourceGenerator
namespace GitBuildInfo.SourceGenerator;

internal class Generator
{
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
private readonly GeneratorOptions options;
private readonly GitInfo gitInfo;

internal class Generator
private Generator(GeneratorOptions options, GitInfo gitInfo)
{
private readonly GeneratorOptions options;
private readonly GitInfo gitInfo;

private Generator(GeneratorOptions options, GitInfo gitInfo)
{
this.options = options;
this.gitInfo = gitInfo;
}
this.options = options;
this.gitInfo = gitInfo;
}

public static string CreateAndGenerateCode(GeneratorOptions options, GitInfo gitInfo, GeneratorExecutionContext context)
public static string CreateAndGenerateCode(GeneratorOptions options, GitInfo gitInfo, GeneratorExecutionContext context)
{
try
{
try
var generator = Create(options, gitInfo, context);
if (generator.options.IsCSharp10OrGreater)
{
var generator = Create(options, gitInfo, context);
if (generator.options.IsCSharp10OrGreater)
{
return generator.GenerateCodeCSharp10(generator.options.AssemblyType).ToFullString();
}

return generator.GenerateCodeCSharp9(
string.IsNullOrEmpty(generator.options.RootNamespace) ? Array.Empty<string>() : generator.options.RootNamespace.Split('.'),
"Elskom.Generic.Libs",
generator.options.AssemblyType).ToFullString();
return generator.GenerateCodeCSharp10(generator.options.AssemblyType).ToFullString();
}
catch (InvalidOperationException)
{
return string.Empty;
}
}

public CompilationUnitSyntax GenerateCodeCSharp9(string[] usings, string originalnamespace, string typeName)
=> SyntaxFactory.CompilationUnit().WithUsings(
SyntaxFactory.List(
string.Equals(string.Join(".", usings), originalnamespace, StringComparison.Ordinal) ||
usings.Length is 0
? new[]
{
AddUsing(new[] {"Elskom", "Generic", "Libs"}, true)
}
: new[]
{
AddUsing(new[] {"Elskom", "Generic", "Libs"}, true),
AddUsing(usings, false)
}))
.WithAttributeLists(
SyntaxFactory.SingletonList(
SyntaxFactory.AttributeList(
SyntaxFactory.SingletonSeparatedList(
SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("GitInformationAttribute"))
.WithArgumentList(
SyntaxFactory.AttributeArgumentList(
SyntaxFactory.SeparatedList<AttributeArgumentSyntax>(
this.MakeAttributeArgumentList(typeName))))))
.WithOpenBracketToken(
SyntaxFactory.Token(
SyntaxFactory.TriviaList(SyntaxFactory.LineFeed),
SyntaxKind.OpenBracketToken,
SyntaxFactory.TriviaList()))
.WithTarget(
SyntaxFactory.AttributeTargetSpecifier(SyntaxFactory.Token(SyntaxKind.AssemblyKeyword))
.WithColonToken(
SyntaxFactory.Token(
SyntaxFactory.TriviaList(),
SyntaxKind.ColonToken,
SyntaxFactory.TriviaList(SyntaxFactory.Space))))
.WithCloseBracketToken(
SyntaxFactory.Token(
SyntaxFactory.TriviaList(),
SyntaxKind.CloseBracketToken,
SyntaxFactory.TriviaList(SyntaxFactory.LineFeed)))));
return generator.GenerateCodeCSharp9(
string.IsNullOrEmpty(generator.options.RootNamespace) ? Array.Empty<string>() : generator.options.RootNamespace.Split('.'),
"Elskom.Generic.Libs",
generator.options.AssemblyType).ToFullString();
}
catch (InvalidOperationException)
{
return string.Empty;
}
}

public CompilationUnitSyntax GenerateCodeCSharp10(string typeName)
=> SyntaxFactory.CompilationUnit().WithAttributeLists(
public CompilationUnitSyntax GenerateCodeCSharp9(string[] usings, string originalnamespace, string typeName)
=> SyntaxFactory.CompilationUnit().WithUsings(
SyntaxFactory.List(
string.Equals(string.Join(".", usings), originalnamespace, StringComparison.Ordinal) ||
usings.Length is 0
? new[]
{
AddUsing(new[] {"Elskom", "Generic", "Libs"}, true)
}
: new[]
{
AddUsing(new[] {"Elskom", "Generic", "Libs"}, true),
AddUsing(usings, false)
}))
.WithAttributeLists(
SyntaxFactory.SingletonList(
SyntaxFactory.AttributeList(
SyntaxFactory.SingletonSeparatedList(
Expand All @@ -91,10 +57,7 @@ public CompilationUnitSyntax GenerateCodeCSharp10(string typeName)
this.MakeAttributeArgumentList(typeName))))))
.WithOpenBracketToken(
SyntaxFactory.Token(
SyntaxFactory.TriviaList(
SyntaxFactory.Comment("// <autogenerated/>"),
SyntaxFactory.LineFeed,
SyntaxFactory.LineFeed),
SyntaxFactory.TriviaList(SyntaxFactory.LineFeed),
SyntaxKind.OpenBracketToken,
SyntaxFactory.TriviaList()))
.WithTarget(
Expand All @@ -110,83 +73,113 @@ public CompilationUnitSyntax GenerateCodeCSharp10(string typeName)
SyntaxKind.CloseBracketToken,
SyntaxFactory.TriviaList(SyntaxFactory.LineFeed)))));

private static Generator Create(GeneratorOptions options, GitInfo gitInfo, GeneratorExecutionContext context)
{
var generator = new Generator(options, gitInfo);
generator.options.Validate(context);
return generator;
}
public CompilationUnitSyntax GenerateCodeCSharp10(string typeName)
=> SyntaxFactory.CompilationUnit().WithAttributeLists(
SyntaxFactory.SingletonList(
SyntaxFactory.AttributeList(
SyntaxFactory.SingletonSeparatedList(
SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("GitInformationAttribute"))
.WithArgumentList(
SyntaxFactory.AttributeArgumentList(
SyntaxFactory.SeparatedList<AttributeArgumentSyntax>(
this.MakeAttributeArgumentList(typeName))))))
.WithOpenBracketToken(
SyntaxFactory.Token(
SyntaxFactory.TriviaList(
SyntaxFactory.Comment("// <autogenerated/>"),
SyntaxFactory.LineFeed,
SyntaxFactory.LineFeed),
SyntaxKind.OpenBracketToken,
SyntaxFactory.TriviaList()))
.WithTarget(
SyntaxFactory.AttributeTargetSpecifier(SyntaxFactory.Token(SyntaxKind.AssemblyKeyword))
.WithColonToken(
SyntaxFactory.Token(
SyntaxFactory.TriviaList(),
SyntaxKind.ColonToken,
SyntaxFactory.TriviaList(SyntaxFactory.Space))))
.WithCloseBracketToken(
SyntaxFactory.Token(
SyntaxFactory.TriviaList(),
SyntaxKind.CloseBracketToken,
SyntaxFactory.TriviaList(SyntaxFactory.LineFeed)))));

private static Generator Create(GeneratorOptions options, GitInfo gitInfo, GeneratorExecutionContext context)
{
var generator = new Generator(options, gitInfo);
generator.options.Validate(context);
return generator;
}

private static UsingDirectiveSyntax AddUsing(string[] strings, bool autogeneratedheader)
private static UsingDirectiveSyntax AddUsing(string[] strings, bool autogeneratedheader)
{
NameSyntax qualifiedName = null;
List<string> strs = new();
foreach (var str in strings)
{
NameSyntax qualifiedName = null;
List<string> strs = new();
foreach (var str in strings)
// avoid regressions here.
if (strs.Contains(str))
{
// avoid regressions here.
if (strs.Contains(str))
{
continue;
}

qualifiedName = strings.Length > 1 && str == strings[0]
? SyntaxFactory.QualifiedName(
SyntaxFactory.IdentifierName(str),
SyntaxFactory.IdentifierName(strings[Array.IndexOf(strings, str) + 1]))
: strings.Length is 1
? SyntaxFactory.IdentifierName(str)
: SyntaxFactory.QualifiedName(qualifiedName!, SyntaxFactory.IdentifierName(str));
strs.Add(str);
if (strings.Length > 1 && str == strings[0])
{
strs.Add(strings[Array.IndexOf(strings, str) + 1]);
}
continue;
}

strs.Clear();
return SyntaxFactory.UsingDirective(qualifiedName!)
.WithUsingKeyword(SyntaxFactory.Token(
SyntaxFactory.TriviaList(autogeneratedheader
? new[] {SyntaxFactory.Comment("// <autogenerated/>"), SyntaxFactory.LineFeed}
: Array.Empty<SyntaxTrivia>()),
SyntaxKind.UsingKeyword,
SyntaxFactory.TriviaList(SyntaxFactory.Space)))
.WithSemicolonToken(SyntaxFactory.Token(
SyntaxFactory.TriviaList(),
SyntaxKind.SemicolonToken,
SyntaxFactory.TriviaList(SyntaxFactory.LineFeed)));
}

private SyntaxNodeOrToken[] MakeAttributeArgumentList(string typeName)
{
var lst = new SyntaxNodeOrToken[7];
var args = new[]
{
this.gitInfo.GitHead,
this.gitInfo.CommitHash,
this.gitInfo.GitBranch
};
var lstIndex = 0;
foreach (var arg in args)
qualifiedName = strings.Length > 1 && str == strings[0]
? SyntaxFactory.QualifiedName(
SyntaxFactory.IdentifierName(str),
SyntaxFactory.IdentifierName(strings[Array.IndexOf(strings, str) + 1]))
: strings.Length is 1
? SyntaxFactory.IdentifierName(str)
: SyntaxFactory.QualifiedName(qualifiedName!, SyntaxFactory.IdentifierName(str));
strs.Add(str);
if (strings.Length > 1 && str == strings[0])
{
lst[lstIndex] = SyntaxFactory.AttributeArgument(
SyntaxFactory.LiteralExpression(
SyntaxKind.StringLiteralExpression,
SyntaxFactory.Literal(arg)));
lstIndex++;
lst[lstIndex] = SyntaxFactory.Token(
SyntaxFactory.TriviaList(),
SyntaxKind.CommaToken,
SyntaxFactory.TriviaList(SyntaxFactory.Space));
lstIndex++;
strs.Add(strings[Array.IndexOf(strings, str) + 1]);
}
}

strs.Clear();
return SyntaxFactory.UsingDirective(qualifiedName!)
.WithUsingKeyword(SyntaxFactory.Token(
SyntaxFactory.TriviaList(autogeneratedheader
? new[] {SyntaxFactory.Comment("// <autogenerated/>"), SyntaxFactory.LineFeed}
: Array.Empty<SyntaxTrivia>()),
SyntaxKind.UsingKeyword,
SyntaxFactory.TriviaList(SyntaxFactory.Space)))
.WithSemicolonToken(SyntaxFactory.Token(
SyntaxFactory.TriviaList(),
SyntaxKind.SemicolonToken,
SyntaxFactory.TriviaList(SyntaxFactory.LineFeed)));
}

private SyntaxNodeOrToken[] MakeAttributeArgumentList(string typeName)
{
var lst = new SyntaxNodeOrToken[7];
var args = new[]
{
this.gitInfo.GitHead,
this.gitInfo.CommitHash,
this.gitInfo.GitBranch
};
var lstIndex = 0;
foreach (var arg in args)
{
lst[lstIndex] = SyntaxFactory.AttributeArgument(
SyntaxFactory.TypeOfExpression(
this.options.IsGeneric
? SyntaxFactory.GenericName(typeName)
: SyntaxFactory.IdentifierName(typeName)));
return lst;
SyntaxFactory.LiteralExpression(
SyntaxKind.StringLiteralExpression,
SyntaxFactory.Literal(arg)));
lstIndex++;
lst[lstIndex] = SyntaxFactory.Token(
SyntaxFactory.TriviaList(),
SyntaxKind.CommaToken,
SyntaxFactory.TriviaList(SyntaxFactory.Space));
lstIndex++;
}

lst[lstIndex] = SyntaxFactory.AttributeArgument(
SyntaxFactory.TypeOfExpression(
this.options.IsGeneric
? SyntaxFactory.GenericName(typeName)
: SyntaxFactory.IdentifierName(typeName)));
return lst;
}
}
Loading

0 comments on commit d5beac0

Please sign in to comment.