Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS-472 Improve instantiation of Analysis classes (Analysis with program or watch program) #4984

Merged
merged 10 commits into from
Dec 4, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,6 @@ public void define(Context context) {
RulesBundles.class,
JsTsChecks.class,
AnalysisWarningsWrapper.class,
AnalysisWithProgram.class,
AnalysisWithWatchProgram.class,
AnalysisProcessor.class,
YamlSensor.class,
HtmlSensor.class,
Expand Down Expand Up @@ -282,7 +280,8 @@ public void define(Context context) {
EslintReportSensor.class,
EslintRulesDefinition.class,
TslintReportSensor.class,
TslintRulesDefinition.class
TslintRulesDefinition.class,
AnalysisWithProgram.class
);

context.addExtension(
Expand Down Expand Up @@ -342,7 +341,7 @@ public void addSonarLintExtensions(
SonarLintPluginAPIVersion sonarLintPluginAPIVersion
) {
if (sonarLintPluginAPIVersion.isDependencyAvailable()) {
context.addExtension(TsConfigCacheImpl.class);
context.addExtensions(TsConfigCacheImpl.class, AnalysisWithWatchProgram.class);
} else {
LOG.debug("Error while trying to inject SonarLint extensions");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
import org.sonar.plugins.javascript.bridge.protobuf.Node;
import org.sonar.plugins.javascript.utils.ProgressReport;

abstract class AbstractAnalysis {
public abstract class AbstractAnalysis {

private static final Logger LOG = LoggerFactory.getLogger(AbstractAnalysis.class);
static final String PROGRESS_REPORT_TITLE = "Progress of JavaScript/TypeScript analysis";
Expand Down Expand Up @@ -90,7 +90,7 @@ protected boolean isJavaScript(InputFile file) {
return inputFileLanguage(file).equals(JavaScriptLanguage.KEY);
}

abstract void analyzeFiles(List<InputFile> inputFiles, List<String> tsConfigs) throws IOException;
abstract void analyzeFiles(List<InputFile> inputFiles) throws IOException;

protected void analyzeFile(
InputFile file,
Expand Down Expand Up @@ -180,4 +180,8 @@ private BridgeServer.JsAnalysisRequest getJsAnalysisRequest(
shouldClearDependenciesCache
);
}

protected String createTsConfigFile(String content) throws IOException {
return bridgeServer.createTsConfigFile(content).getFilename();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,4 @@ protected void logErrorOrWarn(String msg, Throwable e) {
protected abstract void analyzeFiles(List<InputFile> inputFiles) throws IOException;

protected abstract List<InputFile> getInputFiles();

protected boolean shouldAnalyzeWithProgram() {
if (contextUtils.isSonarLint()) {
LOG.debug("Will use AnalysisWithWatchProgram because we are in SonarLint context");
return false;
}
LOG.debug("Will use AnalysisWithProgram");
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@
import org.sonar.plugins.javascript.bridge.BridgeServer.TsProgram;
import org.sonar.plugins.javascript.bridge.BridgeServer.TsProgramRequest;
import org.sonar.plugins.javascript.utils.ProgressReport;
import org.sonarsource.api.sonarlint.SonarLintSide;

@ScannerSide
@SonarLintSide
public class AnalysisWithProgram extends AbstractAnalysis {

private static final Logger LOG = LoggerFactory.getLogger(AnalysisWithProgram.class);
Expand All @@ -50,7 +48,8 @@ public AnalysisWithProgram(
}

@Override
void analyzeFiles(List<InputFile> inputFiles, List<String> tsConfigs) throws IOException {
void analyzeFiles(List<InputFile> inputFiles) throws IOException {
var tsConfigs = TsConfigProvider.getTsConfigs(contextUtils, this::createTsConfigFile);
progressReport = new ProgressReport(PROGRESS_REPORT_TITLE, PROGRESS_REPORT_PERIOD);
progressReport.start(inputFiles.size(), inputFiles.iterator().next().toString());
boolean success = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,31 @@

import java.io.IOException;
import java.util.List;
import javax.annotation.Nullable;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.scanner.ScannerSide;
import org.sonar.plugins.javascript.bridge.AnalysisWarningsWrapper;
import org.sonar.plugins.javascript.bridge.BridgeServer;
import org.sonar.plugins.javascript.sonarlint.TsConfigCache;
import org.sonar.plugins.javascript.utils.ProgressReport;
import org.sonarsource.api.sonarlint.SonarLintSide;

@ScannerSide
@SonarLintSide
public class AnalysisWithWatchProgram extends AbstractAnalysis {

TsConfigCache tsConfigCache;

public AnalysisWithWatchProgram(
BridgeServer bridgeServer,
AnalysisProcessor analysisProcessor,
AnalysisWarningsWrapper analysisWarnings
) {
this(bridgeServer, analysisProcessor, analysisWarnings, null);
}

public AnalysisWithWatchProgram(
BridgeServer bridgeServer,
AnalysisProcessor analysisProcessor,
AnalysisWarningsWrapper analysisWarnings,
@Nullable TsConfigCache tsConfigCache
TsConfigCache tsConfigCache
) {
super(bridgeServer, analysisProcessor, analysisWarnings);
this.tsConfigCache = tsConfigCache;
}

@Override
public void analyzeFiles(List<InputFile> inputFiles, List<String> tsConfigs) throws IOException {
public void analyzeFiles(List<InputFile> inputFiles) throws IOException {
TsConfigProvider.initializeTsConfigCache(contextUtils, this::createTsConfigFile, tsConfigCache);
boolean success = false;
progressReport = new ProgressReport(PROGRESS_REPORT_TITLE, PROGRESS_REPORT_PERIOD);
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.plugins.javascript.JavaScriptPlugin;

class ContextUtils {
public class ContextUtils {

/**
* Internal property to enable SonarArmor (disabled by default), now called Jasmin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,9 @@
*/
package org.sonar.plugins.javascript.analysis;

import static org.sonar.plugins.javascript.analysis.TsConfigProvider.getTsConfigs;

import java.io.IOException;
import java.util.List;
import java.util.stream.StreamSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.DependedUpon;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.FileSystem;
Expand All @@ -33,31 +29,24 @@
import org.sonar.plugins.javascript.TypeScriptLanguage;
import org.sonar.plugins.javascript.bridge.AnalysisMode;
import org.sonar.plugins.javascript.bridge.BridgeServer;
import org.sonar.plugins.javascript.sonarlint.TsConfigCache;

@DependedUpon("js-analysis")
public class JsTsSensor extends AbstractBridgeSensor {

private static final Logger LOG = LoggerFactory.getLogger(JsTsSensor.class);
private final AnalysisWithProgram analysisWithProgram;
private final AnalysisWithWatchProgram analysisWithWatchProgram;
private final AbstractAnalysis analysis;
private final JsTsChecks checks;
private final AnalysisConsumers consumers;
private final TsConfigCache tsConfigCache;

public JsTsSensor(
JsTsChecks checks,
BridgeServer bridgeServer,
AnalysisWithProgram analysisWithProgram,
AnalysisWithWatchProgram analysisWithWatchProgram,
AbstractAnalysis analysis,
AnalysisConsumers consumers
) {
super(bridgeServer, "JS/TS");
this.analysisWithProgram = analysisWithProgram;
this.analysisWithWatchProgram = analysisWithWatchProgram;
this.checks = checks;
this.consumers = consumers;
this.tsConfigCache = analysisWithWatchProgram.tsConfigCache;
this.analysis = analysis;
}

@Override
Expand Down Expand Up @@ -89,22 +78,8 @@ protected void analyzeFiles(List<InputFile> inputFiles) throws IOException {
exclusions
);

var tsConfigs = getTsConfigs(contextUtils, this::createTsConfigFile, tsConfigCache);
AbstractAnalysis analysis;
if (shouldAnalyzeWithProgram()) {
analysis = analysisWithProgram;
} else {
analysis = analysisWithWatchProgram;
}
if (tsConfigs.isEmpty()) {
LOG.info("No tsconfig.json file found");
}
analysis.initialize(context, checks, analysisMode, consumers);
analysis.analyzeFiles(inputFiles, tsConfigs);
analysis.analyzeFiles(inputFiles);
consumers.doneAnalysis();
}

private String createTsConfigFile(String content) throws IOException {
return bridgeServer.createTsConfigFile(content).getFilename();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public class TsConfigProvider {

interface Provider {
List<String> tsconfigs(SensorContext context) throws IOException;

TsConfigOrigin type();
}

Expand All @@ -71,6 +72,10 @@ interface TsConfigFileCreator {
this.cache = cache;
}

TsConfigProvider(List<Provider> providers) {
this(providers, null);
}

/**
* Relying on (in order of priority)
* 1. Property sonar.typescript.tsconfigPath(s)
Expand All @@ -79,26 +84,40 @@ interface TsConfigFileCreator {
*/
static List<String> getTsConfigs(
ContextUtils contextUtils,
TsConfigProvider.TsConfigFileCreator tsConfigFileCreator,
@Nullable TsConfigCache tsConfigCache
TsConfigProvider.TsConfigFileCreator tsConfigFileCreator
) throws IOException {
var defaultProvider = contextUtils.isSonarLint()
? new TsConfigProvider.WildcardTsConfigProvider(tsConfigCache, tsConfigFileCreator)
: new TsConfigProvider.DefaultTsConfigProvider(
tsConfigFileCreator,
JavaScriptFilePredicate::getJsTsPredicate
);
var provider = new TsConfigProvider(
List.of(
new PropertyTsConfigProvider(),
new LookupTsConfigProvider(),
new TsConfigProvider.DefaultTsConfigProvider(
tsConfigFileCreator,
JavaScriptFilePredicate::getJsTsPredicate
)
)
);
return provider.tsconfigs(contextUtils.context());
}

/**
* Fill tsConfigCache with the tsconfigs found in the order listed by the
* providers. No need to return the list of tsconfigs
* because we get the tsconfig file from the cache.
*/
static void initializeTsConfigCache(
ContextUtils contextUtils,
TsConfigProvider.TsConfigFileCreator tsConfigFileCreator,
TsConfigCache tsConfigCache
) throws IOException {
var provider = new TsConfigProvider(
List.of(
new PropertyTsConfigProvider(),
new LookupTsConfigProvider(tsConfigCache),
defaultProvider
new TsConfigProvider.WildcardTsConfigProvider(tsConfigCache, tsConfigFileCreator)
),
tsConfigCache
);

return provider.tsconfigs(contextUtils.context());
provider.tsconfigs(contextUtils.context());
}

List<String> tsconfigs(SensorContext context) throws IOException {
Expand Down Expand Up @@ -134,11 +153,8 @@ public List<String> tsconfigs(SensorContext context) {
Arrays.asList(context.config().getStringArray(property))
);

LOG.info(
"Resolving TSConfig files using '{}' from property {}",
String.join(",", patterns),
property
);
var patternString = String.join(",", patterns);
LOG.info("Resolving TSConfig files using '{}' from property {}", patternString, property);

File baseDir = context.fileSystem().baseDir();

Expand Down Expand Up @@ -191,6 +207,10 @@ static class LookupTsConfigProvider implements Provider {
this.cache = cache;
}

LookupTsConfigProvider() {
this(null);
}

@Override
public List<String> tsconfigs(SensorContext context) {
if (cache != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.scanner.ScannerSide;
import org.sonar.plugins.javascript.JavaScriptFilePredicate;
import org.sonar.plugins.javascript.analysis.TsConfigOrigin;
import org.sonar.plugins.javascript.bridge.BridgeServer;
Expand All @@ -39,7 +38,6 @@
import org.sonarsource.sonarlint.plugin.api.module.file.ModuleFileEvent;
import org.sonarsource.sonarlint.plugin.api.module.file.ModuleFileListener;

@ScannerSide
@SonarLintSide(lifespan = SonarLintSide.MODULE)
public class TsConfigCacheImpl implements TsConfigCache, ModuleFileListener {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,37 +36,30 @@

class JavaScriptPluginTest {

private static final int BASE_EXTENSIONS = 37;
private static final int JS_ADDITIONAL_EXTENSIONS = 4;
private static final int TS_ADDITIONAL_EXTENSIONS = 3;
private static final int CSS_ADDITIONAL_EXTENSIONS = 3;
private static final int SONARLINT_ADDITIONAL_EXTENSIONS = 1;
private static final int BASE_EXTENSIONS = 35;
private static final int SCANNER_EXTENSIONS = 11;
private static final int SONARLINT_ADDITIONAL_EXTENSIONS = 2;

public static final Version LTS_VERSION = Version.create(7, 9);

@RegisterExtension
public LogTesterJUnit5 logTester = new LogTesterJUnit5().setLevel(Level.DEBUG);

@Test
void count_extensions_lts() throws Exception {
void count_extensions_lts() {
Plugin.Context context = setupContext(
SonarRuntimeImpl.forSonarQube(LTS_VERSION, SonarQubeSide.SERVER, SonarEdition.COMMUNITY)
);
assertThat(context.getExtensions()).hasSize(
BASE_EXTENSIONS +
JS_ADDITIONAL_EXTENSIONS +
TS_ADDITIONAL_EXTENSIONS +
CSS_ADDITIONAL_EXTENSIONS
);
assertThat(context.getExtensions()).hasSize(BASE_EXTENSIONS + SCANNER_EXTENSIONS);
}

@Test
void should_contain_right_properties_number() throws Exception {
void should_contain_right_properties_number() {
assertThat(properties()).hasSize(13);
}

@Test
void count_extensions_for_sonarlint() throws Exception {
void count_extensions_for_sonarlint() {
Plugin.Context context = setupContext(SonarRuntimeImpl.forSonarLint(LTS_VERSION));
assertThat(context.getExtensions()).hasSize(BASE_EXTENSIONS + SONARLINT_ADDITIONAL_EXTENSIONS);
}
Expand Down
Loading
Loading