private static string LogSynchronizeWithBuild(OptionSet options, ImmutableDictionary <ProjectId, ImmutableArray <DiagnosticData> > map) { using var pooledObject = SharedPools.Default <StringBuilder>().GetPooledObject(); var sb = pooledObject.Object; sb.Append($"PreferBuildError:{PreferBuildErrors(options)}, PreferLiveOnOpenFiles:{PreferLiveErrorsOnOpenedFiles(options)}"); if (map.Count > 0) { foreach (var(projectId, diagnostics) in map) { sb.AppendLine($"{projectId}, Count: {diagnostics.Length}"); foreach (var diagnostic in diagnostics) { sb.AppendLine($" {diagnostic.ToString()}"); } } } return(sb.ToString()); }
public async Task <FirstDiagnosticResult> GetFirstDiagnosticWithFixAsync(Document document, TextSpan range, bool considerSuppressionFixes, CancellationToken cancellationToken) { if (document == null || !document.IsOpen()) { return(default(FirstDiagnosticResult)); } using (var diagnostics = SharedPools.Default <List <DiagnosticData> >().GetPooledObject()) { var fullResult = await _diagnosticService.TryAppendDiagnosticsForSpanAsync(document, range, diagnostics.Object, cancellationToken : cancellationToken).ConfigureAwait(false); foreach (var diagnostic in diagnostics.Object) { cancellationToken.ThrowIfCancellationRequested(); if (!range.IntersectsWith(diagnostic.TextSpan)) { continue; } // REVIEW: 2 possible designs. // 1. find the first fix and then return right away. if the lightbulb is actually expanded, find all fixes for the line synchronously. or // 2. kick off a task that finds all fixes for the given range here but return once we find the first one. // at the same time, let the task to run to finish. if the lightbulb is expanded, we just simply use the task to get all fixes. // // first approach is simpler, so I will implement that first. if the first approach turns out to be not good enough, then // I will try the second approach which will be more complex but quicker var hasFix = await ContainsAnyFix(document, diagnostic, considerSuppressionFixes, cancellationToken).ConfigureAwait(false); if (hasFix) { // ReSharper disable once ConditionIsAlwaysTrueOrFalse return(new FirstDiagnosticResult(!fullResult, hasFix, diagnostic)); } } return(new FirstDiagnosticResult(!fullResult, false, default(DiagnosticData))); } }
private SyntaxNode CreateFormattedRoot(CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Formatting_CreateFormattedRoot, cancellationToken)) { var changes = GetChanges(cancellationToken); // create a map using (var pooledObject = SharedPools.Default <Dictionary <ValueTuple <SyntaxToken, SyntaxToken>, TriviaData> >().GetPooledObject()) { var map = pooledObject.Object; changes.Do(change => map.Add(change.Item1, change.Item2)); // no changes, return as it is. if (map.Count == 0) { return(this.TreeInfo.Root); } return(Rewriter(map, cancellationToken)); } } }
private IEnumerable <CompletionItem> CreateCompletionItems( Workspace workspace, SemanticModel semanticModel, IEnumerable <ISymbol> symbols, SyntaxToken token, TextSpan itemSpan, int position, ImmutableDictionary <string, string> options) { var builder = SharedPools.Default <StringBuilder>().Allocate(); try { foreach (var symbol in symbols) { yield return(CreateItem(workspace, semanticModel, symbol, token, position, builder, options)); if (TryCreateSpecialTypeItem(workspace, semanticModel, symbol, token, position, builder, options, out var item)) { yield return(item); } } } finally { SharedPools.Default <StringBuilder>().ClearAndFree(builder); } }
private static void ApplyChanges( IProjectionBuffer subjectBuffer, IEnumerable <TextChange> changes, IList <TextSpan> visibleSpansInOriginal, out IEnumerable <int> affectedVisibleSpansInNew) { using var edit = subjectBuffer.CreateEdit(s_venusEditOptions, reiteratedVersionNumber: null, editTag: null); var affectedSpans = SharedPools.Default <HashSet <int> >().AllocateAndClear(); affectedVisibleSpansInNew = affectedSpans; var currentVisibleSpanIndex = 0; foreach (var change in changes) { // Find the next visible span that either overlaps or intersects with while (currentVisibleSpanIndex < visibleSpansInOriginal.Count && visibleSpansInOriginal[currentVisibleSpanIndex].End < change.Span.Start) { currentVisibleSpanIndex++; } // no more place to apply text changes if (currentVisibleSpanIndex >= visibleSpansInOriginal.Count) { break; } var newText = change.NewText; var span = change.Span.ToSpan(); edit.Replace(span, newText); affectedSpans.Add(currentVisibleSpanIndex); } edit.ApplyAndLogExceptions(); }
private static string LogSynchronizeWithBuild(Workspace workspace, ImmutableDictionary <ProjectId, ImmutableArray <DiagnosticData> > map) { using var pooledObject = SharedPools.Default <StringBuilder>().GetPooledObject(); var sb = pooledObject.Object; sb.Append($"PreferBuildError:{PreferBuildErrors(workspace)}, PreferLiveOnOpenFiles:{PreferLiveErrorsOnOpenedFiles(workspace)}"); if (map.Count > 0) { foreach (var kv in map) { sb.AppendLine($"{kv.Key}, Count: {kv.Value.Length}"); foreach (var diagnostic in kv.Value) { sb.AppendLine($" {diagnostic.ToString()}"); } } } return(sb.ToString()); }
private async Task <IEnumerable <Diagnostic> > ComputeProjectDiagnosticAnalyzerDiagnosticsAsync( Project project, ProjectDiagnosticAnalyzer analyzer, Compilation compilationOpt, CancellationToken cancellationToken) { using (var pooledObject = SharedPools.Default <List <Diagnostic> >().GetPooledObject()) { var diagnostics = pooledObject.Object; cancellationToken.ThrowIfCancellationRequested(); try { await analyzer.AnalyzeProjectAsync(project, diagnostics.Add, cancellationToken).ConfigureAwait(false); // REVIEW: V1 doesn't convert diagnostics to effective diagnostics. not sure why. return(compilationOpt == null?diagnostics.ToImmutableArrayOrEmpty() : CompilationWithAnalyzers.GetEffectiveDiagnostics(diagnostics, compilationOpt)); } catch (Exception e) when(!IsCanceled(e, cancellationToken)) { OnAnalyzerException(analyzer, project.Id, compilationOpt, e); return(ImmutableArray <Diagnostic> .Empty); } } }
private ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> CreateAnalysisResults( Project project, ImmutableArray <StateSet> stateSets, ProjectAnalysisData oldAnalysisData, ImmutableArray <DiagnosticData> diagnostics) { using var poolObject = SharedPools.Default <HashSet <string> >().GetPooledObject(); var lookup = diagnostics.ToLookup(d => d.Id); var builder = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, DiagnosticAnalysisResult>(); foreach (var stateSet in stateSets) { var descriptors = DiagnosticAnalyzerInfoCache.GetDiagnosticDescriptors(stateSet.Analyzer); var liveDiagnostics = MergeDiagnostics( ConvertToLiveDiagnostics(lookup, descriptors, poolObject.Object), oldAnalysisData.GetResult(stateSet.Analyzer).GetAllDiagnostics()); builder.Add(stateSet.Analyzer, DiagnosticAnalysisResult.CreateFromBuild(project, liveDiagnostics)); } return(builder.ToImmutable()); }
public List <ILexerRule> GetExpectedLexerRules() { var list = SharedPools.Default <List <ILexerRule> >().AllocateAndClear(); if (_chart.FrameSets.Count == 0) { return(list); } var frameSet = _chart.FrameSets[_chart.FrameSets.Count - 1]; for (var i = 0; i < frameSet.Frames.Count; i++) { var stateFrame = frameSet.Frames[i]; for (int j = 0; j < stateFrame.Frame.ScanKeys.Count; j++) { var lexerRule = stateFrame.Frame.ScanKeys[j]; list.Add(lexerRule); } } return(list); }
private async Task SynchronizeAssetsAsync( Dictionary <ProjectId, ProjectStateChecksums> oldMap, Dictionary <ProjectId, ProjectStateChecksums> newMap ) { using var pooledObject = SharedPools.Default <HashSet <Checksum> >().GetPooledObject(); // added project foreach (var kv in newMap) { if (oldMap.ContainsKey(kv.Key)) { continue; } pooledObject.Object.Add(kv.Value.Checksum); } await _assetProvider .SynchronizeProjectAssetsAsync(pooledObject.Object, _cancellationToken) .ConfigureAwait(false); }
private Worker( SemanticModel semanticModel, TextSpan textSpan, ArrayBuilder <ClassifiedSpan> list, Func <SyntaxNode, ImmutableArray <ISyntaxClassifier> > getNodeClassifiers, Func <SyntaxToken, ImmutableArray <ISyntaxClassifier> > getTokenClassifiers, ClassificationOptions options, CancellationToken cancellationToken) { _getNodeClassifiers = getNodeClassifiers; _getTokenClassifiers = getTokenClassifiers; _semanticModel = semanticModel; _syntaxTree = semanticModel.SyntaxTree; _textSpan = textSpan; _list = list; _cancellationToken = cancellationToken; _options = options; // get one from pool _set = SharedPools.Default <HashSet <ClassifiedSpan> >().AllocateAndClear(); _pendingNodes = SharedPools.Default <Stack <SyntaxNodeOrToken> >().AllocateAndClear(); }
protected override async Task ExecuteAsync() { // wait for global operation such as build await GlobalOperationTask.ConfigureAwait(false); using (var pooledObject = SharedPools.Default <List <ExpensiveAnalyzerInfo> >().GetPooledObject()) using (RoslynLogger.LogBlock(FunctionId.Diagnostics_GeneratePerformaceReport, CancellationToken)) { _diagnosticAnalyzerPerformanceTracker.GenerateReport(pooledObject.Object); foreach (var badAnalyzerInfo in pooledObject.Object) { var newAnalyzer = _reported.Add(badAnalyzerInfo.AnalyzerId); var internalUser = WatsonReporter.IsUserMicrosoftInternal; // we only report same analyzer once unless it is internal user if (internalUser || newAnalyzer) { // this will report telemetry under VS. this will let us see how accurate our performance tracking is RoslynLogger.Log(FunctionId.Diagnostics_BadAnalyzer, KeyValueLogMessage.Create(m => { // since it is telemetry, we hash analyzer name if it is not builtin analyzer m[nameof(badAnalyzerInfo.AnalyzerId)] = internalUser ? badAnalyzerInfo.AnalyzerId : badAnalyzerInfo.PIISafeAnalyzerId; m[nameof(badAnalyzerInfo.LocalOutlierFactor)] = badAnalyzerInfo.LocalOutlierFactor; m[nameof(badAnalyzerInfo.Average)] = badAnalyzerInfo.Average; m[nameof(badAnalyzerInfo.AdjustedStandardDeviation)] = badAnalyzerInfo.AdjustedStandardDeviation; })); } // for logging, we only log once. we log here so that we can ask users to provide this log to us // when we want to find out VS performance issue that could be caused by analyzer if (newAnalyzer) { _logger.TraceEvent(TraceEventType.Error, 0, $"[{badAnalyzerInfo.AnalyzerId} ({badAnalyzerInfo.AnalyzerIdHash})] LOF: {badAnalyzerInfo.LocalOutlierFactor}, Avg: {badAnalyzerInfo.Average}, Stddev: {badAnalyzerInfo.AdjustedStandardDeviation}"); } } } }
internal static void Classify( SemanticModel semanticModel, TextSpan textSpan, ArrayBuilder <ClassifiedSpan> list, Func <SyntaxNode, ImmutableArray <ISyntaxClassifier> > getNodeClassifiers, Func <SyntaxToken, ImmutableArray <ISyntaxClassifier> > getTokenClassifiers, ClassificationOptions options, CancellationToken cancellationToken) { var worker = new Worker(semanticModel, textSpan, list, getNodeClassifiers, getTokenClassifiers, options, cancellationToken); try { worker._pendingNodes.Push(worker._syntaxTree.GetRoot(cancellationToken)); worker.ProcessNodes(); } finally { // release collections to the pool SharedPools.Default <HashSet <ClassifiedSpan> >().ClearAndFree(worker._set); SharedPools.Default <Stack <SyntaxNodeOrToken> >().ClearAndFree(worker._pendingNodes); } }
private BidirectionalMap <string, DiagnosticAnalyzer> CreateAnalyzerMap(IEnumerable <AnalyzerReference> hostAnalyzers, Project project) { // we could consider creating a service so that we don't do this repeatedly if this shows up as perf cost using var pooledObject = SharedPools.Default <HashSet <object> >().GetPooledObject(); using var pooledMap = SharedPools.Default <Dictionary <string, DiagnosticAnalyzer> >().GetPooledObject(); var referenceSet = pooledObject.Object; var analyzerMap = pooledMap.Object; // this follow what we do in DiagnosticAnalyzerInfoCache.CheckAnalyzerReferenceIdentity foreach (var reference in hostAnalyzers.Concat(project.AnalyzerReferences)) { if (!referenceSet.Add(reference.Id)) { // already exist continue; } analyzerMap.AppendAnalyzerMap(reference.GetAnalyzers(project.Language)); } // convert regular map to bidirectional map return(new BidirectionalMap <string, DiagnosticAnalyzer>(analyzerMap)); }
private void RaiseDiagnosticsCleared(IDiagnosticUpdateSource source) { var ev = _eventMap.GetEventHandlers <EventHandler <DiagnosticsUpdatedArgs> >(DiagnosticsUpdatedEventName); _eventQueue.ScheduleTask(DiagnosticsUpdatedEventName, () => { using var pooledObject = SharedPools.Default <List <DiagnosticsUpdatedArgs> >().GetPooledObject(); var removed = pooledObject.Object; if (!ClearDiagnosticsReportedBySource(source, removed)) { // there is no change, nothing to raise events for. return; } // don't create event listener if it haven't created yet. if there is a diagnostic to remove // listener should have already created since all events are done in the serialized queue foreach (var args in removed) { ev.RaiseEvent(handler => handler(source, args)); } }, CancellationToken.None); }
internal static void Classify( Workspace workspace, SemanticModel semanticModel, TextSpan textSpan, List <ClassifiedSpan> list, Func <SyntaxNode, List <ISyntaxClassifier> > getNodeClassifiers, Func <SyntaxToken, List <ISyntaxClassifier> > getTokenClassifiers, CancellationToken cancellationToken) { var worker = new Worker(workspace, semanticModel, textSpan, list, getNodeClassifiers, getTokenClassifiers, cancellationToken); try { worker.pendingNodes.Push(worker.syntaxTree.GetRoot(cancellationToken)); worker.ProcessNodes(); } finally { // release collections to the pool SharedPools.Default <HashSet <ClassifiedSpan> >().ClearAndFree(worker.set); SharedPools.Default <Stack <SyntaxNodeOrToken> >().ClearAndFree(worker.pendingNodes); } }
private static string SnapshotLogger(IEnumerable <AnalyzerPerformanceInfo> snapshots, int unitCount) { using (var pooledObject = SharedPools.Default <StringBuilder>().GetPooledObject()) { var sb = pooledObject.Object; sb.Append(unitCount); foreach (var snapshot in snapshots) { sb.Append("|"); sb.Append(snapshot.AnalyzerId); sb.Append(":"); sb.Append(snapshot.BuiltIn); sb.Append(":"); sb.Append(snapshot.TimeSpan.TotalMilliseconds); } sb.Append("*"); return(sb.ToString()); } }
private bool MatchesExistingIgnoreLexemes(char character) { if (!AnyExistingIngoreLexemes()) { return(false); } var pool = SharedPools.Default <List <ILexeme> >(); List <ILexeme> matches = null; for (int i = 0; i < _ignoreLexemes.Count; i++) { var lexeme = _ignoreLexemes[i]; if (!lexeme.Scan(character)) { FreeLexeme(lexeme); continue; } if (matches == null) { matches = pool.AllocateAndClear(); } matches.Add(lexeme); } if (matches == null) { _ignoreLexemes.Clear(); pool.ClearAndFree(matches); return(false); } pool.ClearAndFree(_ignoreLexemes); _ignoreLexemes = matches; return(_ignoreLexemes.Count > 0); }
private async Task SynchronizeWithBuildAsync(Document document, IEnumerable <StateSet> stateSets, IEnumerable <DiagnosticData> diagnostics) { var workspace = document.Project.Solution.Workspace; // check whether, for opened documents, we want to prefer live diagnostics if (PreferLiveErrorsOnOpenedFiles(workspace) && workspace.IsDocumentOpen(document.Id)) { // enqueue re-analysis of open documents. this.Owner.Reanalyze(workspace, documentIds: SpecializedCollections.SingletonEnumerable(document.Id), highPriority: true); return; } using (var poolObject = SharedPools.Default <HashSet <string> >().GetPooledObject()) { var lookup = CreateDiagnosticIdLookup(diagnostics); foreach (var stateSet in stateSets) { // we are using Default so that things like LB can't use cached information var textVersion = VersionStamp.Default; var semanticVersion = await document.Project.GetDependentSemanticVersionAsync(CancellationToken.None).ConfigureAwait(false); // clear document and project live errors await PersistAndReportAsync(stateSet, StateType.Project, document, textVersion, semanticVersion, ImmutableArray <DiagnosticData> .Empty).ConfigureAwait(false); await PersistAndReportAsync(stateSet, StateType.Syntax, document, textVersion, semanticVersion, ImmutableArray <DiagnosticData> .Empty).ConfigureAwait(false); var descriptors = HostAnalyzerManager.GetDiagnosticDescriptors(stateSet.Analyzer); var liveDiagnostics = ConvertToLiveDiagnostics(lookup, descriptors, poolObject.Object); // REVIEW: for now, we are putting build error in document state rather than creating its own state. // reason is so that live error can take over it as soon as possible // this also means there can be slight race where it will clean up eventually. if live analysis runs for syntax but didn't run // for document yet, then we can have duplicated entries in the error list until live analysis catch. await PersistAndReportAsync(stateSet, StateType.Document, document, textVersion, semanticVersion, liveDiagnostics).ConfigureAwait(false); } } }
private StrongBox <ImmutableArray <DiagnosticData> > ReadFrom(ObjectReader reader, Project project, Document document, CancellationToken cancellationToken) { try { using (var pooledObject = SharedPools.Default <List <DiagnosticData> >().GetPooledObject()) { var list = pooledObject.Object; var format = reader.ReadInt32(); if (format != FormatVersion) { return(null); } // saved data is for same analyzer of different version of dll var analyzerVersion = VersionStamp.ReadFrom(reader); if (analyzerVersion != AnalyzerVersion) { return(null); } var version = VersionStamp.ReadFrom(reader); if (version != VersionStamp.Default && version != Version) { return(null); } ReadFrom(reader, project, document, list, cancellationToken); return(new StrongBox <ImmutableArray <DiagnosticData> >(list.ToImmutableArray())); } } catch (Exception) { return(null); } }
private async Task SynchronizeWithBuildAsync(Project project, IEnumerable <StateSet> stateSets, IEnumerable <DiagnosticData> diagnostics) { using (var poolObject = SharedPools.Default <HashSet <string> >().GetPooledObject()) { var lookup = CreateDiagnosticIdLookup(diagnostics); foreach (var stateSet in stateSets) { var descriptors = HostAnalyzerManager.GetDiagnosticDescriptors(stateSet.Analyzer); var liveDiagnostics = ConvertToLiveDiagnostics(lookup, descriptors, poolObject.Object); // we are using Default so that things like LB can't use cached information var projectTextVersion = VersionStamp.Default; var semanticVersion = await project.GetDependentSemanticVersionAsync(CancellationToken.None).ConfigureAwait(false); var state = stateSet.GetState(StateType.Project); var existingDiagnostics = await state.TryGetExistingDataAsync(project, CancellationToken.None).ConfigureAwait(false); var mergedDiagnostics = MergeDiagnostics(liveDiagnostics, GetExistingDiagnostics(existingDiagnostics)); await state.PersistAsync(project, new AnalysisData(projectTextVersion, semanticVersion, mergedDiagnostics), CancellationToken.None).ConfigureAwait(false); RaiseDiagnosticsCreated(StateType.Project, project.Id, stateSet, new SolutionArgument(project), mergedDiagnostics); } } }
private bool TryGetSubTextChanges( SourceText originalText, TextSpan visibleSpanInOriginalText, string leftText, string rightText, int offsetInOriginalText, List <TextChange> changes) { // these are expensive. but hopely, we don't hit this as much except the boundary cases. using (var leftPool = SharedPools.Default <List <TextSpan> >().GetPooledObject()) using (var rightPool = SharedPools.Default <List <TextSpan> >().GetPooledObject()) { var spansInLeftText = leftPool.Object; var spansInRightText = rightPool.Object; if (TryGetWhitespaceOnlyChanges(leftText, rightText, spansInLeftText, spansInRightText)) { for (var i = 0; i < spansInLeftText.Count; i++) { var spanInLeftText = spansInLeftText[i]; var spanInRightText = spansInRightText[i]; if (spanInLeftText.IsEmpty && spanInRightText.IsEmpty) { continue; } var spanInOriginalText = new TextSpan(offsetInOriginalText + spanInLeftText.Start, spanInLeftText.Length); TextChange textChange; if (TryGetSubTextChange(originalText, visibleSpanInOriginalText, rightText, spanInOriginalText, spanInRightText, out textChange)) { changes.Add(textChange); } } return(true); } return(false); } }
public async Task <ImmutableArray <Diagnostic> > GetProjectDiagnosticsAsync(DiagnosticAnalyzer analyzer) { try { Contract.ThrowIfNull(_project); Contract.ThrowIfFalse(_document == null); using (var diagnostics = SharedPools.Default <List <Diagnostic> >().GetPooledObject()) { if (_project.SupportsCompilation) { await this.GetCompilationDiagnosticsAsync(analyzer, diagnostics.Object).ConfigureAwait(false); } await this.GetProjectDiagnosticsWorkerAsync(analyzer, diagnostics.Object).ConfigureAwait(false); return(diagnostics.Object.ToImmutableArray()); } } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
private bool MatchesExistingIncompleteIgnoreLexemes(char character) { if (!AnyExistingIngoreLexemes()) { return(false); } var pool = SharedPools.Default <List <ILexeme> >(); var matches = pool.AllocateAndClear(); for (var i = 0; i < _ignoreLexemes.Count; i++) { var lexeme = _ignoreLexemes[i]; if (!lexeme.IsAccepted()) { if (lexeme.Scan(character)) { matches.Add(lexeme); } else { FreeLexeme(lexeme); } } } if (matches.Count == 0) { pool.ClearAndFree(matches); return(false); } pool.ClearAndFree(_ignoreLexemes); _ignoreLexemes = matches; return(true); }
private IEnumerable <DiagnosticData> GetDiagnostics( Workspace workspace, ProjectId projectId, DocumentId documentId, bool includeSuppressedDiagnostics, CancellationToken cancellationToken) { foreach (var source in _updateSources) { cancellationToken.ThrowIfCancellationRequested(); if (source.SupportGetDiagnostics) { foreach (var diagnostic in source.GetDiagnostics(workspace, projectId, documentId, null, includeSuppressedDiagnostics, cancellationToken)) { AssertIfNull(diagnostic); yield return(diagnostic); } } else { using (var list = SharedPools.Default <List <Data> >().GetPooledObject()) { AppendMatchingData(source, workspace, projectId, documentId, null, list.Object); foreach (var data in list.Object) { foreach (var diagnostic in data.Diagnostics) { AssertIfNull(diagnostic); if (includeSuppressedDiagnostics || !diagnostic.IsSuppressed) { yield return(diagnostic); } } } } } } }
private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeOutOfProcAsync( RemoteHostClient client, CompilationWithAnalyzers analyzerDriver, Project project, bool forcedAnalysis, CancellationToken cancellationToken) { var solution = project.Solution; var snapshotService = solution.Workspace.Services.GetService <IRemotableDataService>(); using var pooledObject = SharedPools.Default <Dictionary <string, DiagnosticAnalyzer> >().GetPooledObject(); var analyzerMap = pooledObject.Object; analyzerMap.AppendAnalyzerMap(analyzerDriver.Analyzers.Where(a => forcedAnalysis || !a.IsOpenFileOnly(solution.Options))); if (analyzerMap.Count == 0) { return(DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty); } var argument = new DiagnosticArguments( forcedAnalysis, analyzerDriver.AnalysisOptions.ReportSuppressedDiagnostics, analyzerDriver.AnalysisOptions.LogAnalyzerExecutionTime, project.Id, analyzerMap.Keys.ToArray()); using var session = await client.TryCreateSessionAsync(WellKnownServiceHubServices.CodeAnalysisService, solution, callbackTarget : null, cancellationToken).ConfigureAwait(false); if (session == null) { // session is not available return(DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty); } var result = await session.Connection.InvokeAsync( nameof(IRemoteDiagnosticAnalyzerService.CalculateDiagnosticsAsync), new object[] { argument }, (stream, cancellationToken) => ReadCompilerAnalysisResultAsync(stream, analyzerMap, project, cancellationToken), cancellationToken).ConfigureAwait(false); ReportAnalyzerExceptions(project, result.Exceptions); return(result); }
private async Task <Project> UpdateDocumentsAsync( Project project, IEnumerable <TextDocumentState> existingTextDocumentStates, ChecksumCollection oldChecksums, ChecksumCollection newChecksums, Func <Solution, ImmutableArray <DocumentInfo>, Solution> addDocuments, Func <Solution, DocumentId, Solution> removeDocument) { using var olds = SharedPools.Default <HashSet <Checksum> >().GetPooledObject(); using var news = SharedPools.Default <HashSet <Checksum> >().GetPooledObject(); olds.Object.UnionWith(oldChecksums); news.Object.UnionWith(newChecksums); // remove documents that exist in both side olds.Object.ExceptWith(newChecksums); news.Object.ExceptWith(oldChecksums); var oldMap = await GetDocumentMapAsync(existingTextDocumentStates, olds.Object).ConfigureAwait(false); var newMap = await GetDocumentMapAsync(_assetProvider, news.Object).ConfigureAwait(false); // added document ImmutableArray <DocumentInfo> .Builder?lazyDocumentsToAdd = null; foreach (var(documentId, newDocumentChecksums) in newMap) { if (!oldMap.ContainsKey(documentId)) { lazyDocumentsToAdd ??= ImmutableArray.CreateBuilder <DocumentInfo>(); // we have new document added var documentInfo = await _assetProvider.CreateDocumentInfoAsync(newDocumentChecksums.Checksum, _cancellationToken).ConfigureAwait(false); lazyDocumentsToAdd.Add(documentInfo); } } if (lazyDocumentsToAdd != null) { project = addDocuments(project.Solution, lazyDocumentsToAdd.ToImmutable()).GetProject(project.Id) !; } // changed document foreach (var(documentId, newDocumentChecksums) in newMap) { if (!oldMap.TryGetValue(documentId, out var oldDocumentChecksums)) { continue; } Contract.ThrowIfTrue(oldDocumentChecksums.Checksum == newDocumentChecksums.Checksum); var document = project.GetDocument(documentId) ?? project.GetAdditionalDocument(documentId) ?? project.GetAnalyzerConfigDocument(documentId); Contract.ThrowIfNull(document); project = await UpdateDocumentAsync(document, oldDocumentChecksums, newDocumentChecksums).ConfigureAwait(false); } // removed document foreach (var(documentId, _) in oldMap) { if (!newMap.ContainsKey(documentId)) { // we have a document removed project = removeDocument(project.Solution, documentId).GetProject(project.Id) !; } } return(project); }
public static List <T> Allocate() { return(SharedPools.Default <List <T> >().AllocateAndClear()); }
public static void Free(List <T> list) { SharedPools.Default <List <T> >().ClearAndFree(list); }
private void DeallocateStringBuilderAndAssignCapture() { _capture = _stringBuilder.ToString(); SharedPools.Default <StringBuilder>().ClearAndFree(_stringBuilder); _stringBuilder = null; }