Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
Basically, executing the tests using the CI platform.
  • Loading branch information
Eric Morand committed Jan 31, 2025
1 parent b21c5c7 commit 1ea98f8
Show file tree
Hide file tree
Showing 17 changed files with 207 additions and 156 deletions.
2 changes: 2 additions & 0 deletions packages/bridge/tests/router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ describe('router', () => {
"Remove this conditional structure or edit its code blocks so that they're not all the same.",
quickFixes: [],
secondaryLocations: [],
ruleESLintKey: 'sonarjs/S3923',
});
});

Expand All @@ -238,6 +239,7 @@ describe('router', () => {
"Remove this conditional structure or edit its code blocks so that they're not all the same.",
quickFixes: [],
secondaryLocations: [],
ruleESLintKey: 'sonarjs/S3923',
});
});

Expand Down
1 change: 1 addition & 0 deletions packages/jsts/src/linter/issues/issue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ export interface Issue {
cost?: number;
secondaryLocations: Location[];
quickFixes?: QuickFix[];
ruleESLintKey: string | null;
}
1 change: 1 addition & 0 deletions packages/jsts/src/linter/issues/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@ export function convertMessage(source: SourceCode, message: Linter.LintMessage):
message: message.message,
quickFixes: transformFixes(source, message),
secondaryLocations: [],
ruleESLintKey: message.ruleId,
};
}
1 change: 1 addition & 0 deletions packages/jsts/tests/analysis/analyzer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ describe('analyzeJSTS', () => {
message: 'Octal literals should not be used.',
quickFixes: [],
secondaryLocations: [],
ruleESLintKey: 'sonarjs/S1314',
},
]);
});
Expand Down
7 changes: 7 additions & 0 deletions packages/jsts/tests/linter/issues/extract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ describe('extract', () => {
references: [{ startLine: 10, startCol: 20, endLine: 30, endCol: 40 }],
}),
secondaryLocations: [],
ruleESLintKey: null,
},
];
expect(extractHighlightedSymbols(issues)).toEqual({
Expand All @@ -56,6 +57,7 @@ describe('extract', () => {
column: 2,
message: '42',
secondaryLocations: [],
ruleESLintKey: null,
},
];
expect(extractCognitiveComplexity(issues)).toEqual(42);
Expand All @@ -69,6 +71,7 @@ describe('extract', () => {
column: 2,
message: 'nan',
secondaryLocations: [],
ruleESLintKey: null,
},
];
expect(extractCognitiveComplexity(issues)).toEqual(undefined);
Expand All @@ -89,20 +92,23 @@ describe('extract', () => {
references: [{ startLine: 10, startCol: 20, endLine: 30, endCol: 40 }],
}),
secondaryLocations: [],
ruleESLintKey: null,
},
{
ruleId: 'non-extracted-rule',
line: 1,
column: 2,
message: 'non-extract-message',
secondaryLocations: [],
ruleESLintKey: null,
},
{
ruleId: cognitiveComplexityRule.ruleId,
line: 1,
column: 2,
message: '42',
secondaryLocations: [],
ruleESLintKey: null,
},
];
extractHighlightedSymbols(issues);
Expand All @@ -114,6 +120,7 @@ describe('extract', () => {
column: 2,
message: 'non-extract-message',
secondaryLocations: [],
ruleESLintKey: null,
},
]);
});
Expand Down
1 change: 1 addition & 0 deletions packages/jsts/tests/linter/issues/message.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ describe('convertMessage', () => {
},
],
secondaryLocations: [],
ruleESLintKey: 'sonarjs/S1116',
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ record Issue(
String ruleId,
List<IssueLocation> secondaryLocations,
Double cost,
List<QuickFix> quickFixes
List<QuickFix> quickFixes,
String ruleESLintKey
) {}

record QuickFix(String message, List<QuickFixEdit> edits) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@
import org.sonar.plugins.javascript.bridge.Environment;
import org.sonar.plugins.javascript.bridge.NodeDeprecationWarning;
import org.sonar.plugins.javascript.bridge.RulesBundles;
import org.sonar.plugins.javascript.external.EslintReportSensor;
import org.sonar.plugins.javascript.external.TslintReportSensor;
import org.sonar.plugins.javascript.filter.JavaScriptExclusionsFileFilter;
import org.sonar.plugins.javascript.lcov.CoverageSensor;
import org.sonar.plugins.javascript.nodejs.NodeCommandBuilderImpl;
Expand Down Expand Up @@ -277,9 +275,7 @@ public void define(Context context) {
if (!context.getRuntime().getProduct().equals(SonarProduct.SONARLINT)) {
context.addExtensions(
CoverageSensor.class,
EslintReportSensor.class,
EslintRulesDefinition.class,
TslintReportSensor.class,
TslintRulesDefinition.class,
AnalysisWithProgram.class
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,17 @@

import com.google.gson.Gson;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
import org.sonarsource.analyzer.commons.ExternalReportProvider;

abstract class AbstractExternalIssuesSensor implements Sensor {
abstract class AbstractExternalIssuesSensor {

private static final Logger LOG = LoggerFactory.getLogger(AbstractExternalIssuesSensor.class);
static final Gson gson = new Gson();
Expand All @@ -39,17 +38,17 @@ abstract class AbstractExternalIssuesSensor implements Sensor {
static final String FILE_EXCEPTION_MESSAGE =
"No issues information will be saved as the report file can't be read.";

@Override
public void describe(SensorDescriptor sensorDescriptor) {
sensorDescriptor
.onlyWhenConfiguration(conf -> conf.hasKey(reportsPropertyName()))
.name("Import of " + linterName() + " issues");
}

@Override
public void execute(SensorContext context) {
public List<Issue> execute(SensorContext context) {
var results = new ArrayList<Issue>();
List<File> reportFiles = ExternalReportProvider.getReportFiles(context, reportsPropertyName());
reportFiles.forEach(report -> importReport(report, context));

reportFiles.forEach(report -> {
var externalIssues = importReport(report, context);

results.addAll(externalIssues);
});

return results;
}

InputFile getInputFile(SensorContext context, String fileName) {
Expand All @@ -70,5 +69,5 @@ InputFile getInputFile(SensorContext context, String fileName) {

abstract String reportsPropertyName();

abstract void importReport(File report, SensorContext context);
abstract List<Issue> importReport(File report, SensorContext context);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.TextPointer;
import org.sonar.api.batch.fs.TextRange;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.issue.NewExternalIssue;
import org.sonar.api.batch.sensor.issue.NewIssueLocation;
import org.sonar.api.rules.RuleType;
import org.sonar.plugins.javascript.rules.EslintRulesDefinition;
import org.sonarsource.analyzer.commons.ExternalRuleLoader;
Expand All @@ -52,9 +51,11 @@ String reportsPropertyName() {
}

@Override
void importReport(File report, SensorContext context) {
List<Issue> importReport(File report, SensorContext context) {
LOG.info("Importing {}", report.getAbsoluteFile());

var results = new ArrayList<Issue>();

try (
InputStreamReader inputStreamReader = new InputStreamReader(
new FileInputStream(report),
Expand All @@ -70,62 +71,76 @@ void importReport(File report, SensorContext context) {
InputFile inputFile = getInputFile(context, fileWithMessages.filePath);
if (inputFile != null) {
for (EslintError eslintError : fileWithMessages.messages) {
saveEslintError(context, eslintError, inputFile, fileWithMessages.filePath);
if (eslintError.ruleId == null) {
LOG.warn(
"Parse error issue from ESLint will not be imported, file {}",
inputFile.uri()
);
} else {
results.add(createIssue(eslintError, inputFile, fileWithMessages.filePath));
}
}
}
}
} catch (IOException | JsonSyntaxException e) {
LOG.warn(FILE_EXCEPTION_MESSAGE, e);
}

return results;
}

private static void saveEslintError(
SensorContext context,
private static Issue createIssue(
EslintError eslintError,
InputFile inputFile,
String originalFilePath
String originalFilePath // todo: ???
) {
String eslintKey = eslintError.ruleId;
if (eslintKey == null) {
LOG.warn("Parse error issue from ESLint will not be imported, file {}", inputFile.uri());
return;
}

TextRange location = getLocation(eslintError, inputFile);
TextPointer start = location.start();
ExternalRuleLoader ruleLoader = EslintRulesDefinition.loader(eslintKey);
RuleType ruleType = ruleLoader.ruleType(eslintKey);
Severity severity = ruleLoader.ruleSeverity(eslintKey);
Long effortInMinutes = ruleLoader.ruleConstantDebtMinutes(eslintKey);

LOG.debug(
"Saving external ESLint issue { file:\"{}\", id:{}, message:\"{}\", line:{}, offset:{}, type: {}, severity:{}, remediation:{} }",
originalFilePath,
// todo: move to the analysis sensor
// LOG.debug(
// "Saving external ESLint issue { file:\"{}\", id:{}, message:\"{}\", line:{}, offset:{}, type: {}, severity:{}, remediation:{} }",
// originalFilePath,
// eslintKey,
// eslintError.message,
// start.line(),
// start.lineOffset(),
// ruleType,
// severity,
// effortInMinutes
// );

var issue = new Issue(
eslintKey,
eslintError.message,
start.line(),
start.lineOffset(),
inputFile,
location,
ruleType,
eslintError.message,
severity,
effortInMinutes
effortInMinutes.doubleValue()
);

NewExternalIssue newExternalIssue = context.newExternalIssue();

NewIssueLocation primaryLocation = newExternalIssue
.newLocation()
.message(eslintError.message)
.on(inputFile)
.at(location);

newExternalIssue
.at(primaryLocation)
.engineId(EslintRulesDefinition.REPOSITORY_KEY)
.ruleId(eslintKey)
.type(ruleType)
.severity(severity)
.remediationEffortMinutes(effortInMinutes)
.save();
// todo: move to the analysis sensor
// NewIssueLocation primaryLocation = newExternalIssue
// .newLocation()
// .message(eslintError.message)
// .on(inputFile)
// .at(location);
//
// newExternalIssue
// .at(primaryLocation)
// .engineId(EslintRulesDefinition.REPOSITORY_KEY)
// .ruleId(eslintKey)
// .type(ruleType)
// .severity(severity)
// .remediationEffortMinutes(effortInMinutes)
// .save();

return issue;
}

private static TextRange getLocation(EslintError eslintError, InputFile inputFile) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2011-2025 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Sonar Source-Available License for more details.
*
* You should have received a copy of the Sonar Source-Available License
* along with this program; if not, see https://sonarsource.com/license/ssal/
*/
package org.sonar.plugins.javascript.external;

import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.TextRange;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.rules.RuleType;

public record Issue(
String name,
InputFile file,
TextRange location,
RuleType type,
String message,
Severity severity,
Double effort
) {}
Loading

0 comments on commit 1ea98f8

Please sign in to comment.