示例#1
0
        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);
        }
示例#2
0
        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);
            }
        }
示例#3
0
 public void ExecuteAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages,
                             IIssueConsumer consumer,
                             ProjectItem projectItem, IAnalyzerOptions analyzerOptions, CancellationToken cancellationToken)
 {
     RequestAnalysisCallCount++;
     RequestAnalysisOperation?.Invoke();
 }
示例#4
0
        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);
                }
            }
        }
示例#6
0
        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();
        }
示例#7
0
            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);
        }
示例#10
0
 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;
 }
示例#11
0
        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
        }
示例#13
0
        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 });
        }
示例#14
0
        /// <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}");
            }
        }
示例#17
0
        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);
            }
        }
示例#19
0
        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);
            }
        }
示例#21
0
 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);
        }
示例#24
0
        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}");
            }
        }
示例#25
0
 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()}");
     }
 }
示例#26
0
        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);
        }
示例#27
0
        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;
            }
示例#29
0
 public void ExecuteAnalysis(string path, string charset, IEnumerable <AnalysisLanguage> detectedLanguages,
                             IIssueConsumer consumer, IAnalyzerOptions analyzerOptions,
                             CancellationToken cancellationToken)
 {
     ExecuteAnalysis(path, detectedLanguages, consumer, analyzerOptions, analysisStatusNotifier, cancellationToken);
 }
示例#30
0
 protected /* for testing */ virtual void TriggerAnalysis(Request request, IIssueConsumer consumer, IAnalysisStatusNotifier statusNotifier, CancellationToken cancellationToken) =>
 TriggerAnalysisAsync(request, consumer, statusNotifier, cancellationToken)
 .Forget();         // fire and forget