Browse Source

Avoid reparse source in codegen stage

pull/7935/head
Steven He 5 years ago
parent
commit
d7a098b75e
  1. 30
      src/Avalonia.SourceGenerator/SubtypesFactoryGenerator.cs

30
src/Avalonia.SourceGenerator/SubtypesFactoryGenerator.cs

@ -11,7 +11,7 @@ namespace Avalonia.SourceGenerator
[Generator(LanguageNames.CSharp)] [Generator(LanguageNames.CSharp)]
public class SubtypesFactoryGenerator : IIncrementalGenerator public class SubtypesFactoryGenerator : IIncrementalGenerator
{ {
private record struct MethodTarget(IMethodSymbol Method, ITypeSymbol BaseType, string Namespace); private record struct MethodTarget(IMethodSymbol Method, string MethodDecl, ITypeSymbol BaseType, string Namespace);
private static readonly string s_attributeName = typeof(SubtypesFactoryAttribute).FullName; private static readonly string s_attributeName = typeof(SubtypesFactoryAttribute).FullName;
private static bool IsSubtypeOf(ITypeSymbol type, ITypeSymbol baseType) private static bool IsSubtypeOf(ITypeSymbol type, ITypeSymbol baseType)
@ -21,26 +21,12 @@ namespace Avalonia.SourceGenerator
private static void GenerateSubTypes(SourceProductionContext context, MethodTarget methodTarget, ImmutableArray<ITypeSymbol> types) private static void GenerateSubTypes(SourceProductionContext context, MethodTarget methodTarget, ImmutableArray<ITypeSymbol> types)
{ {
var (method, baseType, @namespace) = methodTarget; var (method, methodDecl, baseType, @namespace) = methodTarget;
var candidateTypes = types.Where(i => IsSubtypeOf(i, baseType)).Where(i => $"{i.ContainingNamespace}.".StartsWith($"{@namespace}.")).ToArray(); var candidateTypes = types.Where(i => IsSubtypeOf(i, baseType)).Where(i => $"{i.ContainingNamespace}.".StartsWith($"{@namespace}.")).ToArray();
var type = method.ContainingType; var type = method.ContainingType;
var isGeneric = type.TypeParameters.Length > 0; var isGeneric = type.TypeParameters.Length > 0;
var isClass = type.TypeKind == TypeKind.Class; var isClass = type.TypeKind == TypeKind.Class;
if (method.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() is not MethodDeclarationSyntax methodDecl)
{
return;
}
var parameters = new SeparatedSyntaxList<ParameterSyntax>().AddRange(methodDecl.ParameterList.Parameters.Select(i => i.WithAttributeLists(new SyntaxList<AttributeListSyntax>())));
var methodDeclText = methodDecl
.WithAttributeLists(new SyntaxList<AttributeListSyntax>())
.WithParameterList(methodDecl.ParameterList.WithParameters(parameters))
.WithBody(null)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None))
.WithoutTrivia().ToString();
var typeDecl = $"partial {(isClass ? "class" : "struct")} {type.Name}{(isGeneric ? $"<{string.Join(", ", type.TypeParameters)}>" : "")}"; var typeDecl = $"partial {(isClass ? "class" : "struct")} {type.Name}{(isGeneric ? $"<{string.Join(", ", type.TypeParameters)}>" : "")}";
var source = $@"using System; var source = $@"using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -49,7 +35,7 @@ namespace {method.ContainingNamespace}
{{ {{
{typeDecl} {typeDecl}
{{ {{
{methodDeclText} {methodDecl}
{{ {{
var hasMatch = false; var hasMatch = false;
(hasMatch, {method.Parameters[1].Name}) = {method.Parameters[0].Name} switch (hasMatch, {method.Parameters[1].Name}) = {method.Parameters[0].Name} switch
@ -109,7 +95,15 @@ namespace {method.ContainingNamespace}
continue; continue;
} }
return new MethodTarget(methodSymbol, baseType, nsValue); var parameters = new SeparatedSyntaxList<ParameterSyntax>().AddRange(method.ParameterList.Parameters.Select(i => i.WithAttributeLists(new SyntaxList<AttributeListSyntax>())));
var methodDecl = method
.WithAttributeLists(new SyntaxList<AttributeListSyntax>())
.WithParameterList(method.ParameterList.WithParameters(parameters))
.WithBody(null)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None))
.WithoutTrivia().ToString();
return new MethodTarget(methodSymbol, methodDecl, baseType, nsValue);
} }
} }

Loading…
Cancel
Save