@@ -100,10 +100,20 @@ private BlockSyntax AsyncLockBlock(BlockSyntax block)
100
100
) ;
101
101
}
102
102
103
- private MethodDeclarationSyntax RewiteMethod ( MethodInfo methodInfo , MethodAnalyzeResult analyzeResult )
103
+ private MethodDeclarationSyntax RewiteMethod ( MethodInfo methodInfo )
104
104
{
105
+ // TODO: if a method cannot be converted to async we should not convert dependencies too
106
+ if ( ! methodInfo . CanBeAsnyc && ! methodInfo . Dependencies . Any ( ) && ! methodInfo . Missing )
107
+ {
108
+ if ( methodInfo . TypeInfo . TypeTransformation == TypeTransformation . Partial )
109
+ {
110
+ return null ;
111
+ }
112
+ return methodInfo . Node ;
113
+ }
114
+
105
115
var taskConflict = ! DocumentInfo . ProjectInfo . IsNameUniqueInsideNamespace ( methodInfo . TypeInfo . NamespaceInfo . Symbol , "Task" ) ;
106
- if ( ! analyzeResult . HasBody )
116
+ if ( ! methodInfo . HasBody )
107
117
{
108
118
return methodInfo . Node
109
119
. WithoutAttribute ( "Async" )
@@ -136,8 +146,8 @@ private MethodDeclarationSyntax RewiteMethod(MethodInfo methodInfo, MethodAnalyz
136
146
}
137
147
138
148
var referenceAnnotations = new Dictionary < string , MethodReferenceResult > ( ) ;
139
- foreach ( var referenceResult in analyzeResult . ReferenceResults
140
- . Where ( o => o . CanBeAsync ) )
149
+ foreach ( var referenceResult in methodInfo . ReferenceResults
150
+ . Where ( o => ! o . Ignore ) )
141
151
{
142
152
var reference = referenceResult . ReferenceLocation ;
143
153
var startSpan = reference . Location . SourceSpan . Start - methodInfo . Node . Span . Start ;
@@ -180,7 +190,7 @@ private MethodDeclarationSyntax RewiteMethod(MethodInfo methodInfo, MethodAnalyz
180
190
continue ;
181
191
}
182
192
183
- if ( analyzeResult . CanSkipAsync )
193
+ if ( methodInfo . CanSkipAsync )
184
194
{
185
195
// return task instead of awaiting
186
196
if ( referenceResult . UsedAsReturnValue )
@@ -254,8 +264,8 @@ private MethodDeclarationSyntax RewiteMethod(MethodInfo methodInfo, MethodAnalyz
254
264
}
255
265
256
266
if ( methodInfo . TypeInfo . ParentTypeInfo ? . TypeTransformation != TypeTransformation . NewType &&
257
- methodInfo . TypeInfo . TypeTransformation != TypeTransformation . NewType &&
258
- ! analyzeResult . CanBeAsnyc && ! analyzeResult . IsEmpty ) // forward call
267
+ methodInfo . TypeInfo . TypeTransformation != TypeTransformation . NewType &&
268
+ ! methodInfo . CanBeAsnyc && ! methodInfo . IsEmpty ) // forward call
259
269
{
260
270
var name = methodInfo . Node . TypeParameterList != null
261
271
? GenericName ( methodInfo . Node . Identifier . ValueText )
@@ -282,20 +292,20 @@ private MethodDeclarationSyntax RewiteMethod(MethodInfo methodInfo, MethodAnalyz
282
292
methodNode = methodNode . WithBody ( Block ( ReturnStatement ( invocation ) ) ) ;
283
293
}
284
294
}
285
- else if ( analyzeResult . Yields )
295
+ else if ( methodInfo . HasYields )
286
296
{
287
297
var yieldRewriter = new YieldToAsyncMethodRewriter ( ) ;
288
298
methodNode = ( MethodDeclarationSyntax ) yieldRewriter . VisitMethodDeclaration ( methodNode ) ;
289
299
}
290
300
291
- if ( ! analyzeResult . CanBeAsnyc || analyzeResult . CanSkipAsync || analyzeResult . Yields )
301
+ if ( ! methodInfo . CanBeAsnyc || methodInfo . CanSkipAsync || methodInfo . HasYields )
292
302
{
293
303
var taskRewriter = new ReturnTaskMethodRewriter ( Configuration . Async . CustomTaskType ) ;
294
304
methodNode = ( MethodDeclarationSyntax ) taskRewriter . VisitMethodDeclaration ( methodNode ) ;
295
305
}
296
306
297
307
// check if method must run synhronized
298
- if ( analyzeResult . MustRunSynchronized )
308
+ if ( methodInfo . MustRunSynchronized )
299
309
{
300
310
methodNode = methodNode
301
311
. WithBody ( AsyncLockBlock ( methodNode . Body ) )
@@ -306,15 +316,52 @@ private MethodDeclarationSyntax RewiteMethod(MethodInfo methodInfo, MethodAnalyz
306
316
. ReturnAsTask ( methodInfo . Symbol , taskConflict )
307
317
. WithIdentifier ( Identifier ( methodNode . Identifier . Value + "Async" ) ) ;
308
318
309
- if ( analyzeResult . MustRunSynchronized || ( ! analyzeResult . CanSkipAsync && ! analyzeResult . Yields && analyzeResult . CanBeAsnyc ) )
319
+ if ( methodInfo . MustRunSynchronized || ( ! methodInfo . CanSkipAsync && ! methodInfo . HasYields && methodInfo . CanBeAsnyc ) )
310
320
{
311
321
methodNode = methodNode . AddAsync ( methodNode ) ;
312
322
}
313
- return methodNode
314
- . WithLeadingTrivia ( methodInfo . Node . GetLeadingTrivia ( ) )
323
+
324
+ return RemoveLeadingRegions ( methodNode . WithLeadingTrivia ( methodInfo . Node . GetLeadingTrivia ( ) ) )
315
325
. WithTrailingTrivia ( methodInfo . Node . GetTrailingTrivia ( ) ) ;
316
326
}
317
327
328
+ private SyntaxTriviaList RemoveRegions ( SyntaxTriviaList list )
329
+ {
330
+ var toRemove = new List < int > ( ) ;
331
+ for ( var i = list . Count - 1 ; i >= 0 ; i -- )
332
+ {
333
+ var trivia = list [ i ] ;
334
+ if ( trivia . IsKind ( SyntaxKind . RegionDirectiveTrivia ) || trivia . IsKind ( SyntaxKind . EndRegionDirectiveTrivia ) )
335
+ {
336
+ toRemove . Add ( i ) ;
337
+ }
338
+ }
339
+ while ( toRemove . Count > 0 )
340
+ {
341
+ list = list . RemoveAt ( toRemove [ 0 ] ) ;
342
+ toRemove . RemoveAt ( 0 ) ;
343
+ }
344
+ return list ;
345
+ }
346
+
347
+ private T RemoveLeadingRegions < T > ( T memberNode ) where T : MemberDeclarationSyntax
348
+ {
349
+ // remove all regions as not all methods will be written in the type
350
+ var leadingTrivia = memberNode . GetLeadingTrivia ( ) ;
351
+ memberNode = memberNode . WithLeadingTrivia ( RemoveRegions ( leadingTrivia ) ) ;
352
+
353
+ var baseTypeNode = memberNode as BaseTypeDeclarationSyntax ;
354
+ if ( baseTypeNode == null )
355
+ {
356
+ return memberNode ;
357
+ }
358
+ return memberNode
359
+ . ReplaceToken (
360
+ baseTypeNode . CloseBraceToken ,
361
+ baseTypeNode . CloseBraceToken
362
+ . WithLeadingTrivia ( RemoveRegions ( baseTypeNode . CloseBraceToken . LeadingTrivia ) ) ) ;
363
+ }
364
+
318
365
private class RewrittenNode
319
366
{
320
367
public SyntaxNode Original { get ; set ; }
@@ -353,7 +400,6 @@ private RewriteTypeResult RewriteType(TypeInfo rootTypeInfo, bool onlyMissingMem
353
400
var startRootTypeSpan = rootTypeInfo . Node . SpanStart ;
354
401
355
402
rootTypeNode = rootTypeNode . WithoutTrivia ( ) ; // references have spans without trivia
356
- var leadingTrivia = rootTypeInfo . Node . GetLeadingTrivia ( ) ;
357
403
358
404
// we first need to annotate nodes that will be modified in order to find them later on. We cannot rely on spans after the first modification as they will change
359
405
var typeInfoMetadatas = new Dictionary < TypeInfo , TypeInfoMetadata > ( ) ;
@@ -415,7 +461,7 @@ private RewriteTypeResult RewriteType(TypeInfo rootTypeInfo, bool onlyMissingMem
415
461
416
462
417
463
// process methods
418
- foreach ( var methodInfo in typeInfo . MethodInfos . Values . Where ( o => ! o . Ignore ) )
464
+ foreach ( var methodInfo in typeInfo . MethodInfos . Values )
419
465
{
420
466
var methodSpanStart = methodInfo . Node . SpanStart - startRootTypeSpan ;
421
467
var methodSpanLength = methodInfo . Node . Span . Length ;
@@ -425,27 +471,25 @@ private RewriteTypeResult RewriteType(TypeInfo rootTypeInfo, bool onlyMissingMem
425
471
annotation = Guid . NewGuid ( ) . ToString ( ) ;
426
472
rootTypeNode = rootTypeNode . ReplaceNode ( methodNode , methodNode . WithAdditionalAnnotations ( new SyntaxAnnotation ( annotation ) ) ) ;
427
473
428
- var methodAnalyzeResult = methodInfo . PostAnalyzeResult ;
429
- if ( ! methodAnalyzeResult . IsValid )
430
- {
431
- continue ;
432
- }
433
- var removeNode = false ;
474
+ var removeNode = methodInfo . Ignore ;
475
+
476
+ //TODO: REMOVE THIS
477
+ /*
434
478
if (typeInfo.TypeTransformation == TypeTransformation.NewType &&
435
- methodAnalyzeResult . ReferenceResults . Any ( o => ! o . CanBeAsync && o . DeclaredWithinSameType ) )
479
+ methodInfo .ReferenceResults.Any(o => !o.CanBeAsync && o.DeclaredWithinSameType))
436
480
{
437
481
//TODO: handle dependencies and methods from other types
438
482
removeNode = true;
439
- }
483
+ }*/
440
484
441
- metadata . TaskUsed |= methodAnalyzeResult . CanSkipAsync || methodAnalyzeResult . IsEmpty || methodAnalyzeResult . Yields || ! methodAnalyzeResult . CanBeAsnyc ;
485
+ metadata . TaskUsed |= methodInfo . CanSkipAsync || methodInfo . IsEmpty || methodInfo . HasYields || ! methodInfo . CanBeAsnyc ;
442
486
result . TaskUsed |= metadata . TaskUsed ;
443
- metadata . AsyncLockUsed |= methodAnalyzeResult . MustRunSynchronized ;
487
+ metadata . AsyncLockUsed |= methodInfo . MustRunSynchronized ;
444
488
result . AsyncLockUsed |= metadata . AsyncLockUsed ;
445
489
metadata . RewrittenNodes . Add ( new RewrittenNode
446
490
{
447
491
Original = methodNode ,
448
- Rewritten = removeNode ? null : RewiteMethod ( methodInfo , methodAnalyzeResult ) ,
492
+ Rewritten = removeNode ? null : RewiteMethod ( methodInfo ) ,
449
493
MethodInfo = methodInfo ,
450
494
Annotation = annotation
451
495
} ) ;
@@ -473,7 +517,7 @@ private RewriteTypeResult RewriteType(TypeInfo rootTypeInfo, bool onlyMissingMem
473
517
{
474
518
// replace all rewritten nodes
475
519
foreach ( var rewNode in metadata . RewrittenNodes
476
- . Where ( o => o . MethodInfo == null || ( ! o . MethodInfo . Missing && ! o . MethodInfo . IsRequired ) )
520
+ . Where ( o => o . MethodInfo == null || ( ! o . MethodInfo . Missing /* && !o.MethodInfo.HasRequiredExternalMethods()*/ ) )
477
521
. OrderByDescending ( o => o . Original . SpanStart ) )
478
522
{
479
523
var node = rootTypeNode . GetAnnotatedNodes ( rewNode . Annotation ) . First ( ) ;
@@ -488,9 +532,11 @@ private RewriteTypeResult RewriteType(TypeInfo rootTypeInfo, bool onlyMissingMem
488
532
}
489
533
// add missing members
490
534
var typeNode = rootTypeNode . GetAnnotatedNodes ( metadata . NodeAnnotation ) . OfType < TypeDeclarationSyntax > ( ) . First ( ) ;
535
+
491
536
rootTypeNode = rootTypeNode . ReplaceNode ( typeNode , typeNode . WithMembers (
492
- typeNode . Members . AddRange (
493
- metadata . RewrittenNodes
537
+ typeNode . Members . Select ( RemoveLeadingRegions ) . ToSyntaxList ( )
538
+ . AddRange (
539
+ metadata . RewrittenNodes
494
540
. OrderBy ( o => o . Original . SpanStart )
495
541
. Where ( o => o . MethodInfo != null && o . MethodInfo . Missing )
496
542
. Select ( o => o . Rewritten )
@@ -509,7 +555,7 @@ private RewriteTypeResult RewriteType(TypeInfo rootTypeInfo, bool onlyMissingMem
509
555
// rename all constructors
510
556
if ( typeInfo . TypeTransformation == TypeTransformation . NewType )
511
557
{
512
- while ( true )
558
+ while ( true )
513
559
{
514
560
var ctorNode = rootTypeNode . DescendantNodes ( )
515
561
. OfType < ConstructorDeclarationSyntax > ( )
@@ -527,11 +573,13 @@ private RewriteTypeResult RewriteType(TypeInfo rootTypeInfo, bool onlyMissingMem
527
573
var typeNode = rootTypeNode . GetAnnotatedNodes ( metadata . NodeAnnotation ) . OfType < TypeDeclarationSyntax > ( ) . First ( ) ;
528
574
var newNodes = ( onlyMissingMembers
529
575
? metadata . RewrittenNodes
576
+ . Where ( o => o . Rewritten != null )
530
577
. Where ( o => o . MethodInfo != null && o . MethodInfo . Missing )
531
578
. OrderBy ( o => o . Original . SpanStart )
532
579
. Select ( o => o . Rewritten )
533
580
: metadata . RewrittenNodes
534
- . Where ( o => o . MethodInfo == null || ( o . MethodInfo != null && ( ! o . MethodInfo . IsRequired || o . MethodInfo . Missing ) ) ) // for partials we wont have onlyMissingMembers = true
581
+ . Where ( o => o . Rewritten != null )
582
+ . Where ( o => o . MethodInfo == null || ( o . MethodInfo != null && ( ! o . MethodInfo . HasRequiredExternalMethods ( ) || o . MethodInfo . Missing ) ) ) // for partials we wont have onlyMissingMembers = true
535
583
. OrderBy ( o => o . Original . SpanStart )
536
584
. Select ( o => o . Rewritten ) )
537
585
. Union ( typeNode . DescendantNodes ( ) . OfType < TypeDeclarationSyntax > ( ) )
@@ -552,11 +600,12 @@ private RewriteTypeResult RewriteType(TypeInfo rootTypeInfo, bool onlyMissingMem
552
600
. Any ( n => n . AttributeLists . Any ( o => o . Attributes . Any ( a => a . Name . ToString ( ) . EndsWith ( "GeneratedCode" ) ) ) )
553
601
? newTypeNode . WithoutAttributes ( )
554
602
: newTypeNode . AddGeneratedCodeAttribute ( false ) ;
603
+ /*
555
604
newTypeNode = newTypeNode.RemoveNodes(
556
605
newTypeNode.DescendantNodes(descendIntoTrivia: true).OfType<DirectiveTriviaSyntax>(), SyntaxRemoveOptions.KeepNoTrivia); // remove invalid #endregion
557
-
606
+ */
558
607
rootTypeNode = rootTypeNode
559
- . ReplaceNode ( typeNode , newTypeNode ) ;
608
+ . ReplaceNode ( typeNode , RemoveLeadingRegions ( newTypeNode ) ) ;
560
609
}
561
610
}
562
611
@@ -569,7 +618,8 @@ private RewriteTypeResult RewriteType(TypeInfo rootTypeInfo, bool onlyMissingMem
569
618
}
570
619
}
571
620
572
- result . Node = rootTypeNode
621
+ // remove all regions as not all methods will be written in the type
622
+ result . Node = RemoveLeadingRegions ( rootTypeNode ) ;
573
623
/*.WithTriviaFrom(rootTypeInfo.Node)*/ ;
574
624
return result ;
575
625
}
@@ -592,6 +642,11 @@ public void Write()
592
642
var typeNodes = new List < MemberDeclarationSyntax > ( ) ;
593
643
foreach ( var typeInfo in namespaceInfo . Values . Where ( o => o . TypeTransformation != TypeTransformation . None ) . OrderBy ( o => o . Node . SpanStart ) )
594
644
{
645
+ if ( typeInfo . CanIgnore ( ) )
646
+ {
647
+ continue ;
648
+ }
649
+
595
650
var rewriteResult = RewriteType ( typeInfo ) ;
596
651
if ( rewriteResult . Node == null )
597
652
{
0 commit comments