Example #1
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var cancellationToken = context.CancellationToken;
            var uniqueIdentities  = await GetUniqueIdentitiesAsync(context).ConfigureAwait(false);

            var addPackageCodeActions = await GetAddPackagesCodeActionsAsync(context, uniqueIdentities).ConfigureAwait(false);

            var addReferenceCodeActions = await GetAddReferencesCodeActionsAsync(context, uniqueIdentities).ConfigureAwait(false);

            context.RegisterFixes(addPackageCodeActions, context.Diagnostics);
            context.RegisterFixes(addReferenceCodeActions, context.Diagnostics);
        }
        public override Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var diagnostics = context.Diagnostics;

            context.RegisterFixes(GetUpgradeProjectCodeActionsAsync(context), diagnostics);
            return(Task.CompletedTask);
        }
Example #3
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var span              = context.Span;
            var cancellationToken = context.CancellationToken;

            var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token = root.FindToken(span.Start);

            if (!token.Span.IntersectsWith(span))
            {
                return;
            }

            var service = document.GetRequiredLanguageService <IImplementInterfaceService>();
            var model   = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var actions = token.Parent.GetAncestorsOrThis <TypeSyntax>()
                          .Where(_interfaceName)
                          .Select(n => service.GetCodeActions(document, context.Options.GetImplementTypeGenerationOptions(document.Project.LanguageServices), model, n, cancellationToken))
                          .FirstOrDefault(a => !a.IsEmpty);

            if (actions.IsDefaultOrEmpty)
            {
                return;
            }

            context.RegisterFixes(actions, context.Diagnostics);
        }
Example #4
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var span              = context.Span;
            var cancellationToken = context.CancellationToken;
            var diagnostics       = context.Diagnostics;

            var addImportService = document.GetLanguageService <IAddImportFeatureService>();

            var solution = document.Project.Solution;
            var options  = solution.Options;

            var searchReferenceAssemblies = options.GetOption(SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, document.Project.Language);
            var searchNuGetPackages       = options.GetOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages, document.Project.Language);

            var symbolSearchService = searchReferenceAssemblies || searchNuGetPackages
                ? _symbolSearchService ?? solution.Workspace.Services.GetService <ISymbolSearchService>()
                : null;

            var installerService = GetPackageInstallerService(document);
            var packageSources   = searchNuGetPackages && symbolSearchService != null && installerService != null
                ? installerService.PackageSources
                : ImmutableArray <PackageSource> .Empty;

            var fixesForDiagnostic = await addImportService.GetFixesForDiagnosticsAsync(
                document, span, diagnostics, MaxResults, symbolSearchService, searchReferenceAssemblies, packageSources, cancellationToken).ConfigureAwait(false);

            foreach (var(diagnostic, fixes) in fixesForDiagnostic)
            {
                // Limit the results returned since this will be displayed to the user
                var codeActions = addImportService.GetCodeActionsForFixes(document, fixes, installerService, MaxResults);
                context.RegisterFixes(codeActions, diagnostic);
            }
        }
Example #5
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            // NOTE(DustinCa): Not supported in REPL for now.
            if (context.Document.SourceCodeKind == SourceCodeKind.Interactive)
            {
                return;
            }

            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var names = GetTargetNodes(root, context.Span);

            foreach (var name in names)
            {
                var codeActions = await GetCodeActionsAsync(context.Document, name, context.CancellationToken).ConfigureAwait(false);

                if (codeActions == null || codeActions.IsEmpty())
                {
                    continue;
                }

                context.RegisterFixes(codeActions, context.Diagnostics);
                return;
            }
        }
Example #6
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            // TODO: https://github.com/dotnet/roslyn/issues/5777
            // Not supported in REPL for now.
            if (context.Project.IsSubmission)
            {
                return;
            }

            var diagnostic  = context.Diagnostics.First();
            var document    = context.Document;
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            var root = await document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var names = GetTargetNodes(syntaxFacts, root, context.Span, diagnostic);

            foreach (var name in names)
            {
                var codeActions = await GetCodeActionsAsync(context.Document, name, context.CancellationToken).ConfigureAwait(false);

                if (codeActions.IsDefaultOrEmpty)
                {
                    continue;
                }

                context.RegisterFixes(codeActions, context.Diagnostics);
                return;
            }
        }
Example #7
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            // TODO: https://github.com/dotnet/roslyn/issues/5777
            // Not supported in REPL for now.
            if (context.Project.IsSubmission)
            {
                return;
            }

            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var names = GetTargetNodes(root, context.Span);

            foreach (var name in names)
            {
                var codeActions = await GetCodeActionsAsync(context.Document, name, context.CancellationToken).ConfigureAwait(false);

                if (codeActions == null || codeActions.IsEmpty())
                {
                    continue;
                }

                context.RegisterFixes(codeActions, context.Diagnostics);
                return;
            }
        }
Example #8
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var cancellationToken = context.CancellationToken;
            var document          = context.Document;
            var diagnostic        = context.Diagnostics.FirstOrDefault();

            if (diagnostic == null)
            {
                return;
            }

            var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>();
            var headerFacts = document.GetRequiredLanguageService <IHeaderFactsService>();

            var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            if (!headerFacts.IsOnTypeHeader(root, diagnostic.Location.SourceSpan.Start, fullHeader: true, out var typeDecl))
            {
                return;
            }

            var typeName = syntaxFacts.GetIdentifierOfTypeDeclaration(typeDecl);
            var service  = document.GetRequiredLanguageService <IGenerateDefaultConstructorsService>();
            var actions  = await service.GenerateDefaultConstructorsAsync(
                document, new TextSpan(typeName.Span.Start, 0), forRefactoring : false, cancellationToken).ConfigureAwait(false);

            context.RegisterFixes(actions, diagnostic);
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var span              = context.Span;
            var cancellationToken = context.CancellationToken;

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token = root.FindToken(span.Start);

            if (!token.Span.IntersectsWith(span))
            {
                return;
            }

            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            if (model.IsFromGeneratedCode(cancellationToken))
            {
                return;
            }

            var actions = token.Parent.GetAncestorsOrThis <TypeSyntax>()
                          .Where(_interfaceName)
                          .Select(n => service.GetCodeActions(document, model, n, cancellationToken))
                          .FirstOrDefault(_codeActionAvailable);

            if (_codeActionAvailable(actions))
            {
                context.RegisterFixes(actions, context.Diagnostics);
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var span              = context.Span;
            var diagnostics       = context.Diagnostics;
            var cancellationToken = context.CancellationToken;

            var project    = document.Project;
            var diagnostic = diagnostics.First();
            var root       = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var node = root.FindToken(span.Start).GetAncestors <SyntaxNode>().First(n => n.Span.Contains(span));

            using (Logger.LogBlock(FunctionId.Refactoring_FullyQualify, cancellationToken))
            {
                // Has to be a simple identifier or generic name.
                if (node == null || !CanFullyQualify(diagnostic, ref node))
                {
                    return;
                }

                var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                var matchingTypes = await this.GetMatchingTypesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false);

                var matchingNamespaces = await this.GetMatchingNamespacesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false);

                if (matchingTypes.IsEmpty && matchingNamespaces.IsEmpty)
                {
                    return;
                }

                var matchingTypeContainers      = FilterAndSort(GetContainers(matchingTypes, semanticModel.Compilation));
                var matchingNamespaceContainers = FilterAndSort(GetContainers(matchingNamespaces, semanticModel.Compilation));

                var proposedContainers =
                    matchingTypeContainers.Concat(matchingNamespaceContainers)
                    .Distinct()
                    .Take(MaxResults);

                var displayService = project.LanguageServices.GetService <ISymbolDisplayService>();
                var codeActions    = CreateActions(context, document, diagnostic, node, semanticModel, proposedContainers, displayService).ToImmutableArray();

                if (codeActions.Length > 1)
                {
                    // Wrap the spell checking actions into a single top level suggestion
                    // so as to not clutter the list.
                    context.RegisterCodeFix(new GroupingCodeAction(
                                                string.Format(FeaturesResources.Fully_qualify_0, GetNodeName(document, node)),
                                                codeActions), context.Diagnostics);
                }
                else
                {
                    context.RegisterFixes(codeActions, context.Diagnostics);
                }
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document = context.Document;
            var span = context.Span;
            var diagnostics = context.Diagnostics;
            var cancellationToken = context.CancellationToken;

            var project = document.Project;
            var diagnostic = diagnostics.First();
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
            var node = root.FindToken(span.Start).GetAncestors<SyntaxNode>().First(n => n.Span.Contains(span));

            using (Logger.LogBlock(FunctionId.Refactoring_FullyQualify, cancellationToken))
            {
                // Has to be a simple identifier or generic name.
                if (node == null || !CanFullyQualify(diagnostic, ref node))
                {
                    return;
                }

                var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                var matchingTypes = await this.GetMatchingTypesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false);
                var matchingNamespaces = await this.GetMatchingNamespacesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false);

                if (matchingTypes.IsEmpty && matchingNamespaces.IsEmpty)
                {
                    return;
                }

                var matchingTypeContainers = FilterAndSort(GetContainers(matchingTypes, semanticModel.Compilation));
                var matchingNamespaceContainers = FilterAndSort(GetContainers(matchingNamespaces, semanticModel.Compilation));

                var proposedContainers =
                    matchingTypeContainers.Concat(matchingNamespaceContainers)
                                            .Distinct()
                                            .Take(MaxResults);

                var displayService = project.LanguageServices.GetService<ISymbolDisplayService>();
                var codeActions = CreateActions(context, document, diagnostic, node, semanticModel, proposedContainers, displayService).ToImmutableArray();

                if (codeActions.Length > 1)
                {
                    // Wrap the spell checking actions into a single top level suggestion
                    // so as to not clutter the list.
                    context.RegisterCodeFix(new GroupingCodeAction(
                        string.Format(FeaturesResources.Fully_qualify_0, GetNodeName(document, node)),
                        codeActions), context.Diagnostics);
                }
                else
                {
                    context.RegisterFixes(codeActions, context.Diagnostics);
                }
            }
        }
        private async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var diagnostic        = context.Diagnostics[0];
            var cancellationToken = context.CancellationToken;

            var codeFixes = await ComputeCodeActionsAsync(
                document, diagnostic, cancellationToken).ConfigureAwait(false);

            context.RegisterFixes(codeFixes, context.Diagnostics);
        }
Example #13
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var span              = context.Span;
            var cancellationToken = context.CancellationToken;

            var addImportService = document.GetLanguageService <IAddImportFeatureService>();

            var solution = document.Project.Solution;
            var options  = solution.Options;

            var searchReferenceAssemblies = options.GetOption(SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, document.Project.Language);
            var searchNuGetPackages       = options.GetOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages, document.Project.Language);

            var symbolSearchService = searchReferenceAssemblies || searchNuGetPackages
                ? _symbolSearchService ?? solution.Workspace.Services.GetService <ISymbolSearchService>()
                : null;

            var packageSources = symbolSearchService != null && searchNuGetPackages
                ? GetPackageSources(document)
                : ImmutableArray <PackageSource> .Empty;

            // We might have multiple different diagnostics covering the same span.  Have to
            // process them all as we might produce different fixes for each diagnostic.

            var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            var placeSystemNamespaceFirst = documentOptions.GetOption(GenerationOptions.PlaceSystemNamespaceFirst);

            foreach (var diagnostic in context.Diagnostics)
            {
                var fixes = await addImportService.GetFixesAsync(
                    document, span, diagnostic.Id, placeSystemNamespaceFirst,
                    symbolSearchService, searchReferenceAssemblies,
                    packageSources, cancellationToken).ConfigureAwait(false);

                var codeActions = ArrayBuilder <CodeAction> .GetInstance();

                foreach (var fix in fixes)
                {
                    var codeAction = TryCreateCodeAction(document, fix);
                    codeActions.AddIfNotNull(codeAction);

                    if (codeActions.Count >= MaxResults)
                    {
                        break;
                    }
                }

                context.RegisterFixes(codeActions, diagnostic);
                codeActions.Free();
            }
        }
        private async Task CreateSpellCheckCodeIssueAsync(CodeFixContext context, TSimpleName nameNode, string nameText, CancellationToken cancellationToken)
        {
            var document = context.Document;
            var service  = CompletionService.GetService(document);

            // Disable snippets from ever appearing in the completion items. It's
            // very unlikely the user would ever mispell a snippet, then use spell-
            // checking to fix it, then try to invoke the snippet.
            var originalOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            var options = originalOptions.WithChangedOption(CompletionOptions.SnippetsBehavior, document.Project.Language, SnippetsRule.NeverInclude);

            var completionList = await service.GetCompletionsAsync(
                document, nameNode.SpanStart, options : options, cancellationToken : cancellationToken).ConfigureAwait(false);

            if (completionList == null)
            {
                return;
            }

            var onlyConsiderGenerics = IsGeneric(nameNode);
            var results = new MultiDictionary <double, string>();

            using (var similarityChecker = new WordSimilarityChecker(nameText, substringsAreSimilar: true))
            {
                foreach (var item in completionList.Items)
                {
                    if (onlyConsiderGenerics && !IsGeneric(item))
                    {
                        continue;
                    }

                    var    candidateText = item.FilterText;
                    double matchCost;
                    if (!similarityChecker.AreSimilar(candidateText, out matchCost))
                    {
                        continue;
                    }

                    var insertionText = await GetInsertionTextAsync(document, item, cancellationToken : cancellationToken).ConfigureAwait(false);

                    results.Add(matchCost, insertionText);
                }
            }

            var matches = results.OrderBy(kvp => kvp.Key)
                          .SelectMany(kvp => kvp.Value.Order())
                          .Where(t => t != nameText)
                          .Take(3)
                          .Select(n => CreateCodeAction(nameNode, nameText, n, document));

            context.RegisterFixes(matches, context.Diagnostics);
        }
Example #15
0
        private async Task CheckItemsAsync(
            CodeFixContext context, SyntaxToken nameToken, bool isGeneric,
            CompletionList completionList, WordSimilarityChecker similarityChecker)
        {
            var document          = context.Document;
            var cancellationToken = context.CancellationToken;

            var onlyConsiderGenerics = isGeneric;
            var results = new MultiDictionary <double, string>();

            foreach (var item in completionList.ItemsList)
            {
                if (onlyConsiderGenerics && !IsGeneric(item))
                {
                    continue;
                }

                var candidateText = item.FilterText;
                if (!similarityChecker.AreSimilar(candidateText, out var matchCost))
                {
                    continue;
                }

                var insertionText = await GetInsertionTextAsync(document, item, cancellationToken : cancellationToken).ConfigureAwait(false);

                results.Add(matchCost, insertionText);
            }

            var nameText    = nameToken.ValueText;
            var codeActions = results.OrderBy(kvp => kvp.Key)
                              .SelectMany(kvp => kvp.Value.Order())
                              .Where(t => t != nameText)
                              .Take(3)
                              .Select(n => CreateCodeAction(nameToken, nameText, n, document))
                              .ToImmutableArrayOrEmpty <CodeAction>();

            if (codeActions.Length > 1)
            {
                // Wrap the spell checking actions into a single top level suggestion
                // so as to not clutter the list.
                context.RegisterCodeFix(
                    CodeAction.CreateWithPriority(
                        CodeActionPriority.Low,
                        string.Format(FeaturesResources.Fix_typo_0, nameText),
                        codeActions,
                        isInlinable: true),
                    context.Diagnostics);
            }
            else
            {
                context.RegisterFixes(codeActions, context.Diagnostics);
            }
        }
Example #16
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var assemblyName = GetAssemblyName(context.Diagnostics[0].Id);

            if (assemblyName != null)
            {
                var assemblyNames = new HashSet <string> {
                    assemblyName
                };
                var addPackageCodeActions = await GetAddPackagesCodeActionsAsync(context, assemblyNames).ConfigureAwait(false);

                context.RegisterFixes(addPackageCodeActions, context.Diagnostics);
            }
        }
Example #17
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var span              = context.Span;
            var cancellationToken = context.CancellationToken;
            var diagnostics       = context.Diagnostics;

            var addImportService = document.GetRequiredLanguageService <IAddImportFeatureService>();
            var services         = document.Project.Solution.Workspace.Services;

            var codeActionOptions = context.Options.GetOptions(document.Project.LanguageServices);
            var searchOptions     = codeActionOptions.SearchOptions;

            var symbolSearchService = _symbolSearchService ?? services.GetRequiredService <ISymbolSearchService>();

            var installerService = searchOptions.SearchNuGetPackages ?
                                   _packageInstallerService ?? services.GetService <IPackageInstallerService>() : null;

            var packageSources = installerService?.IsEnabled(document.Project.Id) == true
                ? installerService.TryGetPackageSources()
                : ImmutableArray <PackageSource> .Empty;

            if (packageSources.IsEmpty)
            {
                searchOptions = searchOptions with {
                    SearchNuGetPackages = false
                };
            }

            var cleanupOptions = await document.GetCodeCleanupOptionsAsync(context.Options, cancellationToken).ConfigureAwait(false);

            var addImportOptions = new AddImportOptions(
                searchOptions,
                cleanupOptions,
                codeActionOptions.HideAdvancedMembers);

            var fixesForDiagnostic = await addImportService.GetFixesForDiagnosticsAsync(
                document, span, diagnostics, MaxResults, symbolSearchService, addImportOptions, packageSources, cancellationToken).ConfigureAwait(false);

            foreach (var(diagnostic, fixes) in fixesForDiagnostic)
            {
                // Limit the results returned since this will be displayed to the user
                var codeActions = addImportService.GetCodeActionsForFixes(document, fixes, installerService, MaxResults);
                context.RegisterFixes(codeActions, diagnostic);
            }
        }
    }
Example #18
0
        private async Task CreateSpellCheckCodeIssueAsync(CodeFixContext context, TSimpleName nameNode, string nameText, CancellationToken cancellationToken)
        {
            var document       = context.Document;
            var service        = CompletionService.GetService(document);
            var completionList = await service.GetCompletionsAsync(
                document, nameNode.SpanStart, cancellationToken : cancellationToken).ConfigureAwait(false);

            if (completionList == null)
            {
                return;
            }

            var onlyConsiderGenerics = IsGeneric(nameNode);
            var results = new MultiDictionary <double, string>();

            using (var similarityChecker = new WordSimilarityChecker(nameText, substringsAreSimilar: true))
            {
                foreach (var item in completionList.Items)
                {
                    if (onlyConsiderGenerics && !IsGeneric(item))
                    {
                        continue;
                    }

                    var    candidateText = item.FilterText;
                    double matchCost;
                    if (!similarityChecker.AreSimilar(candidateText, out matchCost))
                    {
                        continue;
                    }

                    var insertionText = await GetInsertionTextAsync(document, item, cancellationToken : cancellationToken).ConfigureAwait(false);

                    results.Add(matchCost, insertionText);
                }
            }

            var matches = results.OrderBy(kvp => kvp.Key)
                          .SelectMany(kvp => kvp.Value.Order())
                          .Where(t => t != nameText)
                          .Take(3)
                          .Select(n => CreateCodeAction(nameNode, nameText, n, document));

            context.RegisterFixes(matches, context.Diagnostics);
        }
Example #19
0
        private async Task CreateSpellCheckCodeIssueAsync(CodeFixContext context, TSimpleName nameNode, string nameText, CancellationToken cancellationToken)
        {
            var document       = context.Document;
            var completionList = await CompletionService.GetCompletionListAsync(
                document, nameNode.SpanStart, CompletionTriggerInfo.CreateInvokeCompletionTriggerInfo(), cancellationToken : cancellationToken).ConfigureAwait(false);

            if (completionList == null)
            {
                return;
            }

            var completionRules      = CompletionService.GetCompletionRules(document);
            var onlyConsiderGenerics = IsGeneric(nameNode);
            var results = new MultiDictionary <double, string>();

            int closeMatchThreshold = EditDistance.GetCloseMatchThreshold(nameText);

            foreach (var item in completionList.Items)
            {
                if (onlyConsiderGenerics && !IsGeneric(item))
                {
                    continue;
                }

                var    candidateText = item.FilterText;
                double matchCost;
                if (!EditDistance.IsCloseMatch(nameText, candidateText, closeMatchThreshold, out matchCost))
                {
                    continue;
                }

                var insertionText = completionRules.GetTextChange(item).NewText;
                results.Add(matchCost, insertionText);
            }

            var matches = results.OrderBy(kvp => kvp.Key)
                          .SelectMany(kvp => kvp.Value.Order())
                          .Where(t => t != nameText)
                          .Take(3)
                          .Select(n => CreateCodeAction(nameNode, nameText, n, document));

            context.RegisterFixes(matches, context.Diagnostics);
        }
Example #20
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var span              = context.Span;
            var cancellationToken = context.CancellationToken;
            var diagnostics       = context.Diagnostics;

            var addImportService = document.GetLanguageService <IAddImportFeatureService>();

            var solution = document.Project.Solution;
            var options  = solution.Options;

            var searchReferenceAssemblies = options.GetOption(SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, document.Project.Language);
            var searchNuGetPackages       = options.GetOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages, document.Project.Language);

            var symbolSearchService = searchReferenceAssemblies || searchNuGetPackages
                ? _symbolSearchService ?? solution.Workspace.Services.GetService <ISymbolSearchService>()
                : null;

            var installerService = GetPackageInstallerService(document);
            var packageSources   = searchNuGetPackages && symbolSearchService != null && installerService?.IsEnabled(document.Project.Id) == true
                ? await installerService.TryGetPackageSourcesAsync(allowSwitchToMainThread : false, context.CancellationToken).ConfigureAwait(false)
                : ImmutableArray <PackageSource> .Empty;

            if (packageSources is null)
            {
                // Information about package sources is not available. This code fix cannot provide results for NuGet
                // packages at this time, but future invocations of the code fix will work. For the current code fix
                // operation, just treat the package sources as empty.
                packageSources = ImmutableArray <PackageSource> .Empty;
            }

            var fixesForDiagnostic = await addImportService.GetFixesForDiagnosticsAsync(
                document, span, diagnostics, MaxResults, symbolSearchService, searchReferenceAssemblies, packageSources.Value, cancellationToken).ConfigureAwait(false);

            foreach (var(diagnostic, fixes) in fixesForDiagnostic)
            {
                // Limit the results returned since this will be displayed to the user
                var codeActions = addImportService.GetCodeActionsForFixes(document, fixes, installerService, MaxResults);
                context.RegisterFixes(codeActions, diagnostic);
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            // NOTE(DustinCa): Not supported in REPL for now.
            if (context.Document.SourceCodeKind == SourceCodeKind.Interactive)
            {
                return;
            }

            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
            var names = GetTargetNodes(root, context.Span);
            foreach (var name in names)
            {
                var codeActions = await GetCodeActionsAsync(context.Document, name, context.CancellationToken).ConfigureAwait(false);
                if (codeActions == null || codeActions.IsEmpty())
                {
                    continue;
                }

                context.RegisterFixes(codeActions, context.Diagnostics);
                return;
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            // TODO: https://github.com/dotnet/roslyn/issues/5777
            // Not supported in REPL for now.
            if (context.Project.IsSubmission)
            {
                return;
            }

            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
            var names = GetTargetNodes(root, context.Span);
            foreach (var name in names)
            {
                var codeActions = await GetCodeActionsAsync(context.Document, name, context.CancellationToken).ConfigureAwait(false);
                if (codeActions == null || codeActions.IsEmpty())
                {
                    continue;
                }

                context.RegisterFixes(codeActions, context.Diagnostics);
                return;
            }
        }
Example #23
0
        private void RegisterFixForMethodOverloads(
            CodeFixContext context,
            SeparatedSyntaxList <TArgumentSyntax> arguments,
            ImmutableArray <ArgumentInsertPositionData <TArgumentSyntax> > methodsAndArgumentsToAdd)
        {
            var codeFixData = PrepareCreationOfCodeActions(context.Document, arguments, methodsAndArgumentsToAdd);

            // To keep the list of offered fixes short we create one menu entry per overload only
            // as long as there are two or less overloads present. If there are more overloads we
            // create two menu entries. One entry for non-cascading fixes and one with cascading fixes.
            var fixes = codeFixData.Length <= 2
                ? NestByOverload()
                : NestByCascading();

            context.RegisterFixes(fixes, context.Diagnostics);
            return;

            ImmutableArray <CodeAction> NestByOverload()
            {
                var builder = ArrayBuilder <CodeAction> .GetInstance(codeFixData.Length);

                foreach (var data in codeFixData)
                {
                    // We create the mandatory data.CreateChangedSolutionNonCascading fix first.
                    var        title      = GetCodeFixTitle(FeaturesResources.Add_parameter_to_0, data.Method, includeParameters: true);
                    CodeAction codeAction = new MyCodeAction(
                        title: title,
                        data.CreateChangedSolutionNonCascading);
                    if (data.CreateChangedSolutionCascading != null)
                    {
                        // We have two fixes to offer. We nest the two fixes in an inlinable CodeAction
                        // so the IDE is free to either show both at once or to create a sub-menu.
                        var titleForNesting = GetCodeFixTitle(FeaturesResources.Add_parameter_to_0, data.Method, includeParameters: true);
                        var titleCascading  = GetCodeFixTitle(FeaturesResources.Add_parameter_to_0_and_overrides_implementations, data.Method,
                                                              includeParameters: true);
                        codeAction = new CodeAction.CodeActionWithNestedActions(
                            title: titleForNesting,
                            ImmutableArray.Create(
                                codeAction,
                                new MyCodeAction(
                                    title: titleCascading,
                                    data.CreateChangedSolutionCascading)),
                            isInlinable: true);
                    }

                    // codeAction is now either a single fix or two fixes wrapped in a CodeActionWithNestedActions
                    builder.Add(codeAction);
                }

                return(builder.ToImmutableAndFree());
            }

            ImmutableArray <CodeAction> NestByCascading()
            {
                var builder = ArrayBuilder <CodeAction> .GetInstance(2);

                var nonCascadingActions = ImmutableArray.CreateRange <CodeFixData, CodeAction>(codeFixData, data =>
                {
                    var title = GetCodeFixTitle(FeaturesResources.Add_to_0, data.Method, includeParameters: true);
                    return(new MyCodeAction(title: title, data.CreateChangedSolutionNonCascading));
                });

                var cascading        = codeFixData.Where(data => data.CreateChangedSolutionCascading != null);
                var cascadingActions = ImmutableArray.CreateRange <CodeAction>(cascading.Select(data =>
                {
                    var title = GetCodeFixTitle(FeaturesResources.Add_to_0, data.Method, includeParameters: true);
                    return(new MyCodeAction(title: title, data.CreateChangedSolutionCascading));
                }));

                var aMethod = codeFixData.First().Method; // We need to term the MethodGroup and need an arbitrary IMethodSymbol to do so.
                var nestedNonCascadingTitle = GetCodeFixTitle(FeaturesResources.Add_parameter_to_0, aMethod, includeParameters: false);

                // Create a sub-menu entry with all the non-cascading CodeActions.
                // We make sure the IDE does not inline. Otherwise the context menu gets flooded with our fixes.
                builder.Add(new CodeAction.CodeActionWithNestedActions(nestedNonCascadingTitle, nonCascadingActions, isInlinable: false));

                if (cascadingActions.Length > 0)
                {
                    // if there are cascading CodeActions create a second sub-menu.
                    var nestedCascadingTitle = GetCodeFixTitle(FeaturesResources.Add_parameter_to_0_and_overrides_implementations,
                                                               aMethod, includeParameters: false);
                    builder.Add(new CodeAction.CodeActionWithNestedActions(nestedCascadingTitle, cascadingActions, isInlinable: false));
                }

                return(builder.ToImmutableAndFree());
            }
        }
Example #24
0
        public async override Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var cancellationToken = context.CancellationToken;
            var span        = context.Span;
            var diagnostics = context.Diagnostics;
            var model       = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var diagnostic = diagnostics.First();
            var node       = root.FindToken(context.Span.Start).Parent as LiteralExpressionSyntax;

            if (node == null)
            {
                return;
            }
            var argumentList = node.Parent.Parent as ArgumentListSyntax;

            var objectCreateExpression = argumentList.Parent as ObjectCreationExpressionSyntax;
            var validNames             = NotResolvedInTextAnalyzer.GetValidParameterNames(objectCreateExpression);
            var guessName = NotResolvedInTextAnalyzer.GuessParameterName(model, objectCreateExpression, validNames);

            ExpressionSyntax paramNode;
            ExpressionSyntax altParamNode;
            bool             canAddParameterName;

            NotResolvedInTextAnalyzer.CheckExceptionType(model, objectCreateExpression, out paramNode, out altParamNode, out canAddParameterName);

            if (diagnostic.Id == CSharpDiagnosticIDs.NotResolvedInTextAnalyzer_SwapID)
            {
                context.RegisterCodeFix(
                    CodeActionFactory.Create(
                        node.Span,
                        diagnostic.Severity,
                        GettextCatalog.GetString("Swap parameter"),
                        (token) =>
                {
                    var list = new List <ArgumentSyntax>();
                    foreach (var arg in argumentList.Arguments)
                    {
                        if (arg.Expression == paramNode)
                        {
                            list.Add((Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax)altParamNode.Parent);
                            continue;
                        }
                        if (arg.Expression == altParamNode)
                        {
                            list.Add((Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax)paramNode.Parent);
                            continue;
                        }

                        list.Add(arg);
                    }
                    var newRoot = root.ReplaceNode(argumentList, SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(list)).WithAdditionalAnnotations(Formatter.Annotation));
                    return(Task.FromResult(document.WithSyntaxRoot(newRoot)));
                }
                        ),
                    diagnostic
                    );
            }
            else if (diagnostic.Id == CSharpDiagnosticIDs.NotResolvedInTextAnalyzerID)
            {
                var fixes = new List <CodeAction>();
                if (canAddParameterName)
                {
                    fixes.Add(
                        CodeActionFactory.Create(
                            node.Span,
                            diagnostic.Severity,
                            string.Format(GettextCatalog.GetString("Add '\"{0}\"' parameter."), guessName),
                            (token) =>
                    {
                        var newArgument = SyntaxFactory.ParseExpression('"' + guessName + '"');
                        var newRoot     = root.ReplaceNode(argumentList, argumentList.WithArguments(argumentList.Arguments.Insert(0, SyntaxFactory.Argument(newArgument))).WithAdditionalAnnotations(Formatter.Annotation));
                        return(Task.FromResult(document.WithSyntaxRoot(newRoot)));
                    }
                            )
                        );
                }

                fixes.Add(CodeActionFactory.Create(
                              node.Span,
                              diagnostic.Severity,
                              string.Format(GettextCatalog.GetString("Replace with '\"{0}\"'."), guessName),
                              (token) =>
                {
                    var newArgument = SyntaxFactory.ParseExpression('"' + guessName + '"');
                    var newRoot     = root.ReplaceNode(node, newArgument.WithLeadingTrivia(node.GetLeadingTrivia()).WithTrailingTrivia(node.GetTrailingTrivia()));
                    return(Task.FromResult(document.WithSyntaxRoot(newRoot)));
                }
                              ));

                context.RegisterFixes(
                    fixes,
                    diagnostic
                    );
            }
        }
        private void RegisterFixForMethodOverloads(
            CodeFixContext context,
            SeparatedSyntaxList <TArgumentSyntax> arguments,
            ImmutableArray <ArgumentInsertPositionData <TArgumentSyntax> > methodsAndArgumentsToAdd)
        {
            var codeFixData = PrepareCreationOfCodeActions(context.Document, arguments, methodsAndArgumentsToAdd);

            // To keep the list of offered fixes short we create one menu entry per overload only
            // as long as there are two or less overloads present. If there are more overloads we
            // create two menu entries. One entry for non-cascading fixes and one with cascading fixes.
            var fixes = codeFixData.Length <= 2
                ? NestByOverload()
                : NestByCascading();

            context.RegisterFixes(fixes, context.Diagnostics);
            return;

            ImmutableArray <CodeAction> NestByOverload()
            {
                using var builderDisposer = ArrayBuilder <CodeAction> .GetInstance(codeFixData.Length, out var builder);

                foreach (var data in codeFixData)
                {
                    // We create the mandatory data.CreateChangedSolutionNonCascading fix first.
                    var title      = GetCodeFixTitle(FeaturesResources.Add_parameter_to_0, data.Method, includeParameters: true);
                    var codeAction = CodeAction.Create(
                        title,
                        data.CreateChangedSolutionNonCascading,
                        equivalenceKey: title);
                    if (data.CreateChangedSolutionCascading != null)
                    {
                        // We have two fixes to offer. We nest the two fixes in an inlinable CodeAction
                        // so the IDE is free to either show both at once or to create a sub-menu.
                        var titleForNesting = GetCodeFixTitle(FeaturesResources.Add_parameter_to_0, data.Method, includeParameters: true);
                        var titleCascading  = GetCodeFixTitle(FeaturesResources.Add_parameter_to_0_and_overrides_implementations, data.Method,
                                                              includeParameters: true);
                        codeAction = CodeAction.CodeActionWithNestedActions.Create(
                            title: titleForNesting,
                            ImmutableArray.Create(
                                codeAction,
                                CodeAction.Create(
                                    titleCascading,
                                    data.CreateChangedSolutionCascading,
                                    equivalenceKey: titleCascading)),
                            isInlinable: true);
                    }

                    // codeAction is now either a single fix or two fixes wrapped in a CodeActionWithNestedActions
                    builder.Add(codeAction);
                }

                return(builder.ToImmutable());
            }

            ImmutableArray <CodeAction> NestByCascading()
            {
                using var builderDisposer = ArrayBuilder <CodeAction> .GetInstance(capacity : 2, out var builder);

                var nonCascadingActions = codeFixData.SelectAsArray(data =>
                {
                    var title = GetCodeFixTitle(FeaturesResources.Add_to_0, data.Method, includeParameters: true);
                    return(CodeAction.Create(title, data.CreateChangedSolutionNonCascading, equivalenceKey: title));
                });

                var cascadingActions = codeFixData.SelectAsArray(
                    data => data.CreateChangedSolutionCascading != null,
                    data =>
                {
                    var title = GetCodeFixTitle(FeaturesResources.Add_to_0, data.Method, includeParameters: true);
                    return(CodeAction.Create(title, data.CreateChangedSolutionCascading !, equivalenceKey: title));
                });
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            // Not supported in REPL
            if (context.Project.IsSubmission)
            {
                return;
            }

            var document          = context.Document;
            var cancellationToken = context.CancellationToken;
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var span  = context.Span;
            var token = root.FindToken(span.Start);

            var deconstruction = token.GetAncestors <SyntaxNode>()
                                 .FirstOrDefault(n => n.IsKind(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.ForStatement));

            if (deconstruction is null)
            {
                Debug.Fail("The diagnostic can only be produced in context of a deconstruction-assignment or deconstruction-foreach");
                return;
            }

            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            DeconstructionInfo info;
            ITypeSymbol        type;
            ExpressionSyntax   target;

            switch (deconstruction)
            {
            case ForStatementSyntax @foreach:
                info   = model.GetDeconstructionInfo(@foreach);
                type   = model.GetForEachStatementInfo(@foreach).ElementType;
                target = @foreach.Variable;
                break;

            case AssignmentExpressionSyntax assignment:
                info   = model.GetDeconstructionInfo(assignment);
                type   = model.GetTypeInfo(assignment.Right).Type;
                target = assignment.Left;
                break;

            default:
                throw ExceptionUtilities.Unreachable;
            }

            if (type?.Kind != SymbolKind.NamedType)
            {
                return;
            }

            if (info.Method != null || !info.Nested.IsEmpty)
            {
                // There is already a Deconstruct method, or we have a nesting situation
                return;
            }

            var service     = document.GetLanguageService <IGenerateDeconstructMemberService>();
            var codeActions = await service.GenerateDeconstructMethodAsync(document, target, (INamedTypeSymbol)type, cancellationToken).ConfigureAwait(false);

            Debug.Assert(!codeActions.IsDefault);
            context.RegisterFixes(codeActions, context.Diagnostics);
        }
Example #27
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document = context.Document;

            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }
            var span = context.Span;
            var cancellationToken = context.CancellationToken;

            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }
            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            if (model.IsFromGeneratedCode(cancellationToken))
            {
                return;
            }
            var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);

            var diagnostic = context.Diagnostics.First();
            var syntaxNode = root.FindNode(span);
            var node       = syntaxNode as MethodDeclarationSyntax;

            if (node != null && node.Identifier.Span.Contains(span))
            {
                context.RegisterFixes(
                    new[] {
                    CodeActionFactory.Create(
                        node.Span,
                        DiagnosticSeverity.Error,
                        GettextCatalog.GetString("This is a constructor"),
                        t => Task.FromResult(
                            document.WithSyntaxRoot(
                                root.ReplaceNode(
                                    (SyntaxNode)node,
                                    node.WithIdentifier(node.AncestorsAndSelf().OfType <BaseTypeDeclarationSyntax> ().First().Identifier.WithoutTrivia()).WithAdditionalAnnotations(Formatter.Annotation)
                                    )
                                )
                            )
                        ),
                    CodeActionFactory.Create(
                        node.Span,
                        DiagnosticSeverity.Error,
                        GettextCatalog.GetString("This is a void method"),
                        t => Task.FromResult(
                            document.WithSyntaxRoot(
                                root.ReplaceNode(
                                    (SyntaxNode)node,
                                    node.WithReturnType(SyntaxFactory.ParseTypeName("void")).WithAdditionalAnnotations(Formatter.Annotation)
                                    )
                                )
                            )
                        )
                },
                    diagnostic
                    );
            }
            var constructor = syntaxNode as MethodDeclarationSyntax;

            if (constructor != null)
            {
                context.RegisterFixes(
                    new[] {
                    CodeActionFactory.Create(
                        node.Span,
                        DiagnosticSeverity.Error,
                        GettextCatalog.GetString("Fix constructor"),
                        t => Task.FromResult(
                            document.WithSyntaxRoot(
                                root.ReplaceNode(
                                    (SyntaxNode)node,
                                    node.WithIdentifier(node.AncestorsAndSelf().OfType <BaseTypeDeclarationSyntax> ().First().Identifier.WithoutTrivia()).WithAdditionalAnnotations(Formatter.Annotation)
                                    )
                                )
                            )
                        )
                },
                    diagnostic
                    );
            }
        }