protected override InlineDiagnosticsTag?CreateTag(Workspace workspace, DiagnosticData diagnostic)
        {
            Debug.Assert(!string.IsNullOrWhiteSpace(diagnostic.Message));
            var errorType = GetErrorTypeFromDiagnostic(diagnostic);

            if (errorType is null)
            {
                return(null);
            }

            if (diagnostic.DocumentId is null)
            {
                return(null);
            }

            var project = workspace.CurrentSolution.GetProject(diagnostic.DocumentId.ProjectId);

            if (project is null)
            {
                return(null);
            }

            var locationOption  = GlobalOptions.GetOption(InlineDiagnosticsOptions.Location, project.Language);
            var navigateService = workspace.Services.GetRequiredService <INavigateToLinkService>();

            return(new InlineDiagnosticsTag(errorType, diagnostic, _editorFormatMap, _classificationFormatMapService,
                                            _classificationTypeRegistryService, locationOption, navigateService));
        }
예제 #2
0
        /// <summary>
        /// Return CompilationWithAnalyzer for given project with given stateSets
        /// </summary>
        private async Task <CompilationWithAnalyzers?> GetOrCreateCompilationWithAnalyzersAsync(Project project, IEnumerable <StateSet> stateSets, CancellationToken cancellationToken)
        {
            if (!project.SupportsCompilation)
            {
                return(null);
            }

            if (_projectCompilationsWithAnalyzers.TryGetValue(project, out var compilationWithAnalyzers))
            {
                // we have cached one, return that.
                AssertAnalyzers(compilationWithAnalyzers, stateSets);
                return(compilationWithAnalyzers);
            }

            // Create driver that holds onto compilation and associated analyzers
            var crashOnAnalyzerException    = GlobalOptions.GetOption(InternalDiagnosticsOptions.CrashOnAnalyzerException);
            var newCompilationWithAnalyzers = await CreateCompilationWithAnalyzersAsync(project, stateSets, includeSuppressedDiagnostics : true, crashOnAnalyzerException, cancellationToken).ConfigureAwait(false);

            // Add new analyzer driver to the map
            compilationWithAnalyzers = _projectCompilationsWithAnalyzers.GetValue(project, _ => newCompilationWithAnalyzers);

            // if somebody has beat us, make sure analyzers are good.
            if (compilationWithAnalyzers != newCompilationWithAnalyzers)
            {
                AssertAnalyzers(compilationWithAnalyzers, stateSets);
            }

            return(compilationWithAnalyzers);
        }
        public override ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities)
        {
            // If the LSP editor feature flag is enabled advertise support for LSP features here so they are available locally and remote.
            var isLspEditorEnabled = GlobalOptions.GetOption(LspOptions.LspEditorFeatureFlag);

            var serverCapabilities = isLspEditorEnabled
                ? (VSInternalServerCapabilities)_defaultCapabilitiesProvider.GetCapabilities(clientCapabilities)
                : new VSInternalServerCapabilities()
            {
                // Even if the flag is off, we want to include text sync capabilities.
                TextDocumentSync = new TextDocumentSyncOptions
                {
                    Change    = TextDocumentSyncKind.Incremental,
                    OpenClose = true,
                },
            };

            serverCapabilities.ProjectContextProvider = true;
            serverCapabilities.BreakableRangeProvider = true;

            var isPullDiagnostics = GlobalOptions.IsPullDiagnostics(InternalDiagnosticsOptions.NormalDiagnosticMode);

            if (isPullDiagnostics)
            {
                serverCapabilities.SupportsDiagnosticRequests     = true;
                serverCapabilities.MultipleContextSupportProvider = new VSInternalMultipleContextFeatures {
                    SupportsMultipleContextsDiagnostics = true
                };
            }

            // This capability is always enabled as we provide cntrl+Q VS search only via LSP in ever scenario.
            serverCapabilities.WorkspaceSymbolProvider = true;
            // This capability prevents NavigateTo (cntrl+,) from using LSP symbol search when the server also supports WorkspaceSymbolProvider.
            // Since WorkspaceSymbolProvider=true always to allow cntrl+Q VS search to function, we set DisableGoToWorkspaceSymbols=true
            // when not running the experimental LSP editor.  This ensures NavigateTo uses the existing editor APIs.
            // However, when the experimental LSP editor is enabled we want LSP to power NavigateTo, so we set DisableGoToWorkspaceSymbols=false.
            serverCapabilities.DisableGoToWorkspaceSymbols = !isLspEditorEnabled;

            var isLspSemanticTokensEnabled = GlobalOptions.GetOption(LspOptions.LspSemanticTokensFeatureFlag);

            if (isLspSemanticTokensEnabled)
            {
                // Using only range handling has shown to be more performant than using a combination of full/edits/range handling,
                // especially for larger files. With range handling, we only need to compute tokens for whatever is in view, while
                // with full/edits handling we need to compute tokens for the entire file and then potentially run a diff between
                // the old and new tokens.
                serverCapabilities.SemanticTokensOptions = new SemanticTokensOptions
                {
                    Full   = false,
                    Range  = true,
                    Legend = new SemanticTokensLegend
                    {
                        TokenTypes     = SemanticTokenTypes.AllTypes.Concat(SemanticTokensHelpers.RoslynCustomTokenTypes).ToArray(),
                        TokenModifiers = new string[] { SemanticTokenModifiers.Static }
                    }
                };
            }

            return(serverCapabilities);
        }
        protected override bool ComputeInitialTagsSynchronously(ITextBuffer subjectBuffer)
        {
            // If we can't find this doc, or outlining is not enabled for it, no need to computed anything synchronously.

            var openDocument = subjectBuffer.AsTextContainer().GetRelatedDocuments().FirstOrDefault();

            if (openDocument == null)
            {
                return(false);
            }

            if (!GlobalOptions.GetOption(FeatureOnOffOptions.Outlining, openDocument.Project.Language))
            {
                return(false);
            }

            // If we're a metadata-as-source doc, we need to compute the initial set of tags synchronously
            // so that we can collapse all the .IsImplementation tags to keep the UI clean and condensed.
            var isMetadataAsSource = openDocument.Project.Solution.Workspace.Kind == WorkspaceKind.MetadataAsSource;

            if (isMetadataAsSource)
            {
                return(true);
            }

            // If we contain any #region sections, we want to collapse those automatically on open the first
            // time a doc is ever opened.  So we need to compute the initial tags synchronously in order to
            // do that.
            if (ContainsRegionTag(subjectBuffer.CurrentSnapshot))
            {
                return(true);
            }

            return(false);
예제 #5
0
        public override ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities)
        {
            var isLspEditorEnabled = GlobalOptions.GetOption(LspOptions.LspEditorFeatureFlag);

            // If the preview feature flag to turn on the LSP editor in local scenarios is on, advertise no capabilities for this Live Share
            // LSP server as LSP requests will be serviced by the AlwaysActiveInProcLanguageClient in both local and remote scenarios.
            if (isLspEditorEnabled)
            {
                return(new VSServerCapabilities
                {
                    TextDocumentSync = new TextDocumentSyncOptions
                    {
                        OpenClose = false,
                        Change = TextDocumentSyncKind.None,
                    }
                });
            }

            var defaultCapabilities = _defaultCapabilitiesProvider.GetCapabilities(clientCapabilities);

            // If the LSP semantic tokens feature flag is enabled, advertise no semantic tokens capabilities for this Live Share
            // LSP server as LSP semantic tokens requests will be serviced by the AlwaysActiveInProcLanguageClient in both local and
            // remote scenarios.
            var isLspSemanticTokenEnabled = GlobalOptions.GetOption(LspOptions.LspSemanticTokensFeatureFlag);

            if (isLspSemanticTokenEnabled)
            {
                defaultCapabilities.SemanticTokensOptions = null;
            }

            return(defaultCapabilities);
        }
예제 #6
0
        private void RaiseDiagnosticsRemovedIfRequiredForClosedOrResetDocument(TextDocument document, IEnumerable <StateSet> stateSets, bool documentHadDiagnostics)
        {
            // If there was no diagnostic reported for this document, nothing to clean up
            // This is done for Perf to reduce raising events unnecessarily.
            if (!documentHadDiagnostics)
            {
                return;
            }

            // If full solution analysis is enabled for both compiler diagnostics and analyzers,
            // we don't need to clear diagnostics for individual documents on document close/reset.
            // This is done for Perf to reduce raising events unnecessarily.
            var _ = GlobalOptions.IsFullSolutionAnalysisEnabled(document.Project.Language, out var compilerFullAnalysisEnabled, out var analyzersFullAnalysisEnabled);

            if (compilerFullAnalysisEnabled && analyzersFullAnalysisEnabled)
            {
                return;
            }

            var removeDiagnosticsOnDocumentClose = GlobalOptions.GetOption(SolutionCrawlerOptionsStorage.RemoveDocumentDiagnosticsOnDocumentClose, document.Project.Language);

            if (!removeDiagnosticsOnDocumentClose)
            {
                return;
            }

            RaiseDiagnosticsRemovedForDocument(document.Id, stateSets);
        }
예제 #7
0
        public override ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities)
        {
            var serverCapabilities = new VSInternalServerCapabilities();

            // If the LSP editor feature flag is enabled advertise support for LSP features here so they are available locally and remote.
            var isLspEditorEnabled = GlobalOptions.GetOption(LspOptions.LspEditorFeatureFlag);

            if (isLspEditorEnabled)
            {
                serverCapabilities = (VSInternalServerCapabilities)_defaultCapabilitiesProvider.GetCapabilities(clientCapabilities);
            }
            else
            {
                // Even if the flag is off, we want to include text sync capabilities.
                serverCapabilities.TextDocumentSync = new TextDocumentSyncOptions
                {
                    Change    = TextDocumentSyncKind.Incremental,
                    OpenClose = true,
                };
            }

            serverCapabilities.SupportsDiagnosticRequests = GlobalOptions.IsPullDiagnostics(InternalDiagnosticsOptions.NormalDiagnosticMode);

            // This capability is always enabled as we provide cntrl+Q VS search only via LSP in ever scenario.
            serverCapabilities.WorkspaceSymbolProvider = true;
            // This capability prevents NavigateTo (cntrl+,) from using LSP symbol search when the server also supports WorkspaceSymbolProvider.
            // Since WorkspaceSymbolProvider=true always to allow cntrl+Q VS search to function, we set DisableGoToWorkspaceSymbols=true
            // when not running the experimental LSP editor.  This ensures NavigateTo uses the existing editor APIs.
            // However, when the experimental LSP editor is enabled we want LSP to power NavigateTo, so we set DisableGoToWorkspaceSymbols=false.
            serverCapabilities.DisableGoToWorkspaceSymbols = !isLspEditorEnabled;

            return(serverCapabilities);
        }
예제 #8
0
        public override ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities)
        {
            var isLspExperimentEnabled = GlobalOptions.GetOption(XamlOptions.EnableLspIntelliSenseFeatureFlag);
            var capabilities           = isLspExperimentEnabled ? XamlCapabilities.None : XamlCapabilities.Current;

            // Only turn on CodeAction support for client scenarios. Hosts will get non-LSP lightbulbs automatically.
            capabilities.CodeActionProvider = new CodeActionOptions {
                CodeActionKinds = new[] { CodeActionKind.QuickFix, CodeActionKind.Refactor }, ResolveProvider = true
            };

            return(capabilities);
        }
        protected override async Task ProduceTagsAsync(
            TaggerContext <StringIndentationTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition, CancellationToken cancellationToken)
        {
            var document = documentSnapshotSpan.Document;

            if (document == null)
            {
                return;
            }

            if (!GlobalOptions.GetOption(FeatureOnOffOptions.StringIdentation, document.Project.Language))
            {
                return;
            }

            var service = document.GetLanguageService <IStringIndentationService>();

            if (service == null)
            {
                return;
            }

            var snapshotSpan = documentSnapshotSpan.SnapshotSpan;
            var regions      = await service.GetStringIndentationRegionsAsync(document, snapshotSpan.Span.ToTextSpan(), cancellationToken).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            if (regions.Length == 0)
            {
                return;
            }

            var snapshot = snapshotSpan.Snapshot;

            foreach (var region in regions)
            {
                var line = snapshot.GetLineFromPosition(region.IndentSpan.End);

                // If the indent is on the first column, then no need to actually show anything (plus we can't as we
                // want to draw one column earlier, and that column doesn't exist).
                if (line.Start == region.IndentSpan.End)
                {
                    continue;
                }

                context.AddTag(new TagSpan <StringIndentationTag>(
                                   region.IndentSpan.ToSnapshotSpan(snapshot),
                                   new StringIndentationTag(
                                       _editorFormatMap,
                                       region.OrderedHoleSpans.SelectAsArray(s => s.ToSnapshotSpan(snapshot)))));
            }
        }
        protected override async Task InitializeServiceForOpenedDocumentAsync(Document document)
        {
            // Only pre-populate cache if import completion is enabled
            if (GlobalOptions.GetOption(CompletionOptionsStorage.ShowItemsFromUnimportedNamespaces, LanguageNames.CSharp) != true)
            {
                return;
            }

            var service = document.GetRequiredLanguageService <ITypeImportCompletionService>();

            service.QueueCacheWarmUpTask(document.Project);
            await ExtensionMethodImportCompletionHelper.WarmUpCacheAsync(document.Project, CancellationToken.None).ConfigureAwait(false);
        }
        protected override bool ComputeInitialTagsSynchronously(ITextBuffer subjectBuffer)
        {
            // If we can't find this doc, or outlining is not enabled for it, no need to computed anything synchronously.

            var openDocument = subjectBuffer.AsTextContainer().GetRelatedDocuments().FirstOrDefault();

            if (openDocument == null)
            {
                return(false);
            }

            // If the main Outlining option is turned off, we can just skip computing tags synchronously
            // so when the document first opens, there won't be any tags yet. When the tags do come in
            // the IsDefaultCollapsed property, which controls the initial collapsing, won't have any effect
            // because the document will already be open.
            if (!GlobalOptions.GetOption(FeatureOnOffOptions.Outlining, openDocument.Project.Language))
            {
                return(false);
            }

            var options = BlockStructureOptionsStorage.GetBlockStructureOptions(GlobalOptions, openDocument.Project);

            // If we're a metadata-as-source doc, we need to compute the initial set of tags synchronously
            // so that we can collapse all the .IsImplementation tags to keep the UI clean and condensed.
            if (openDocument.Project.Solution.Workspace is MetadataAsSourceWorkspace masWorkspace &&
                masWorkspace.FileService.ShouldCollapseOnOpen(openDocument.FilePath, options))
            {
                return(true);
            }

            // If the user wants to collapse imports or #regions then we need to compute
            // synchronously, but only if there are imports or #regions in the file. To
            // save some work, we'll look for both in a single pass.
            var collapseRegions = GlobalOptions.GetOption(BlockStructureOptionsStorage.CollapseRegionsWhenFirstOpened, openDocument.Project.Language);
            var collapseImports = GlobalOptions.GetOption(BlockStructureOptionsStorage.CollapseImportsWhenFirstOpened, openDocument.Project.Language);

            if (!collapseRegions && !collapseImports)
            {
                return(false);
            }

            if (ContainsRegionOrImport(subjectBuffer.CurrentSnapshot, collapseRegions, collapseImports, openDocument.Project.Language))
            {
                return(true);
            }

            return(false);
        }
        private async Task AnalyzeProjectAsync(Project project, bool forceAnalyzerRun, CancellationToken cancellationToken)
        {
            try
            {
                var stateSets = GetStateSetsForFullSolutionAnalysis(_stateManager.GetOrUpdateStateSets(project), project);
                var options   = project.Solution.Options;

                // PERF: get analyzers that are not suppressed and marked as open file only
                // this is perf optimization. we cache these result since we know the result. (no diagnostics)
                var activeAnalyzers = stateSets
                                      .Select(s => s.Analyzer)
                                      .Where(a => DocumentAnalysisExecutor.IsAnalyzerEnabledForProject(a, project, GlobalOptions) && !a.IsOpenFileOnly(options));

                // get driver only with active analyzers.
                var crashOnAnalyzerException = GlobalOptions.GetOption(InternalDiagnosticsOptions.CrashOnAnalyzerException);
                var compilationWithAnalyzers = await DocumentAnalysisExecutor.CreateCompilationWithAnalyzersAsync(project, activeAnalyzers, includeSuppressedDiagnostics : true, crashOnAnalyzerException, cancellationToken).ConfigureAwait(false);

                var result = await GetProjectAnalysisDataAsync(compilationWithAnalyzers, project, stateSets, forceAnalyzerRun, cancellationToken).ConfigureAwait(false);

                if (result.OldResult == null)
                {
                    RaiseProjectDiagnosticsIfNeeded(project, stateSets, result.Result);
                    return;
                }

                // we might not have compilationWithAnalyzers even if project supports compilation if we are called with no analyzers.
                var compilation = compilationWithAnalyzers?.Compilation ??
                                  (project.SupportsCompilation ? await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false) : null);

                // no cancellation after this point.
                // any analyzer that doesn't have result will be treated as returned empty set
                // which means we will remove those from error list
                foreach (var stateSet in stateSets)
                {
                    var state = stateSet.GetOrCreateProjectState(project.Id);

                    await state.SaveToInMemoryStorageAsync(project, result.GetResult(stateSet.Analyzer)).ConfigureAwait(false);
                }

                RaiseProjectDiagnosticsIfNeeded(project, stateSets, result.OldResult, result.Result);
            }
            catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
예제 #13
0
        protected override async Task ProduceTagsAsync(
            TaggerContext <LineSeparatorTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition, CancellationToken cancellationToken)
        {
            var document = documentSnapshotSpan.Document;

            if (document == null)
            {
                return;
            }

            if (!GlobalOptions.GetOption(FeatureOnOffOptions.LineSeparator, document.Project.Language))
            {
                return;
            }

            using (Logger.LogBlock(FunctionId.Tagger_LineSeparator_TagProducer_ProduceTags, cancellationToken))
            {
                var snapshotSpan         = documentSnapshotSpan.SnapshotSpan;
                var lineSeparatorService = document.GetLanguageService <ILineSeparatorService>();
                if (lineSeparatorService == null)
                {
                    return;
                }

                var lineSeparatorSpans = await lineSeparatorService.GetLineSeparatorsAsync(document, snapshotSpan.Span.ToTextSpan(), cancellationToken).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                if (lineSeparatorSpans.Length == 0)
                {
                    return;
                }

                LineSeparatorTag tag;
                lock (_lineSeperatorTagGate)
                {
                    tag = _lineSeparatorTag;
                }

                foreach (var span in lineSeparatorSpans)
                {
                    context.AddTag(new TagSpan <LineSeparatorTag>(span.ToSnapshotSpan(snapshotSpan.Snapshot), tag));
                }
            }
        }
        private void RaiseDiagnosticsRemovedIfRequiredForClosedOrResetDocument(TextDocument document, IEnumerable <StateSet> stateSets, bool documentHadDiagnostics)
        {
            // if there was no diagnostic reported for this document OR Full solution analysis is enabled, nothing to clean up
            if (!documentHadDiagnostics ||
                FullAnalysisEnabled(document.Project, forceAnalyzerRun: false))
            {
                // this is Perf to reduce raising events unnecessarily.
                return;
            }

            var removeDiagnosticsOnDocumentClose = GlobalOptions.GetOption(SolutionCrawlerOptionsStorage.RemoveDocumentDiagnosticsOnDocumentClose, document.Project.Language);

            if (!removeDiagnosticsOnDocumentClose)
            {
                return;
            }

            RaiseDiagnosticsRemovedForDocument(document.Id, stateSets);
        }
        public override ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities)
        {
            var isLspEditorEnabled = GlobalOptions.GetOption(LspOptions.LspEditorFeatureFlag);

            // If the preview feature flag to turn on the LSP editor in local scenarios is on, advertise no capabilities for this Live Share
            // LSP server as LSP requests will be serviced by the AlwaysActiveInProcLanguageClient in both local and remote scenarios.
            if (isLspEditorEnabled)
            {
                return(new VSServerCapabilities
                {
                    TextDocumentSync = new TextDocumentSyncOptions
                    {
                        OpenClose = false,
                        Change = TextDocumentSyncKind.None,
                    }
                });
            }

            var defaultCapabilities = _experimentalCapabilitiesProvider.GetCapabilities(clientCapabilities);

            // If the LSP semantic tokens feature flag is enabled, advertise no semantic tokens capabilities for this Live Share
            // LSP server as LSP semantic tokens requests will be serviced by the AlwaysActiveInProcLanguageClient in both local and
            // remote scenarios.
            var isLspSemanticTokenEnabled = GlobalOptions.GetOption(LspOptions.LspSemanticTokensFeatureFlag);

            if (isLspSemanticTokenEnabled)
            {
                defaultCapabilities.SemanticTokensOptions = null;
            }

            // When the lsp pull diagnostics feature flag is enabled we do not advertise pull diagnostics capabilities from here
            // as the AlwaysActivateInProcLanguageClient will provide pull diagnostics both locally and remote.
            var isPullDiagnosticsEnabled = GlobalOptions.IsPullDiagnostics(InternalDiagnosticsOptions.NormalDiagnosticMode);

            if (!isPullDiagnosticsEnabled)
            {
                // Pull diagnostics isn't enabled, let the live share server provide pull diagnostics.
                ((VSInternalServerCapabilities)defaultCapabilities).SupportsDiagnosticRequests = true;
            }

            return(defaultCapabilities);
        }
예제 #16
0
        private async Task AnalyzeDocumentForKindAsync(TextDocument document, AnalysisKind kind, CancellationToken cancellationToken)
        {
            try
            {
                if (!document.SupportsDiagnostics())
                {
                    return;
                }

                var isActiveDocument         = _documentTrackingService.TryGetActiveDocument() == document.Id;
                var isOpenDocument           = document.IsOpen();
                var isGeneratedRazorDocument = document.IsRazorDocument();

                // Only analyze open/active documents, unless it is a generated Razor document.
                if (!isActiveDocument && !isOpenDocument && !isGeneratedRazorDocument)
                {
                    return;
                }

                var stateSets = _stateManager.GetOrUpdateStateSets(document.Project);
                var compilationWithAnalyzers = await GetOrCreateCompilationWithAnalyzersAsync(document.Project, stateSets, cancellationToken).ConfigureAwait(false);

                var version = await GetDiagnosticVersionAsync(document.Project, cancellationToken).ConfigureAwait(false);

                var backgroundAnalysisScope  = GlobalOptions.GetBackgroundAnalysisScope(document.Project.Language);
                var compilerDiagnosticsScope = GlobalOptions.GetOption(SolutionCrawlerOptionsStorage.CompilerDiagnosticsScopeOption, document.Project.Language);

                // TODO: Switch to a more reliable service to determine visible documents.
                //       DocumentTrackingService is known be unreliable at times.
                var isVisibleDocument = _documentTrackingService.GetVisibleDocuments().Contains(document.Id);

                // We split the diagnostic computation for document into following steps:
                //  1. Try to get cached diagnostics for each analyzer, while computing the set of analyzers that do not have cached diagnostics.
                //  2. Execute all the non-cached analyzers with a single invocation into CompilationWithAnalyzers.
                //  3. Fetch computed diagnostics per-analyzer from the above invocation, and cache and raise diagnostic reported events.
                // In near future, the diagnostic computation invocation into CompilationWithAnalyzers will be moved to OOP.
                // This should help simplify and/or remove the IDE layer diagnostic caching in devenv process.

                // First attempt to fetch diagnostics from the cache, while computing the state sets for analyzers that are not cached.
                using var _ = ArrayBuilder <StateSet> .GetInstance(out var nonCachedStateSets);

                foreach (var stateSet in stateSets)
                {
                    var data = TryGetCachedDocumentAnalysisData(document, stateSet, kind, version,
                                                                backgroundAnalysisScope, compilerDiagnosticsScope, isActiveDocument, isVisibleDocument,
                                                                isOpenDocument, isGeneratedRazorDocument, cancellationToken);
                    if (data.HasValue)
                    {
                        // We need to persist and raise diagnostics for suppressed analyzer.
                        PersistAndRaiseDiagnosticsIfNeeded(data.Value, stateSet);
                    }
                    else
                    {
                        nonCachedStateSets.Add(stateSet);
                    }
                }

                // Then, compute the diagnostics for non-cached state sets, and cache and raise diagnostic reported events for these diagnostics.
                if (nonCachedStateSets.Count > 0)
                {
                    var analysisScope = new DocumentAnalysisScope(document, span: null, nonCachedStateSets.SelectAsArray(s => s.Analyzer), kind);
                    var executor      = new DocumentAnalysisExecutor(analysisScope, compilationWithAnalyzers, _diagnosticAnalyzerRunner, logPerformanceInfo: true, onAnalysisException: OnAnalysisException);
                    var logTelemetry  = GlobalOptions.GetOption(DiagnosticOptions.LogTelemetryForBackgroundAnalyzerExecution);
                    foreach (var stateSet in nonCachedStateSets)
                    {
                        var computedData = await ComputeDocumentAnalysisDataAsync(executor, stateSet, logTelemetry, cancellationToken).ConfigureAwait(false);

                        PersistAndRaiseDiagnosticsIfNeeded(computedData, stateSet);
                    }
                }
            }
            catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken))
            {
                throw ExceptionUtilities.Unreachable;
            }

            void PersistAndRaiseDiagnosticsIfNeeded(DocumentAnalysisData result, StateSet stateSet)
            {
                if (result.FromCache == true)
                {
                    RaiseDocumentDiagnosticsIfNeeded(document, stateSet, kind, result.Items);
                    return;
                }

                // no cancellation after this point.
                var state = stateSet.GetOrCreateActiveFileState(document.Id);

                state.Save(kind, result.ToPersistData());

                RaiseDocumentDiagnosticsIfNeeded(document, stateSet, kind, result.OldItems, result.Items);
            }

            void OnAnalysisException()
            {
                // Do not re-use cached CompilationWithAnalyzers instance in presence of an exception, as the underlying analysis state might be corrupt.
                ClearCompilationsWithAnalyzersCache(document.Project);
            }
        }
예제 #17
0
        protected override async Task ProduceTagsAsync(
            TaggerContext <InheritanceMarginTag> context,
            DocumentSnapshotSpan spanToTag,
            int?caretPosition,
            CancellationToken cancellationToken)
        {
            var document = spanToTag.Document;

            if (document == null)
            {
                return;
            }

            var inheritanceMarginInfoService = document.GetLanguageService <IInheritanceMarginService>();

            if (inheritanceMarginInfoService == null)
            {
                return;
            }

            if (GlobalOptions.GetOption(FeatureOnOffOptions.ShowInheritanceMargin, document.Project.Language) == false)
            {
                return;
            }

            var includeGlobalImports = GlobalOptions.GetOption(FeatureOnOffOptions.InheritanceMarginIncludeGlobalImports, document.Project.Language);

            // Use FrozenSemantics Version of document to get the semantics ready, therefore we could have faster
            // response. (Since the full load might take a long time)
            // We also subscribe to CompilationAvailableTaggerEventSource, so this will finally reach the correct state.
            document = document.WithFrozenPartialSemantics(cancellationToken);

            var spanToSearch           = spanToTag.SnapshotSpan.Span.ToTextSpan();
            var stopwatch              = SharedStopwatch.StartNew();
            var inheritanceMemberItems = await inheritanceMarginInfoService.GetInheritanceMemberItemsAsync(
                document,
                spanToSearch,
                includeGlobalImports,
                cancellationToken).ConfigureAwait(false);

            var elapsed = stopwatch.Elapsed;

            if (inheritanceMemberItems.IsEmpty)
            {
                return;
            }

            InheritanceMarginLogger.LogGenerateBackgroundInheritanceInfo(elapsed);

            // One line might have multiple members to show, so group them.
            // For example:
            // interface IBar { void Foo1(); void Foo2(); }
            // class Bar : IBar { void Foo1() { } void Foo2() { } }
            var lineToMembers = inheritanceMemberItems.GroupBy(item => item.LineNumber);

            var snapshot = spanToTag.SnapshotSpan.Snapshot;

            foreach (var(lineNumber, membersOnTheLine) in lineToMembers)
            {
                var membersOnTheLineArray = membersOnTheLine.ToImmutableArray();

                // One line should at least have one member on it.
                Contract.ThrowIfTrue(membersOnTheLineArray.IsEmpty);

                var line = snapshot.GetLineFromLineNumber(lineNumber);
                // We only care about the line, so just tag the start.
                context.AddTag(new TagSpan <InheritanceMarginTag>(
                                   new SnapshotSpan(snapshot, line.Start, length: 0),
                                   new InheritanceMarginTag(document.Project.Solution.Workspace, lineNumber, membersOnTheLineArray)));
            }
        }
예제 #18
0
 private bool IsXamlLspIntelliSenseEnabled()
 => GlobalOptions.GetOption(XamlOptions.EnableLspIntelliSenseFeatureFlag);