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-163 New Java API to process files during the analysis #4706

Merged
merged 6 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions its/plugin/plugins/consumer-plugin/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.sonarsource.javascript</groupId>
<artifactId>javascript-it-plugin-plugins</artifactId>
<version>10.15.0-SNAPSHOT</version>
</parent>

<artifactId>consumer-plugin</artifactId>
<packaging>sonar-plugin</packaging>

<name>JavaScript :: IT :: Plugin :: Plugins :: Consumer Plugin</name>
<description>Consumer Plugin</description>

<dependencies>
<dependency>
<groupId>org.sonarsource.api.plugin</groupId>
<artifactId>sonar-plugin-api</artifactId>
</dependency>
<dependency>
<groupId>org.sonarsource.javascript</groupId>
<artifactId>api</artifactId>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope></dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
<artifactId>sonar-packaging-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<pluginApiMinVersion>${pluginApiMinVersion}</pluginApiMinVersion>
<pluginClass>org.sonar.samples.javascript.consumer.ConsumerPlugin</pluginClass>
<requiredForLanguages>js</requiredForLanguages>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2012-2024 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 GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.samples.javascript.consumer;

import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.plugins.javascript.api.JsAnalysisConsumer;
import org.sonar.plugins.javascript.api.JsFile;

public class Consumer implements JsAnalysisConsumer {

private static final Logger LOG = LoggerFactory.getLogger(Consumer.class);

private final List<JsFile> jsFiles = new ArrayList<>();
private boolean done;

@Override
public void accept(JsFile jsFile) {
LOG.info("Accepted file: {}", jsFile.inputFile());
jsFiles.add(jsFile);
}

@Override
public void doneAnalysis() {
ilia-kebets-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
LOG.info("Done analysis");
done = true;
}

public List<JsFile> getJsFiles() {
return jsFiles;
}

public boolean isDone() {
return done;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2012-2024 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 GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.samples.javascript.consumer;

import org.sonar.api.Plugin;

public class ConsumerPlugin implements Plugin {

@Override
public void define(Context context) {
context.addExtensions(
Consumer.class,
ConsumerSensor.class
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2012-2024 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 GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.samples.javascript.consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.DependsUpon;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.scanner.sensor.ProjectSensor;
import org.sonar.plugins.javascript.api.JsFile;

@ScannerSide
// We depend on the "js-analysis" extension to make sure that the analysis is done before we consume it
@DependsUpon("js-analysis")
public class ConsumerSensor implements ProjectSensor {

private static final Logger LOG = LoggerFactory.getLogger(ConsumerSensor.class);

private final Consumer consumer;

/**
* We use Dependency Injection to get Consumer instance
*
* @param consumer Consumer instance
*/
public ConsumerSensor(Consumer consumer) {
this.consumer = consumer;
}

@Override
public void describe(SensorDescriptor descriptor) {
descriptor.name("Consumer Sensor");
}

@Override
public void execute(SensorContext context) {
if (!consumer.isDone()) {
throw new IllegalStateException("Consumer is not done");
}
for (JsFile jsFile : consumer.getJsFiles()) {
LOG.info("Processing file {}", jsFile.inputFile());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2011-2024 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 GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ParametersAreNonnullByDefault
package org.sonar.samples.javascript.consumer;

import javax.annotation.ParametersAreNonnullByDefault;
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2012-2024 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 GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.samples.javascript.consumer;

import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

class ConsumerTest {

@Test
void test() {
var consumer = new Consumer();
consumer.doneAnalysis();
assertTrue(consumer.isDone());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2011-2024 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 GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ParametersAreNonnullByDefault
package org.sonar.samples.javascript;

import javax.annotation.ParametersAreNonnullByDefault;
1 change: 1 addition & 0 deletions its/plugin/plugins/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

<modules>
<module>eslint-custom-rules-plugin</module>
<module>consumer-plugin</module>
</modules>

</project>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this IT runs both the JS and Consumer plugins and validates that the consumer plugin runs execute() if and only if once the JS plugin is done processing all the files? Is that correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it is asserting that execute is invoked only after the analysis. The order of execution of sensors is implemented with DependsUpon/@DependedUpon annotation

Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2012-2024 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 GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sonar.javascript.it.plugin;

import static com.sonar.javascript.it.plugin.OrchestratorStarter.JAVASCRIPT_PLUGIN_LOCATION;
import static org.assertj.core.api.Assertions.assertThat;

import com.sonar.orchestrator.Orchestrator;
import com.sonar.orchestrator.build.BuildResult;
import com.sonar.orchestrator.build.SonarScanner;
import com.sonar.orchestrator.junit5.OrchestratorExtension;
import com.sonar.orchestrator.locator.FileLocation;
import java.io.File;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

class ConsumerPluginTest {

private static final String PLUGIN_ARTIFACT_ID = "consumer-plugin";

private static OrchestratorExtension orchestrator;

@BeforeAll
public static void before() {
orchestrator = initOrchestrator(PLUGIN_ARTIFACT_ID);
}

@AfterAll
public static void after() {
orchestrator.stop();
}

static OrchestratorExtension initOrchestrator(String customRulesArtifactId) {
var orchestrator = OrchestratorExtension
.builderEnv()
.useDefaultAdminCredentialsForBuilds(true)
.setSonarVersion(System.getProperty("sonar.runtimeVersion", "LATEST_RELEASE"))
.addPlugin(JAVASCRIPT_PLUGIN_LOCATION)
.restoreProfileAtStartup(FileLocation.ofClasspath("/empty-js-profile.xml"))
.addPlugin(
FileLocation.byWildcardMavenFilename(
new File("../plugins/" + customRulesArtifactId + "/target"),
customRulesArtifactId + "-*.jar"
)
)
.restoreProfileAtStartup(FileLocation.ofClasspath("/profile-javascript-custom-rules.xml"))
.restoreProfileAtStartup(FileLocation.ofClasspath("/profile-typescript-custom-rules.xml"))
.restoreProfileAtStartup(FileLocation.ofClasspath("/nosonar.xml"))
.build();
// Installation of SQ server in orchestrator is not thread-safe, so we need to synchronize
synchronized (OrchestratorStarter.class) {
orchestrator.start();
}
return orchestrator;
}

static BuildResult runBuild(Orchestrator orchestrator) {
SonarScanner build = OrchestratorStarter
.createScanner()
.setProjectDir(TestUtils.projectDirNoCopy("custom_rules"))
.setProjectKey("custom-rules")
.setProjectName("Custom Rules")
.setProjectVersion("1.0")
.setDebugLogs(true)
.setSourceDirs("src");
orchestrator.getServer().provisionProject("custom-rules", "Custom Rules");
orchestrator
.getServer()
.associateProjectToQualityProfile("custom-rules", "js", "javascript-custom-rules-profile");
orchestrator
.getServer()
.associateProjectToQualityProfile("custom-rules", "ts", "ts-custom-rules-profile");
return orchestrator.executeBuild(build);
}

@Test
void test() {
var buildResult = runBuild(orchestrator);
var logMatch = ".*DEBUG: Registered JsAnalysisConsumers \\[org.sonar.samples.javascript.consumer.Consumer.*]";
assertThat(buildResult.getLogsLines(l -> l.matches(logMatch))).hasSize(1);

assertThat(buildResult.getLogsLines(l -> l.matches(".*Processing file src/dir.*"))).hasSize(2);
}
}
Loading
Loading