public void ExecuteAnalysis(string path, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer, IAnalyzerOptions analyzerOptions, IAnalysisStatusNotifier statusNotifier, CancellationToken cancellationToken) { var projectItem = dte?.Solution?.FindProjectItem(path); if (projectItem == null) { return; } Debug.Assert(IsAnalysisSupported(detectedLanguages)); var request = CreateRequest(logger, projectItem, path, cFamilyRulesConfigProvider, analyzerOptions); if (request == null) { return; } TriggerAnalysis(request, consumer, statusNotifier, cancellationToken); }
public static void ProcessFile(ISonarLintDaemon daemon, IIssueConsumer issueConsumer, ILogger logger, ProjectItem projectItem, string absoluteFilePath, string charset) { if (IsHeaderFile(absoluteFilePath)) { // We can't analyze header files currently because we can't get all // of the required configuration information logger.WriteLine($"Cannot analyze header files. File: '{absoluteFilePath}'"); return; } if (!IsFileInSolution(projectItem)) { logger.WriteLine($"Unable to retrieve the configuration for file '{absoluteFilePath}'. Check the file is part of a project in the current solution."); return; } string sqLanguage; string json = TryGetConfig(logger, projectItem, absoluteFilePath, out sqLanguage); if (json != null && sqLanguage != null) { daemon.RequestAnalysis(absoluteFilePath, charset, sqLanguage, json, issueConsumer); } }
public void ExecuteAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer, ProjectItem projectItem, IAnalyzerOptions analyzerOptions, CancellationToken cancellationToken) { RequestAnalysisCallCount++; RequestAnalysisOperation?.Invoke(); }
internal async Task ExecuteAnalysis(string filePath, IIssueConsumer consumer, CancellationToken cancellationToken) { telemetryManager.LanguageAnalyzed("js"); // Switch to a background thread await TaskScheduler.Default; analysisStatusNotifier.AnalysisStarted(filePath); try { var stopwatch = Stopwatch.StartNew(); var issues = await eslintBridgeAnalyzer.Analyze(filePath, null, cancellationToken); analysisStatusNotifier.AnalysisFinished(filePath, issues.Count, stopwatch.Elapsed); if (issues.Any()) { consumer.Accept(filePath, issues); } } catch (TaskCanceledException) { analysisStatusNotifier.AnalysisCancelled(filePath); } catch (Exception ex) when(!ErrorHandler.IsCriticalException(ex)) { analysisStatusNotifier.AnalysisFailed(filePath, ex); } }
private async void Analyze(string path, string charset, string sqLanguage, IIssueConsumer consumer) { var request = new AnalysisReq { BaseDir = path, WorkDir = WorkingDirectory, }; request.File.Add(new InputFile { Path = path, Charset = charset, Language = sqLanguage }); // Concurrent requests should not use same directory: var buildWrapperOutDir = CreateTempDirectory(WorkingDirectory); using (var call = daemonClient.Analyze(request)) { try { await ProcessIssues(call, path, consumer); } catch (Exception e) { Debug.WriteLine("Call to client.Analyze failed: {0}", e); } finally { Directory.Delete(buildWrapperOutDir, true); } } }
private async void Analyze(string path, string charset, IIssueConsumer consumer) { var request = new AnalysisReq { BaseDir = path, WorkDir = workingDirectory, }; request.File.Add(new InputFile { Path = path, Charset = charset, }); var channel = new Channel($"{DAEMON_HOST}:{port}", ChannelCredentials.Insecure); var client = new StandaloneSonarLint.StandaloneSonarLintClient(channel); using (var call = client.Analyze(request)) { try { await ProcessIssues(call, path, consumer); } catch (Exception e) { Debug.WriteLine("Call to client.Analyze failed: {0}", e); } } await channel.ShutdownAsync(); }
public void ExecuteAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer, IAnalyzerOptions analyzerOptions, CancellationToken cancellationToken) { detectedLanguages.Should().NotBeNull(); detectedLanguages.Any().Should().BeTrue(); IsAnalysisSupported(detectedLanguages).Should().BeTrue(); RequestAnalysisCalled = true; }
private void RequestAnalysis(string path, string charset, string sqLanguage, IIssueConsumer consumer) { if (daemonClient == null) { Debug.WriteLine("Daemon not ready yet"); return; } WritelnToPane($"Analyzing {path}"); Analyze(path, charset, sqLanguage, consumer); }
private void InvokeDaemon(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer, ProjectItem projectItem, CancellationToken cancellationToken, IAnalyzerOptions analyzerOptions) { Debug.Assert(detectedLanguages?.Contains(AnalysisLanguage.Javascript) ?? false, "Not expecting the daemon to be called for languages other than JavaScript"); // TODO refactor the daemon so it does not implement IAnalyzer or make any // decisions about whether to run or not. That should all be handled by // this class. telemetryManager.LanguageAnalyzed("js"); daemon.ExecuteAnalysis(path, charset, detectedLanguages, consumer, projectItem, analyzerOptions, cancellationToken); }
public DelayedRequest(DaemonAnalyzer daemonAnalyzer, string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer) { this.daemonAnalyzer = daemonAnalyzer; this.daemon = daemonAnalyzer.daemon; this.daemonInstaller = daemonAnalyzer.installer; this.path = path; this.charset = charset; this.detectedLanguages = detectedLanguages; this.consumer = consumer; }
public void ExecuteAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer, IAnalyzerOptions analyzerOptions, CancellationToken cancellationToken) { Debug.Assert(IsAnalysisSupported(detectedLanguages)); ExecuteAnalysis(path, consumer, cancellationToken).Forget(); // fire and forget }
public void ExecuteAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer, ProjectItem projectItem, IAnalyzerOptions analyzerOptions, CancellationToken cancellationToken) { Debug.Assert(IsAnalysisSupported(detectedLanguages)); var request = CFamilyHelper.CreateRequest(logger, projectItem, path, cFamilyRulesConfigProvider, analyzerOptions); if (request == null) { return; } TriggerAnalysisAsync(request, consumer, cancellationToken) .Forget(); // fire and forget }
private void HandleMessage(Message message, Request request, IIssueConsumer consumer, ref int issueCount) { Debug.Assert(message.Filename == request.File, $"Issue for unexpected file returned: {message.Filename}"); if (!IsIssueForActiveRule(message, request.RulesConfiguration)) { return; } issueCount++; var issue = issueConverter.Convert(message, request.CFamilyLanguage, request.RulesConfiguration); // Note: the file being analyzed might have been closed by the time the analysis results are // returned. This doesn't cause a crash; all active taggers will have been detached from the // TextBufferIssueTracker when the file was closed, but the TextBufferIssueTracker will // still exist and handle the call. consumer.Accept(request.File, new[] { issue }); }
/// <summary> /// Executes analysis for the given path. CancellationToken is not currently supported. /// </summary> public void ExecuteAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer, IAnalyzerOptions analyzerOptions, CancellationToken cancellationToken) { if (!IsAnalysisSupported(detectedLanguages)) { return; } // Optimise for the common case of daemon up and running if (installer.IsInstalled() && daemon.IsRunning) { InvokeDaemon(path, charset, detectedLanguages, consumer, cancellationToken, analyzerOptions); return; } new DelayedRequest(this, path, charset, detectedLanguages, consumer).Execute(); }
public void ExecuteAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer, IAnalyzerOptions analyzerOptions, CancellationToken cancellationToken) { if (!settings.IsActivateMoreEnabled) { // User might have disable additional languages in the meantime return; } if (!IsRunning) // daemon might not have finished starting / might have shutdown { // TODO: handle as part of #926: Delay starting the daemon until a file needs to be analyzed // https://github.com/SonarSource/sonarlint-visualstudio/issues/926 logger.WriteLine("Daemon has not started yet. Analysis will not be performed"); return; } RequestAnalysis(path, charset, "js", consumer); }
public void ExecuteAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer, IAnalyzerOptions analyzerOptions, CancellationToken cancellationToken) { bool handled = false; foreach (var analyzer in analyzers) { if (analyzer.IsAnalysisSupported(detectedLanguages)) { handled = true; analyzer.ExecuteAnalysis(path, charset, detectedLanguages, consumer, analyzerOptions, cancellationToken); } } if (!handled) { logger.WriteLine($"No analyzer supported analysis of {path}"); } }
internal /* for testing */ async Task TriggerAnalysisAsync(Request request, IIssueConsumer consumer, IAnalysisStatusNotifier statusNotifier, CancellationToken cancellationToken) { // For notes on VS threading, see https://github.com/microsoft/vs-threading/blob/master/doc/cookbook_vs.md // Note: we support multiple versions of VS which prevents us from using some threading helper methods // that are only available in newer versions of VS e.g. [Import] IThreadHandling. // Switch to a background thread await TaskScheduler.Default; var analysisStartTime = DateTime.Now; statusNotifier?.AnalysisStarted(request.File); int issueCount = 0; var handleMessage = consumer == null ? (Action <Message>)(message => { }) : message => HandleMessage(message, request, consumer, ref issueCount); try { // We're tying up a background thread waiting for out-of-process analysis. We could // change the process runner so it works asynchronously. Alternatively, we could change the // RequestAnalysis method to be asynchronous, rather than fire-and-forget. CallSubProcess(handleMessage, request, settings, logger, cancellationToken); if (cancellationToken.IsCancellationRequested) { statusNotifier?.AnalysisCancelled(request.File); } else { var analysisTime = DateTime.Now - analysisStartTime; statusNotifier?.AnalysisFinished(request.File, issueCount, analysisTime); } } catch (Exception ex) when(!ErrorHandler.IsCriticalException(ex)) { statusNotifier?.AnalysisFailed(request.File, ex); } telemetryManager.LanguageAnalyzed(request.CFamilyLanguage); // different keys for C and C++ }
internal async Task ExecuteAnalysis(string filePath, IIssueConsumer consumer, CancellationToken cancellationToken) { telemetryManager.LanguageAnalyzed("js"); // Switch to a background thread await TaskScheduler.Default; analysisStatusNotifier.AnalysisStarted(filePath); try { await EnsureEslintBridgeClientIsInitialized(cancellationToken); var stopwatch = Stopwatch.StartNew(); var analysisResponse = await eslintBridgeClient.AnalyzeJs(filePath, cancellationToken); var numberOfIssues = analysisResponse.Issues?.Count() ?? 0; analysisStatusNotifier.AnalysisFinished(filePath, numberOfIssues, stopwatch.Elapsed); if (analysisResponse.ParsingError != null) { LogParsingError(filePath, analysisResponse.ParsingError); return; } var issues = ConvertIssues(filePath, analysisResponse.Issues); if (issues.Any()) { consumer.Accept(filePath, issues); } } catch (TaskCanceledException) { analysisStatusNotifier.AnalysisCancelled(filePath); } catch (Exception ex) when(!ErrorHandler.IsCriticalException(ex)) { analysisStatusNotifier.AnalysisFailed(filePath, ex); } }
internal async Task ExecuteAnalysis(string filePath, IIssueConsumer consumer, CancellationToken cancellationToken) { telemetryManager.LanguageAnalyzed("ts"); // Switch to a background thread await TaskScheduler.Default; analysisStatusNotifier.AnalysisStarted(filePath); try { var stopwatch = Stopwatch.StartNew(); var tsConfig = await tsConfigProvider.GetConfigForFile(filePath, cancellationToken); if (string.IsNullOrEmpty(tsConfig)) { analysisStatusNotifier.AnalysisFailed(filePath, Resources.ERR_NoTsConfig); return; } logger.WriteLine("[TypescriptAnalyzer] time to find ts config: " + stopwatch.ElapsedMilliseconds); stopwatch.Restart(); var issues = await eslintBridgeAnalyzer.Analyze(filePath, tsConfig, cancellationToken); analysisStatusNotifier.AnalysisFinished(filePath, issues.Count, stopwatch.Elapsed); if (issues.Any()) { consumer.Accept(filePath, issues); } } catch (TaskCanceledException) { analysisStatusNotifier.AnalysisCancelled(filePath); } catch (Exception ex) when(!ErrorHandler.IsCriticalException(ex)) { analysisStatusNotifier.AnalysisFailed(filePath, ex); } }
private async Task TriggerAnalysisAsync(Request request, IIssueConsumer consumer, CancellationToken cancellationToken) { // For notes on VS threading, see https://github.com/microsoft/vs-threading/blob/master/doc/cookbook_vs.md // Note: we support multiple versions of VS which prevents us from using some threading helper methods // that are only available in newer versions of VS e.g. [Import] IThreadHandling. // Switch a background thread await TaskScheduler.Default; logger.WriteLine($"Analyzing {request.File}"); // We're tying up a background thread waiting for out-of-process analysis. We could // change the process runner so it works asynchronously. Alternatively, we could change the // RequestAnalysis method to be synchronous, rather than fire-and-forget. var response = CFamilyHelper.CallClangAnalyzer(request, new ProcessRunner(settings, logger), logger, cancellationToken); if (response != null) { Debug.Assert(response.Messages.All(m => m.Filename == request.File), "Issue for unexpected file returned"); var issues = response.Messages .Where(m => IsIssueForActiveRule(m, request.RulesConfiguration)) .Select(m => CFamilyHelper.ToSonarLintIssue(m, request.CFamilyLanguage, request.RulesConfiguration)) .ToList(); telemetryManager.LanguageAnalyzed(request.CFamilyLanguage); // different keys for C and C++ logger.WriteLine($"Found {issues.Count} issue(s)"); // Switch back to the UI thread await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // Note: the file being analyzed might have been closed by the time the analysis results are // returned. This doesn't cause a crash; all active taggers will have been detached from the // TextBufferIssueTracker when the file was closed, but the TextBufferIssueTracker will // still exist and handle the call. consumer.Accept(request.File, issues); } }
public void RequestAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer issueConsumer, ProjectItem projectItem, IAnalyzerOptions analyzerOptions) { // May be called on the UI thread -> unhandled exceptions will crash VS try { scheduler.Schedule(path, cancellationToken => analyzerController.ExecuteAnalysis(path, charset, detectedLanguages, issueConsumer, projectItem, analyzerOptions, cancellationToken)); } catch (Exception ex) when(!Microsoft.VisualStudio.ErrorHandler.IsCriticalException(ex)) { logger.WriteLine($"Analysis error: {ex}"); } }
protected override void TriggerAnalysis(Request request, IIssueConsumer consumer, IAnalysisStatusNotifier analysisStatusNotifier, CancellationToken cancellationToken) { TriggerAnalysisCallCount++; }
private async System.Threading.Tasks.Task ProcessIssues(AsyncServerStreamingCall <Issue> call, string path, IIssueConsumer consumer) { var issues = new List <IAnalysisIssue>(); int issueCount = 0; while (await call.ResponseStream.MoveNext()) { var issue = call.ResponseStream.Current; issues.Add(ToAnalysisIssue(issue)); issueCount++; } WritelnToPane($"Found {issueCount} issue(s)"); consumer.Accept(path, issues); }
private void UnsafeRequestAnalysis(string path, string charset, IEnumerable <SonarLanguage> detectedLanguages, IIssueConsumer issueConsumer, ProjectItem projectItem) { bool handled = false; foreach (var language in detectedLanguages) { switch (language) { case SonarLanguage.Javascript: handled = true; daemon.RequestAnalysis(path, charset, "js", null, issueConsumer); break; case SonarLanguage.CFamily: handled = true; CFamily.ProcessFile(daemon, issueConsumer, logger, projectItem, path, charset); break; default: break; } } if (!handled) { logger.WriteLine($"Unsupported content type for {path}"); } }
public void RequestAnalysis(string path, string charset, IEnumerable <SonarLanguage> detectedLanguages, IIssueConsumer issueConsumer, ProjectItem projectItem) { // Called on the UI thread -> unhandled exceptions will crash VS try { UnsafeRequestAnalysis(path, charset, detectedLanguages, issueConsumer, projectItem); } catch (Exception ex) when(!Microsoft.VisualStudio.ErrorHandler.IsCriticalException(ex)) { logger.WriteLine($"Daemon error: {ex.ToString()}"); } }
private async System.Threading.Tasks.Task ProcessIssues(AsyncServerStreamingCall <Issue> call, string path, IIssueConsumer consumer) { var issues = new List <Issue>(); while (await call.ResponseStream.MoveNext()) { var issue = call.ResponseStream.Current; issues.Add(issue); } consumer.Accept(path, issues); }
public void RequestAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer issueConsumer, IAnalyzerOptions analyzerOptions) { // May be called on the UI thread -> unhandled exceptions will crash VS try { var analysisTimeout = GetAnalysisTimeoutInMilliseconds(); scheduler.Schedule(path, cancellationToken => analyzerController.ExecuteAnalysis(path, charset, detectedLanguages, issueConsumer, analyzerOptions, cancellationToken), analysisTimeout); } catch (NotSupportedException ex) { // Display a simple user-friendly message for options we know are not supported. // See https://github.com/SonarSource/sonarlint-visualstudio/pull/2212 logger.WriteLine($"Unable to analyze: {ex.Message}"); } catch (Exception ex) when(!Microsoft.VisualStudio.ErrorHandler.IsCriticalException(ex)) { logger.WriteLine($"Analysis error: {ex}"); } }
public void ExecuteAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer, ProjectItem projectItem) { detectedLanguages.Should().NotBeNull(); detectedLanguages.Any().Should().BeTrue(); IsAnalysisSupported(detectedLanguages).Should().BeTrue(); RequestAnalysisCalled = true; }
public void ExecuteAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages, IIssueConsumer consumer, IAnalyzerOptions analyzerOptions, CancellationToken cancellationToken) { ExecuteAnalysis(path, detectedLanguages, consumer, analyzerOptions, analysisStatusNotifier, cancellationToken); }
protected /* for testing */ virtual void TriggerAnalysis(Request request, IIssueConsumer consumer, IAnalysisStatusNotifier statusNotifier, CancellationToken cancellationToken) => TriggerAnalysisAsync(request, consumer, statusNotifier, cancellationToken) .Forget(); // fire and forget