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 e798f3386c8..5c916f8d7b6 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 @@ -135,6 +135,7 @@ public class JavaScriptPlugin implements Plugin { private static final String FILE_SUFFIXES_DESCRIPTION = "List of suffixes for files to analyze."; public static final String PROPERTY_KEY_MAX_FILE_SIZE = "sonar.javascript.maxFileSize"; + public static final String SKIP_NODE_PROVISIONING_PROPERTY = "sonar.scanner.skipNodeProvisioning"; @Override public void define(Context context) { @@ -251,6 +252,16 @@ public void define(Context context) { .subCategory(GENERAL) .multiValues(true) .category(JS_TS_CATEGORY) + .build(), + PropertyDefinition + .builder(SKIP_NODE_PROVISIONING_PROPERTY) + .defaultValue("false") + .name("Skip the deployment of the embedded Node.js runtime") + .description(JavaScriptPlugin.getHTMLMarkup("Controls whether the scanner should skip the deployment of the embedded Node.js runtime, and use the host-provided runtime instead.\n\nAnalysis will fail if a compatible version of Node.js is not provided via `sonar.nodejs.executable` or the `PATH`.")) + .onQualifiers(Qualifiers.PROJECT) + .subCategory(GENERAL) + .category(JS_TS_CATEGORY) + .type(PropertyType.BOOLEAN) .build() ); @@ -330,6 +341,18 @@ public void define(Context context) { } } + /** + * From a Markdown markup, returns the corresponding HTML markup. + * + * Note that this method should probably not be hosted here: either it should be part of a dedicated helper class, or it should be provided by a Markdown-to-HTML library. Since it is only used in this specific class, it is acceptable for now to have it hosted here. + */ + private static String getHTMLMarkup(String markdownMarkup) { + return markdownMarkup + .replace("\n", "
") + .replaceAll("`(.*?)`", "$1") + ; + } + static class SonarLintPluginAPIManager { public void addSonarLintExtensions( diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/JavaScriptPluginTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/JavaScriptPluginTest.java index 694373ece5a..55a5354148d 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/JavaScriptPluginTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/JavaScriptPluginTest.java @@ -23,8 +23,9 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.util.ArrayList; import java.util.List; +import java.util.Objects; + import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.slf4j.event.Level; @@ -39,7 +40,7 @@ class JavaScriptPluginTest { - private static final int BASE_EXTENSIONS = 36; + 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; @@ -66,7 +67,7 @@ void count_extensions_lts() throws Exception { @Test void should_contain_right_properties_number() throws Exception { - assertThat(properties()).hasSize(12); + assertThat(properties()).hasSize(13); } @Test @@ -114,20 +115,28 @@ void globalsDefaultValue() { ); } + @Test + void skipNodeProvisioningPropertyIsCorrectlyExposed() { + var propertyDefinition = properties().stream().filter((item) -> { + return Objects.equals(item.key(), "sonar.scanner.skipNodeProvisioning"); + }).findFirst().get(); + + assertThat(propertyDefinition.name()).isEqualTo("Skip the deployment of the embedded Node.js runtime"); + assertThat(propertyDefinition.description()).isEqualTo("Controls whether the scanner should skip the deployment of the embedded Node.js runtime, and use the host-provided runtime instead.

Analysis will fail if a compatible version of Node.js is not provided via sonar.nodejs.executable or the PATH."); + assertThat(propertyDefinition.type().toString()).isEqualTo("BOOLEAN"); + assertThat(propertyDefinition.defaultValue()).isEqualTo("false"); + assertThat(propertyDefinition.category()).isEqualTo("JavaScript / TypeScript"); + assertThat(propertyDefinition.subCategory()).isEqualTo("General"); + } + private List properties() { - List propertiesList = new ArrayList<>(); - List extensions = setupContext( + var extensions = setupContext( SonarRuntimeImpl.forSonarQube(LTS_VERSION, SonarQubeSide.SERVER, SonarEdition.COMMUNITY) - ) - .getExtensions(); - - for (Object extension : extensions) { - if (extension instanceof PropertyDefinition) { - propertiesList.add((PropertyDefinition) extension); - } - } + ).getExtensions(); - return propertiesList; + return extensions.stream().filter((extension) -> { + return extension instanceof PropertyDefinition; + }).toList(); } private Plugin.Context setupContext(SonarRuntime runtime) {