@@ -19,7 +19,7 @@ namespace StyleCop.Analyzers.CodeGeneration
1919 using Microsoft . CodeAnalysis . Text ;
2020
2121 [ Generator ]
22- internal sealed class SyntaxLightupGenerator : ISourceGenerator
22+ internal sealed class SyntaxLightupGenerator : IIncrementalGenerator
2323 {
2424 private enum NodeKind
2525 {
@@ -28,33 +28,37 @@ private enum NodeKind
2828 Concrete ,
2929 }
3030
31- public void Initialize ( GeneratorInitializationContext context )
31+ public void Initialize ( IncrementalGeneratorInitializationContext context )
3232 {
33+ var compilation = context . CompilationProvider ;
34+ var syntaxFiles = context . AdditionalTextsProvider . Where ( static x => Path . GetFileName ( x . Path ) == "Syntax.xml" ) ;
35+ context . RegisterSourceOutput (
36+ syntaxFiles . Combine ( compilation ) ,
37+ ( context , value ) => this . Execute ( in context , value . Right , value . Left ) ) ;
3338 }
3439
35- public void Execute ( GeneratorExecutionContext context )
40+ private void Execute ( in SourceProductionContext context , Compilation compilation , AdditionalText syntaxFile )
3641 {
37- var syntaxFile = context . AdditionalFiles . Single ( x => Path . GetFileName ( x . Path ) == "Syntax.xml" ) ;
3842 var syntaxText = syntaxFile . GetText ( context . CancellationToken ) ;
3943 if ( syntaxText is null )
4044 {
4145 throw new InvalidOperationException ( "Failed to read Syntax.xml" ) ;
4246 }
4347
44- var syntaxData = new SyntaxData ( in context , XDocument . Parse ( syntaxText . ToString ( ) ) ) ;
48+ var syntaxData = new SyntaxData ( compilation , XDocument . Parse ( syntaxText . ToString ( ) ) ) ;
4549 this . GenerateSyntaxWrappers ( in context , syntaxData ) ;
4650 this . GenerateSyntaxWrapperHelper ( in context , syntaxData . Nodes ) ;
4751 }
4852
49- private void GenerateSyntaxWrappers ( in GeneratorExecutionContext context , SyntaxData syntaxData )
53+ private void GenerateSyntaxWrappers ( in SourceProductionContext context , SyntaxData syntaxData )
5054 {
5155 foreach ( var node in syntaxData . Nodes )
5256 {
5357 this . GenerateSyntaxWrapper ( in context , syntaxData , node ) ;
5458 }
5559 }
5660
57- private void GenerateSyntaxWrapper ( in GeneratorExecutionContext context , SyntaxData syntaxData , NodeData nodeData )
61+ private void GenerateSyntaxWrapper ( in SourceProductionContext context , SyntaxData syntaxData , NodeData nodeData )
5862 {
5963 if ( nodeData . WrapperName is null )
6064 {
@@ -806,7 +810,7 @@ private void GenerateSyntaxWrapper(in GeneratorExecutionContext context, SyntaxD
806810 context . AddSource ( nodeData . WrapperName + ".g.cs" , SourceText . From ( wrapperNamespace . ToFullString ( ) , Encoding . UTF8 ) ) ;
807811 }
808812
809- private void GenerateSyntaxWrapperHelper ( in GeneratorExecutionContext context , ImmutableArray < NodeData > wrapperTypes )
813+ private void GenerateSyntaxWrapperHelper ( in SourceProductionContext context , ImmutableArray < NodeData > wrapperTypes )
810814 {
811815 // private static readonly ImmutableDictionary<Type, Type> WrappedTypes;
812816 var wrappedTypes = SyntaxFactory . FieldDeclaration (
@@ -982,6 +986,65 @@ private void GenerateSyntaxWrapperHelper(in GeneratorExecutionContext context, I
982986 continue ;
983987 }
984988
989+ if ( node . Name == nameof ( BaseNamespaceDeclarationSyntax ) )
990+ {
991+ // Prior to C# 10, NamespaceDeclarationSyntax was the base type for all namespace declarations.
992+ // If the BaseNamespaceDeclarationSyntax type isn't found at runtime, we fall back
993+ // to using this type instead.
994+ //
995+ // var baseNamespaceDeclarationSyntaxType = csharpCodeAnalysisAssembly.GetType(BaseNamespaceDeclarationSyntaxWrapper.WrappedTypeName)
996+ // ?? csharpCodeAnalysisAssembly.GetType(BaseNamespaceDeclarationSyntaxWrapper.WrappedTypeName);
997+ LocalDeclarationStatementSyntax localStatement =
998+ SyntaxFactory . LocalDeclarationStatement ( SyntaxFactory . VariableDeclaration (
999+ type : SyntaxFactory . IdentifierName ( "var" ) ,
1000+ variables : SyntaxFactory . SingletonSeparatedList ( SyntaxFactory . VariableDeclarator (
1001+ identifier : SyntaxFactory . Identifier ( "baseNamespaceDeclarationSyntaxType" ) ,
1002+ argumentList : null ,
1003+ initializer : SyntaxFactory . EqualsValueClause (
1004+ SyntaxFactory . BinaryExpression (
1005+ SyntaxKind . CoalesceExpression ,
1006+ left : SyntaxFactory . InvocationExpression (
1007+ expression : SyntaxFactory . MemberAccessExpression (
1008+ SyntaxKind . SimpleMemberAccessExpression ,
1009+ expression : SyntaxFactory . IdentifierName ( "csharpCodeAnalysisAssembly" ) ,
1010+ name : SyntaxFactory . IdentifierName ( "GetType" ) ) ,
1011+ argumentList : SyntaxFactory . ArgumentList ( SyntaxFactory . SingletonSeparatedList ( SyntaxFactory . Argument (
1012+ SyntaxFactory . MemberAccessExpression (
1013+ SyntaxKind . SimpleMemberAccessExpression ,
1014+ expression : SyntaxFactory . IdentifierName ( node . WrapperName ) ,
1015+ name : SyntaxFactory . IdentifierName ( "WrappedTypeName" ) ) ) ) ) ) ,
1016+ right : SyntaxFactory . InvocationExpression (
1017+ expression : SyntaxFactory . MemberAccessExpression (
1018+ SyntaxKind . SimpleMemberAccessExpression ,
1019+ expression : SyntaxFactory . IdentifierName ( "csharpCodeAnalysisAssembly" ) ,
1020+ name : SyntaxFactory . IdentifierName ( "GetType" ) ) ,
1021+ argumentList : SyntaxFactory . ArgumentList ( SyntaxFactory . SingletonSeparatedList ( SyntaxFactory . Argument (
1022+ SyntaxFactory . MemberAccessExpression (
1023+ SyntaxKind . SimpleMemberAccessExpression ,
1024+ expression : SyntaxFactory . IdentifierName ( node . WrapperName ) ,
1025+ name : SyntaxFactory . IdentifierName ( "FallbackWrappedTypeName" ) ) ) ) ) ) ) ) ) ) ) ) ;
1026+
1027+ // This is the first line of the statements that initialize 'builder', so start it with a blank line
1028+ staticCtorStatements = staticCtorStatements . Add ( localStatement . WithLeadingBlankLine ( ) ) ;
1029+
1030+ // builder.Add(typeof(BaseNamespaceDeclarationSyntaxWrapper), baseNamespaceDeclarationSyntaxType);
1031+ staticCtorStatements = staticCtorStatements . Add ( SyntaxFactory . ExpressionStatement (
1032+ SyntaxFactory . InvocationExpression (
1033+ expression : SyntaxFactory . MemberAccessExpression (
1034+ SyntaxKind . SimpleMemberAccessExpression ,
1035+ expression : SyntaxFactory . IdentifierName ( "builder" ) ,
1036+ name : SyntaxFactory . IdentifierName ( "Add" ) ) ,
1037+ argumentList : SyntaxFactory . ArgumentList (
1038+ SyntaxFactory . SeparatedList (
1039+ new [ ]
1040+ {
1041+ SyntaxFactory . Argument ( SyntaxFactory . TypeOfExpression ( SyntaxFactory . IdentifierName ( node . WrapperName ) ) ) ,
1042+ SyntaxFactory . Argument ( SyntaxFactory . IdentifierName ( "baseNamespaceDeclarationSyntaxType" ) ) ,
1043+ } ) ) ) ) ) ;
1044+
1045+ continue ;
1046+ }
1047+
9851048 // builder.Add(typeof(ConstantPatternSyntaxWrapper), csharpCodeAnalysisAssembly.GetType(ConstantPatternSyntaxWrapper.WrappedTypeName));
9861049 staticCtorStatements = staticCtorStatements . Add ( SyntaxFactory . ExpressionStatement (
9871050 SyntaxFactory . InvocationExpression (
@@ -1138,12 +1201,12 @@ private sealed class SyntaxData
11381201 {
11391202 private readonly Dictionary < string , NodeData > nameToNode ;
11401203
1141- public SyntaxData ( in GeneratorExecutionContext context , XDocument document )
1204+ public SyntaxData ( Compilation compilation , XDocument document )
11421205 {
11431206 var nodesBuilder = ImmutableArray . CreateBuilder < NodeData > ( ) ;
11441207 foreach ( var element in document . XPathSelectElement ( "/Tree[@Root='SyntaxNode']" ) . XPathSelectElements ( "PredefinedNode|AbstractNode|Node" ) )
11451208 {
1146- nodesBuilder . Add ( new NodeData ( in context , element ) ) ;
1209+ nodesBuilder . Add ( new NodeData ( compilation , element ) ) ;
11471210 }
11481211
11491212 this . Nodes = nodesBuilder . ToImmutable ( ) ;
@@ -1180,7 +1243,7 @@ public SyntaxData(in GeneratorExecutionContext context, XDocument document)
11801243
11811244 private sealed class NodeData
11821245 {
1183- public NodeData ( in GeneratorExecutionContext context , XElement element )
1246+ public NodeData ( Compilation compilation , XElement element )
11841247 {
11851248 this . Kind = element . Name . LocalName switch
11861249 {
@@ -1192,9 +1255,9 @@ public NodeData(in GeneratorExecutionContext context, XElement element)
11921255
11931256 this . Name = element . Attribute ( "Name" ) . Value ;
11941257
1195- this . ExistingType = context . Compilation . GetTypeByMetadataName ( $ "Microsoft.CodeAnalysis.CSharp.Syntax.{ this . Name } ")
1196- ?? context . Compilation . GetTypeByMetadataName ( $ "Microsoft.CodeAnalysis.CSharp.{ this . Name } ")
1197- ?? context . Compilation . GetTypeByMetadataName ( $ "Microsoft.CodeAnalysis.{ this . Name } ") ;
1258+ this . ExistingType = compilation . GetTypeByMetadataName ( $ "Microsoft.CodeAnalysis.CSharp.Syntax.{ this . Name } ")
1259+ ?? compilation . GetTypeByMetadataName ( $ "Microsoft.CodeAnalysis.CSharp.{ this . Name } ")
1260+ ?? compilation . GetTypeByMetadataName ( $ "Microsoft.CodeAnalysis.{ this . Name } ") ;
11981261 if ( this . ExistingType ? . DeclaredAccessibility == Accessibility . Public )
11991262 {
12001263 this . WrapperName = null ;
0 commit comments