1313using Microsoft . CodeAnalysis . CSharp ;
1414using Microsoft . CodeAnalysis . CSharp . Syntax ;
1515using Microsoft . CodeAnalysis . FindSymbols ;
16+ using Microsoft . Extensions . Logging ;
1617using Microsoft . Extensions . Options ;
1718using Silk . NET . SilkTouch . Clang ;
1819using Silk . NET . SilkTouch . Naming ;
@@ -37,7 +38,7 @@ namespace Silk.NET.SilkTouch.Mods;
3738/// <c>Program</c>, <c>Program</c> must be declared in <c>Silk.NET.OpenGL</c>, <c>Silk.NET</c>, or <c>Silk</c>.
3839/// </remarks>
3940[ ModConfiguration < Config > ]
40- public class TransformHandles ( IOptionsSnapshot < TransformHandles . Config > config ) : Mod
41+ public class TransformHandles ( IOptionsSnapshot < TransformHandles . Config > config , ILogger < TransformHandles > logger ) : Mod
4142{
4243 /// <summary>
4344 /// The configuration for the <see cref="TransformHandles"/> mod.
@@ -69,12 +70,14 @@ public override async Task ExecuteAsync(IModContext ctx, CancellationToken ct =
6970
7071 var cfg = config . Get ( ctx . JobKey ) ;
7172
72- // First pass to gather data
73+ // Phase 1. Gather data before modifying
74+ // Find handle documents
7375 var handleTypeDiscoverer = new HandleTypeDiscoverer ( proj , compilation , ct ) ;
7476 var handleTypes = await handleTypeDiscoverer . GetHandleTypesAsync ( ) ;
7577
76- // Second pass to modify the project based on gathered data
77- var handleTypeRewriter = new HandleTypeRewriter ( cfg . UseDSL ) ;
78+ // Store handle document IDs for later
79+ // We will use these IDs to know which documents to rewrite and rename
80+ var handleTypeDocumentIds = new List < ( string OriginalName , DocumentId DocumentId ) > ( ) ;
7881 foreach ( var handleTypeSymbol in handleTypes )
7982 {
8083 if ( handleTypeSymbol . DeclaringSyntaxReferences . Length > 1 )
@@ -85,25 +88,45 @@ public override async Task ExecuteAsync(IModContext ctx, CancellationToken ct =
8588 }
8689
8790 var declaringSyntaxReference = handleTypeSymbol . DeclaringSyntaxReferences . Single ( ) ;
88- var document = proj . GetDocument ( declaringSyntaxReference . SyntaxTree ) ;
89- if ( document != null )
91+ var documentId = proj . GetDocumentId ( declaringSyntaxReference . SyntaxTree ) ;
92+ if ( documentId != null )
9093 {
91- var syntaxTree = await document . GetSyntaxTreeAsync ( ct ) ;
92- if ( syntaxTree == null )
93- {
94- continue ;
95- }
94+ handleTypeDocumentIds . Add ( ( handleTypeSymbol . Name , documentId ) ) ;
95+ }
96+ }
9697
97- var syntaxRoot = await syntaxTree . GetRootAsync ( ct ) ;
98+ // Phase 2. Modify project after gathering data
99+ // Add -Handle suffix
100+ ctx . SourceProject = proj ;
101+ await NameUtils . RenameAllAsync ( ctx , logger , handleTypes . Select ( t => ( ( ISymbol ) t , $ "{ t . Name } Handle") ) , ct ) ;
102+ proj = ctx . SourceProject ;
98103
99- // Rewrite handle struct to include handle members
100- document = document . WithSyntaxRoot ( handleTypeRewriter . Visit ( syntaxRoot ) . NormalizeWhitespace ( ) ) ;
104+ // Use document IDs from earlier
105+ var handleTypeRewriter = new HandleTypeRewriter ( cfg . UseDSL ) ;
106+ foreach ( var ( originalName , documentId ) in handleTypeDocumentIds )
107+ {
108+ var document = proj . GetDocument ( documentId ) ?? throw new InvalidOperationException ( "Failed to find document" ) ;
101109
102- proj = document . Project ;
110+ var syntaxTree = await document . GetSyntaxTreeAsync ( ct ) ;
111+ if ( syntaxTree == null )
112+ {
113+ continue ;
103114 }
115+
116+ var syntaxRoot = await syntaxTree . GetRootAsync ( ct ) ;
117+
118+ // Rewrite handle struct to include handle members
119+ document = document . WithSyntaxRoot ( handleTypeRewriter . Visit ( syntaxRoot ) . NormalizeWhitespace ( ) ) ;
120+
121+ // Add -Handle suffix to end of document name
122+ document = document . WithFilePath (
123+ document . FilePath ! . Replace ( originalName , $ "{ originalName } Handle")
124+ )
125+ . WithName ( document . Name . Replace ( originalName , $ "{ originalName } Handle") ) ;
126+
127+ proj = document . Project ;
104128 }
105129
106- // TODO: Add -Handle prefix to handle type names
107130 // TODO: Reduce handle pointer dimensions by 1
108131
109132 // TODO: Old code. Cleanup needed
@@ -132,12 +155,12 @@ public override async Task ExecuteAsync(IModContext ctx, CancellationToken ct =
132155
133156 private class HandleTypeDiscoverer ( Project project , Compilation compilation , CancellationToken ct ) : SymbolVisitor
134157 {
135- private readonly Solution solution = project . Solution ;
158+ private readonly Solution _solution = project . Solution ;
136159
137160 /// <summary>
138161 /// All discovered empty structs. These are not all handle types.
139162 /// </summary>
140- private readonly List < INamedTypeSymbol > emptyStructs = new ( ) ;
163+ private readonly List < INamedTypeSymbol > _emptyStructs = new ( ) ;
141164
142165 /// <summary>
143166 /// Finds all symbols that correspond to a handle type.
@@ -151,12 +174,12 @@ public async Task<List<INamedTypeSymbol>> GetHandleTypesAsync()
151174
152175 var results = new List < INamedTypeSymbol > ( ) ;
153176 var documents = project . Documents . ToImmutableHashSet ( ) ;
154- foreach ( var structSymbol in emptyStructs )
177+ foreach ( var structSymbol in _emptyStructs )
155178 {
156179 // For each struct, find its references
157180 // Verify that all references are through pointers
158181 // Also verify that there is at least one reference through a pointer
159- var references = await SymbolFinder . FindReferencesAsync ( structSymbol , solution , documents , ct ) ;
182+ var references = await SymbolFinder . FindReferencesAsync ( structSymbol , _solution , documents , ct ) ;
160183
161184 var wasReferencedAsPointer = false ;
162185 var wasReferencedAsNonPointer = false ;
@@ -198,10 +221,7 @@ public async Task<List<INamedTypeSymbol>> GetHandleTypesAsync()
198221 /// <summary>
199222 /// Clears all internal state
200223 /// </summary>
201- private void Clear ( )
202- {
203- emptyStructs . Clear ( ) ;
204- }
224+ private void Clear ( ) => _emptyStructs . Clear ( ) ;
205225
206226 public override void VisitNamespace ( INamespaceSymbol symbol )
207227 {
@@ -225,7 +245,7 @@ public override void VisitNamedType(INamedTypeSymbol symbol)
225245 return ;
226246 }
227247
228- emptyStructs . Add ( symbol ) ;
248+ _emptyStructs . Add ( symbol ) ;
229249 }
230250 }
231251
0 commit comments