Exemple #1
0
            private static async Task <Document> BatchPragmaFixesAsync(
                AbstractSuppressionCodeFixProvider suppressionFixProvider,
                Document document,
                ImmutableArray <IPragmaBasedCodeAction> pragmaActions,
                ImmutableArray <Diagnostic> diagnostics,
                CancellationToken cancellationToken)
            {
                // We apply all the pragma suppression fixes sequentially.
                // At every application, we track the updated locations for remaining diagnostics in the document.
                var currentDiagnosticSpans = new Dictionary <Diagnostic, TextSpan>();

                foreach (var diagnostic in diagnostics)
                {
                    currentDiagnosticSpans.Add(diagnostic, diagnostic.Location.SourceSpan);
                }

                var currentDocument = document;

                for (int i = 0; i < pragmaActions.Length; i++)
                {
                    var originalpragmaAction = pragmaActions[i];
                    var diagnostic           = diagnostics[i];

                    // Get the diagnostic span for the diagnostic in latest document snapshot.
                    TextSpan currentDiagnosticSpan;
                    if (!currentDiagnosticSpans.TryGetValue(diagnostic, out currentDiagnosticSpan))
                    {
                        // Diagnostic whose location conflicts with a prior fix.
                        continue;
                    }

                    // Compute and apply pragma suppression fix.
                    var currentTree = await currentDocument.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                    var currentLocation = Location.Create(currentTree, currentDiagnosticSpan);
                    diagnostic = Diagnostic.Create(
                        id: diagnostic.Id,
                        category: diagnostic.Descriptor.Category,
                        message: diagnostic.GetMessage(),
                        severity: diagnostic.Severity,
                        defaultSeverity: diagnostic.DefaultSeverity,
                        isEnabledByDefault: diagnostic.Descriptor.IsEnabledByDefault,
                        warningLevel: diagnostic.WarningLevel,
                        title: diagnostic.Descriptor.Title,
                        description: diagnostic.Descriptor.Description,
                        helpLink: diagnostic.Descriptor.HelpLinkUri,
                        location: currentLocation,
                        additionalLocations: diagnostic.AdditionalLocations,
                        customTags: diagnostic.Descriptor.CustomTags,
                        properties: diagnostic.Properties,
                        isSuppressed: diagnostic.IsSuppressed);

                    var newSuppressionFixes = await suppressionFixProvider.GetSuppressionsAsync(currentDocument, currentDiagnosticSpan, SpecializedCollections.SingletonEnumerable(diagnostic), cancellationToken).ConfigureAwait(false);

                    var newSuppressionFix = newSuppressionFixes.SingleOrDefault();
                    if (newSuppressionFix != null)
                    {
                        var newPragmaAction = newSuppressionFix.Action as IPragmaBasedCodeAction ??
                                              newSuppressionFix.Action.GetCodeActions().OfType <IPragmaBasedCodeAction>().SingleOrDefault();
                        if (newPragmaAction != null)
                        {
                            // Get the changed document with pragma suppression add/removals.
                            // Note: We do it one token at a time to ensure we get single text change in the new document, otherwise UpdateDiagnosticSpans won't function as expected.
                            // Update the diagnostics spans based on the text changes.
                            var startTokenChanges = await GetChangedDocumentAsync(newPragmaAction, currentDocument, diagnostics, currentDiagnosticSpans,
                                                                                  includeStartTokenChange : true, includeEndTokenChange : false, cancellationToken : cancellationToken).ConfigureAwait(false);

                            var endTokenChanges = await GetChangedDocumentAsync(newPragmaAction, currentDocument, diagnostics, currentDiagnosticSpans,
                                                                                includeStartTokenChange : false, includeEndTokenChange : true, cancellationToken : cancellationToken).ConfigureAwait(false);

                            var currentText = await currentDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);

                            var orderedChanges = startTokenChanges.Concat(endTokenChanges).OrderBy(change => change.Span).Distinct();
                            var newText        = currentText.WithChanges(orderedChanges);
                            currentDocument = currentDocument.WithText(newText);
                        }
                    }
                }

                return(currentDocument);
            }
        protected override async Task <SyntaxNode> RewriteFieldNameAndAccessibilityAsync(string originalFieldName, bool makePrivate, Document document, SyntaxAnnotation declarationAnnotation, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var declarator = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(declarationAnnotation).FirstOrDefault();

            // There may be no field to rewrite if this document is part of a set of linked files
            // and the declaration is not conditionally compiled in this document's project.
            if (declarator == null)
            {
                return(root);
            }

            var tempAnnotation = new SyntaxAnnotation();
            var escapedName    = originalFieldName.EscapeIdentifier();
            var newIdentifier  = SyntaxFactory.Identifier(
                leading: SyntaxTriviaList.Create(SyntaxFactory.ElasticMarker),
                contextualKind: SyntaxKind.IdentifierName,
                text: escapedName,
                valueText: originalFieldName,
                trailing: SyntaxTriviaList.Create(SyntaxFactory.ElasticMarker))
                                 .WithTrailingTrivia(declarator.Identifier.TrailingTrivia)
                                 .WithLeadingTrivia(declarator.Identifier.LeadingTrivia);

            var updatedDeclarator = declarator.WithIdentifier(newIdentifier).WithAdditionalAnnotations(tempAnnotation);

            root     = root.ReplaceNode(declarator, updatedDeclarator);
            document = document.WithSyntaxRoot(root);

            var declaration = root.GetAnnotatedNodes <SyntaxNode>(tempAnnotation).First().Parent as VariableDeclarationSyntax;

            if (declaration.Variables.Count == 1)
            {
                var fieldSyntax = declaration.Parent as FieldDeclarationSyntax;

                var modifierKinds = new[] { SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.InternalKeyword, SyntaxKind.PublicKeyword };

                if (makePrivate)
                {
                    var modifiers = SpecializedCollections.SingletonEnumerable(SyntaxFactory.Token(SyntaxKind.PrivateKeyword))
                                    .Concat(fieldSyntax.Modifiers.Where(m => !modifierKinds.Contains(m.Kind())));

                    root = root.ReplaceNode(fieldSyntax, fieldSyntax.WithModifiers(
                                                SyntaxFactory.TokenList(modifiers))
                                            .WithAdditionalAnnotations(Formatter.Annotation)
                                            .WithLeadingTrivia(fieldSyntax.GetLeadingTrivia())
                                            .WithTrailingTrivia(fieldSyntax.GetTrailingTrivia()));
                }
            }
            else if (declaration.Variables.Count > 1 && makePrivate)
            {
                document = document.WithSyntaxRoot(root);
                var codeGenService = document.GetLanguageService <ICodeGenerationService>();
                var semanticModel  = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

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

                declarator  = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(tempAnnotation).First();
                declaration = declarator.Parent as VariableDeclarationSyntax;

                var field = semanticModel.GetDeclaredSymbol(declarator, cancellationToken) as IFieldSymbol;

                var fieldToAdd = declarationAnnotation.AddAnnotationToSymbol(CodeGenerationSymbolFactory.CreateFieldSymbol(
                                                                                 field.GetAttributes(),
                                                                                 Accessibility.Private,
                                                                                 new DeclarationModifiers(isStatic: field.IsStatic, isReadOnly: field.IsReadOnly, isConst: field.IsConst),
                                                                                 field.Type,
                                                                                 field.Name,
                                                                                 field.HasConstantValue,
                                                                                 field.ConstantValue,
                                                                                 declarator.Initializer));

                var withField = await codeGenService.AddFieldAsync(
                    new CodeGenerationSolutionContext(
                        document.Project.Solution,
                        CodeGenerationContext.Default,
                        fallbackOptions),
                    field.ContainingType,
                    fieldToAdd,
                    cancellationToken).ConfigureAwait(false);

                root = await withField.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                declarator  = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(tempAnnotation).First();
                declaration = declarator.Parent as VariableDeclarationSyntax;

                return(root.RemoveNode(declarator, SyntaxRemoveOptions.KeepNoTrivia));
            }

            return(root);
        }
 private IEnumerable <INamedTypeSymbol> ResolveErrorTypesWorker(Compilation compilation, bool ignoreAssemblyKey)
 {
     return(_containerKey == null
         ? SpecializedCollections.EmptyEnumerable <INamedTypeSymbol>()
         : ResolveErrorTypeWithContainer(compilation, ignoreAssemblyKey));
 }
Exemple #4
0
            internal void ApplyConflictResolutionEdits(IInlineRenameReplacementInfo conflictResolution, LinkedFileMergeSessionResult mergeResult, IEnumerable <Document> documents, CancellationToken cancellationToken)
            {
                AssertIsForeground();

                if (!AreAllReferenceSpansMappable())
                {
                    // don't dynamically update the reference spans for documents with unmappable projections
                    return;
                }

                using (new SelectionTracking(this))
                {
                    // 1. Undo any previous edits and update the buffer to resulting document after conflict resolution
                    _session.UndoManager.UndoTemporaryEdits(_subjectBuffer, disconnect: false);

                    var newDocument      = mergeResult.MergedSolution.GetDocument(documents.First().Id);
                    var originalDocument = _baseDocuments.Single(d => d.Id == newDocument.Id);

                    var changes = GetTextChangesFromTextDifferencingServiceAsync(originalDocument, newDocument, cancellationToken).WaitAndGetResult(cancellationToken);

                    // TODO: why does the following line hang when uncommented?
                    // newDocument.GetTextChangesAsync(this.baseDocuments.Single(d => d.Id == newDocument.Id), cancellationToken).WaitAndGetResult(cancellationToken).Reverse();

                    _session.UndoManager.CreateConflictResolutionUndoTransaction(_subjectBuffer, () =>
                    {
                        using (var edit = _subjectBuffer.CreateEdit(EditOptions.DefaultMinimalChange, null, s_propagateSpansEditTag))
                        {
                            foreach (var change in changes)
                            {
                                edit.Replace(change.Span.Start, change.Span.Length, change.NewText);
                            }

                            edit.ApplyAndLogExceptions();
                        }
                    });

                    // 2. We want to update referenceSpanToLinkedRenameSpanMap where spans were affected by conflict resolution.
                    // We also need to add the remaining document edits to conflictResolutionRenameTrackingSpans
                    // so they get classified/tagged correctly in the editor.
                    _conflictResolutionRenameTrackingSpans.Clear();

                    var documentReplacements = documents
                                               .Select(document => (document, conflictResolution.GetReplacements(document.Id).Where(r => GetRenameSpanKind(r.Kind) != RenameSpanKind.None).ToImmutableArray()))
                                               .ToImmutableArray();

                    var firstDocumentReplacements     = documentReplacements.FirstOrDefault(d => !d.Item2.IsEmpty);
                    var bufferContainsLinkedDocuments = documentReplacements.Length > 1 && firstDocumentReplacements.document != null;
                    var linkedDocumentsMightConflict  = bufferContainsLinkedDocuments;
                    if (linkedDocumentsMightConflict)
                    {
                        // When changes are made and linked documents are involved, some of the linked documents may
                        // have changes that differ from others. When these changes conflict (both differ and overlap),
                        // the inline rename UI reveals the conflicts. However, the merge process for finding these
                        // conflicts is slow, so we want to avoid it when possible. This code block attempts to set
                        // linkedDocumentsMightConflict back to false, eliminating the need to merge the changes as part
                        // of the conflict detection process. Currently we only special case one scenario: ignoring
                        // documents that have no changes at all, we check if all linked documents have exactly the same
                        // set of changes.

                        // 1. Check if all documents have the same replacement spans (or no replacements)
                        var spansMatch = true;
                        foreach (var(document, replacements) in documentReplacements)
                        {
                            if (document == firstDocumentReplacements.document || replacements.IsEmpty)
                            {
                                continue;
                            }

                            if (replacements.Length != firstDocumentReplacements.Item2.Length)
                            {
                                spansMatch = false;
                                break;
                            }

                            for (var i = 0; i < replacements.Length; i++)
                            {
                                if (!replacements[i].Equals(firstDocumentReplacements.Item2[i]))
                                {
                                    spansMatch = false;
                                    break;
                                }
                            }

                            if (!spansMatch)
                            {
                                break;
                            }
                        }

                        // 2. If spans match, check content
                        if (spansMatch)
                        {
                            linkedDocumentsMightConflict = false;

                            // Only need to check the new span's content
                            var firstDocumentNewText     = conflictResolution.NewSolution.GetDocument(firstDocumentReplacements.document.Id).GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken);
                            var firstDocumentNewSpanText = firstDocumentReplacements.Item2.SelectAsArray(replacement => firstDocumentNewText.ToString(replacement.NewSpan));
                            foreach (var(document, replacements) in documentReplacements)
                            {
                                if (document == firstDocumentReplacements.document || replacements.IsEmpty)
                                {
                                    continue;
                                }

                                var documentNewText = conflictResolution.NewSolution.GetDocument(document.Id).GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken);
                                for (var i = 0; i < replacements.Length; i++)
                                {
                                    if (documentNewText.ToString(replacements[i].NewSpan) != firstDocumentNewSpanText[i])
                                    {
                                        // Have to use the slower merge process
                                        linkedDocumentsMightConflict = true;
                                        break;
                                    }
                                }

                                if (linkedDocumentsMightConflict)
                                {
                                    break;
                                }
                            }
                        }
                    }

                    foreach (var document in documents)
                    {
                        var relevantReplacements = conflictResolution.GetReplacements(document.Id).Where(r => GetRenameSpanKind(r.Kind) != RenameSpanKind.None);
                        if (!relevantReplacements.Any())
                        {
                            continue;
                        }

                        var mergedReplacements = linkedDocumentsMightConflict
                            ? GetMergedReplacementInfos(
                            relevantReplacements,
                            conflictResolution.NewSolution.GetDocument(document.Id),
                            mergeResult.MergedSolution.GetDocument(document.Id),
                            cancellationToken)
                            : relevantReplacements;

                        // Show merge conflicts comments as unresolvable conflicts, and do not
                        // show any other rename-related spans that overlap a merge conflict comment.
                        var mergeConflictComments = mergeResult.MergeConflictCommentSpans.ContainsKey(document.Id)
                            ? mergeResult.MergeConflictCommentSpans[document.Id]
                            : SpecializedCollections.EmptyEnumerable <TextSpan>();

                        foreach (var conflict in mergeConflictComments)
                        {
                            // TODO: Add these to the unresolvable conflict counts in the dashboard

                            _conflictResolutionRenameTrackingSpans.Add(new RenameTrackingSpan(
                                                                           _subjectBuffer.CurrentSnapshot.CreateTrackingSpan(conflict.ToSpan(), SpanTrackingMode.EdgeInclusive, TrackingFidelityMode.Forward),
                                                                           RenameSpanKind.UnresolvedConflict));
                        }

                        foreach (var replacement in mergedReplacements)
                        {
                            var kind = GetRenameSpanKind(replacement.Kind);

                            if (_referenceSpanToLinkedRenameSpanMap.ContainsKey(replacement.OriginalSpan) && kind != RenameSpanKind.Complexified)
                            {
                                var linkedRenameSpan = _session._renameInfo.GetConflictEditSpan(
                                    new InlineRenameLocation(newDocument, replacement.NewSpan), _session.ReplacementText, cancellationToken);
                                if (linkedRenameSpan.HasValue)
                                {
                                    if (!mergeConflictComments.Any(s => replacement.NewSpan.IntersectsWith(s)))
                                    {
                                        _referenceSpanToLinkedRenameSpanMap[replacement.OriginalSpan] = new RenameTrackingSpan(
                                            _subjectBuffer.CurrentSnapshot.CreateTrackingSpan(
                                                linkedRenameSpan.Value.ToSpan(),
                                                SpanTrackingMode.EdgeInclusive,
                                                TrackingFidelityMode.Forward),
                                            kind);
                                    }
                                }
                                else
                                {
                                    // We might not have a renameable span if an alias conflict completely changed the text
                                    _referenceSpanToLinkedRenameSpanMap[replacement.OriginalSpan] = new RenameTrackingSpan(
                                        _referenceSpanToLinkedRenameSpanMap[replacement.OriginalSpan].TrackingSpan,
                                        RenameSpanKind.None);

                                    if (_activeSpan.HasValue && _activeSpan.Value.IntersectsWith(replacement.OriginalSpan))
                                    {
                                        _activeSpan = null;
                                    }
                                }
                            }
                            else
                            {
                                if (!mergeConflictComments.Any(s => replacement.NewSpan.IntersectsWith(s)))
                                {
                                    _conflictResolutionRenameTrackingSpans.Add(new RenameTrackingSpan(
                                                                                   _subjectBuffer.CurrentSnapshot.CreateTrackingSpan(replacement.NewSpan.ToSpan(), SpanTrackingMode.EdgeInclusive, TrackingFidelityMode.Forward),
                                                                                   kind));
                                }
                            }
                        }

                        if (!linkedDocumentsMightConflict)
                        {
                            break;
                        }
                    }

                    UpdateReadOnlyRegions();

                    // 3. Reset the undo state and notify the taggers.
                    this.ApplyReplacementText(updateSelection: false);
                    RaiseSpansChanged();
                }
            }
Exemple #5
0
        /// <summary>
        /// OBSOLETE: Use VerifyDiagnostics from Roslyn.Compilers.CSharp.Test.Utilities instead.
        /// </summary>
        public static void VerifyErrorCodes(IEnumerable <Diagnostic> actualErrors, params ErrorDescription[] expectedErrorDesp)
        {
            if (expectedErrorDesp == null)
            {
                return;
            }

            int expectedLength = expectedErrorDesp.Length;
            int actualLength   = actualErrors.Count();

            Assert.True(
                expectedLength == actualLength,
                String.Format(
                    "ErrCount {0} != {1}{2}Actual errors are:{2}{3}",
                    expectedLength,
                    actualLength,
                    Environment.NewLine,
                    actualLength == 0 ? "<none>" : string.Join(Environment.NewLine, actualErrors)));

            var actualSortedDesp = (from ae in
                                    (from e in actualErrors
                                     let lineSpan = e.Location.GetMappedLineSpan()
                                                    select new ErrorDescription
            {
                Code = e.Code,
                Line = lineSpan.IsValid ? lineSpan.StartLinePosition.Line + 1 : 0,
                Column = lineSpan.IsValid ? lineSpan.StartLinePosition.Character + 1 : 0,
                IsWarning = e.Severity == DiagnosticSeverity.Warning,
                Parameters = (e.Arguments != null && e.Arguments.Count > 0 && e.Arguments[0] != null) ?
                             e.Arguments.Select(x => x != null ? x.ToString() : null).ToArray() : SpecializedCollections.EmptyArray <string>()
            })
                                    orderby ae.Code, ae.Line, ae.Column
                                    select ae).ToList();

            var expectedSortedDesp = (from ee in expectedErrorDesp
                                      orderby ee.Code, ee.Line, ee.Column
                                      select ee).ToList();

            int idx = 0;

            // actual >= expected
            foreach (var experr in expectedSortedDesp)
            {
                while (idx < actualSortedDesp.Count && actualSortedDesp[idx].Code < experr.Code)
                {
                    idx++;
                }

                if (idx >= actualSortedDesp.Count)
                {
                    idx = actualSortedDesp.Count - 1;
                }

                var acterr = actualSortedDesp[idx];

                Assert.Equal(experr.Code, acterr.Code);
                if (experr.Line > 0 && experr.Column > 0)
                {
                    Assert.True(experr.Line == acterr.Line, String.Format("Line {0}!={1}", experr.Line, acterr.Line));
                    Assert.True(experr.Column == acterr.Column, String.Format("Col {0}!={1}", experr.Column, acterr.Column));
                }

                Assert.Equal(experr.IsWarning, acterr.IsWarning);

                //if the expected contains parameters, validate those too.
                if (experr.Parameters != null)
                {
                    Assert.True(experr.Parameters.SequenceEqual(acterr.Parameters), String.Format("Param: {0}!={1}", experr.Parameters.Count(), acterr.Parameters.Count()));
                }

                idx++;
            }
        }
        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 model      = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

            if (model.IsFromGeneratedCode(context.CancellationToken))
            {
                return;
            }

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

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

            // Has to be a simple identifier or generic name.
            if (node != null && CanFullyQualify(diagnostic, ref node))
            {
                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 != null || matchingNamespaces != null)
                {
                    matchingTypes      = matchingTypes ?? SpecializedCollections.EmptyEnumerable <ISymbol>();
                    matchingNamespaces = matchingNamespaces ?? SpecializedCollections.EmptyEnumerable <ISymbol>();

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

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

                    foreach (var container in proposedContainers)
                    {
                        var containerName = RoslynCompletionData.SafeMinimalDisplayString(container, semanticModel, node.SpanStart);

                        string name;
                        int    arity;
                        node.GetNameAndArityOfSimpleName(out name, out arity);

                        // Actual member name might differ by case.
                        string memberName;
                        if (this.IgnoreCase)
                        {
                            var member = container.GetMembers(name).FirstOrDefault();
                            memberName = member != null ? member.Name : name;
                        }
                        else
                        {
                            memberName = name;
                        }

                        var codeAction = new DocumentChangeAction(
                            node.Span,
                            DiagnosticSeverity.Info,
                            string.Format(GettextCatalog.GetString("Change '{0}' to '{1}.{2}'"), name, containerName, memberName),
                            (c) =>
                        {
                            var newRoot = this.ReplaceNode(node, containerName, c);
                            return(Task.FromResult(document.WithSyntaxRoot(newRoot)));
                        });

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }
                }
            }
        }
        private bool ApplySuppressionFix(IEnumerable <DiagnosticData> diagnosticsToFix, Func <Project, bool> shouldFixInProject, bool filterStaleDiagnostics, bool isAddSuppression, bool isSuppressionInSource, bool onlyCompilerDiagnostics, bool showPreviewChangesDialog)
        {
            if (diagnosticsToFix == null)
            {
                return(false);
            }

            diagnosticsToFix = FilterDiagnostics(diagnosticsToFix, isAddSuppression, isSuppressionInSource, onlyCompilerDiagnostics);
            if (diagnosticsToFix.IsEmpty())
            {
                // Nothing to fix.
                return(true);
            }

            ImmutableDictionary <Document, ImmutableArray <Diagnostic> > documentDiagnosticsToFixMap = null;
            ImmutableDictionary <Project, ImmutableArray <Diagnostic> >  projectDiagnosticsToFixMap  = null;

            var title                  = GetFixTitle(isAddSuppression);
            var waitDialogMessage      = GetWaitDialogMessage(isAddSuppression);
            var noDiagnosticsToFix     = false;
            var cancelled              = false;
            var newSolution            = _workspace.CurrentSolution;
            HashSet <string> languages = null;

            Action <IWaitContext> computeDiagnosticsAndFix = context =>
            {
                var cancellationToken = context.CancellationToken;
                cancellationToken.ThrowIfCancellationRequested();
                documentDiagnosticsToFixMap = GetDocumentDiagnosticsToFixAsync(diagnosticsToFix, shouldFixInProject, filterStaleDiagnostics: filterStaleDiagnostics, cancellationToken: cancellationToken)
                                              .WaitAndGetResult(cancellationToken);

                cancellationToken.ThrowIfCancellationRequested();
                projectDiagnosticsToFixMap = isSuppressionInSource ?
                                             ImmutableDictionary <Project, ImmutableArray <Diagnostic> > .Empty :
                                             GetProjectDiagnosticsToFixAsync(diagnosticsToFix, shouldFixInProject, filterStaleDiagnostics: filterStaleDiagnostics, cancellationToken: cancellationToken)
                                             .WaitAndGetResult(cancellationToken);

                if (documentDiagnosticsToFixMap == null ||
                    projectDiagnosticsToFixMap == null ||
                    (documentDiagnosticsToFixMap.IsEmpty && projectDiagnosticsToFixMap.IsEmpty))
                {
                    // Nothing to fix.
                    noDiagnosticsToFix = true;
                    return;
                }

                cancellationToken.ThrowIfCancellationRequested();

                // Equivalence key determines what fix will be applied.
                // Make sure we don't include any specific diagnostic ID, as we want all of the given diagnostics (which can have varied ID) to be fixed.
                var equivalenceKey = isAddSuppression ?
                                     (isSuppressionInSource ? FeaturesResources.SuppressWithPragma : FeaturesResources.SuppressWithGlobalSuppressMessage) :
                                     FeaturesResources.RemoveSuppressionEquivalenceKeyPrefix;

                // We have different suppression fixers for every language.
                // So we need to group diagnostics by the containing project language and apply fixes separately.
                languages = new HashSet <string>(projectDiagnosticsToFixMap.Keys.Select(p => p.Language).Concat(documentDiagnosticsToFixMap.Select(kvp => kvp.Key.Project.Language)));

                foreach (var language in languages)
                {
                    // Use the Fix multiple occurrences service to compute a bulk suppression fix for the specified document and project diagnostics,
                    // show a preview changes dialog and then apply the fix to the workspace.

                    cancellationToken.ThrowIfCancellationRequested();

                    var documentDiagnosticsPerLanguage = GetDocumentDiagnosticsMappedToNewSolution(documentDiagnosticsToFixMap, newSolution, language);
                    if (!documentDiagnosticsPerLanguage.IsEmpty)
                    {
                        var suppressionFixer = GetSuppressionFixer(documentDiagnosticsPerLanguage.SelectMany(kvp => kvp.Value), language, _codeFixService);
                        if (suppressionFixer != null)
                        {
                            var suppressionFixAllProvider = suppressionFixer.GetFixAllProvider();
                            newSolution = _fixMultipleOccurencesService.GetFix(
                                documentDiagnosticsPerLanguage,
                                _workspace,
                                suppressionFixer,
                                suppressionFixAllProvider,
                                equivalenceKey,
                                title,
                                waitDialogMessage,
                                cancellationToken);
                            if (newSolution == null)
                            {
                                // User cancelled or fixer threw an exception, so we just bail out.
                                cancelled = true;
                                return;
                            }
                        }
                    }

                    var projectDiagnosticsPerLanguage = GetProjectDiagnosticsMappedToNewSolution(projectDiagnosticsToFixMap, newSolution, language);
                    if (!projectDiagnosticsPerLanguage.IsEmpty)
                    {
                        var suppressionFixer = GetSuppressionFixer(projectDiagnosticsPerLanguage.SelectMany(kvp => kvp.Value), language, _codeFixService);
                        if (suppressionFixer != null)
                        {
                            var suppressionFixAllProvider = suppressionFixer.GetFixAllProvider();
                            newSolution = _fixMultipleOccurencesService.GetFix(
                                projectDiagnosticsPerLanguage,
                                _workspace,
                                suppressionFixer,
                                suppressionFixAllProvider,
                                equivalenceKey,
                                title,
                                waitDialogMessage,
                                cancellationToken);
                            if (newSolution == null)
                            {
                                // User cancelled or fixer threw an exception, so we just bail out.
                                cancelled = true;
                                return;
                            }
                        }
                    }
                }
            };

            var result = InvokeWithWaitDialog(computeDiagnosticsAndFix, title, waitDialogMessage);

            // Bail out if the user cancelled.
            if (cancelled || result == WaitIndicatorResult.Canceled)
            {
                return(false);
            }
            else if (noDiagnosticsToFix || newSolution == _workspace.CurrentSolution)
            {
                // No changes.
                return(true);
            }

            if (showPreviewChangesDialog)
            {
                newSolution = FixAllGetFixesService.PreviewChanges(
                    _workspace.CurrentSolution,
                    newSolution,
                    fixAllPreviewChangesTitle: title,
                    fixAllTopLevelHeader: title,
                    languageOpt: languages?.Count == 1 ? languages.Single() : null,
                    workspace: _workspace);
                if (newSolution == null)
                {
                    return(false);
                }
            }

            waitDialogMessage = isAddSuppression ? ServicesVSResources.ApplyingSuppressionFix : ServicesVSResources.ApplyingRemoveSuppressionFix;
            Action <IWaitContext> applyFix = context =>
            {
                var operations = SpecializedCollections.SingletonEnumerable <CodeActionOperation>(new ApplyChangesOperation(newSolution));
                _editHandlerService.Apply(
                    _workspace,
                    fromDocument: null,
                    operations: operations,
                    title: title,
                    progressTracker: context.ProgressTracker,
                    cancellationToken: context.CancellationToken);
            };

            result = InvokeWithWaitDialog(applyFix, title, waitDialogMessage);
            if (result == WaitIndicatorResult.Canceled)
            {
                return(false);
            }

            // Kick off diagnostic re-analysis for affected projects so that diagnostics gets refreshed.
            Task.Run(() =>
            {
                var reanalyzeDocuments = diagnosticsToFix.Where(d => d.DocumentId != null).Select(d => d.DocumentId).Distinct();
                _diagnosticService.Reanalyze(_workspace, documentIds: reanalyzeDocuments, highPriority: true);
            });

            return(true);
        }
 public IEnumerable <INestedTypeDefinition> GetNestedTypes(EmitContext context)
 {
     return(SpecializedCollections.EmptyEnumerable <INestedTypeDefinition>());
 }
 public IEnumerable <IPropertyDefinition> GetProperties(EmitContext context)
 {
     return(SpecializedCollections.EmptyEnumerable <IPropertyDefinition>());
 }
 private void OnDocumentActiveContextChanged(object sender, DocumentActiveContextChangedEventArgs e)
 {
     Reanalyze(e.Solution.Workspace, documentIds: SpecializedCollections.SingletonEnumerable(e.NewActiveContextDocumentId), highPriority: true);
 }
Exemple #11
0
 public static bool SpansPreprocessorDirective(this ISyntaxFactsService service, SyntaxNode node)
 => service.SpansPreprocessorDirective(SpecializedCollections.SingletonEnumerable(node));
Exemple #12
0
 public override IEnumerable <Cci.IFileReference> GetFiles(EmitContext context) => SpecializedCollections.EmptyEnumerable <Cci.IFileReference>();
        internal static void VerifyParamArrayAttribute(ParameterSymbol parameter, SourceModuleSymbol module, bool expected = true, OutputKind outputKind = OutputKind.ConsoleApplication)
        {
            Assert.Equal(expected, parameter.IsParams);

            var  emitModule = new PEAssemblyBuilder(module.ContainingSourceAssembly, null, outputKind, GetDefaultModulePropertiesForSerialization(), SpecializedCollections.EmptyEnumerable <ResourceDescription>());
            var  paramArrayAttributeCtor = (MethodSymbol)emitModule.Compilation.GetWellKnownTypeMember(WellKnownMember.System_ParamArrayAttribute__ctor);
            bool found = false;

            var context = new Microsoft.CodeAnalysis.Emit.Context(emitModule, null, new DiagnosticBag());

            foreach (Microsoft.Cci.ICustomAttribute attr in parameter.GetSynthesizedAttributes())
            {
                if (paramArrayAttributeCtor == (MethodSymbol)attr.Constructor(context))
                {
                    Assert.False(found, "Multiple ParamArrayAttribute");
                    found = true;
                }
            }

            Assert.Equal(expected, found);
            context.Diagnostics.Verify();
        }
 internal override IEnumerable <Cci.SecurityAttribute> GetSecurityInformation()
 {
     return(SpecializedCollections.EmptyEnumerable <Cci.SecurityAttribute>());
 }
Exemple #15
0
        private void ProcessUnreachableDiagnostic(
            SyntaxNodeAnalysisContext context, SyntaxNode root, TextSpan sourceSpan, bool fadeOutCode)
        {
            var node = root.FindNode(sourceSpan);

            // Note: this approach works as the language only supports the concept of
            // unreachable statements.  If we ever get unreachable subexpressions, then
            // we'll need to revise this code accordingly.
            var firstUnreachableStatement = node.FirstAncestorOrSelf <StatementSyntax>();

            if (firstUnreachableStatement == null ||
                firstUnreachableStatement.SpanStart != sourceSpan.Start)
            {
                return;
            }

            // At a high level, we can think about us wanting to fade out a "section" of unreachable
            // statements.  However, the compiler only reports the first statement in that "section".
            // We want to figure out what other statements are in that section and fade them all out
            // along with the first statement.  This is made somewhat tricky due to the fact that
            // subsequent sibling statements possibly being reachable due to explicit gotos+labels.
            //
            // On top of this, an unreachable section might not be contiguous.  This is possible
            // when there is unreachable code that contains a local function declaration in-situ.
            // This is legal, and the local function declaration may be called from other reachable code.
            //
            // As such, it's not possible to just get first unreachable statement, and the last, and
            // then report that whole region as unreachable.  Instead, when we are told about an
            // unreachable statement, we simply determine which other statements are also unreachable
            // and bucket them into contiguous chunks.
            //
            // We then fade each of these contiguous chunks, while also having each diagnostic we
            // report point back to the first unreachable statement so that we can easily determine
            // what to remove if the user fixes the issue.  (The fix itself has to go recompute this
            // as the total set of statements to remove may be larger than the actual faded code
            // that that diagnostic corresponds to).

            // Get the location of this first unreachable statement.  It will be given to all
            // the diagnostics we create off of this single compiler diagnostic so that we always
            // know how to find it regardless of which of our diagnostics the user invokes the
            // fix off of.
            var firstStatementLocation = root.SyntaxTree.GetLocation(firstUnreachableStatement.FullSpan);

            if (!firstUnreachableStatement.IsParentKind(SyntaxKind.Block) &&
                !firstUnreachableStatement.IsParentKind(SyntaxKind.SwitchSection))
            {
                // Can't actually remove this statement (it's an embedded statement in something
                // like an 'if-statement').  Just fade the code out, but don't offer to remove it.
                if (fadeOutCode)
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(UnnecessaryWithoutSuggestionDescriptor, firstStatementLocation));
                }
                return;
            }

            // 'additionalLocations' is how we always pass along the locaiton of the first unreachable
            // statement in this group.
            var additionalLocations = SpecializedCollections.SingletonEnumerable(firstStatementLocation);

            var descriptor = fadeOutCode ? UnnecessaryWithSuggestionDescriptor : HiddenDescriptor;

            context.ReportDiagnostic(
                Diagnostic.Create(descriptor, firstStatementLocation, additionalLocations));

            var sections = RemoveUnreachableCodeHelpers.GetSubsequentUnreachableSections(firstUnreachableStatement);

            foreach (var section in sections)
            {
                var span     = TextSpan.FromBounds(section[0].FullSpan.Start, section.Last().FullSpan.End);
                var location = root.SyntaxTree.GetLocation(span);

                // Mark subsequent sections as being 'cascaded'.  We don't need to actually process them
                // when doing a fix-all as they'll be scooped up when we process the fix for the first
                // section.
                context.ReportDiagnostic(
                    Diagnostic.Create(descriptor, location, additionalLocations, s_subsequentSectionProperties));
            }
        }
Exemple #16
0
 public IEnumerable <ICustomAttribute> GetAttributes(EmitContext context)
 {
     return(SpecializedCollections.EmptyEnumerable <ICustomAttribute>());
 }
Exemple #17
0
 public AnalyzerManager(DiagnosticAnalyzer analyzer)
 {
     _analyzerExecutionContextMap = CreateAnalyzerExecutionContextMap(SpecializedCollections.SingletonEnumerable(analyzer));
 }
Exemple #18
0
 public IEnumerable <IEventDefinition> GetEvents(EmitContext context)
 {
     return(SpecializedCollections.EmptyEnumerable <IEventDefinition>());
 }
            private Tuple <string[], string> GetNamespaceContainersAndAddUsingsOrImport(
                bool isDialog,
                IList <string> folders,
                bool areFoldersValidIdentifiers,
                Project targetProject,
                Project triggeringProject)
            {
                string includeUsingsOrImports = null;

                if (!areFoldersValidIdentifiers)
                {
                    folders = SpecializedCollections.EmptyList <string>();
                }

                // Now actually create the symbol that we want to add to the root namespace.  The
                // symbol may either be a named type (if we're not generating into a namespace) or
                // it may be a namespace symbol.
                string[] containers = null;
                if (!isDialog)
                {
                    // Not generated from the Dialog
                    containers = GetNamespaceToGenerateInto().Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                }
                else if (!_service.IsSimpleName(_state.NameOrMemberAccessExpression))
                {
                    // If the usage was with a namespace
                    containers = GetNamespaceToGenerateIntoForUsageWithNamespace(targetProject, triggeringProject).Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                }
                else
                {
                    // Generated from the Dialog
                    List <string> containerList = new List <string>();

                    string rootNamespaceOfTheProjectGeneratedInto;

                    if (_targetProjectChangeInLanguage == TargetProjectChangeInLanguage.NoChange)
                    {
                        rootNamespaceOfTheProjectGeneratedInto = _service.GetRootNamespace(_generateTypeOptionsResult.Project.CompilationOptions).Trim();
                    }
                    else
                    {
                        rootNamespaceOfTheProjectGeneratedInto = _targetLanguageService.GetRootNamespace(_generateTypeOptionsResult.Project.CompilationOptions).Trim();
                    }

                    var projectManagementService = _document.Project.Solution.Workspace.Services.GetService <IProjectManagementService>();
                    var defaultNamespace         = _generateTypeOptionsResult.DefaultNamespace;

                    // Case 1 : If the type is generated into the same C# project or
                    // Case 2 : If the type is generated from a C# project to a C# Project
                    // Case 3 : If the Type is generated from a VB Project to a C# Project
                    // Using and Namespace will be the DefaultNamespace + Folder Structure
                    if ((_document.Project == _generateTypeOptionsResult.Project && _document.Project.Language == LanguageNames.CSharp) ||
                        (_targetProjectChangeInLanguage == TargetProjectChangeInLanguage.NoChange && _generateTypeOptionsResult.Project.Language == LanguageNames.CSharp) ||
                        _targetProjectChangeInLanguage == TargetProjectChangeInLanguage.VisualBasicToCSharp)
                    {
                        if (!string.IsNullOrWhiteSpace(defaultNamespace))
                        {
                            containerList.Add(defaultNamespace);
                        }

                        // Populate the ContainerList
                        AddFoldersToNamespaceContainers(containerList, folders);

                        containers             = containerList.ToArray();
                        includeUsingsOrImports = string.Join(".", containerList.ToArray());
                    }

                    // Case 4 : If the type is generated into the same VB project or
                    // Case 5 : If Type is generated from a VB Project to VB Project
                    // Case 6 : If Type is generated from a C# Project to VB Project
                    // Namespace will be Folder Structure and Import will have the RootNamespace of the project generated into as part of the Imports
                    if ((_document.Project == _generateTypeOptionsResult.Project && _document.Project.Language == LanguageNames.VisualBasic) ||
                        (_document.Project != _generateTypeOptionsResult.Project && _targetProjectChangeInLanguage == TargetProjectChangeInLanguage.NoChange && _generateTypeOptionsResult.Project.Language == LanguageNames.VisualBasic) ||
                        _targetProjectChangeInLanguage == TargetProjectChangeInLanguage.CSharpToVisualBasic)
                    {
                        // Populate the ContainerList
                        AddFoldersToNamespaceContainers(containerList, folders);
                        containers             = containerList.ToArray();
                        includeUsingsOrImports = string.Join(".", containerList.ToArray());
                        if (!string.IsNullOrWhiteSpace(rootNamespaceOfTheProjectGeneratedInto))
                        {
                            includeUsingsOrImports = string.IsNullOrEmpty(includeUsingsOrImports) ?
                                                     rootNamespaceOfTheProjectGeneratedInto :
                                                     rootNamespaceOfTheProjectGeneratedInto + "." + includeUsingsOrImports;
                        }
                    }

                    Contract.Assert(includeUsingsOrImports != null);
                }

                return(Tuple.Create(containers, includeUsingsOrImports));
            }
Exemple #20
0
 public IEnumerable <MethodImplementation> GetExplicitImplementationOverrides(EmitContext context)
 {
     return(SpecializedCollections.EmptyEnumerable <MethodImplementation>());
 }
 IEnumerable <Cci.ICustomAttribute> Cci.IReference.GetAttributes(EmitContext context) => SpecializedCollections.EmptyEnumerable <Cci.ICustomAttribute>();
Exemple #22
0
 public IEnumerable <IFieldDefinition> GetFields(EmitContext context)
 {
     return(SpecializedCollections.EmptyEnumerable <IFieldDefinition>());
 }
Exemple #23
0
 private static SyntaxNode CreateNotImplementedException(SyntaxGenerator codeDefinitionFactory, Compilation compilation)
 => codeDefinitionFactory.ObjectCreationExpression(
     codeDefinitionFactory.TypeExpression(compilation.NotImplementedExceptionType(), addImport: false),
     SpecializedCollections.EmptyList <SyntaxNode>());
Exemple #24
0
 public IEnumerable <TypeReferenceWithAttributes> Interfaces(EmitContext context)
 {
     return(SpecializedCollections.EmptyEnumerable <TypeReferenceWithAttributes>());
 }
 public override IEnumerable <TextChange> GetTextChanges(TextSpan textSpan)
 {
     return(SpecializedCollections.SingletonEnumerable <TextChange>(new TextChange(textSpan, _newString)));
 }
Exemple #26
0
            internal virtual async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > GetDocumentDiagnosticsToFixAsync(
                FixAllContext fixAllContext)
            {
                using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Diagnostics, fixAllContext.CancellationToken))
                {
                    var allDiagnostics = ImmutableArray <Diagnostic> .Empty;
                    var projectsToFix  = ImmutableArray <Project> .Empty;

                    var document = fixAllContext.Document;
                    var project  = fixAllContext.Project;
                    var generatedCodeServices = project.Solution.Workspace.Services.GetService <IGeneratedCodeRecognitionService>();

                    switch (fixAllContext.Scope)
                    {
                    case FixAllScope.Document:
                        if (document != null && !generatedCodeServices.IsGeneratedCode(document))
                        {
                            var documentDiagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);

                            var kvp = SpecializedCollections.SingletonEnumerable(KeyValuePair.Create(document, documentDiagnostics));
                            return(ImmutableDictionary.CreateRange(kvp));
                        }

                        break;

                    case FixAllScope.Project:
                        projectsToFix  = ImmutableArray.Create(project);
                        allDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                        break;

                    case FixAllScope.Solution:
                        projectsToFix = project.Solution.Projects
                                        .Where(p => p.Language == project.Language)
                                        .ToImmutableArray();

                        var diagnostics = new ConcurrentBag <Diagnostic>();
                        var tasks       = new Task[projectsToFix.Length];
                        for (int i = 0; i < projectsToFix.Length; i++)
                        {
                            fixAllContext.CancellationToken.ThrowIfCancellationRequested();
                            var projectToFix = projectsToFix[i];
                            tasks[i] = Task.Run(async() =>
                            {
                                var projectDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(projectToFix).ConfigureAwait(false);
                                foreach (var diagnostic in projectDiagnostics)
                                {
                                    fixAllContext.CancellationToken.ThrowIfCancellationRequested();
                                    diagnostics.Add(diagnostic);
                                }
                            }, fixAllContext.CancellationToken);
                        }

                        await Task.WhenAll(tasks).ConfigureAwait(false);

                        allDiagnostics = allDiagnostics.AddRange(diagnostics);
                        break;
                    }

                    if (allDiagnostics.IsEmpty)
                    {
                        return(ImmutableDictionary <Document, ImmutableArray <Diagnostic> > .Empty);
                    }

                    return(await GetDocumentDiagnosticsToFixAsync(allDiagnostics, projectsToFix, generatedCodeServices.IsGeneratedCode, fixAllContext.CancellationToken).ConfigureAwait(false));
                }
            }
Exemple #27
0
 internal override IEnumerable <FieldSymbol> GetFieldsToEmit()
 {
     return(SpecializedCollections.EmptyEnumerable <FieldSymbol>());
 }
Exemple #28
0
        protected static void AddMappedDocument(Workspace workspace, string markup)
        {
            var generatedDocumentId = DocumentId.CreateNewId(workspace.CurrentSolution.ProjectIds.First());
            var version             = VersionStamp.Create();
            var loader = TextLoader.From(TextAndVersion.Create(SourceText.From(markup), version, TestSpanMapper.GeneratedFileName));
            var generatedDocumentInfo = DocumentInfo.Create(generatedDocumentId, TestSpanMapper.GeneratedFileName, SpecializedCollections.EmptyReadOnlyList <string>(),
                                                            SourceCodeKind.Regular, loader, $"C:\\{TestSpanMapper.GeneratedFileName}", isGenerated: true, designTimeOnly: false, new TestSpanMapperProvider());
            var newSolution = workspace.CurrentSolution.AddDocument(generatedDocumentInfo);

            workspace.TryApplyChanges(newSolution);
        }
 private IEnumerable <IFormattingRule> GetFormattingRules(Document document)
 {
     return(SpecializedCollections.SingletonEnumerable(BraceCompletionFormattingRule.Instance).Concat(Formatter.GetDefaultFormattingRules(document)));
 }
        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 model      = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

            if (model.IsFromGeneratedCode(context.CancellationToken))
            {
                return;
            }
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            if (root.FullSpan.Length < span.Start)
            {
                return;
            }
            var ancestors = root.FindToken(span.Start, findInsideTrivia: true).GetAncestors <SyntaxNode>();

            if (!ancestors.Any())
            {
                return;
            }

            var node = ancestors.FirstOrDefault(n => n.Span.Contains(span) && n != root);

            if (node == null)
            {
                return;
            }

            var placeSystemNamespaceFirst = true;             //document.Project.Solution.Workspace.Options.GetOption(Microsoft.CodeAnalysis.Shared.Options.OrganizerOptions.PlaceSystemNamespaceFirst, document.Project.Language);

            if (!cancellationToken.IsCancellationRequested)
            {
                if (this.CanAddImport(node, cancellationToken))
                {
                    var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                    //var containingType = semanticModel.GetEnclosingNamedType(node.SpanStart, cancellationToken);
                    //var containingTypeOrAssembly = containingType ?? (ISymbol)semanticModel.Compilation.Assembly;
                    var namespacesInScope = this.GetNamespacesInScope(semanticModel, node, cancellationToken);

                    var matchingTypesNamespaces = await this.GetNamespacesForMatchingTypesAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false);

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

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

                    var matchingExtensionMethodsNamespaces = await this.GetNamespacesForMatchingExtensionMethodsAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false);

                    var matchingFieldsAndPropertiesAsync = await this.GetNamespacesForMatchingFieldsAndPropertiesAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false);

                    var queryPatternsNamespaces = await this.GetNamespacesForQueryPatternsAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false);

                    if (matchingTypesNamespaces != null || matchingNamespaces != null || matchingExtensionMethodsNamespaces != null || matchingFieldsAndPropertiesAsync != null || queryPatternsNamespaces != null || matchingTypes != null)
                    {
                        matchingTypesNamespaces            = matchingTypesNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>();
                        matchingNamespaces                 = matchingNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>();
                        matchingExtensionMethodsNamespaces = matchingExtensionMethodsNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>();
                        matchingFieldsAndPropertiesAsync   = matchingFieldsAndPropertiesAsync ?? SpecializedCollections.EmptyList <INamespaceSymbol>();
                        queryPatternsNamespaces            = queryPatternsNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>();
                        matchingTypes = matchingTypes ?? SpecializedCollections.EmptyList <ITypeSymbol>();

                        var proposedImports =
                            matchingTypesNamespaces.Cast <INamespaceOrTypeSymbol> ()
                            .Concat(matchingNamespaces.Cast <INamespaceOrTypeSymbol> ())
                            .Concat(matchingExtensionMethodsNamespaces.Cast <INamespaceOrTypeSymbol> ())
                            .Concat(matchingFieldsAndPropertiesAsync.Cast <INamespaceOrTypeSymbol> ())
                            .Concat(queryPatternsNamespaces.Cast <INamespaceOrTypeSymbol> ())
                            .Concat(matchingTypes.Cast <INamespaceOrTypeSymbol> ())
                            .Distinct()
                            .Where(NotNull)
                            .Where(NotGlobalNamespace)
                            .ToList();
                        proposedImports.Sort(INamespaceOrTypeSymbolExtensions.CompareNamespaceOrTypeSymbols);
                        proposedImports = proposedImports.Take(8).ToList();

                        if (proposedImports.Count > 0)
                        {
                            cancellationToken.ThrowIfCancellationRequested();

                            foreach (var import in proposedImports)
                            {
                                var action = new DocumentChangeAction(
                                    node.Span,
                                    DiagnosticSeverity.Error,
                                    this.GetDescription(import, semanticModel, node),
                                    (c) => this.AddImportAsync(node, import, document, placeSystemNamespaceFirst, cancellationToken)
                                    );

                                context.RegisterCodeFix(action, diagnostic);
                            }
                        }
                    }
                }
            }
        }