diff --git a/build.gradle.kts b/build.gradle.kts index 1b6affe..d99a170 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,14 +32,12 @@ val sonarQubeVersion = "9.9.0.65466" dependencies { implementation("org.sonarsource.api.plugin", "sonar-plugin-api", "9.14.0.375") - // в jitpack лежат в группе com.github.1c-syntax, в централе - io.github.1c-syntax - implementation("io.github.1c-syntax", "bsl-language-server", "0.22.0") { - exclude("com.github.1c-syntax", "utils") + implementation("io.github.1c-syntax", "bsl-language-server", "0.23.0-rc.5") { + exclude("com.contrastsecurity", "java-sarif") + exclude("io.sentry", "sentry-logback") + exclude("org.springframework.boot", "spring-boot-starter-websocket") } - implementation("com.github.1c-syntax", "utils", "0.5.1") - implementation("org.apache.commons", "commons-lang3", "3.14.0") - implementation("com.fasterxml.jackson.core", "jackson-databind", "2.16.1") implementation("org.sonarsource.analyzer-commons", "sonar-analyzer-commons", "2.5.0.1358") // MD to HTML converter of BSL LS rule descriptions @@ -47,16 +45,6 @@ dependencies { implementation("org.commonmark", "commonmark-ext-gfm-tables", "0.21.0") implementation("org.commonmark", "commonmark-ext-autolink", "0.21.0") implementation("org.commonmark", "commonmark-ext-heading-anchor", "0.21.0") - implementation("me.tongfei", "progressbar", "0.10.0") - - // CONSTRAINTS - implementation("com.google.guava", "guava") { - version { - strictly("32.0.1-jre") - } - } - - compileOnly("com.google.code.findbugs", "jsr305", "3.0.2") testImplementation("org.junit.jupiter", "junit-jupiter-api", "5.8.0") testImplementation("org.assertj", "assertj-core", "3.25.1") diff --git a/src/main/java/com/github/_1c_syntax/bsl/sonar/BSLCoreSensor.java b/src/main/java/com/github/_1c_syntax/bsl/sonar/BSLCoreSensor.java index f4d40d9..79a14d4 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/sonar/BSLCoreSensor.java +++ b/src/main/java/com/github/_1c_syntax/bsl/sonar/BSLCoreSensor.java @@ -27,6 +27,7 @@ import com.github._1c_syntax.bsl.languageserver.configuration.diagnostics.SkipSupport; import com.github._1c_syntax.bsl.languageserver.context.DocumentContext; import com.github._1c_syntax.bsl.languageserver.context.ServerContext; +import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticCode; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticInfo; import com.github._1c_syntax.bsl.parser.BSLLexer; import com.github._1c_syntax.bsl.sonar.language.BSLLanguage; @@ -36,6 +37,7 @@ import me.tongfei.progressbar.ProgressBarStyle; import org.antlr.v4.runtime.Token; import org.apache.commons.lang3.StringUtils; +import org.eclipse.lsp4j.Diagnostic; import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.jetbrains.annotations.NotNull; import org.sonar.api.batch.fs.InputFile; @@ -55,9 +57,11 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -72,6 +76,9 @@ public class BSLCoreSensor implements Sensor { private final IssuesLoader issuesLoader; private final BSLHighlighter highlighter; + private final Set diagnosticsOnProject; + private final Set diagnosticsWithExtraMins; + public BSLCoreSensor(SensorContext context, FileLinesContextFactory fileLinesContextFactory) { this.context = context; this.fileLinesContextFactory = fileLinesContextFactory; @@ -95,6 +102,9 @@ public BSLCoreSensor(SensorContext context, FileLinesContextFactory fileLinesCon issuesLoader = new IssuesLoader(context); highlighter = new BSLHighlighter(context); + + diagnosticsOnProject = new HashSet<>(); + diagnosticsWithExtraMins = new HashSet<>(); } @Override @@ -170,7 +180,6 @@ public void execute(SensorContext context) { BSLLSBinding.getApplicationContext().close(); } - private void processFile(InputFile inputFile, ServerContext bslServerContext) { var uri = inputFile.uri(); var documentContext = bslServerContext.addDocument(uri); @@ -178,7 +187,16 @@ private void processFile(InputFile inputFile, ServerContext bslServerContext) { if (langServerEnabled) { documentContext.getDiagnostics() - .forEach(diagnostic -> issuesLoader.createIssue(inputFile, diagnostic)); + .forEach((Diagnostic diagnostic) -> { + var code = DiagnosticCode.getStringValue(diagnostic.getCode()); + var hasExtraMins = diagnosticsWithExtraMins.contains(code); + + if (diagnosticsOnProject.contains(code)) { + issuesLoader.createIssue(Either.forRight(context.project()), diagnostic, hasExtraMins); + } else { + issuesLoader.createIssue(Either.forLeft(inputFile), diagnostic, hasExtraMins); + } + }); } saveCpd(inputFile, documentContext); @@ -221,7 +239,6 @@ private void saveCpd(InputFile inputFile, DocumentContext documentContext) { synchronized (this) { cpdTokens.save(); } - } private void saveMeasures(InputFile inputFile, DocumentContext documentContext) { @@ -332,6 +349,14 @@ private LanguageServerConfiguration getLanguageServerConfiguration() { diagnosticCode, Either.forRight(diagnosticConfiguration) ); + + if (diagnosticInfo.canLocateOnProject()) { + diagnosticsOnProject.add(diagnosticCode); + } + + if (diagnosticInfo.getExtraMinForComplexity() > 0) { + diagnosticsWithExtraMins.add(diagnosticCode); + } } } diff --git a/src/main/java/com/github/_1c_syntax/bsl/sonar/BSLHighlighter.java b/src/main/java/com/github/_1c_syntax/bsl/sonar/BSLHighlighter.java index 99fbe71..01f9b2c 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/sonar/BSLHighlighter.java +++ b/src/main/java/com/github/_1c_syntax/bsl/sonar/BSLHighlighter.java @@ -65,6 +65,7 @@ public class BSLHighlighter { private static final Set SDBL_STRINGS = createSdblStrings(); private static final Set SDBL_COMMENTS = createSdblComments(); private static final Set SDBL_PARAMETERS = createSdblParameters(); + private static final Set SDBL_EDS = createSdblEDS(); private final SensorContext context; @@ -258,6 +259,8 @@ private static TypeOfText getTypeOfTextSDBL(int tokenType) { typeOfText = TypeOfText.COMMENT; } else if (SDBL_PARAMETERS.contains(tokenType)) { typeOfText = TypeOfText.ANNOTATION; + } else if (SDBL_EDS.contains(tokenType)) { + typeOfText = TypeOfText.KEYWORD_LIGHT; } else { typeOfText = null; } @@ -525,7 +528,30 @@ private static Set createSdblFunctions() { SDBLLexer.VALUETYPE, SDBLLexer.WEEK, SDBLLexer.WEEKDAY, - SDBLLexer.YEAR + SDBLLexer.YEAR, + SDBLLexer.INT, + SDBLLexer.ACOS, + SDBLLexer.ASIN, + SDBLLexer.ATAN, + SDBLLexer.COS, + SDBLLexer.SIN, + SDBLLexer.TAN, + SDBLLexer.LOG, + SDBLLexer.LOG10, + SDBLLexer.EXP, + SDBLLexer.POW, + SDBLLexer.SQRT, + SDBLLexer.LOWER, + SDBLLexer.STRINGLENGTH, + SDBLLexer.TRIMALL, + SDBLLexer.TRIML, + SDBLLexer.TRIMR, + SDBLLexer.UPPER, + SDBLLexer.ROUND, + SDBLLexer.STOREDDATASIZE, + SDBLLexer.UUID, + SDBLLexer.STRFIND, + SDBLLexer.STRREPLACE ); } @@ -610,6 +636,14 @@ private static Set createSdblParameters() { ); } + private static Set createSdblEDS() { + return Set.of( + SDBLLexer.EDS_CUBE, + SDBLLexer.EDS_TABLE, + SDBLLexer.EDS_CUBE_DIMTABLE + ); + } + @Data @RequiredArgsConstructor @EqualsAndHashCode(exclude = "active") diff --git a/src/main/java/com/github/_1c_syntax/bsl/sonar/IssuesLoader.java b/src/main/java/com/github/_1c_syntax/bsl/sonar/IssuesLoader.java index 63a32c3..db6c0e2 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/sonar/IssuesLoader.java +++ b/src/main/java/com/github/_1c_syntax/bsl/sonar/IssuesLoader.java @@ -32,6 +32,7 @@ import org.eclipse.lsp4j.DiagnosticRelatedInformation; import org.eclipse.lsp4j.DiagnosticSeverity; import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.jetbrains.annotations.NotNull; import org.sonar.api.batch.fs.FilePredicates; import org.sonar.api.batch.fs.FileSystem; @@ -42,6 +43,7 @@ import org.sonar.api.batch.sensor.issue.NewIssueLocation; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.RuleType; +import org.sonar.api.scanner.fs.InputProject; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; @@ -152,7 +154,15 @@ private Map computeLoaderSettings(SensorContext context) return settings; } - public void createIssue(InputFile inputFile, Diagnostic diagnostic) { + public void createIssue(InputFile file, Diagnostic diagnostic) { + createIssue(Either.forLeft(file), diagnostic, false); + } + + public void createIssue(InputProject project, Diagnostic diagnostic) { + createIssue(Either.forRight(project), diagnostic, false); + } + + public void createIssue(Either fileOrProject, Diagnostic diagnostic, boolean hasExtraMins) { var ruleId = DiagnosticCode.getStringValue(diagnostic.getCode()); @@ -166,37 +176,43 @@ public void createIssue(InputFile inputFile, Diagnostic diagnostic) { var activeRule = context.activeRules().find(ruleKey); if (settings.needCreateExternalIssues && activeRule == null) { - createExternalIssue(settings, inputFile, diagnostic); + createExternalIssue(settings, fileOrProject, diagnostic); return; } var issue = context.newIssue(); issue.forRule(ruleKey); - - processDiagnostic(inputFile, + processDiagnostic(fileOrProject, diagnostic, ruleId, issue::newLocation, issue::addLocation, issue::at); + if (hasExtraMins && diagnostic.getRelatedInformation() != null) { + issue.gap((double) diagnostic.getRelatedInformation().size() - 1); // первый - это основной + } + issue.save(); } - private void processDiagnostic(InputFile inputFile, + private void processDiagnostic(Either fileOrProject, Diagnostic diagnostic, String ruleId, Supplier newIssueLocationSupplier, Consumer newIssueAddLocationConsumer, Consumer newIssueAtConsumer) { - var textRange = getTextRange(inputFile, diagnostic.getRange(), ruleId); - var location = newIssueLocationSupplier.get(); - location.on(inputFile); - location.at(textRange); - location.message(diagnostic.getMessage()); + if (fileOrProject.isLeft()) { + var textRange = getTextRange(fileOrProject.getLeft(), diagnostic.getRange(), ruleId); + location.on(fileOrProject.getLeft()); + location.at(textRange); + } else { + location.on(fileOrProject.getRight()); + } + location.message(diagnostic.getMessage()); newIssueAtConsumer.accept(location); var relatedInformation = diagnostic.getRelatedInformation(); @@ -221,7 +237,9 @@ private void processDiagnostic(InputFile inputFile, } } - private void createExternalIssue(LoaderSettings settings, InputFile inputFile, Diagnostic diagnostic) { + private void createExternalIssue(LoaderSettings settings, + Either fileOrProject, + Diagnostic diagnostic) { var issue = context.newExternalIssue(); issue.engineId(settings.engineId); @@ -232,7 +250,7 @@ private void createExternalIssue(LoaderSettings settings, InputFile inputFile, D issue.type(ruleTypeMap.get(diagnostic.getSeverity())); issue.severity(severityMap.get(diagnostic.getSeverity())); - processDiagnostic(inputFile, + processDiagnostic(fileOrProject, diagnostic, ruleId, issue::newLocation, diff --git a/src/main/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageServerRuleDefinition.java b/src/main/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageServerRuleDefinition.java index 3753bf6..3d638a7 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageServerRuleDefinition.java +++ b/src/main/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageServerRuleDefinition.java @@ -138,11 +138,20 @@ private void setUpNewRule(NewRule newRule) { newRule.addTags(tagsName); } - newRule.setDebtRemediationFunction( - newRule.debtRemediationFunctions().linear( - diagnosticInfo.getMinutesToFix() + "min" - ) - ); + if (diagnosticInfo.getExtraMinForComplexity() > 0) { + newRule.setDebtRemediationFunction( + newRule.debtRemediationFunctions().linearWithOffset( + (int) diagnosticInfo.getExtraMinForComplexity() + "min", + diagnosticInfo.getMinutesToFix() + "min" + ) + ); + } else { + newRule.setDebtRemediationFunction( + newRule.debtRemediationFunctions().constantPerIssue( + diagnosticInfo.getMinutesToFix() + "min" + ) + ); + } } private String getHtmlDescription(String markdownDescription) { diff --git a/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLCoreSensorTest.java b/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLCoreSensorTest.java index 081c1d1..dc13037 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLCoreSensorTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLCoreSensorTest.java @@ -212,9 +212,6 @@ void testComplexity() { @Test void testCPD() { - var diagnosticName = "OneStatementPerLine"; - var ruleKey = RuleKey.of(BSLLanguageServerRuleDefinition.REPOSITORY_KEY, diagnosticName); - // Mock visitor for metrics. var fileLinesContext = mock(FileLinesContext.class); var fileLinesContextFactory = mock(FileLinesContextFactory.class); @@ -235,7 +232,6 @@ void testCPD() { assertThat(context.cpdTokens(componentKey)) .filteredOn(tok -> tok.getValue().startsWith("ПропущенныйТокен")) .isEmpty(); - } private void setActiveRules(SensorContextTester context, String diagnosticName, RuleKey ruleKey) { @@ -276,5 +272,4 @@ private SensorContextTester createSensorContext() { return context; } - } diff --git a/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLHighlighterTest.java b/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLHighlighterTest.java index 2611213..b13fd46 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLHighlighterTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLHighlighterTest.java @@ -154,7 +154,7 @@ private void initContext(Vocabulary vocabulary) { documentContext = mock(DocumentContext.class); List tokens = new ArrayList<>(); - int maxTokenType = vocabulary.getMaxTokenType(); + var maxTokenType = vocabulary.getMaxTokenType(); for (var tokenType = 1; tokenType <= maxTokenType; tokenType++) { var token = new CommonToken(tokenType, "a"); token.setLine(1); @@ -382,7 +382,30 @@ private Map getHighlightingMapSDBL(Vocabulary vocabulary) { "VALUETYPE", "WEEK", "WEEKDAY", - "YEAR" + "YEAR", + "INT", + "ACOS", + "ASIN", + "ATAN", + "COS", + "SIN", + "TAN", + "LOG", + "LOG10", + "EXP", + "POW", + "SQRT", + "LOWER", + "STRINGLENGTH", + "TRIMALL", + "TRIML", + "TRIMR", + "UPPER", + "ROUND", + "STOREDDATASIZE", + "UUID", + "STRFIND", + "STRREPLACE" ); Set metadataTypes = Set.of( @@ -460,6 +483,12 @@ private Map getHighlightingMapSDBL(Vocabulary vocabulary) { "BAR" // TODO: Убрать из лексера ); + Set eds = Set.of( + "EDS_CUBE", + "EDS_TABLE", + "EDS_CUBE_DIMTABLE" + ); + var maxTokenType = vocabulary.getMaxTokenType(); Map highlightingMap = new HashMap<>(); @@ -485,6 +514,8 @@ private Map getHighlightingMapSDBL(Vocabulary vocabulary) { typeOfText = TypeOfText.KEYWORD_LIGHT; } else if (virtualTables.contains(ruleName)) { typeOfText = TypeOfText.KEYWORD_LIGHT; + } else if (eds.contains(ruleName)) { + typeOfText = TypeOfText.KEYWORD_LIGHT; } else if (ruleName.equals("STR")) { typeOfText = TypeOfText.STRING; } else if (ruleName.contains("LINE_COMMENT")) { @@ -501,5 +532,4 @@ private Map getHighlightingMapSDBL(Vocabulary vocabulary) { } return highlightingMap; } - } diff --git a/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLPluginTest.java b/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLPluginTest.java index a35d18a..f75f562 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLPluginTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/sonar/BSLPluginTest.java @@ -80,5 +80,4 @@ void testQualityProfileAll() { profile.define(contextProfile); assertThat(contextProfile.profilesByLanguageAndName().get(BSLLanguage.KEY)).hasSize(5); } - } diff --git a/src/test/java/com/github/_1c_syntax/bsl/sonar/IssuesLoaderTest.java b/src/test/java/com/github/_1c_syntax/bsl/sonar/IssuesLoaderTest.java index d631159..d9cd995 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/sonar/IssuesLoaderTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/sonar/IssuesLoaderTest.java @@ -31,7 +31,6 @@ import org.junit.jupiter.api.Test; import org.sonar.api.batch.fs.internal.DefaultTextPointer; import org.sonar.api.batch.fs.internal.DefaultTextRange; -import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; import org.sonar.api.batch.rule.internal.NewActiveRule; import org.sonar.api.batch.sensor.internal.SensorContextTester; @@ -141,6 +140,41 @@ void test_createIssue() { } + @Test + void test_createIssueOnProject() { + var issueSeverity = DiagnosticSeverity.Information; + var diagnosticName = "OneStatementPerLine"; + var ruleKey = RuleKey.of(BSLLanguageServerRuleDefinition.REPOSITORY_KEY, diagnosticName); + + var context = SensorContextTester.create(BASE_DIR); + + var activeRules = new ActiveRulesBuilder() + .addRule(new NewActiveRule.Builder() + .setRuleKey(ruleKey) + .setName(diagnosticName) + .build()) + .build(); + context.setActiveRules(activeRules); + + var inputFile = Tools.inputFileBSL(FILE_NAME, BASE_DIR); + context.fileSystem().add(inputFile); + + var issuesLoader = new IssuesLoader(context); + + var diagnostic = new Diagnostic(); + diagnostic.setCode(diagnosticName); + diagnostic.setSeverity(issueSeverity); + diagnostic.setMessage("Check message OneStatementPerLine"); + diagnostic.setRange(new Range(new Position(0, 0), new Position(0, 1))); + + issuesLoader.createIssue(context.project(), diagnostic); + + assertThat(context.allIssues()).hasSize(1); + var issue = (DefaultIssue) context.allIssues().toArray()[0]; + assertThat(issue.ruleKey()).isEqualTo(ruleKey); + assertThat(issue.primaryLocation().inputComponent()).isEqualTo(context.project()); + } + @Test void issueWithIncorrectRange() { // given @@ -150,7 +184,7 @@ void issueWithIncorrectRange() { var context = SensorContextTester.create(BASE_DIR); - ActiveRules activeRules = new ActiveRulesBuilder() + var activeRules = new ActiveRulesBuilder() .addRule(new NewActiveRule.Builder() .setRuleKey(ruleKey) .setName(diagnosticName) diff --git a/src/test/java/com/github/_1c_syntax/bsl/sonar/ext_issues/QualityProfileTest.java b/src/test/java/com/github/_1c_syntax/bsl/sonar/ext_issues/QualityProfileTest.java index d122047..321a3a5 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/sonar/ext_issues/QualityProfileTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/sonar/ext_issues/QualityProfileTest.java @@ -73,5 +73,4 @@ void testQualityProfileEnabledWithoutFiles() { profile.define(context); assertThat(context.profilesByLanguageAndName().get(BSLLanguage.KEY)).hasSize(3); } - } diff --git a/src/test/java/com/github/_1c_syntax/bsl/sonar/ext_issues/RuleDefinitionTest.java b/src/test/java/com/github/_1c_syntax/bsl/sonar/ext_issues/RuleDefinitionTest.java index abceec4..faf4c3e 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/sonar/ext_issues/RuleDefinitionTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/sonar/ext_issues/RuleDefinitionTest.java @@ -86,5 +86,4 @@ void testExternalFile() { assertThat(repository).isNotNull(); assertThat(repository.rules()).hasSize(183); } - } diff --git a/src/test/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageServerRuleDefinitionTest.java b/src/test/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageServerRuleDefinitionTest.java index 62c0f2d..b6ad8c0 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageServerRuleDefinitionTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageServerRuleDefinitionTest.java @@ -63,5 +63,4 @@ void testCheckTagParameters() { .count() ).isZero(); } - } diff --git a/src/test/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageTest.java b/src/test/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageTest.java index d7b8111..a7abac6 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/sonar/language/BSLLanguageTest.java @@ -44,5 +44,4 @@ void test_create() { assertThat(language.getFileSuffixes()).containsOnly(".bsl", ".os"); } - }