From 9f1283018f99f0c05e42d5d8a651dd952668a2bc Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 6 Dec 2023 16:41:28 +0100 Subject: [PATCH] Add more analysis warnings (#4455) Co-authored-by: Ilia Kebets <104737176+ilia-kebets-sonarsource@users.noreply.github.com> --- .../plugins/javascript/JavaScriptPlugin.java | 1 + .../javascript/bridge/AbstractAnalysis.java | 5 ++++- .../javascript/bridge/AnalysisProcessor.java | 8 +++++++ .../bridge/AnalysisWithProgram.java | 20 ++++++++++++++--- .../bridge/AnalysisWithWatchProgram.java | 13 +++++++++-- .../JavaScriptEslintBasedSensorTest.java | 10 +++++---- .../javascript/bridge/JsTsSensorTest.java | 22 ++++++++++++++++++- 7 files changed, 68 insertions(+), 11 deletions(-) diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/JavaScriptPlugin.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/JavaScriptPlugin.java index 4bd341f1e9b..5557bd2da05 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/JavaScriptPlugin.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/JavaScriptPlugin.java @@ -61,6 +61,7 @@ public class JavaScriptPlugin implements Plugin { + public static final String TYPESCRIPT_VERSION = "5.3.2"; private static final Logger LOG = Loggers.get(JavaScriptPlugin.class); // Subcategories diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AbstractAnalysis.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AbstractAnalysis.java index 795d1b66af5..69b2d1b87d1 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AbstractAnalysis.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AbstractAnalysis.java @@ -45,15 +45,18 @@ abstract class AbstractAnalysis { JsTsChecks checks; ProgressReport progressReport; AnalysisMode analysisMode; + protected final AnalysisWarningsWrapper analysisWarnings; AbstractAnalysis( BridgeServer bridgeServer, Monitoring monitoring, - AnalysisProcessor analysisProcessor + AnalysisProcessor analysisProcessor, + AnalysisWarningsWrapper analysisWarnings ) { this.bridgeServer = bridgeServer; this.monitoring = monitoring; this.analysisProcessor = analysisProcessor; + this.analysisWarnings = analysisWarnings; } protected static String inputFileLanguage(InputFile file) { diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisProcessor.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisProcessor.java index 0fac76bd1a8..602846afc20 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisProcessor.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisProcessor.java @@ -29,6 +29,7 @@ import java.io.Serializable; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; import org.sonar.api.batch.fs.InputFile; @@ -70,6 +71,7 @@ public class AnalysisProcessor { private ContextUtils contextUtils; private InputFile file; private JsTsChecks checks; + HashSet uniqueParsingErrors; public AnalysisProcessor( NoSonarFilter noSonarFilter, @@ -79,6 +81,7 @@ public AnalysisProcessor( this.noSonarFilter = noSonarFilter; this.fileLinesContextFactory = fileLinesContextFactory; this.monitoring = monitoring; + this.uniqueParsingErrors = new HashSet<>(); } void processResponse( @@ -92,6 +95,7 @@ void processResponse( this.checks = checks; this.file = file; if (response.parsingError != null) { + uniqueParsingErrors.add(file.absolutePath()); processParsingError(response.parsingError); return; } @@ -117,6 +121,10 @@ void processResponse( } } + public int parsingErrorFilesCount() { + return uniqueParsingErrors.size(); + } + void processCacheAnalysis(SensorContext context, InputFile file, CacheAnalysis cacheAnalysis) { this.context = context; contextUtils = new ContextUtils(context); diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisWithProgram.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisWithProgram.java index 6176a6caa27..75743a2216e 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisWithProgram.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisWithProgram.java @@ -33,6 +33,7 @@ import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.log.Profiler; import org.sonar.plugins.javascript.CancellationException; +import org.sonar.plugins.javascript.JavaScriptPlugin; import org.sonar.plugins.javascript.bridge.BridgeServer.TsProgram; import org.sonar.plugins.javascript.bridge.BridgeServer.TsProgramRequest; import org.sonar.plugins.javascript.bridge.cache.CacheAnalysis; @@ -46,7 +47,6 @@ public class AnalysisWithProgram extends AbstractAnalysis { private static final Logger LOG = Loggers.get(AnalysisWithProgram.class); private static final Profiler PROFILER = Profiler.create(LOG); - private final AnalysisWarningsWrapper analysisWarnings; public AnalysisWithProgram( BridgeServer bridgeServer, @@ -54,8 +54,7 @@ public AnalysisWithProgram( AnalysisProcessor analysisProcessor, AnalysisWarningsWrapper analysisWarnings ) { - super(bridgeServer, monitoring, analysisProcessor); - this.analysisWarnings = analysisWarnings; + super(bridgeServer, monitoring, analysisProcessor, analysisWarnings); } @Override @@ -80,6 +79,13 @@ void analyzeFiles(List inputFiles, List tsConfigs) throws IOE var program = bridgeServer.createProgram(new TsProgramRequest(tsConfig)); if (program.error != null) { LOG.error("Failed to create program: " + program.error); + this.analysisWarnings.addUnique( + String.format( + "Failed to create TypeScript program with TSConfig file %s. Highest TypeScript supported version is %s.", + tsConfig, + JavaScriptPlugin.TYPESCRIPT_VERSION + ) + ); PROFILER.stopInfo(); continue; } @@ -110,6 +116,14 @@ void analyzeFiles(List inputFiles, List tsConfigs) throws IOE } } success = true; + if (analysisProcessor.parsingErrorFilesCount() > 0) { + this.analysisWarnings.addUnique( + String.format( + "There were parsing errors in %d files while analyzing the project. Check the logs for further details.", + analysisProcessor.parsingErrorFilesCount() + ) + ); + } } finally { if (success) { progressReport.stop(); diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisWithWatchProgram.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisWithWatchProgram.java index bf0432655e6..d7ae0960acf 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisWithWatchProgram.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AnalysisWithWatchProgram.java @@ -48,9 +48,10 @@ public class AnalysisWithWatchProgram extends AbstractAnalysis { public AnalysisWithWatchProgram( BridgeServer bridgeServer, Monitoring monitoring, - AnalysisProcessor analysisProcessor + AnalysisProcessor analysisProcessor, + AnalysisWarningsWrapper analysisWarnings ) { - super(bridgeServer, monitoring, analysisProcessor); + super(bridgeServer, monitoring, analysisProcessor, analysisWarnings); } @Override @@ -82,6 +83,14 @@ public void analyzeFiles(List inputFiles, List tsConfigs) thr } } success = true; + if (analysisProcessor.parsingErrorFilesCount() > 0) { + this.analysisWarnings.addUnique( + String.format( + "There were parsing errors in %d files while analyzing the project. Check the logs for further details.", + analysisProcessor.parsingErrorFilesCount() + ) + ); + } } finally { if (success) { progressReport.stop(); diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JavaScriptEslintBasedSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JavaScriptEslintBasedSensorTest.java index a7266632032..4295d950bfd 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JavaScriptEslintBasedSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JavaScriptEslintBasedSensorTest.java @@ -156,15 +156,17 @@ public void setUp() throws Exception { when(fileLinesContextFactory.createFor(any(InputFile.class))).thenReturn(fileLinesContext); analysisProcessor = new AnalysisProcessor(new DefaultNoSonarFilter(), fileLinesContextFactory, monitoring); + var analysisWarnings = new AnalysisWarningsWrapper(); + analysisWithProgram = - new AnalysisWithProgram( + new AnalysisWithProgram(bridgeServerMock, monitoring, analysisProcessor, analysisWarnings); + analysisWithWatchProgram = + new AnalysisWithWatchProgram( bridgeServerMock, monitoring, analysisProcessor, - new AnalysisWarningsWrapper() + analysisWarnings ); - analysisWithWatchProgram = - new AnalysisWithWatchProgram(bridgeServerMock, monitoring, analysisProcessor); } @Test diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JsTsSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JsTsSensorTest.java index 2ce6078d17e..0e629cb3292 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JsTsSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JsTsSensorTest.java @@ -42,6 +42,7 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import org.junit.jupiter.api.BeforeEach; @@ -83,6 +84,7 @@ import org.sonar.api.utils.Version; import org.sonar.api.utils.log.LoggerLevel; import org.sonar.javascript.checks.CheckList; +import org.sonar.plugins.javascript.JavaScriptPlugin; import org.sonar.plugins.javascript.TestUtils; import org.sonar.plugins.javascript.bridge.BridgeServer.AnalysisResponse; import org.sonar.plugins.javascript.bridge.BridgeServer.JsAnalysisRequest; @@ -509,8 +511,12 @@ void should_analyze_by_program() throws Exception { when(bridgeServerMock.analyzeTypeScript(any())).thenReturn(new AnalysisResponse()); ArgumentCaptor captor = ArgumentCaptor.forClass(JsAnalysisRequest.class); + ArgumentCaptor captorProgram = ArgumentCaptor.forClass( + TsProgramRequest.class + ); createSensor().execute(context); verify(bridgeServerMock, times(4)).analyzeTypeScript(captor.capture()); + verify(bridgeServerMock, times(4)).createProgram(captorProgram.capture()); assertThat(captor.getAllValues()) .extracting(req -> req.filePath) .containsExactlyInAnyOrder( @@ -530,6 +536,15 @@ void should_analyze_by_program() throws Exception { ); assertThat(logTester.logs(LoggerLevel.ERROR)) .contains("Failed to create program: something went wrong"); + + assertThat(analysisWarnings.warnings) + .contains( + String.format( + "Failed to create TypeScript program with TSConfig file %s. Highest TypeScript supported version is %s.", + captorProgram.getAllValues().get(2).tsConfig, + JavaScriptPlugin.TYPESCRIPT_VERSION + ) + ); } @Test @@ -796,7 +811,12 @@ private AnalysisWithProgram analysisWithProgram() { } private AnalysisWithWatchProgram analysisWithWatchProgram() { - return new AnalysisWithWatchProgram(bridgeServerMock, monitoring, processAnalysis); + return new AnalysisWithWatchProgram( + bridgeServerMock, + monitoring, + processAnalysis, + analysisWarnings + ); } private AnalysisResponse createResponse() {