private ValueTask <ImmutableArray <DiagnosticData> > DeserializeDiagnosticsAsync(
                IPersistentStorageService persistentService,
                DiagnosticDataSerializer serializer,
                Project project,
                TextDocument?document,
                object key,
                string stateKey,
                CancellationToken cancellationToken
                )
            {
                Contract.ThrowIfFalse(document == null || document.Project == project);

                if (
                    InMemoryStorage.TryGetValue(_owner.Analyzer, (key, stateKey), out var entry) &&
                    serializer.Version == entry.Version
                    )
                {
                    return(ValueTaskFactory.FromResult(entry.Diagnostics));
                }

                return(serializer.DeserializeAsync(
                           persistentService,
                           project,
                           document,
                           stateKey,
                           cancellationToken
                           ));
            }
Beispiel #2
0
            protected override async Task <Solution> GetChangedSolutionAsync(CancellationToken cancellationToken)
            {
                var updatedPublicSurfaceAreaText = new List <KeyValuePair <DocumentId, SourceText> >();

                foreach (KeyValuePair <Project, ImmutableArray <Diagnostic> > pair in _diagnosticsToFix)
                {
                    Project      project           = pair.Key;
                    TextDocument?shippedDocument   = DeclarePublicApiFix.GetShippedDocument(project);
                    SourceText?  shippedSourceText = shippedDocument is null ? null : await shippedDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    if (shippedSourceText is object)
                    {
                        SourceText newShippedSourceText = AddNullableEnable(shippedSourceText);
                        updatedPublicSurfaceAreaText.Add(new KeyValuePair <DocumentId, SourceText>(shippedDocument !.Id, newShippedSourceText));
                    }
                }

                Solution newSolution = _solution;

                foreach (KeyValuePair <DocumentId, SourceText> pair in updatedPublicSurfaceAreaText)
                {
                    newSolution = newSolution.WithAdditionalDocumentText(pair.Key, pair.Value);
                }

                return(newSolution);
            }
            protected override async Task <Solution> GetChangedSolutionAsync(CancellationToken cancellationToken)
            {
                var updatedPublicSurfaceAreaText = new List <KeyValuePair <DocumentId, SourceText> >();

                using var uniqueShippedDocuments = PooledHashSet <string> .GetInstance();

                foreach (var project in _projectsToFix)
                {
                    TextDocument?shippedDocument = project.GetShippedDocument();
                    if (shippedDocument == null ||
                        shippedDocument.FilePath != null && !uniqueShippedDocuments.Add(shippedDocument.FilePath))
                    {
                        // Skip past duplicate shipped documents.
                        // Multi-tfm projects can likely share the same api files, and we want to avoid duplicate code fix application.
                        continue;
                    }

                    var shippedSourceText = await shippedDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    SourceText newShippedSourceText = AddNullableEnable(shippedSourceText);
                    updatedPublicSurfaceAreaText.Add(new KeyValuePair <DocumentId, SourceText>(shippedDocument !.Id, newShippedSourceText));
                }

                Solution newSolution = _solution;

                foreach (KeyValuePair <DocumentId, SourceText> pair in updatedPublicSurfaceAreaText)
                {
                    newSolution = newSolution.WithAdditionalDocumentText(pair.Key, pair.Value);
                }

                return(newSolution);
            }
Beispiel #4
0
        public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            Project project = context.Document.Project;

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                string minimalSymbolName = diagnostic.Properties[DeclarePublicApiAnalyzer.MinimalNamePropertyBagKey];
                string publicSymbolName  = diagnostic.Properties[DeclarePublicApiAnalyzer.PublicApiNamePropertyBagKey];
                string publicSymbolNameWithNullability = diagnostic.Properties[DeclarePublicApiAnalyzer.PublicApiNameWithNullabilityPropertyBagKey];
                string fileName = diagnostic.Properties[DeclarePublicApiAnalyzer.FileName];

                TextDocument?document = project.GetPublicApiDocument(fileName);

                if (document != null)
                {
                    context.RegisterCodeFix(
                        new DeclarePublicApiFix.AdditionalDocumentChangeAction(
                            $"Annotate {minimalSymbolName} in public API",
                            document.Id,
                            c => GetFix(document, publicSymbolName, publicSymbolNameWithNullability, c)),
                        diagnostic);
                }
            }

            return(Task.CompletedTask);
            // Local functions.
            static Project AddAdditionalDocument(Project project, string name, SourceText text)
            {
                TextDocument?additionalDocument = project.AdditionalDocuments.FirstOrDefault(doc => string.Equals(doc.Name, name, StringComparison.OrdinalIgnoreCase));

                if (additionalDocument == null)
                {
                    project = project.AddAdditionalDocument(name, text).Project;
                }

                return(project);
            }
Beispiel #6
0
        public DiagnosticComputer(
            TextDocument?document,
            Project project,
            TextSpan?span,
            AnalysisKind?analysisKind,
            DiagnosticAnalyzerInfoCache analyzerInfoCache)
        {
            _document          = document;
            _project           = project;
            _span              = span;
            _analysisKind      = analysisKind;
            _analyzerInfoCache = analyzerInfoCache;

            // We only track performance from primary branch. All forked branch we don't care such as preview.
            _performanceTracker = project.IsFromPrimaryBranch() ? project.Solution.Workspace.Services.GetService <IPerformanceTrackerService>() : null;
        }
        private static async Task <Solution> GetFixAsync(TextDocument?publicSurfaceAreaDocument, Project project, string newSymbolName, ImmutableHashSet <string> siblingSymbolNamesToRemove, CancellationToken cancellationToken)
        {
            if (publicSurfaceAreaDocument == null)
            {
                var newSourceText = AddSymbolNamesToSourceText(sourceText: null, new[] { newSymbolName });
                return(AddPublicApiFiles(project, newSourceText));
            }
            else
            {
                var sourceText = await publicSurfaceAreaDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);

                var newSourceText = AddSymbolNamesToSourceText(sourceText, new[] { newSymbolName });
                newSourceText = RemoveSymbolNamesFromSourceText(newSourceText, siblingSymbolNamesToRemove);

                return(publicSurfaceAreaDocument.Project.Solution.WithAdditionalDocumentText(publicSurfaceAreaDocument.Id, newSourceText));
            }
        }
        public async ValueTask <ImmutableArray <DiagnosticData> > DeserializeAsync(
            IPersistentStorageService persistentService,
            Project project,
            TextDocument?textDocument,
            string key,
            CancellationToken cancellationToken
            )
        {
            Contract.ThrowIfFalse(textDocument == null || textDocument.Project == project);

            var storage = await persistentService
                          .GetStorageAsync(project.Solution, cancellationToken)
                          .ConfigureAwait(false);

            await using var _ = storage.ConfigureAwait(false);

            var readTask =
                (textDocument != null)
                    ? textDocument is Document document
                        ? storage.ReadStreamAsync(document, key, cancellationToken)
                        : storage.ReadStreamAsync(
                    GetSerializationKeyForNonSourceDocument(textDocument, key),
                    cancellationToken
                    )
                    : storage.ReadStreamAsync(project, key, cancellationToken);

            using var stream = await readTask.ConfigureAwait(false);

            using var reader = ObjectReader.TryGetReader(
                      stream,
                      cancellationToken: cancellationToken
                      );

            if (
                reader == null ||
                !TryReadDiagnosticData(
                    reader,
                    project,
                    textDocument,
                    cancellationToken,
                    out var data
                    )
                )
            {
                return(default);
        void textArea_DocumentChanged(object?sender, EventArgs e)
        {
            if (textArea == null)
            {
                return;
            }

            if (currentDocument != null)
            {
                currentDocument.TextChanged -= textArea_Document_TextChanged;
            }
            currentDocument = textArea.Document;
            if (currentDocument != null)
            {
                currentDocument.TextChanged += textArea_Document_TextChanged;
                DoSearch(false);
            }
        }
Beispiel #10
0
        private void AddDocumentDiagnostic(
            ref Dictionary <DocumentId, List <DiagnosticData> >?map,
            TextDocument?document,
            Diagnostic diagnostic
            )
        {
            if (document is null || !document.SupportsDiagnostics())
            {
                return;
            }

            map ??= new Dictionary <DocumentId, List <DiagnosticData> >();
            map.GetOrAdd(document.Id, _ => new List <DiagnosticData>())
            .Add(DiagnosticData.Create(diagnostic, document));

            _lazyDocumentsWithDiagnostics ??= new HashSet <DocumentId>();
            _lazyDocumentsWithDiagnostics.Add(document.Id);
        }
                protected override async Task <Solution> GetChangedSolutionAsync(CancellationToken cancellationToken)
                {
                    var updatedUnshippedText = new List <(DocumentId, SourceText)>();

                    foreach (KeyValuePair <Project, ImmutableArray <Diagnostic> > pair in _diagnosticsToFix)
                    {
                        Project project = pair.Key;
                        ImmutableArray <Diagnostic> diagnostics = pair.Value;

                        TextDocument?unshippedDocument = project.AdditionalDocuments.FirstOrDefault(a => a.Name == ReleaseTrackingHelper.UnshippedFileName);
                        if (unshippedDocument == null || diagnostics.IsEmpty)
                        {
                            continue;
                        }

                        if (EquivalenceKey == CodeAnalysisDiagnosticsResources.AddEntryForDiagnosticIdInAnalyzerReleaseCodeFixTitle)
                        {
                            var newText = await AddEntriesToUnshippedFileForDiagnosticsAsync(unshippedDocument, diagnostics, cancellationToken).ConfigureAwait(false);

                            updatedUnshippedText.Add((unshippedDocument.Id, newText));
                        }
                        else if (EquivalenceKey == CodeAnalysisDiagnosticsResources.UpdateEntryForDiagnosticIdInAnalyzerReleaseCodeFixTitle)
                        {
                            var newText = await UpdateEntriesInUnshippedFileForDiagnosticsAsync(unshippedDocument, diagnostics, cancellationToken).ConfigureAwait(false);

                            updatedUnshippedText.Add((unshippedDocument.Id, newText));
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }

                    Solution newSolution = _solution;

                    foreach (var(unshippedDocumentId, newText) in updatedUnshippedText)
                    {
                        newSolution = newSolution.WithAdditionalDocumentText(unshippedDocumentId, newText);
                    }

                    return(newSolution);
                }
        void AttachInternal(TextArea textArea)
        {
            this.textArea = textArea;
            adorner       = new SearchPanelAdorner(textArea, this);
            DataContext   = this;

            //renderer
            currentDocument = textArea.Document;
            if (currentDocument != null)
            {
                currentDocument.TextChanged += textArea_Document_TextChanged;
            }
            textArea.DocumentChanged += textArea_DocumentChanged;
            KeyDown += SearchLayerKeyDown;

            this.CommandBindings.Add(new CommandBinding(SearchCommands.FindNext, (sender, e) => FindNext()));
            this.CommandBindings.Add(new CommandBinding(SearchCommands.FindPrevious, (sender, e) => FindPrevious()));
            this.CommandBindings.Add(new CommandBinding(SearchCommands.CloseSearchPanel, (sender, e) => Close()));
            IsClosed = true;
        }
Beispiel #13
0
        public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            Project project = context.Document.Project;

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                TextDocument?document = DeclarePublicApiFix.GetShippedDocument(project);

                if (document != null)
                {
                    context.RegisterCodeFix(
                        new DeclarePublicApiFix.AdditionalDocumentChangeAction(
                            $"Add '#nullable enable' to public API",
                            c => GetFix(document, c)),
                        diagnostic);
                }
            }

            return(Task.CompletedTask);
        }
            private async Task SerializeAsync(
                IPersistentStorageService?persistentService,
                DiagnosticDataSerializer serializer,
                Project project,
                TextDocument?document,
                object key,
                string stateKey,
                ImmutableArray <DiagnosticData> diagnostics
                )
            {
                Contract.ThrowIfFalse(document == null || document.Project == project);

                // try to serialize it
                if (
                    persistentService != null &&
                    await serializer
                    .SerializeAsync(
                        persistentService,
                        project,
                        document,
                        stateKey,
                        diagnostics,
                        CancellationToken.None
                        )
                    .ConfigureAwait(false)
                    )
                {
                    // we succeeded saving it to persistent storage. remove it from in memory cache if it exists
                    RemoveInMemoryCacheEntry(key, stateKey);
                    return;
                }

                // if serialization fail, hold it in the memory
                InMemoryStorage.Cache(
                    _owner.Analyzer,
                    (key, stateKey),
                    new CacheEntry(serializer.Version, diagnostics)
                    );
            }
        public async Task <bool> SerializeAsync(
            IPersistentStorageService persistentService,
            Project project,
            TextDocument?textDocument,
            string key,
            ImmutableArray <DiagnosticData> items,
            CancellationToken cancellationToken
            )
        {
            Contract.ThrowIfFalse(textDocument == null || textDocument.Project == project);

            using var stream = SerializableBytes.CreateWritableStream();

            using (var writer = new ObjectWriter(stream, leaveOpen: true, cancellationToken))
            {
                WriteDiagnosticData(writer, items, cancellationToken);
            }

            var storage = await persistentService
                          .GetStorageAsync(project.Solution, cancellationToken)
                          .ConfigureAwait(false);

            await using var _ = storage.ConfigureAwait(false);

            stream.Position = 0;

            var writeTask =
                (textDocument != null)
                    ? textDocument is Document document
                        ? storage.WriteStreamAsync(document, key, stream, cancellationToken)
                        : storage.WriteStreamAsync(
                    GetSerializationKeyForNonSourceDocument(textDocument, key),
                    stream,
                    cancellationToken
                    )
                    : storage.WriteStreamAsync(project, key, stream, cancellationToken);

            return(await writeTask.ConfigureAwait(false));
        }
Beispiel #16
0
        public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            Project project = context.Document.Project;

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                string minimalSymbolName = diagnostic.Properties[DeclarePublicApiAnalyzer.MinimalNamePropertyBagKey];
                string publicSymbolName  = diagnostic.Properties[DeclarePublicApiAnalyzer.PublicApiNamePropertyBagKey];
                string publicSymbolNameWithNullability = diagnostic.Properties[DeclarePublicApiAnalyzer.PublicApiNameWithNullabilityPropertyBagKey];
                bool   isShippedDocument = diagnostic.Properties[DeclarePublicApiAnalyzer.PublicApiIsShippedPropertyBagKey] == "true";

                TextDocument?document = isShippedDocument ? PublicApiFixHelpers.GetShippedDocument(project) : PublicApiFixHelpers.GetUnshippedDocument(project);

                if (document != null)
                {
                    context.RegisterCodeFix(
                        new DeclarePublicApiFix.AdditionalDocumentChangeAction(
                            $"Annotate {minimalSymbolName} in public API",
                            c => GetFix(document, publicSymbolName, publicSymbolNameWithNullability, c)),
                        diagnostic);
                }
            }

            return(Task.CompletedTask);
Beispiel #17
0
 public static bool SupportsDiagnostics([NotNullWhen(returnValue: true)] this TextDocument?document)
 => document?.State.SupportsDiagnostics() ?? false;
Beispiel #18
0
 public static bool CanApplyChange([NotNullWhen(returnValue: true)] this TextDocument?document)
 => document?.State.CanApplyChange() ?? false;
            private ValueTask AddToInMemoryStorageAsync(VersionStamp serializerVersion, Project project, TextDocument?document, object key, string stateKey, ImmutableArray <DiagnosticData> diagnostics)
            {
                Contract.ThrowIfFalse(document == null || document.Project == project);

                // if serialization fail, hold it in the memory
                InMemoryStorage.Cache(_owner.Analyzer, (key, stateKey), new CacheEntry(serializerVersion, diagnostics));
                return(default);