async void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e) { if (!enabled) { return; } var doc = DocumentContext.ParsedDocument; if (doc == null || DocumentContext.IsAdHocProject) { return; } if (DocumentContext.AnalysisDocument == null) { return; } if (e.DocumentId != DocumentContext.AnalysisDocument.Id || e.ProjectId != DocumentContext.AnalysisDocument.Project.Id) { return; } var token = CancelUpdateTimeout(e.Id); var ad = new AnalysisDocument(Editor, DocumentContext); try { var result = await CodeDiagnosticRunner.Check(ad, token, e.Diagnostics).ConfigureAwait(false); var updater = new ResultsUpdater(this, result, e.Id, token); updater.Update(); } catch (Exception) { } }
async void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e) { if (!enabled) { return; } var doc = DocumentContext.ParsedDocument; if (doc == null || DocumentContext.IsAdHocProject) { return; } var cad = DocumentContext.AnalysisDocument; if (cad == null || cad.Project == null) { return; } if (e.DocumentId != cad.Id || e.ProjectId != cad.Project.Id) { return; } var token = CancelUpdateTimeout(e.Id); var ad = new AnalysisDocument(Editor, DocumentContext); try { var result = await CodeDiagnosticRunner.Check(ad, token, e.Diagnostics).ConfigureAwait(false); if (result is IReadOnlyList <Result> resultList) { await Runtime.RunInMainThread(delegate { if (resultUpdaters.TryGetValue(e.Id, out var oldUpdater)) { oldUpdater.Cancel(); } var updater = new ResultsUpdater(this, resultList, e.Id); updater.Start(); resultUpdaters [e.Id] = updater; }); }
void OnDocumentParsed(object sender, EventArgs args) { if (!AnalysisOptions.EnableFancyFeatures) { return; } CancelUpdateTimout(); var doc = DocumentContext.ParsedDocument; if (doc == null) { return; } updateTimeout = GLib.Timeout.Add(250, delegate { lock (updateLock) { CancelTask(); src = new CancellationTokenSource(); var token = src.Token; var ad = new AnalysisDocument(Editor, DocumentContext); oldTask = Task.Run(() => { try { var result = CodeDiagnosticRunner.Check(ad, token); if (token.IsCancellationRequested) { return; } var updater = new ResultsUpdater(this, result, token); updater.Update(); } catch (OperationCanceledException) { } catch (AggregateException) { } }); updateTimeout = 0; return(false); } }); }
internal Task <CodeActionContainer> GetCurrentFixesAsync(CancellationToken cancellationToken) { var loc = Editor.CaretOffset; var ad = DocumentContext.AnalysisDocument; if (ad == null) { return(Task.FromResult(CodeActionContainer.Empty)); } TextSpan span; if (Editor.IsSomethingSelected) { var selectionRange = Editor.SelectionRange; span = selectionRange.Offset >= 0 ? TextSpan.FromBounds(selectionRange.Offset, selectionRange.EndOffset) : TextSpan.FromBounds(loc, loc); } else { span = TextSpan.FromBounds(loc, loc); } var rExt = Editor.GetContent <ResultsEditorExtension> (); var errorList = Editor .GetTextSegmentMarkersAt(Editor.CaretOffset) .OfType <IErrorMarker> () .Where(rm => !string.IsNullOrEmpty(rm.Error.Id)).ToList(); return(Task.Run(async delegate { try { var result = await CodeDiagnosticRunner.Check(new AnalysisDocument(Editor, DocumentContext), cancellationToken).ConfigureAwait(false); var diagnosticsAtCaret = result.OfType <DiagnosticResult> ().Where(d => d.Region.Contains(loc)).Select(d => d.Diagnostic).ToList(); var codeIssueFixes = new List <ValidCodeDiagnosticAction> (); var diagnosticIds = diagnosticsAtCaret.Select(diagnostic => diagnostic.Id).Concat(errorList.Select(rm => rm.Error.Id)).ToList(); if (codeFixes == null) { codeFixes = (await CodeRefactoringService.GetCodeFixesAsync(DocumentContext, CodeRefactoringService.MimeTypeToLanguage(Editor.MimeType), cancellationToken).ConfigureAwait(false)).ToList(); } var root = await ad.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); foreach (var cfp in codeFixes) { if (cancellationToken.IsCancellationRequested) { return CodeActionContainer.Empty; } var provider = cfp.GetCodeFixProvider(); if (!provider.FixableDiagnosticIds.Any(diagnosticIds.Contains)) { continue; } // These two delegates were factored out, as using them as lambdas in the inner loop creates more captures than declaring them here. Func <Diagnostic, bool> providerIdsContain = d => provider.FixableDiagnosticIds.Contains(d.Id); Action <Microsoft.CodeAnalysis.CodeActions.CodeAction, ImmutableArray <Diagnostic> > codeFixRegistration = (ca, d) => codeIssueFixes.Add(new ValidCodeDiagnosticAction(cfp, ca, d, d [0].Location.SourceSpan)); try { var groupedDiagnostics = diagnosticsAtCaret .Concat(errorList.Select(em => em.Error.Tag) .OfType <Diagnostic> ()) .GroupBy(d => d.Location.SourceSpan); foreach (var g in groupedDiagnostics) { if (cancellationToken.IsCancellationRequested) { return CodeActionContainer.Empty; } var diagnosticSpan = g.Key; var validDiagnostics = g.Where(providerIdsContain).ToImmutableArray(); if (validDiagnostics.Length == 0) { continue; } if (diagnosticSpan.Start < 0 || diagnosticSpan.End > root.Span.End) { continue; } await provider.RegisterCodeFixesAsync(new CodeFixContext(ad, diagnosticSpan, validDiagnostics, codeFixRegistration, cancellationToken)).ConfigureAwait(false); // TODO: Is that right ? Currently it doesn't really make sense to run one code fix provider on several overlapping diagnostics at the same location // However the generate constructor one has that case and if I run it twice the same code action is generated twice. So there is a dupe check problem there. // Work around for now is to only take the first diagnostic batch. break; } } catch (OperationCanceledException) { return CodeActionContainer.Empty; } catch (AggregateException ae) { ae.Flatten().Handle(aex => aex is OperationCanceledException); return CodeActionContainer.Empty; } catch (Exception ex) { LoggingService.LogError("Error while getting refactorings from code fix provider " + cfp.Name, ex); continue; } } var codeActions = new List <ValidCodeAction> (); foreach (var action in await CodeRefactoringService.GetValidActionsAsync(Editor, DocumentContext, span, cancellationToken).ConfigureAwait(false)) { codeActions.Add(action); } if (cancellationToken.IsCancellationRequested) { return CodeActionContainer.Empty; } var codeActionContainer = new CodeActionContainer(codeIssueFixes, codeActions, diagnosticsAtCaret); Application.Invoke((o, args) => { if (cancellationToken.IsCancellationRequested) { return; } if (codeActionContainer.IsEmpty) { RemoveWidget(); return; } CreateSmartTag(codeActionContainer, loc); }); return codeActionContainer; } catch (AggregateException ae) { ae.Flatten().Handle(aex => aex is OperationCanceledException); return CodeActionContainer.Empty; } catch (OperationCanceledException) { return CodeActionContainer.Empty; } catch (TargetInvocationException ex) { if (ex.InnerException is OperationCanceledException) { return CodeActionContainer.Empty; } throw; } }, cancellationToken)); }