Skip to content

Commit

Permalink
prefer ForAttributeWithMetadataName
Browse files Browse the repository at this point in the history
  • Loading branch information
fforjan committed Dec 6, 2024
1 parent 93690e0 commit 881ea83
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 55 deletions.
89 changes: 34 additions & 55 deletions GitLinkGenerator/GitPathGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,77 +33,56 @@ internal sealed class GitPathAttribute : Attribute
var gitInfo = context.AnalyzerConfigOptionsProvider.
Select ( extraGitInfo);

var classDeclarations = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (s, _) => IsClassWithAttributes(s),
transform: static (ctx, _) => GetSemanticTargetForGeneration(ctx))
.Where(static m => m is not null);

var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect());

context.RegisterSourceOutput(compilationAndClasses.Combine(gitInfo), static (spc, source) => Execute(source.Left.Left, source.Left.Right, source.Right, spc));
}
private static (string repository, string branch, string projectUrl)? extraGitInfo(AnalyzerConfigOptionsProvider provider, CancellationToken token)
{
if(provider.GlobalOptions.TryGetValue("build_property.GitRootDirectory", out var repository)
&& provider.GlobalOptions.TryGetValue("build_property.GitBranch", out var branch)
&& provider.GlobalOptions.TryGetValue("build_property.PackageProjectUrl", out var projectUrl))
{
return (repository, branch, projectUrl);
}

return null;
}

private static bool IsClassWithAttributes(SyntaxNode node)
{
return node is ClassDeclarationSyntax classDeclarationSyntax && classDeclarationSyntax.AttributeLists.Count > 0;
}

private static ClassDeclarationSyntax GetSemanticTargetForGeneration(GeneratorSyntaxContext context)
{
var classDeclarationSyntax = (ClassDeclarationSyntax)context.Node;
return classDeclarationSyntax;
}

private static void Execute(Compilation compilation, ImmutableArray<ClassDeclarationSyntax> classes, (string repository,string branch, string projectUrl)? gitInfo, SourceProductionContext context)
{
if (classes.IsDefaultOrEmpty)
return;

var attributeSymbol = compilation.GetTypeByMetadataName("GitPathGenerator.GitPathAttribute");
if (attributeSymbol == null)
return;
var pipeline = context.SyntaxProvider.ForAttributeWithMetadataName(
fullyQualifiedMetadataName: "GitPathGenerator.GitPathAttribute",
predicate: static (syntaxNode, cancellationToken) => syntaxNode is ClassDeclarationSyntax,
transform: static (context, cancellationToken) =>
{
return new Model(
// Note: this is a simplified example. You will also need to handle the case where the type is in a global namespace, nested, etc.
Namespace: context.TargetSymbol.ContainingNamespace?.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat.WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted)),
ClassName: context.TargetSymbol.Name,
FilePath: context.TargetNode.SyntaxTree.FilePath);
}
);

foreach (var classDeclaration in classes)
context.RegisterSourceOutput(pipeline.Combine(gitInfo), static (context, args) =>
{
var model = compilation.GetSemanticModel(classDeclaration.SyntaxTree);
var classSymbol = model.GetDeclaredSymbol(classDeclaration);

var attributeData = classSymbol.GetAttributes().FirstOrDefault(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default));
if (attributeData != null)
{
var gitInfo = args.Right;
var model = args.Left;
string? filePath = null;

if(GitHubGenerator.IsGitHub(gitInfo.Value.projectUrl))

Check warning on line 55 in GitLinkGenerator/GitPathGenerator.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Nullable value type may be null.

Check warning on line 55 in GitLinkGenerator/GitPathGenerator.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Nullable value type may be null.

Check warning on line 55 in GitLinkGenerator/GitPathGenerator.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest)

Nullable value type may be null.
{
filePath = GitHubGenerator.GitHubGeneratePath(classDeclaration.SyntaxTree.FilePath, gitInfo.Value.projectUrl, gitInfo.Value.branch, gitInfo.Value.repository);
filePath = GitHubGenerator.GitHubGeneratePath(model.FilePath, gitInfo.Value.projectUrl, gitInfo.Value.branch, gitInfo.Value.repository);
}


if(filePath != null) {
var source = $@"
namespace {classSymbol.ContainingNamespace.ToDisplayString()}
namespace {model.Namespace}
{{
public partial class {classSymbol.Name}
public partial class {model.ClassName}
{{
public const string GitPath = ""{filePath}"";
}}
}}";

context.AddSource($"{classSymbol.Name}_GitPath.cs", SourceText.From(source, Encoding.UTF8));
context.AddSource($"{model.ClassName}_GitPath.cs", SourceText.From(source, Encoding.UTF8));
}
}
});
}

private record Model(string? Namespace, string ClassName, string FilePath);

private static (string repository, string branch, string projectUrl)? extraGitInfo(AnalyzerConfigOptionsProvider provider, CancellationToken token)
{
if(provider.GlobalOptions.TryGetValue("build_property.GitRootDirectory", out var repository)
&& provider.GlobalOptions.TryGetValue("build_property.GitBranch", out var branch)
&& provider.GlobalOptions.TryGetValue("build_property.PackageProjectUrl", out var projectUrl))
{
return (repository, branch, projectUrl);
}

return null;
}
}
}
5 changes: 5 additions & 0 deletions GitLinkGenerator/IsExternalInit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

namespace System.Runtime.CompilerServices
{
internal static class IsExternalInit {}
}

0 comments on commit 881ea83

Please sign in to comment.