@@ -365,15 +365,18 @@ private void AnalyzeOperationBlock(
365
365
{
366
366
var value = analysisResult [ platformSpecificOperation . Key . Kind , platformSpecificOperation . Key . Syntax ] ;
367
367
var csAttributes = pair . csAttributes != null ? CopyAttributes ( pair . csAttributes ) : null ;
368
+ var symbol = platformSpecificOperation . Value is IMethodSymbol method && method . IsConstructor ( ) ?
369
+ platformSpecificOperation . Value . ContainingType : platformSpecificOperation . Value ;
370
+ var originalAttributes = platformSpecificMembers [ symbol ] . Platforms ?? pair . attributes ;
368
371
369
- if ( ( value . Kind == GlobalFlowStateAnalysisValueSetKind . Known && IsKnownValueGuarded ( pair . attributes , ref csAttributes , value , pair . csAttributes ) ) ||
372
+ if ( ( value . Kind == GlobalFlowStateAnalysisValueSetKind . Known && IsKnownValueGuarded ( pair . attributes , ref csAttributes , value , pair . csAttributes , originalAttributes ) ) ||
370
373
( value . Kind == GlobalFlowStateAnalysisValueSetKind . Unknown && HasGuardedLambdaOrLocalFunctionResult ( platformSpecificOperation . Key ,
371
- pair . attributes , ref csAttributes , analysisResult , pair . csAttributes ) ) )
374
+ pair . attributes , ref csAttributes , analysisResult , pair . csAttributes , originalAttributes ) ) )
372
375
{
373
376
continue ;
374
377
}
375
378
376
- ReportDiagnostics ( platformSpecificOperation , pair . attributes , csAttributes , context , platformSpecificMembers ) ;
379
+ ReportDiagnostics ( platformSpecificOperation . Key , pair . attributes , csAttributes , context , symbol , originalAttributes ) ;
377
380
}
378
381
}
379
382
finally
@@ -406,7 +409,7 @@ argument.ConstantValue.Value is string platformName &&
406
409
407
410
private static bool HasGuardedLambdaOrLocalFunctionResult ( IOperation platformSpecificOperation , SmallDictionary < string , Versions > attributes ,
408
411
ref SmallDictionary < string , Versions > ? csAttributes , DataFlowAnalysisResult < GlobalFlowStateBlockAnalysisResult ,
409
- GlobalFlowStateAnalysisValueSet > analysisResult , SmallDictionary < string , Versions > ? originalCsAttributes )
412
+ GlobalFlowStateAnalysisValueSet > analysisResult , SmallDictionary < string , Versions > ? originalCsAttributes , SmallDictionary < string , Versions > originalAttributes )
410
413
{
411
414
if ( ! platformSpecificOperation . IsWithinLambdaOrLocalFunction ( out var containingLambdaOrLocalFunctionOperation ) )
412
415
{
@@ -426,7 +429,7 @@ private static bool HasGuardedLambdaOrLocalFunctionResult(IOperation platformSpe
426
429
// NOTE: IsKnownValueGuarded mutates the input values, so we pass in cloned values
427
430
// to ensure that evaluation of each result is independent of evaluation of other parts.
428
431
if ( localValue . Kind != GlobalFlowStateAnalysisValueSetKind . Known ||
429
- ! IsKnownValueGuarded ( CopyAttributes ( attributes ) , ref csAttributes , localValue , originalCsAttributes ) )
432
+ ! IsKnownValueGuarded ( CopyAttributes ( attributes ) , ref csAttributes , localValue , originalCsAttributes , originalAttributes ) )
430
433
{
431
434
return false ;
432
435
}
@@ -474,17 +477,19 @@ invocation.Arguments[0].Value is IPropertyReferenceOperation propertyReference &
474
477
}
475
478
476
479
private static bool IsKnownValueGuarded ( SmallDictionary < string , Versions > attributes ,
477
- ref SmallDictionary < string , Versions > ? csAttributes , GlobalFlowStateAnalysisValueSet value , SmallDictionary < string , Versions > ? originalCsAttributes )
480
+ ref SmallDictionary < string , Versions > ? csAttributes , GlobalFlowStateAnalysisValueSet value ,
481
+ SmallDictionary < string , Versions > ? originalCsAttributes , SmallDictionary < string , Versions > originalAttributes )
478
482
{
479
483
using var capturedVersions = PooledDictionary < string , Version > . GetInstance ( StringComparer . OrdinalIgnoreCase ) ;
480
- return IsKnownValueGuarded ( attributes , ref csAttributes , value , capturedVersions , originalCsAttributes ) ;
484
+ return IsKnownValueGuarded ( attributes , ref csAttributes , value , capturedVersions , originalCsAttributes , originalAttributes ) ;
481
485
482
486
static bool IsKnownValueGuarded (
483
487
SmallDictionary < string , Versions > attributes ,
484
488
ref SmallDictionary < string , Versions > ? csAttributes ,
485
489
GlobalFlowStateAnalysisValueSet value ,
486
490
PooledDictionary < string , Version > capturedVersions ,
487
- SmallDictionary < string , Versions > ? originalCsAttributes )
491
+ SmallDictionary < string , Versions > ? originalCsAttributes ,
492
+ SmallDictionary < string , Versions > originalAttributes )
488
493
{
489
494
// 'GlobalFlowStateAnalysisValueSet.AnalysisValues' represent the && of values.
490
495
foreach ( var analysisValue in value . AnalysisValues )
@@ -630,9 +635,16 @@ static bool IsKnownValueGuarded(
630
635
{
631
636
continue ;
632
637
}
638
+
639
+ // Skip the platform check that was originally in the list and suppressed by callsite attributes
640
+ if ( parent . AnalysisValues . Count == 1 &&
641
+ IsPlatformSupportWasSuppresed ( ( PlatformMethodValue ) parent . AnalysisValues . First ( ) , attributes , originalAttributes ) )
642
+ {
643
+ continue ;
644
+ }
633
645
}
634
646
635
- if ( ! IsKnownValueGuarded ( parentAttributes , ref parentCsAttributes , parent , parentCapturedVersions , originalCsAttributes ) )
647
+ if ( ! IsKnownValueGuarded ( parentAttributes , ref parentCsAttributes , parent , parentCapturedVersions , originalCsAttributes , originalAttributes ) )
636
648
{
637
649
csAttributes = parentCsAttributes ;
638
650
return false ;
@@ -643,6 +655,11 @@ static bool IsKnownValueGuarded(
643
655
return true ;
644
656
}
645
657
658
+ static bool IsPlatformSupportWasSuppresed ( PlatformMethodValue parentValue , SmallDictionary < string , Versions > attributes , SmallDictionary < string , Versions > originalAttributes )
659
+ => ! parentValue . Negated && ! attributes . ContainsKey ( parentValue . PlatformName ) &&
660
+ originalAttributes . TryGetValue ( parentValue . PlatformName , out Versions ? version ) &&
661
+ parentValue . Version . IsGreaterThanOrEqualTo ( version . SupportedFirst ) ;
662
+
646
663
static bool IsOnlySupportNeedsGuard ( string platformName , SmallDictionary < string , Versions > attributes , SmallDictionary < string , Versions > csAttributes )
647
664
=> csAttributes . TryGetValue ( platformName , out var versions ) &&
648
665
AllowList ( versions ) &&
@@ -791,24 +808,21 @@ static void RemoveOtherSupportsOnDifferentPlatforms(SmallDictionary<string, Vers
791
808
792
809
private static bool IsEmptyVersion ( Version version ) => version . Major == 0 && version . Minor == 0 ;
793
810
794
- private static void ReportDiagnostics ( KeyValuePair < IOperation , ISymbol > operationToSymbol , SmallDictionary < string , Versions > attributes ,
811
+ private static void ReportDiagnostics ( IOperation operation , SmallDictionary < string , Versions > attributes ,
795
812
SmallDictionary < string , Versions > ? csAttributes , OperationBlockAnalysisContext context ,
796
- ConcurrentDictionary < ISymbol , PlatformAttributes > platformSpecificMembers )
813
+ ISymbol symbol , SmallDictionary < string , Versions > originalAttributes )
797
814
{
798
- var symbol = operationToSymbol . Value is IMethodSymbol method && method . IsConstructor ( ) ? operationToSymbol . Value . ContainingType : operationToSymbol . Value ;
799
- var operationName = symbol . ToDisplayString ( GetLanguageSpecificFormat ( operationToSymbol . Key ) ) ;
800
-
801
- var originalAttributes = platformSpecificMembers [ symbol ] . Platforms ?? attributes ;
815
+ var operationName = symbol . ToDisplayString ( GetLanguageSpecificFormat ( operation ) ) ;
802
816
803
817
foreach ( var attribute in originalAttributes . Values )
804
818
{
805
819
if ( AllowList ( attribute ) )
806
820
{
807
- ReportSupportedDiagnostic ( operationToSymbol . Key , context , operationName , attributes , csAttributes ) ;
821
+ ReportSupportedDiagnostic ( operation , context , operationName , attributes , csAttributes ) ;
808
822
}
809
823
else
810
824
{
811
- ReportUnsupportedDiagnostic ( operationToSymbol . Key , context , operationName , attributes , csAttributes ) ;
825
+ ReportUnsupportedDiagnostic ( operation , context , operationName , attributes , csAttributes ) ;
812
826
}
813
827
814
828
break ;
0 commit comments