public async Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken) { if (TryGetAnalyzer(project, out var analyzer)) { await analyzer.AnalyzeProjectAsync(project, semanticsChanged, reasons, cancellationToken).ConfigureAwait(false); } }
public async Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken) { if (TryGetAnalyzer(document.Project, out var analyzer)) { await analyzer.AnalyzeDocumentAsync(document, bodyOpt, reasons, cancellationToken).ConfigureAwait(false); } }
public async Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, CancellationToken cancellationToken) { if (!document.SupportsSyntaxTree) { return; } // getting tree is cheap since tree always stays in memory var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var length = tree.Length; while (true) { if (_map.TryAdd(document.Id, length)) { Interlocked.Add(ref _size, length); return; } long size; if (_map.TryGetValue(document.Id, out size)) { if (size == length) { return; } if (_map.TryUpdate(document.Id, length, size)) { Interlocked.Add(ref _size, length - size); return; } } } }
public async Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, CancellationToken cancellationToken) { IIncrementalAnalyzer analyzer; if (TryGetAnalyzer(document.Project, out analyzer)) { await analyzer.AnalyzeSyntaxAsync(document, reasons, cancellationToken).ConfigureAwait(false); } }
public WorkItem( DocumentId documentId, string language, InvocationReasons invocationReasons, bool isLowPriority, SyntaxPath activeMember, IAsyncToken asyncToken) : this(documentId, documentId.ProjectId, language, invocationReasons, isLowPriority, activeMember, ImmutableHashSet.Create<IIncrementalAnalyzer>(), false, asyncToken) { }
public async Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, CancellationToken cancellationToken) { // it has an assumption that this will not be called concurrently for same document. // in fact, in current design, it won't be even called concurrently for different documents. // but, can be called concurrently for different documents in future if we choose to. Contract.ThrowIfFalse(document.IsFromPrimaryBranch()); var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); if (!documentOptions.GetOption(InternalFeatureOnOffOptions.TodoComments)) { return; } // use tree version so that things like compiler option changes are considered var textVersion = await document.GetTextVersionAsync(cancellationToken).ConfigureAwait(false); var syntaxVersion = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false); var existingData = await _state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false); if (existingData != null) { // check whether we can use the data as it is (can happen when re-using persisted data from previous VS session) if (CheckVersions(document, textVersion, syntaxVersion, existingData)) { Contract.Requires(_workspace == document.Project.Solution.Workspace); RaiseTaskListUpdated(_workspace, document.Project.Solution, document.Id, existingData.Items); return; } } var service = document.GetLanguageService<ITodoCommentService>(); if (service == null) { return; } var tokens = await _todoCommentTokens.GetTokensAsync(document, cancellationToken).ConfigureAwait(false); var comments = await service.GetTodoCommentsAsync(document, tokens, cancellationToken).ConfigureAwait(false); var items = await CreateItemsAsync(document, comments, cancellationToken).ConfigureAwait(false); var data = new Data(textVersion, syntaxVersion, items); await _state.PersistAsync(document, data, cancellationToken).ConfigureAwait(false); // * NOTE * cancellation can't throw after this point. if (existingData == null || existingData.Items.Length > 0 || data.Items.Length > 0) { Contract.Requires(_workspace == document.Project.Solution.Workspace); RaiseTaskListUpdated(_workspace, document.Project.Solution, document.Id, data.Items); } }
public override async Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken) { try { var stateSets = GetStateSetsForFullSolutionAnalysis(_stateManager.GetOrUpdateStateSets(project), project).ToList(); // 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) // REVIEW: IsAnalyzerSuppressed call seems can be quite expensive in certain condition. is there any other way to do this? var activeAnalyzers = stateSets .Select(s => s.Analyzer) .Where(a => !Owner.IsAnalyzerSuppressed(a, project) && !a.IsOpenFileOnly(project.Solution.Workspace)); // get driver only with active analyzers. var includeSuppressedDiagnostics = true; var analyzerDriverOpt = await _compilationManager.CreateAnalyzerDriverAsync(project, activeAnalyzers, includeSuppressedDiagnostics, cancellationToken).ConfigureAwait(false); var ignoreFullAnalysisOptions = false; var result = await _executor.GetProjectAnalysisDataAsync(analyzerDriverOpt, project, stateSets, ignoreFullAnalysisOptions, cancellationToken).ConfigureAwait(false); if (result.FromCache) { RaiseProjectDiagnosticsIfNeeded(project, stateSets, result.Result); return; } // 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.GetProjectState(project.Id); await state.SaveAsync(project, result.GetResult(stateSet.Analyzer)).ConfigureAwait(false); } RaiseProjectDiagnosticsIfNeeded(project, stateSets, result.OldResult, result.Result); } catch (Exception e) when (FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
public async Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken) { // method body change if (bodyOpt != null || !document.IsOpen()) { return; } // get semantic version for the project this document belongs to var newVersion = await document.Project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false); // check whether we already saw semantic version change if (_map.TryGetValue(document.Id, out var oldVersion) && oldVersion == newVersion) { return; } // update to new version _map[document.Id] = newVersion; _owner.RaiseOpenDocumentSemanticChangedEvent(document); }
private WorkItem( DocumentId documentId, ProjectId projectId, string language, InvocationReasons invocationReasons, bool isLowPriority, SyntaxPath activeMember, ImmutableHashSet<IIncrementalAnalyzer> analyzers, bool retry, IAsyncToken asyncToken) { this.DocumentId = documentId; this.ProjectId = projectId; this.Language = language; this.InvocationReasons = invocationReasons; this.IsLowPriority = isLowPriority; this.ActiveMember = activeMember; this.Analyzers = analyzers; this.IsRetry = retry; this.AsyncToken = asyncToken; }
public DocumentDifferenceResult(InvocationReasons changeType, SyntaxNode changedMember = null) { this.ChangeType = changeType; this.ChangedMember = changedMember; }
/// <summary> /// Analyze a single project such that diagnostics for the entire project become available. /// Calls <see cref="DiagnosticAnalyzerService.RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs)"/> for each /// unique group of diagnostics, where a group is identified by analysis classification (project), project, and analyzer. /// </summary> /// <param name="project">The project to analyze.</param> /// <param name="semanticsChanged">Indicates a change to the declarative semantics of the project.</param> /// <param name="reasons">The reason(s) this analysis was triggered.</param> /// <param name="cancellationToken"></param> /// <returns></returns> public abstract Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken);
private void EnqueueEvent(Solution solution, DocumentId documentId, InvocationReasons invocationReasons, string eventName) { _eventProcessingQueue.ScheduleTask(eventName, () => EnqueueWorkItemForDocumentAsync(solution, documentId, invocationReasons), _shutdownToken); }
public Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken) { if (bodyOpt == null) { this.DocumentIds.Add(document.Id); } return SpecializedTasks.EmptyTask; }
public override Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken) { if (!document.SupportsSyntaxTree) { // Not a language we can produce indices for (i.e. TypeScript). Bail immediately. return SpecializedTasks.EmptyTask; } if (bodyOpt != null) { // This was a method level edit. This can't change the symbol tree info // for this project. Bail immediately. return SpecializedTasks.EmptyTask; } return UpdateSymbolTreeInfoAsync(document.Project, cancellationToken); }
private Task EnqueueWorkItemForDocumentAsync(Solution solution, DocumentId documentId, InvocationReasons invocationReasons) { var document = solution.GetDocument(documentId); return(EnqueueWorkItemAsync(document, invocationReasons)); }
private Task EnqueueWorkItemForProjectAsync(Solution solution, ProjectId projectId, InvocationReasons invocationReasons) { var project = solution.GetProject(projectId); return(EnqueueWorkItemAsync(project, invocationReasons)); }
private void EnqueueEvent(Solution solution, ProjectId projectId, InvocationReasons invocationReasons, IAsyncToken asyncToken) { _eventProcessingQueue.ScheduleTask( () => EnqueueWorkItemForProjectAsync(solution, projectId, invocationReasons), _shutdownToken).CompletesAsyncOperation(asyncToken); }
private async Task EnqueueWorkItemAsync(IIncrementalAnalyzer analyzer, Document document, InvocationReasons invocationReasons) { var priorityService = document.GetLanguageService <IWorkCoordinatorPriorityService>(); var isLowPriority = priorityService != null && await priorityService.IsLowPriorityAsync(document, _shutdownToken).ConfigureAwait(false); _documentAndProjectWorkerProcessor.Enqueue( new WorkItem(document.Id, document.Project.Language, invocationReasons, isLowPriority, analyzer, _listener.BeginAsyncOperation("WorkItem"))); }
private Task EnqueueWorkItemForDocumentAsync(Solution solution, DocumentId documentId, InvocationReasons invocationReasons) { var project = solution.GetRequiredProject(documentId.ProjectId); return(EnqueueWorkItemAsync(project, documentId, document: null, invocationReasons)); }
private async Task EnqueueWorkItemAsync(Project project, DocumentId documentId, Document?document, InvocationReasons invocationReasons, SyntaxNode?changedMember = null) { // we are shutting down _shutdownToken.ThrowIfCancellationRequested(); var priorityService = project.GetLanguageService <IWorkCoordinatorPriorityService>(); var isLowPriority = priorityService != null && await priorityService.IsLowPriorityAsync(GetRequiredDocument(project, documentId, document), _shutdownToken).ConfigureAwait(false); var currentMember = GetSyntaxPath(changedMember); // call to this method is serialized. and only this method does the writing. _documentAndProjectWorkerProcessor.Enqueue( new WorkItem(documentId, project.Language, invocationReasons, isLowPriority, currentMember, _listener.BeginAsyncOperation("WorkItem"))); // enqueue semantic work planner if (invocationReasons.Contains(PredefinedInvocationReasons.SemanticChanged)) { // must use "Document" here so that the snapshot doesn't go away. we need the snapshot to calculate p2p dependency graph later. // due to this, we might hold onto solution (and things kept alive by it) little bit longer than usual. _semanticChangeProcessor.Enqueue(project, documentId, document, currentMember); } }
public override Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken) { return Analyzer.AnalyzeProjectAsync(project, semanticsChanged, reasons, cancellationToken); }
public DocumentDifferenceResult(InvocationReasons changeType, SyntaxNode changedMember = null) { ChangeType = changeType; ChangedMember = changedMember; }
private static async Task TestAsync(string codeWithMarker) { using (var workspace = await CSharpWorkspaceFactory.CreateWorkspaceFromLinesAsync(codeWithMarker)) { var commentTokens = new TodoCommentTokens(); var provider = new TodoCommentIncrementalAnalyzerProvider(commentTokens); var worker = (TodoCommentIncrementalAnalyzer)provider.CreateIncrementalAnalyzer(workspace); var document = workspace.Documents.First(); var documentId = document.Id; var reasons = new InvocationReasons(PredefinedInvocationReasons.DocumentAdded); await worker.AnalyzeSyntaxAsync(workspace.CurrentSolution.GetDocument(documentId), CancellationToken.None); var todoLists = worker.GetItems_TestingOnly(documentId); var expectedLists = document.SelectedSpans; Assert.Equal(todoLists.Length, expectedLists.Count); for (int i = 0; i < todoLists.Length; i++) { var todo = todoLists[i]; var span = expectedLists[i]; var line = document.InitialTextSnapshot.GetLineFromPosition(span.Start); var text = document.InitialTextSnapshot.GetText(span.ToSpan()); Assert.Equal(todo.MappedLine, line.LineNumber); Assert.Equal(todo.MappedColumn, span.Start - line.Start); Assert.Equal(todo.Message, text); } } }
public InvocationReasons With(InvocationReasons invocationReasons) { return(new InvocationReasons((reasons ?? ImmutableHashSet.Create <string>()).Union(invocationReasons.reasons))); }
public override Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, CancellationToken cancellationToken) { return AnalyzeDocumentForKindAsync(document, AnalysisKind.Syntax, cancellationToken); }
private async Task EnqueueWorkItemAsync(Document document, InvocationReasons invocationReasons, SyntaxNode changedMember = null) { // we are shutting down _shutdownToken.ThrowIfCancellationRequested(); var priorityService = document.GetLanguageService<IWorkCoordinatorPriorityService>(); var isLowPriority = priorityService != null && await priorityService.IsLowPriorityAsync(document, _shutdownToken).ConfigureAwait(false); var currentMember = GetSyntaxPath(changedMember); // call to this method is serialized. and only this method does the writing. _documentAndProjectWorkerProcessor.Enqueue( new WorkItem(document.Id, document.Project.Language, invocationReasons, isLowPriority, currentMember, _listener.BeginAsyncOperation("WorkItem"))); // enqueue semantic work planner if (invocationReasons.Contains(PredefinedInvocationReasons.SemanticChanged)) { // must use "Document" here so that the snapshot doesn't go away. we need the snapshot to calculate p2p dependency graph later. // due to this, we might hold onto solution (and things kept alive by it) little bit longer than usual. _semanticChangeProcessor.Enqueue(document, currentMember); } }
public WorkItem(DocumentId documentId, string language, InvocationReasons invocationReasons, bool isLowPriority, IAsyncToken asyncToken) : this(documentId, documentId.ProjectId, language, invocationReasons, isLowPriority, null, ImmutableHashSet.Create <IIncrementalAnalyzer>(), false, asyncToken) { }
private Task EnqueueWorkItemForDocumentAsync(Solution solution, DocumentId documentId, InvocationReasons invocationReasons) { var document = solution.GetDocument(documentId); return EnqueueWorkItemAsync(document, invocationReasons); }
public InvocationReasons With(InvocationReasons invocationReasons) { return(new InvocationReasons((_reasons ?? ImmutableHashSet <string> .Empty).Union(invocationReasons._reasons))); }
private async Task EnqueueWorkItemForSolutionAsync(Solution solution, InvocationReasons invocationReasons) { foreach (var projectId in solution.ProjectIds) { await EnqueueWorkItemForProjectAsync(solution, projectId, invocationReasons).ConfigureAwait(false); } }
private void EnqueueFullProjectEvent(Solution solution, ProjectId projectId, InvocationReasons invocationReasons, string eventName) { _eventProcessingQueue.ScheduleTask(eventName, () => EnqueueFullProjectWorkItemAsync(solution.GetRequiredProject(projectId), invocationReasons), _shutdownToken); }
public WorkItem(DocumentId documentId, string language, InvocationReasons invocationReasons, bool isLowPriority, IIncrementalAnalyzer?analyzer, IAsyncToken asyncToken) : this(documentId, documentId.ProjectId, language, invocationReasons, isLowPriority, activeMember : null, analyzer == null ? ImmutableHashSet.Create <IIncrementalAnalyzer>() : ImmutableHashSet.Create(analyzer), retry : false, asyncToken) { }
public static void LogWorkItemEnqueue( LogAggregator logAggregator, string language, DocumentId documentId, InvocationReasons reasons, bool lowPriority, SyntaxPath activeMember, bool added) { logAggregator.IncreaseCount(language); logAggregator.IncreaseCount(added ? NewWorkItem : UpdateWorkItem); if (documentId != null) { logAggregator.IncreaseCount(activeMember == null ? TopLevel : MemberLevel); if (lowPriority) { logAggregator.IncreaseCount(LowerPriority); logAggregator.IncreaseCount(ValueTuple.Create(LowerPriority, documentId.Id)); } } foreach (var reason in reasons) { logAggregator.IncreaseCount(reason); } }
private void EnqueueFullDocumentEvent(Solution solution, DocumentId documentId, InvocationReasons invocationReasons, string eventName) { _eventProcessingQueue.ScheduleTask( eventName, () => { var project = solution.GetRequiredProject(documentId.ProjectId); return(EnqueueDocumentWorkItemAsync(project, documentId, document: null, invocationReasons)); }, _shutdownToken); }
private void EnqueueEvent(Solution solution, DocumentId documentId, InvocationReasons invocationReasons, IAsyncToken asyncToken) { _eventProcessingQueue.ScheduleTask( () => EnqueueWorkItemForDocumentAsync(solution, documentId, invocationReasons), _shutdownToken).CompletesAsyncOperation(asyncToken); }
private void EnqueueEvent(Solution solution, DocumentId documentId, InvocationReasons invocationReasons, IAsyncToken asyncToken) { this.eventProcessingQueue.ScheduleTask( () => EnqueueWorkItemForDocument(solution, documentId, invocationReasons), this.shutdownToken).CompletesAsyncOperation(asyncToken); }
private async Task EnqueueWorkItemAsync(Project project, InvocationReasons invocationReasons) { foreach (var documentId in project.DocumentIds) { var document = project.GetDocument(documentId); await EnqueueWorkItemAsync(document, invocationReasons).ConfigureAwait(false); } }
private void EnqueueWorkItemForDocument(Solution solution, DocumentId documentId, InvocationReasons invocationReasons) { var document = solution.GetDocument(documentId); EnqueueWorkItem(document, invocationReasons); }
private Task EnqueueWorkItemForProjectAsync(Solution solution, ProjectId projectId, InvocationReasons invocationReasons) { var project = solution.GetProject(projectId); return EnqueueWorkItemAsync(project, invocationReasons); }
private void EnqueueWorkItemForProject(Solution solution, ProjectId projectId, InvocationReasons invocationReasons) { var project = solution.GetProject(projectId); EnqueueWorkItem(project, invocationReasons); }
/// <summary> /// Analyze a single document such that local diagnostics for that document become available, /// prioritizing analyzing this document over analyzing the rest of the project. /// Calls <see cref="DiagnosticAnalyzerService.RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs)"/> for each /// unique group of diagnostics, where a group is identified by analysis classification (syntax/semantics), document, and analyzer. /// </summary> /// <param name="document">The document to analyze.</param> /// <param name="bodyOpt">If present, indicates a portion (e.g. a method body) of the document to analyze.</param> /// <param name="reasons">The reason(s) this analysis was triggered.</param> /// <param name="cancellationToken"></param> /// <returns></returns> public abstract Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken);
public virtual Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, CancellationToken cancellationToken) => Task.CompletedTask;
/// <summary> /// Apply syntax tree actions (that have not already been applied) to a document. /// Calls <see cref="DiagnosticAnalyzerService.RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs)"/> for each /// unique group of diagnostics, where a group is identified by analysis classification (syntax), document, and analyzer. /// </summary> /// <param name="document">The document to analyze.</param> /// <param name="reasons">The reason(s) this analysis was triggered.</param> /// <param name="cancellationToken"></param> /// <returns></returns> public abstract Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, CancellationToken cancellationToken);
public virtual Task AnalyzeNonSourceDocumentAsync(TextDocument textDocument, InvocationReasons reasons, CancellationToken cancellationToken) => Task.CompletedTask;
public override Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken) { return Analyzer.AnalyzeDocumentAsync(document, bodyOpt, reasons, cancellationToken); }
public virtual Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken) { return(SpecializedTasks.EmptyTask); }
public virtual Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken) { return(SpecializedTasks.EmptyTask); }
static async Task AnalyzeSyntaxAsync(IIncrementalAnalyzer analyzer, TextDocument textDocument, InvocationReasons reasons, CancellationToken cancellationToken) { if (textDocument is Document document) { await analyzer.AnalyzeSyntaxAsync((Document)document, reasons, cancellationToken).ConfigureAwait(false); } else if (analyzer is IIncrementalAnalyzer2 analyzer2) { await analyzer2.AnalyzeNonSourceDocumentAsync(textDocument, reasons, cancellationToken).ConfigureAwait(false); } }
public Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken) { this.ProjectIds.Add(project.Id); return SpecializedTasks.EmptyTask; }
public virtual Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken) { return(Task.CompletedTask); }
public Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, CancellationToken cancellationToken) { this.SyntaxDocumentIds.Add(document.Id); Process(document.Id, cancellationToken); return SpecializedTasks.EmptyTask; }
public virtual Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken) { return(Task.CompletedTask); }
public override Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken) { return AnalyzeDocumentForKindAsync(document, AnalysisKind.Semantic, cancellationToken); }
public override Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken) { return UpdateSymbolTreeInfoAsync(project, cancellationToken); }
private void EnqueueEvent(Solution solution, InvocationReasons invocationReasons, IAsyncToken asyncToken) { var task = _eventProcessingQueue.ScheduleTask( () => EnqueueWorkItemForSolution(solution, invocationReasons), _shutdownToken).CompletesAsyncOperation(asyncToken); }