private void PublishScriptDiagnostics(ScriptFile scriptFile, IReadOnlyList <ScriptFileMarker> markers) { var diagnostics = new Diagnostic[markers.Count]; CorrectionTableEntry fileCorrections = _mostRecentCorrectionsByFile.GetOrAdd( scriptFile, CorrectionTableEntry.CreateForFile); fileCorrections.Corrections.Clear(); for (int i = 0; i < markers.Count; i++) { ScriptFileMarker marker = markers[i]; Diagnostic diagnostic = GetDiagnosticFromMarker(marker); if (marker.Correction != null) { string diagnosticId = GetUniqueIdFromDiagnostic(diagnostic); fileCorrections.Corrections[diagnosticId] = marker.Correction; } diagnostics[i] = diagnostic; } _languageServer.TextDocument.PublishDiagnostics(new PublishDiagnosticsParams { Uri = scriptFile.DocumentUri, Diagnostics = new Container <Diagnostic>(diagnostics) }); }
/// <summary> /// Sets up a script analysis run, eventually returning the result. /// </summary> /// <param name="filesToAnalyze">The files to run script analysis on.</param> /// <param name="cancellationToken">A cancellation token to cancel this call with.</param> /// <returns>A task that finishes when script diagnostics have been published.</returns> public void RunScriptDiagnostics( ScriptFile[] filesToAnalyze, CancellationToken cancellationToken) { if (_configurationService.CurrentSettings.ScriptAnalysis.Enable == false) { return; } EnsureEngineSettingsCurrent(); // Create a cancellation token source that will cancel if we do or if the caller does var cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); // If there's an existing task, we want to cancel it here; CancellationTokenSource oldTaskCancellation = Interlocked.Exchange(ref _diagnosticsCancellationTokenSource, cancellationSource); if (oldTaskCancellation != null) { try { oldTaskCancellation.Cancel(); oldTaskCancellation.Dispose(); } catch (Exception e) { _logger.LogError(e, "Exception occurred while cancelling analysis task"); } } if (filesToAnalyze.Length == 0) { return; } var analysisTask = Task.Run(() => DelayThenInvokeDiagnosticsAsync(filesToAnalyze, _diagnosticsCancellationTokenSource.Token), _diagnosticsCancellationTokenSource.Token); // Ensure that any next corrections request will wait for this diagnostics publication foreach (ScriptFile file in filesToAnalyze) { CorrectionTableEntry fileCorrectionsEntry = _mostRecentCorrectionsByFile.GetOrAdd( file, CorrectionTableEntry.CreateForFile); fileCorrectionsEntry.DiagnosticPublish = analysisTask; } }