public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var(document, textSpan, cancellationToken) = context; var syntaxTree = (await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false)) !; if (!MakeLocalFunctionStaticHelper.IsStaticLocalFunctionSupported(((CSharpParseOptions)syntaxTree.Options).LanguageVersion)) { return; } var localFunction = await context.TryGetRelevantNodeAsync <LocalFunctionStatementSyntax>().ConfigureAwait(false); if (localFunction == null) { return; } if (localFunction.Modifiers.Any(SyntaxKind.StaticKeyword)) { return; } var semanticModel = (await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false)) !; if (MakeLocalFunctionStaticHelper.CanMakeLocalFunctionStaticByRefactoringCaptures(localFunction, semanticModel, out var captures)) { context.RegisterRefactoring(new MyCodeAction( c => MakeLocalFunctionStaticCodeFixHelper.MakeLocalFunctionStaticAsync(document, localFunction, captures, c))); } }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var(document, textSpan, cancellationToken) = context; var syntaxTree = (await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false)) !; if (!MakeLocalFunctionStaticHelper.IsStaticLocalFunctionSupported(syntaxTree)) { return; } var localFunction = await context.TryGetRelevantNodeAsync <LocalFunctionStatementSyntax>().ConfigureAwait(false); if (localFunction == null) { return; } if (localFunction.Modifiers.Any(SyntaxKind.StaticKeyword)) { return; } var semanticModel = (await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false)) !; if (MakeLocalFunctionStaticHelper.TryGetCaputuredSymbolsAndCheckApplicability(localFunction, semanticModel, out var captures)) { context.RegisterRefactoring(new MyCodeAction( FeaturesResources.Make_local_function_static, c => MakeLocalFunctionStaticHelper.MakeLocalFunctionStaticAsync(document, localFunction, captures, c))); } }
protected override void InitializeWorker(AnalysisContext context) => context.RegisterCompilationStartAction(context => { if (MakeLocalFunctionStaticHelper.IsStaticLocalFunctionSupported(context.Compilation.LanguageVersion())) { context.RegisterSyntaxNodeAction(AnalyzeSyntax, SyntaxKind.LocalFunctionStatement); } });
// The purpose of this wrapper is to share some common logic between FixOne and FixAll. // The main reason we chose this approach over the typical "FixOne calls FixAll" approach is // to avoid duplicate code. private static async Task WrapFixAsync( Document document, ImmutableArray <Diagnostic> diagnostics, Func <Document, LocalFunctionStatementSyntax, ImmutableArray <ISymbol>, Task> fixer, CancellationToken cancellationToken ) { var root = ( await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false) ) !; // Even when the language version doesn't support staic local function, the compiler will still // generate this error. So we need to check to make sure we don't provide incorrect fix. if (!MakeLocalFunctionStaticHelper.IsStaticLocalFunctionSupported(root.SyntaxTree)) { return; } // Find all unique local functions that contain the error. var localFunctions = diagnostics .Select( d => root.FindNode(d.Location.SourceSpan) .AncestorsAndSelf() .OfType <LocalFunctionStatementSyntax>() .FirstOrDefault() ) .WhereNotNull() .Distinct() .ToImmutableArrayOrEmpty(); if (localFunctions.Length == 0) { return; } var semanticModel = ( await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false) ) !; foreach (var localFunction in localFunctions) { if ( MakeLocalFunctionStaticHelper.CanMakeLocalFunctionStaticByRefactoringCaptures( localFunction, semanticModel, out var captures ) ) { await fixer(document, localFunction, captures).ConfigureAwait(false); } } }
private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) { var localFunction = (LocalFunctionStatementSyntax)context.Node; if (localFunction.Modifiers.Any(SyntaxKind.StaticKeyword)) { return; } var syntaxTree = context.Node.SyntaxTree; if (!MakeLocalFunctionStaticHelper.IsStaticLocalFunctionSupported(syntaxTree)) { return; } var cancellationToken = context.CancellationToken; var option = context.Options.GetOption( CSharpCodeStyleOptions.PreferStaticLocalFunction, syntaxTree, cancellationToken ); if (!option.Value) { return; } var semanticModel = context.SemanticModel; if ( MakeLocalFunctionStaticHelper.CanMakeLocalFunctionStaticBecauseNoCaptures( localFunction, semanticModel ) ) { context.ReportDiagnostic( DiagnosticHelper.Create( Descriptor, localFunction.Identifier.GetLocation(), option.Notification.Severity, additionalLocations: ImmutableArray.Create(localFunction.GetLocation()), properties: null ) ); } }
private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) { var localFunction = (LocalFunctionStatementSyntax)context.Node; if (localFunction.Modifiers.Any(SyntaxKind.StaticKeyword)) { return; } var syntaxTree = context.Node.SyntaxTree; if (!MakeLocalFunctionStaticHelper.IsStaticLocalFunctionSupported(syntaxTree)) { return; } var cancellationToken = context.CancellationToken; var optionSet = context.Options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult(); if (optionSet == null) { return; } var option = optionSet.GetOption(CSharpCodeStyleOptions.PreferStaticLocalFunction); if (!option.Value) { return; } var semanticModel = context.SemanticModel; if (MakeLocalFunctionStaticHelper.TryGetCaputuredSymbols(localFunction, semanticModel, out var captures) && captures.Length == 0) { context.ReportDiagnostic(DiagnosticHelper.Create( Descriptor, localFunction.Identifier.GetLocation(), option.Notification.Severity, additionalLocations: ImmutableArray.Create(localFunction.GetLocation()), properties: null)); } }