private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
        {
            var localFunction = (LocalFunctionStatementSyntax)context.Node;

            if (localFunction.Modifiers.Any(SyntaxKind.StaticKeyword))
            {
                return;
            }

            var syntaxTree        = context.Node.SyntaxTree;
            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));
            }
        }
Exemple #2
0
        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);
     }
 });
 protected override Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken)
 => WrapFixAsync(
     document,
     diagnostics,
     (d, localFunction, captures) => MakeLocalFunctionStaticHelper.MakeLocalFunctionStaticAsync(
         d,
         localFunction,
         captures,
         editor,
         cancellationToken),
     cancellationToken);
        // 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);
                }
            }
        }
Exemple #7
0
        protected override Task FixAllAsync(
            Document document, ImmutableArray <Diagnostic> diagnostics,
            SyntaxEditor editor, CancellationToken cancellationToken)
        {
            var localFunctions = diagnostics.SelectAsArray(d => d.AdditionalLocations[0].FindNode(cancellationToken));

            foreach (var localFunction in localFunctions)
            {
                editor.ReplaceNode(
                    localFunction,
                    (current, generator) => MakeLocalFunctionStaticHelper.AddStaticModifier(current, generator));
            }

            return(Task.CompletedTask);
        }
        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));
            }
        }
        public override Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();

            return(WrapFixAsync(
                       context.Document,
                       ImmutableArray.Create(diagnostic),
                       (document, localFunction, captures) =>
            {
                context.RegisterCodeFix(
                    new MyCodeAction(c => MakeLocalFunctionStaticHelper.MakeLocalFunctionStaticAsync(
                                         document,
                                         localFunction,
                                         captures,
                                         c)),
                    diagnostic);

                return Task.CompletedTask;
            },
                       context.CancellationToken));
        }