@@ -5,6 +5,8 @@ namespace StyleCop.Analyzers.ReadabilityRules
55{
66 using System . Collections . Immutable ;
77 using Microsoft . CodeAnalysis ;
8+ using Microsoft . CodeAnalysis . CSharp ;
9+ using Microsoft . CodeAnalysis . CSharp . Syntax ;
810 using Microsoft . CodeAnalysis . Diagnostics ;
911
1012 /// <summary>
@@ -22,9 +24,10 @@ internal class SA1130UseLambdaSyntax : DiagnosticAnalyzer
2224 private static readonly LocalizableString MessageFormat = new LocalizableResourceString ( nameof ( ReadabilityResources . SA1130MessageFormat ) , ReadabilityResources . ResourceManager , typeof ( ReadabilityResources ) ) ;
2325 private static readonly LocalizableString Description = new LocalizableResourceString ( nameof ( ReadabilityResources . SA1130Description ) , ReadabilityResources . ResourceManager , typeof ( ReadabilityResources ) ) ;
2426 private static readonly string HelpLink = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1130.md" ;
27+ private static readonly ParameterListSyntax EmptyParameterList = SyntaxFactory . ParameterList ( ) ;
2528
2629 private static readonly DiagnosticDescriptor Descriptor =
27- new DiagnosticDescriptor ( DiagnosticId , Title , MessageFormat , AnalyzerCategory . ReadabilityRules , DiagnosticSeverity . Warning , AnalyzerConstants . DisabledNoTests , Description , HelpLink ) ;
30+ new DiagnosticDescriptor ( DiagnosticId , Title , MessageFormat , AnalyzerCategory . ReadabilityRules , DiagnosticSeverity . Warning , AnalyzerConstants . EnabledByDefault , Description , HelpLink ) ;
2831
2932 /// <inheritdoc/>
3033 public override ImmutableArray < DiagnosticDescriptor > SupportedDiagnostics { get ; }
@@ -33,7 +36,47 @@ internal class SA1130UseLambdaSyntax : DiagnosticAnalyzer
3336 /// <inheritdoc/>
3437 public override void Initialize ( AnalysisContext context )
3538 {
36- // TODO: Implement analysis
39+ context . RegisterCompilationStartAction ( HandleCompilationStart ) ;
40+ }
41+
42+ private static void HandleCompilationStart ( CompilationStartAnalysisContext context )
43+ {
44+ context . RegisterSyntaxNodeActionHonorExclusions ( HandleAnonymousMethodExpression , SyntaxKind . AnonymousMethodExpression ) ;
45+ }
46+
47+ private static void HandleAnonymousMethodExpression ( SyntaxNodeAnalysisContext context )
48+ {
49+ var anonymousMethod = ( AnonymousMethodExpressionSyntax ) context . Node ;
50+
51+ if ( anonymousMethod . Parent . IsKind ( SyntaxKind . Argument ) )
52+ {
53+ // invocation -> argument list -> argument -> anonymous method
54+ var originalInvocationExpression = anonymousMethod ? . Parent ? . Parent ? . Parent as InvocationExpressionSyntax ;
55+
56+ if ( originalInvocationExpression != null )
57+ {
58+ // In some cases passing a delegate as an argument to a method is required to call the right overload
59+ // When there is an other overload that takes an expression.
60+ var lambdaExpression = SyntaxFactory . ParenthesizedLambdaExpression (
61+ anonymousMethod . AsyncKeyword ,
62+ anonymousMethod . ParameterList ?? EmptyParameterList ,
63+ SyntaxFactory . Token ( SyntaxKind . EqualsGreaterThanToken ) ,
64+ anonymousMethod . Body ) ;
65+
66+ var invocationExpression = originalInvocationExpression . ReplaceNode ( anonymousMethod , lambdaExpression ) ;
67+
68+ SymbolInfo originalSymbolInfo = context . SemanticModel . GetSymbolInfo ( originalInvocationExpression ) ;
69+ Location location = originalInvocationExpression . GetLocation ( ) ;
70+ SymbolInfo newSymbolInfo = context . SemanticModel . GetSpeculativeSymbolInfo ( location . SourceSpan . Start , invocationExpression , SpeculativeBindingOption . BindAsExpression ) ;
71+
72+ if ( originalSymbolInfo . Symbol != newSymbolInfo . Symbol )
73+ {
74+ return ;
75+ }
76+ }
77+ }
78+
79+ context . ReportDiagnostic ( Diagnostic . Create ( Descriptor , anonymousMethod . GetLocation ( ) ) ) ;
3780 }
3881 }
3982}
0 commit comments