Browse Source

SONAR-7751, SONAR-7756 SonarLint API

tags/6.0-RC1
Julien HENRY 8 years ago
parent
commit
2d20c0f3f2
30 changed files with 432 additions and 89 deletions
  1. 3
    3
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java
  2. 1
    1
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java
  3. 2
    2
      server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
  4. 3
    3
      server/sonar-ce/src/main/java/org/sonar/ce/platform/ComputeEngineExtensionInstaller.java
  5. 2
    2
      server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java
  6. 6
    7
      server/sonar-server/src/main/java/org/sonar/server/plugins/ServerExtensionInstaller.java
  7. 11
    5
      sonar-plugin-api/src/main/java/org/sonar/api/ExtensionProvider.java
  8. 24
    5
      sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java
  9. 161
    0
      sonar-plugin-api/src/main/java/org/sonar/api/RuntimeApiVersion.java
  10. 5
    26
      sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java
  11. 2
    0
      sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/Sensor.java
  12. 13
    0
      sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java
  13. 14
    4
      sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
  14. 4
    4
      sonar-plugin-api/src/main/java/org/sonar/api/internal/RuntimeApiVersionFactory.java
  15. 2
    0
      sonar-plugin-api/src/main/java/org/sonar/api/resources/Language.java
  16. 23
    1
      sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
  17. 1
    2
      sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionAnnotationLoader.java
  18. 0
    4
      sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionI18nLoader.java
  19. 3
    1
      sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java
  20. 52
    0
      sonar-plugin-api/src/main/java/org/sonarsource/api/sonarlint/SonarLintSide.java
  21. 23
    0
      sonar-plugin-api/src/main/java/org/sonarsource/api/sonarlint/package-info.java
  22. 2
    2
      sonar-plugin-api/src/test/java/org/sonar/api/PluginTest.java
  23. 45
    0
      sonar-plugin-api/src/test/java/org/sonar/api/RuntimeApiVersionTest.java
  24. 2
    1
      sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java
  25. 4
    3
      sonar-plugin-api/src/test/java/org/sonar/api/internal/RuntimeApiVersionFactoryTest.java
  26. 5
    5
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ExtensionInstaller.java
  27. 2
    2
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java
  28. 2
    2
      sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/DeprecatedSensorContext.java
  29. 13
    3
      sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java
  30. 2
    1
      sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorContextTest.java

+ 3
- 3
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java View File

@@ -25,17 +25,17 @@ import org.sonar.api.utils.Version;
import org.sonar.xoo.lang.CpdTokenizerSensor;

import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.SonarQubeVersion.V5_5;
import static org.sonar.api.RuntimeApiVersion.V5_5;

public class XooPluginTest {

@Test
public void provide_extensions_for_5_5() {
Plugin.Context context = new Plugin.Context(V5_5);
Plugin.Context context = new Plugin.Context(V5_5, false);
new XooPlugin().define(context);
assertThat(context.getExtensions()).hasSize(40).contains(CpdTokenizerSensor.class);

context = new Plugin.Context(Version.parse("5.4"));
context = new Plugin.Context(Version.parse("5.4"), false);
new XooPlugin().define(context);
assertThat(context.getExtensions()).hasSize(39).doesNotContain(CpdTokenizerSensor.class);
}

+ 1
- 1
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java View File

@@ -104,7 +104,7 @@ public class OneIssuePerLineSensorTest {
SensorContextTester context = SensorContextTester.create(temp.newFolder());
context.fileSystem().add(inputFile);
context.settings().setProperty(OneIssuePerLineSensor.EFFORT_TO_FIX_PROPERTY, "1.2");
context.setSonarQubeVersion(Version.parse("5.4"));
context.setRuntime(Version.parse("5.4"), false);

sensor.execute(context);


+ 2
- 2
server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java View File

@@ -23,7 +23,7 @@ import com.google.common.annotations.VisibleForTesting;
import java.util.List;
import javax.annotation.CheckForNull;
import org.sonar.api.config.EmailSettings;
import org.sonar.api.internal.SonarQubeVersionFactory;
import org.sonar.api.internal.RuntimeApiVersionFactory;
import org.sonar.api.profiles.AnnotationProfileParser;
import org.sonar.api.profiles.XMLProfileParser;
import org.sonar.api.profiles.XMLProfileSerializer;
@@ -135,7 +135,7 @@ import org.sonarqube.ws.Rules;
public class ComputeEngineContainerImpl implements ComputeEngineContainer {
private static final Object[] LEVEL_1_COMPONENTS = new Object[] {
ComputeEngineSettings.class,
SonarQubeVersionFactory.create(System2.INSTANCE),
RuntimeApiVersionFactory.create(System2.INSTANCE, false),
ServerImpl.class,
UuidFactoryImpl.INSTANCE,
// no EmbeddedDatabaseFactory.class, creating H2 DB if responsibility of WebServer

+ 3
- 3
server/sonar-ce/src/main/java/org/sonar/ce/platform/ComputeEngineExtensionInstaller.java View File

@@ -19,14 +19,14 @@
*/
package org.sonar.ce.platform;

import org.sonar.api.SonarQubeVersion;
import org.sonar.api.RuntimeApiVersion;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
import org.sonar.core.platform.PluginRepository;
import org.sonar.server.plugins.ServerExtensionInstaller;

public class ComputeEngineExtensionInstaller extends ServerExtensionInstaller {
public ComputeEngineExtensionInstaller(SonarQubeVersion sonarQubeVersion, PluginRepository pluginRepository) {
super(sonarQubeVersion, pluginRepository, ServerSide.class, ComputeEngineSide.class);
public ComputeEngineExtensionInstaller(RuntimeApiVersion runtimeApiVersion, PluginRepository pluginRepository) {
super(runtimeApiVersion, pluginRepository, ServerSide.class, ComputeEngineSide.class);
}
}

+ 2
- 2
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java View File

@@ -21,7 +21,7 @@ package org.sonar.server.platform.platformlevel;

import java.util.Properties;
import javax.annotation.Nullable;
import org.sonar.api.internal.SonarQubeVersionFactory;
import org.sonar.api.internal.RuntimeApiVersionFactory;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.internal.TempFolderCleaner;
import org.sonar.ce.property.CePropertyDefinitions;
@@ -68,7 +68,7 @@ public class PlatformLevel1 extends PlatformLevel {
add(platform, properties);
addExtraRootComponents();
add(
SonarQubeVersionFactory.create(System2.INSTANCE),
RuntimeApiVersionFactory.create(System2.INSTANCE, false),
ProcessCommandWrapperImpl.class,
RestartFlagHolderImpl.class,
WebServerSettings.class,

+ 6
- 7
server/sonar-server/src/main/java/org/sonar/server/plugins/ServerExtensionInstaller.java View File

@@ -23,10 +23,9 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import java.lang.annotation.Annotation;
import java.util.Map;
import org.sonar.api.Extension;
import org.sonar.api.ExtensionProvider;
import org.sonar.api.Plugin;
import org.sonar.api.SonarQubeVersion;
import org.sonar.api.RuntimeApiVersion;
import org.sonar.api.utils.AnnotationUtils;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.PluginInfo;
@@ -39,14 +38,14 @@ import static java.util.Objects.requireNonNull;
*/
public abstract class ServerExtensionInstaller {

private final SonarQubeVersion sonarQubeVersion;
private final RuntimeApiVersion runtimeApiVersion;
private final PluginRepository pluginRepository;
private final Class<? extends Annotation>[] supportedAnnotationTypes;

protected ServerExtensionInstaller(SonarQubeVersion sonarQubeVersion, PluginRepository pluginRepository,
protected ServerExtensionInstaller(RuntimeApiVersion runtimeApiVersion, PluginRepository pluginRepository,
Class<? extends Annotation>... supportedAnnotationTypes) {
requireNonNull(supportedAnnotationTypes, "At least one supported annotation type must be specified");
this.sonarQubeVersion = sonarQubeVersion;
this.runtimeApiVersion = runtimeApiVersion;
this.pluginRepository = pluginRepository;
this.supportedAnnotationTypes = supportedAnnotationTypes;
}
@@ -60,7 +59,7 @@ public abstract class ServerExtensionInstaller {
Plugin plugin = pluginRepository.getPluginInstance(pluginKey);
container.addExtension(pluginInfo, plugin);

Plugin.Context context = new Plugin.Context(sonarQubeVersion.get());
Plugin.Context context = new Plugin.Context(runtimeApiVersion.get(), runtimeApiVersion.isSonarlintRuntime());
plugin.define(context);
for (Object extension : context.getExtensions()) {
if (installExtension(container, pluginInfo, extension, true) != null) {
@@ -119,7 +118,7 @@ public abstract class ServerExtensionInstaller {
return isType(extension, ExtensionProvider.class) || extension instanceof ExtensionProvider;
}

static boolean isType(Object extension, Class<? extends Extension> extensionClass) {
static boolean isType(Object extension, Class extensionClass) {
Class clazz = extension instanceof Class ? (Class) extension : extension.getClass();
return extensionClass.isAssignableFrom(clazz);
}

+ 11
- 5
sonar-plugin-api/src/main/java/org/sonar/api/ExtensionProvider.java View File

@@ -19,16 +19,20 @@
*/
package org.sonar.api;

import org.sonar.api.batch.BatchSide;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;

/**
* Factory of extensions. It allows to dynamically create extensions depending upon runtime context. A use-case is
* Factory of extensions. It allows to dynamically create extensions depending upon runtime context. One use-case is
* to create one rule repository by language.
*
* <p>Notes :
* <ul>
* <li>the provider is declared in Plugin.getExtensions()</li>
* <li>the provider must also implement ServerExtension and/or BatchExtension</li>
* <li>the provider must also add annotation {@link ServerSide}, {@link ComputeEngineSide} and/or {@link BatchSide}</li>
* <li>the provider can accept dependencies (parameters) in its constructors.</li>
* <li>the method provide() is executed once by sonar</li>
* <li>the method provide() is executed once by the platform</li>
* <li>the method provide() must return an object, a class or an Iterable of objects. <strong>Arrays are excluded</strong>.</li>
* </ul>
*
@@ -36,7 +40,8 @@ package org.sonar.api;
* <p>Example:
* <pre>
* {@code
* public class RuleRepositoryProvider extends ExtensionProvider implements ServerExtension {
* {@literal @}ServerSide
* public class RuleRepositoryProvider extends ExtensionProvider {
* private Language[] languages;
*
* public RuleRepositoryProvider(Language[] languages) {
@@ -59,7 +64,8 @@ package org.sonar.api;
* @deprecated since 6.0 should no more be used
*/
@Deprecated
public abstract class ExtensionProvider implements Extension {
@ExtensionPoint
public abstract class ExtensionProvider {

public abstract Object provide();
}

+ 24
- 5
sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java View File

@@ -85,18 +85,29 @@ import static java.util.Objects.requireNonNull;
public interface Plugin {

class Context {
private final Version version;
private final Version runtimeApiVersion;
private final List extensions = new ArrayList();
private final boolean sonarlintRuntime;

public Context(Version version) {
this.version = version;
public Context(Version runtimeApiVersion, boolean sonarlintRuntime) {
this.runtimeApiVersion = runtimeApiVersion;
this.sonarlintRuntime = sonarlintRuntime;
}

/**
* Runtime version of SonarQube
* @deprecated since 6.0
*/
@Deprecated
public Version getSonarQubeVersion() {
return version;
return runtimeApiVersion;
}

/**
* Runtime API version. Can be use to conditionnaly add some extensions.
* @since 6.0
*/
public Version getRuntimeApiVersion() {
return runtimeApiVersion;
}

/**
@@ -141,6 +152,14 @@ public interface Plugin {
public List getExtensions() {
return extensions;
}

/**
* Test if plugin is currently executed in SonarLint. Can be use to conditionnaly add some extensions.
* @since 6.0
*/
public boolean isSonarlintRuntime() {
return sonarlintRuntime;
}
}

/**

+ 161
- 0
sonar-plugin-api/src/main/java/org/sonar/api/RuntimeApiVersion.java View File

@@ -0,0 +1,161 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact 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.api;

import javax.annotation.concurrent.Immutable;
import org.sonar.api.batch.BatchSide;
import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.Version;

import static java.util.Objects.requireNonNull;

/**
* Version of SonarQube at runtime. This component can be injected as a dependency
* of plugin extensions. The main usage for a plugin is to benefit from new APIs
* while keeping backward-compatibility with previous versions of SonarQube.
* <br><br>
*
* Example 1: a {@link Sensor} wants to use an API introduced in version 5.5 and still requires to support older versions
* at runtime.
* <pre>
* public class MySensor implements Sensor {
*
* public void execute(SensorContext context) {
* if (context.getRuntimeApiVersion().isGreaterThanOrEqual(RuntimeApiVersion.V5_5)) {
* context.newMethodIntroducedIn5_5();
* }
* }
* }
* </pre>
*
* Example 2: a plugin needs to use an API introduced in version 5.6 ({@code AnApi} in the following
* snippet) and still requires to support version 5.5 at runtime.
* <br>
* <pre>
* // Component provided by sonar-plugin-api
* // @since 5.5
* public interface AnApi {
* // implicitly since 5.5
* public void foo();
*
* // @since 5.6
* public void bar();
* }
*
* // Component provided by plugin
* public class MyExtension {
* private final RuntimeApiVersion runtimeApiVersion;
* private final AnApi api;
*
* public MyExtension(RuntimeApiVersion runtimeApiVersion, AnApi api) {
* this.runtimeApiVersion = runtimeApiVersion;
* this.api = api;
* }
*
* public void doSomething() {
* // assume that runtime is 5.5+
* api.foo();
*
* if (runtimeApiVersion.isGreaterThanOrEqual(SonarQubeVersion.V5_6)) {
* api.bar();
* }
* }
* }
* </pre>
* <p>
* The minimal supported version of plugin API is verified at runtime. As plugin is built
* with sonar-plugin-api 5.6, we assume that the plugin requires v5.6 or greater at runtime.
* For this reason the plugin must default which is the minimal supported version
* in the configuration of sonar-packaging-maven-plugin 1.16+:
* <p>
* <pre>
* &lt;packaging&gt;sonar-plugin&lt;/packaging&gt;
*
* &lt;dependencies&gt;
* &lt;dependency&gt;
* &lt;groupId&gt;org.sonarsource.sonarqube&lt;/groupId&gt;
* &lt;artifactId&gt;sonar-plugin-api&lt;/artifactId&gt;
* &lt;version&gt;5.6&lt;/version&gt;
* &lt;scope&gt;provided&lt;/scope&gt;
* &lt;/dependency&gt;
* &lt;/dependencies&gt;
*
* &lt;build&gt;
* &lt;plugins&gt;
* &lt;plugin&gt;
* &lt;groupId&gt;org.sonarsource.sonar-packaging-maven-plugin&lt;/groupId&gt;
* &lt;artifactId&gt;sonar-packaging-maven-plugin&lt;/artifactId&gt;
* &lt;version&gt;1.16&lt;/version&gt;
* &lt;extensions&gt;true&lt;/extensions&gt;
* &lt;configuration&gt;
* &lt;!-- Override the default value 5.6 which is guessed from sonar-plugin-api dependency --&gt;
* &lt;sonarQubeMinVersion&gt;5.5&lt;/sonarQubeMinVersion&gt;
* &lt;/configuration&gt;
* &lt;/plugin&gt;
* &lt;/plugins&gt;
* &lt;/build&gt;
* </pre>
*
*
* @since 6.0
*/
@BatchSide
@ServerSide
@ComputeEngineSide
@Immutable
public class RuntimeApiVersion {

/**
* Constant for version 5.5
*/
public static final Version V5_5 = Version.create(5, 5);

/**
* Constant for version 5.6
*/
public static final Version V5_6 = Version.create(5, 6);

private final Version version;
private final boolean sonarlint;

public RuntimeApiVersion(Version version, boolean sonarlint) {
requireNonNull(version);
this.version = version;
this.sonarlint = sonarlint;
}

public Version get() {
return this.version;
}

public boolean isGreaterThanOrEqual(Version than) {
return this.version.isGreaterThanOrEqual(than);
}

/**
* @since 6.0 Test if current runtime is SonarLint. Can be used to implement a different behavior.
*/
public boolean isSonarlintRuntime() {
return sonarlint;
}

}

+ 5
- 26
sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java View File

@@ -26,8 +26,6 @@ import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.Version;

import static java.util.Objects.requireNonNull;

/**
* Version of SonarQube at runtime. This component can be injected as a dependency
* of plugin extensions. The main usage for a plugin is to benefit from new APIs
@@ -117,36 +115,17 @@ import static java.util.Objects.requireNonNull;
*
*
* @since 5.5
* @deprecated since 6.0 replaced by {@link RuntimeApiVersion}
*/
@ScannerSide
@ServerSide
@ComputeEngineSide
@Immutable
public class SonarQubeVersion {

/**
* Constant for version 5.5
*/
public static final Version V5_5 = Version.create(5, 5);

/**
* Constant for version 5.6
*/
public static final Version V5_6 = Version.create(5, 6);

private final Version version;

public SonarQubeVersion(Version version) {
requireNonNull(version);
this.version = version;
}

public Version get() {
return this.version;
}
@Deprecated
public class SonarQubeVersion extends RuntimeApiVersion {

public boolean isGreaterThanOrEqual(Version than) {
return this.version.isGreaterThanOrEqual(than);
public SonarQubeVersion(Version version, boolean sonarlint) {
super(version, sonarlint);
}

}

+ 2
- 0
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/Sensor.java View File

@@ -22,6 +22,7 @@ package org.sonar.api.batch.sensor;
import org.sonar.api.ExtensionPoint;
import org.sonar.api.batch.ScannerSide;
import org.sonar.api.batch.sensor.internal.SensorContextTester;
import org.sonarsource.api.sonarlint.SonarLintSide;

/**
* <p>
@@ -34,6 +35,7 @@ import org.sonar.api.batch.sensor.internal.SensorContextTester;
* @since 5.1
*/
@ScannerSide
@SonarLintSide
@ExtensionPoint
public interface Sensor {


+ 13
- 0
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java View File

@@ -64,9 +64,22 @@ public interface SensorContext {

/**
* @since 5.5
* @deprecated since 6.0 replaced by {@link #getRuntimeApiVersion()}
*/
@Deprecated
Version getSonarQubeVersion();

/**
* @since 6.0
*/
Version getRuntimeApiVersion();

/**
* Test if plugin is currently executed in SonarLint. This can allow to implement a different behavior.
* @since 6.0
*/
boolean isSonarLintRuntime();

// ----------- MEASURES --------------

/**

+ 14
- 4
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java View File

@@ -58,7 +58,7 @@ import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
import org.sonar.api.config.Settings;
import org.sonar.api.internal.SonarQubeVersionFactory;
import org.sonar.api.internal.RuntimeApiVersionFactory;
import org.sonar.api.measures.Metric;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.Version;
@@ -95,7 +95,7 @@ public class SensorContextTester implements SensorContext {
this.activeRules = new ActiveRulesBuilder().build();
this.sensorStorage = new InMemorySensorStorage();
this.module = new DefaultInputModule("projectKey");
this.sqVersion = SonarQubeVersionFactory.create(System2.INSTANCE);
this.sqVersion = RuntimeApiVersionFactory.create(System2.INSTANCE, false);
}

public static SensorContextTester create(File moduleBaseDir) {
@@ -145,8 +145,18 @@ public class SensorContextTester implements SensorContext {
return sqVersion.get();
}

public SensorContextTester setSonarQubeVersion(Version version) {
this.sqVersion = new SonarQubeVersion(version);
@Override
public Version getRuntimeApiVersion() {
return sqVersion.get();
}

@Override
public boolean isSonarLintRuntime() {
return sqVersion.isSonarlintRuntime();
}

public SensorContextTester setRuntime(Version version, boolean isSonarLint) {
this.sqVersion = new SonarQubeVersion(version, isSonarLint);
return this;
}


sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarQubeVersionFactory.java → sonar-plugin-api/src/main/java/org/sonar/api/internal/RuntimeApiVersionFactory.java View File

@@ -30,19 +30,19 @@ import org.sonar.api.utils.Version;
/**
* For internal use only.
*/
public class SonarQubeVersionFactory {
public class RuntimeApiVersionFactory {

private static final String FILE_PATH = "/sq-version.txt";

private SonarQubeVersionFactory() {
private RuntimeApiVersionFactory() {
// prevents instantiation
}

public static SonarQubeVersion create(System2 system) {
public static SonarQubeVersion create(System2 system, boolean isSonarLint) {
try {
URL url = system.getResource(FILE_PATH);
String versionInFile = Resources.toString(url, StandardCharsets.UTF_8);
return new SonarQubeVersion(Version.parse(versionInFile));
return new SonarQubeVersion(Version.parse(versionInFile), isSonarLint);
} catch (IOException e) {
throw new IllegalStateException("Can not load " + FILE_PATH + " from classpath", e);
}

+ 2
- 0
sonar-plugin-api/src/main/java/org/sonar/api/resources/Language.java View File

@@ -24,6 +24,7 @@ import org.sonar.api.batch.ScannerSide;
import org.sonar.api.batch.InstantiationStrategy;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
import org.sonarsource.api.sonarlint.SonarLintSide;

/**
* The extension point to define a new language
@@ -35,6 +36,7 @@ import org.sonar.api.server.ServerSide;
@ScannerSide
@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
@ServerSide
@SonarLintSide
@ComputeEngineSide
@ExtensionPoint
public interface Language {

+ 23
- 1
sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java View File

@@ -40,13 +40,14 @@ import javax.annotation.concurrent.Immutable;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.ExtensionPoint;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.RuleType;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.utils.log.Loggers;
import org.sonarsource.api.sonarlint.SonarLintSide;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
@@ -149,6 +150,7 @@ import static org.apache.commons.lang.StringUtils.trimToNull;
*/
@ServerSide
@ComputeEngineSide
@SonarLintSide
@ExtensionPoint
public interface RulesDefinition {

@@ -672,6 +674,7 @@ public interface RulesDefinition {
private final Set<String> tags = Sets.newTreeSet();
private final Map<String, NewParam> paramsByKey = Maps.newHashMap();
private final DebtRemediationFunctions functions;
private boolean activatedByDefault;

private NewRule(String repoKey, String key) {
this.repoKey = repoKey;
@@ -696,6 +699,15 @@ public interface RulesDefinition {
return this;
}

/**
* Should this rule be enabled by default. For example in SonarLint standalone.
* @since 6.0
*/
public NewRule setActivatedByDefault(boolean activatedByDefault) {
this.activatedByDefault = activatedByDefault;
return this;
}

public NewRule setSeverity(String s) {
checkArgument(Severity.ALL.contains(s), "Severity of rule %s is not correct: %s", this, s);
this.severity = s;
@@ -915,6 +927,7 @@ public interface RulesDefinition {
private final Set<String> tags;
private final Map<String, Param> params;
private final RuleStatus status;
private final boolean activatedByDefault;

private Rule(Repository repository, NewRule newRule) {
this.repository = repository;
@@ -936,6 +949,7 @@ public interface RulesDefinition {
paramsBuilder.put(newParam.key, new Param(newParam));
}
this.params = paramsBuilder.build();
this.activatedByDefault = newRule.activatedByDefault;
}

public Repository repository() {
@@ -976,6 +990,14 @@ public interface RulesDefinition {
return template;
}

/**
* Should this rule be enabled by default. For example in SonarLint standalone.
* @since 6.0
*/
public boolean activatedByDefault() {
return activatedByDefault;
}

public RuleStatus status() {
return status;
}

+ 1
- 2
sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionAnnotationLoader.java View File

@@ -54,8 +54,7 @@ public class RulesDefinitionAnnotationLoader {
.put(Boolean.class, RuleParamType.BOOLEAN)
.put(boolean.class, RuleParamType.BOOLEAN)
.build(),
RuleParamType.STRING
);
RuleParamType.STRING);

public void load(RulesDefinition.NewExtendedRepository repo, Class... annotatedClasses) {
for (Class annotatedClass : annotatedClasses) {

+ 0
- 4
sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionI18nLoader.java View File

@@ -21,8 +21,6 @@ package org.sonar.api.server.rule;

import org.apache.commons.lang.StringUtils;
import org.sonar.api.i18n.RuleI18n;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;

/**
* Loads the English bundles of rules (name, description and parameters) that are
@@ -36,8 +34,6 @@ import org.sonar.api.server.ServerSide;
* @see org.sonar.api.server.rule.RulesDefinition for an example
* @since 4.3
*/
@ServerSide
@ComputeEngineSide
public class RulesDefinitionI18nLoader {

private final RuleI18n i18n;

+ 3
- 1
sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java View File

@@ -32,13 +32,14 @@ import javax.xml.stream.XMLStreamException;
import org.codehaus.staxmate.SMInputFactory;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.RuleType;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.check.Cardinality;
import org.sonarsource.api.sonarlint.SonarLintSide;

import static java.lang.String.format;
import static org.apache.commons.lang.StringUtils.equalsIgnoreCase;
@@ -180,6 +181,7 @@ import static org.apache.commons.lang.StringUtils.trim;
*/
@ServerSide
@ComputeEngineSide
@SonarLintSide
public class RulesDefinitionXmlLoader {

private enum DescriptionFormat {

+ 52
- 0
sonar-plugin-api/src/main/java/org/sonarsource/api/sonarlint/SonarLintSide.java View File

@@ -0,0 +1,52 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact 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.sonarsource.api.sonarlint;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Marker annotation for all the components available in container of sonarlint. Note that
* injection of dependencies by constructor is used :
* <pre>
* {@literal @}SonarLintSide
* public class Foo {
*
* }
* {@literal @}SonarLintSide
* public class Bar {
* private final Foo foo;
* public Bar(Foo f) {
* this.foo = f;
* }
* }
*
* </pre>
*
* @since 6.0
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface SonarLintSide {
}

+ 23
- 0
sonar-plugin-api/src/main/java/org/sonarsource/api/sonarlint/package-info.java View File

@@ -0,0 +1,23 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact 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.sonarsource.api.sonarlint;

import javax.annotation.ParametersAreNonnullByDefault;

+ 2
- 2
sonar-plugin-api/src/test/java/org/sonar/api/PluginTest.java View File

@@ -23,13 +23,13 @@ import java.util.Arrays;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.SonarQubeVersion.V5_5;
import static org.sonar.api.RuntimeApiVersion.V5_5;

public class PluginTest {

@Test
public void test_context() {
Plugin.Context context = new Plugin.Context(V5_5);
Plugin.Context context = new Plugin.Context(V5_5, true);

assertThat(context.getSonarQubeVersion()).isEqualTo(V5_5);
assertThat(context.getExtensions()).isEmpty();

+ 45
- 0
sonar-plugin-api/src/test/java/org/sonar/api/RuntimeApiVersionTest.java View File

@@ -0,0 +1,45 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact 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.api;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.Version;

import static org.assertj.core.api.Assertions.assertThat;

public class RuntimeApiVersionTest {

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void isGte() {
Version version = Version.parse("1.2.3");
RuntimeApiVersion apiVersion = new RuntimeApiVersion(version, false);
assertThat(apiVersion.get()).isEqualTo(version);
assertThat(apiVersion.isSonarlintRuntime()).isFalse();
assertThat(apiVersion.isGreaterThanOrEqual(version)).isTrue();
assertThat(apiVersion.isGreaterThanOrEqual(Version.parse("1.1"))).isTrue();
assertThat(apiVersion.isGreaterThanOrEqual(Version.parse("1.3"))).isFalse();
}

}

+ 2
- 1
sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java View File

@@ -34,8 +34,9 @@ public class SonarQubeVersionTest {
@Test
public void isGte() {
Version version = Version.parse("1.2.3");
SonarQubeVersion qubeVersion = new SonarQubeVersion(version);
SonarQubeVersion qubeVersion = new SonarQubeVersion(version, true);
assertThat(qubeVersion.get()).isEqualTo(version);
assertThat(qubeVersion.isSonarlintRuntime()).isTrue();
assertThat(qubeVersion.isGreaterThanOrEqual(version)).isTrue();
assertThat(qubeVersion.isGreaterThanOrEqual(Version.parse("1.1"))).isTrue();
assertThat(qubeVersion.isGreaterThanOrEqual(Version.parse("1.3"))).isFalse();

sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarQubeVersionFactoryTest.java → sonar-plugin-api/src/test/java/org/sonar/api/internal/RuntimeApiVersionFactoryTest.java View File

@@ -31,16 +31,17 @@ import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

public class SonarQubeVersionFactoryTest {
public class RuntimeApiVersionFactoryTest {

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void create() {
SonarQubeVersion version = SonarQubeVersionFactory.create(System2.INSTANCE);
SonarQubeVersion version = RuntimeApiVersionFactory.create(System2.INSTANCE, true);
assertThat(version).isNotNull();
assertThat(version.get().major()).isGreaterThanOrEqualTo(5);
assertThat(version.isSonarlintRuntime()).isTrue();
}

@Test
@@ -50,7 +51,7 @@ public class SonarQubeVersionFactoryTest {

System2 system = spy(System2.class);
when(system.getResource(anyString())).thenReturn(new File("target/unknown").toURI().toURL());
SonarQubeVersionFactory.create(system);
RuntimeApiVersionFactory.create(system, false);
}

}

+ 5
- 5
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ExtensionInstaller.java View File

@@ -23,7 +23,7 @@ import java.util.List;
import javax.annotation.Nullable;
import org.sonar.api.ExtensionProvider;
import org.sonar.api.Plugin;
import org.sonar.api.SonarQubeVersion;
import org.sonar.api.RuntimeApiVersion;
import org.sonar.api.batch.AnalysisMode;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.PluginInfo;
@@ -31,12 +31,12 @@ import org.sonar.core.platform.PluginRepository;

public class ExtensionInstaller {

private final SonarQubeVersion sonarQubeVersion;
private final RuntimeApiVersion runtimeApiVersionVersion;
private final PluginRepository pluginRepository;
private final AnalysisMode analysisMode;

public ExtensionInstaller(SonarQubeVersion sonarQubeVersion, PluginRepository pluginRepository, AnalysisMode analysisMode) {
this.sonarQubeVersion = sonarQubeVersion;
public ExtensionInstaller(RuntimeApiVersion sonarQubeVersion, PluginRepository pluginRepository, AnalysisMode analysisMode) {
this.runtimeApiVersionVersion = sonarQubeVersion;
this.pluginRepository = pluginRepository;
this.analysisMode = analysisMode;
}
@@ -51,7 +51,7 @@ public class ExtensionInstaller {
// plugin extensions
for (PluginInfo pluginInfo : pluginRepository.getPluginInfos()) {
Plugin plugin = pluginRepository.getPluginInstance(pluginInfo.getKey());
Plugin.Context context = new Plugin.Context(sonarQubeVersion.get());
Plugin.Context context = new Plugin.Context(runtimeApiVersionVersion.get(), runtimeApiVersionVersion.isSonarlintRuntime());
plugin.define(context);
for (Object extension : context.getExtensions()) {
doInstall(container, matcher, pluginInfo, extension);

+ 2
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java View File

@@ -23,7 +23,7 @@ import java.util.List;
import java.util.Map;

import org.sonar.api.Plugin;
import org.sonar.api.internal.SonarQubeVersionFactory;
import org.sonar.api.internal.RuntimeApiVersionFactory;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.UriReader;
import org.sonar.api.utils.log.Logger;
@@ -76,7 +76,7 @@ public class GlobalContainer extends ComponentContainer {
BatchPluginPredicate.class,
ExtensionInstaller.class,

SonarQubeVersionFactory.create(System2.INSTANCE),
RuntimeApiVersionFactory.create(System2.INSTANCE, false),
CachesManager.class,
GlobalSettings.class,
new BatchWsClientProvider(),

+ 2
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/DeprecatedSensorContext.java View File

@@ -21,7 +21,7 @@ package org.sonar.scanner.deprecated;

import java.io.Serializable;
import java.util.Collection;
import org.sonar.api.SonarQubeVersion;
import org.sonar.api.RuntimeApiVersion;
import org.sonar.api.batch.AnalysisMode;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.fs.FileSystem;
@@ -51,7 +51,7 @@ public class DeprecatedSensorContext extends DefaultSensorContext implements Sen
private final CoverageExclusions coverageFilter;

public DeprecatedSensorContext(InputModule module, DefaultIndex index, Project project, Settings settings, FileSystem fs, ActiveRules activeRules,
AnalysisMode analysisMode, CoverageExclusions coverageFilter, SensorStorage sensorStorage, SonarQubeVersion sqVersion) {
AnalysisMode analysisMode, CoverageExclusions coverageFilter, SensorStorage sensorStorage, RuntimeApiVersion sqVersion) {
super(module, settings, fs, activeRules, analysisMode, sensorStorage, sqVersion);
this.index = index;
this.project = project;

+ 13
- 3
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java View File

@@ -20,7 +20,7 @@
package org.sonar.scanner.sensor;

import java.io.Serializable;
import org.sonar.api.SonarQubeVersion;
import org.sonar.api.RuntimeApiVersion;
import org.sonar.api.batch.AnalysisMode;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputModule;
@@ -57,10 +57,10 @@ public class DefaultSensorContext implements SensorContext {
private final SensorStorage sensorStorage;
private final AnalysisMode analysisMode;
private final InputModule module;
private final SonarQubeVersion sqVersion;
private final RuntimeApiVersion sqVersion;

public DefaultSensorContext(InputModule module, Settings settings, FileSystem fs, ActiveRules activeRules, AnalysisMode analysisMode, SensorStorage sensorStorage,
SonarQubeVersion sqVersion) {
RuntimeApiVersion sqVersion) {
this.module = module;
this.settings = settings;
this.fs = fs;
@@ -95,6 +95,16 @@ public class DefaultSensorContext implements SensorContext {
return sqVersion.get();
}

@Override
public Version getRuntimeApiVersion() {
return sqVersion.get();
}

@Override
public boolean isSonarLintRuntime() {
return sqVersion.isSonarlintRuntime();
}

@Override
public <G extends Serializable> NewMeasure<G> newMeasure() {
return new DefaultMeasure<>(sensorStorage);

+ 2
- 1
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorContextTest.java View File

@@ -67,7 +67,7 @@ public class DefaultSensorContextTest {
settings = new Settings();
sensorStorage = mock(SensorStorage.class);
analysisMode = mock(AnalysisMode.class);
sqVersion = new SonarQubeVersion(Version.parse("5.5"));
sqVersion = new SonarQubeVersion(Version.parse("5.5"), false);
adaptor = new DefaultSensorContext(mock(InputModule.class), settings, fs, activeRules, analysisMode, sensorStorage, sqVersion);
}

@@ -77,6 +77,7 @@ public class DefaultSensorContextTest {
assertThat(adaptor.fileSystem()).isEqualTo(fs);
assertThat(adaptor.settings()).isEqualTo(settings);
assertThat(adaptor.getSonarQubeVersion()).isEqualTo(Version.parse("5.5"));
assertThat(adaptor.isSonarLintRuntime()).isFalse();

assertThat(adaptor.newIssue()).isNotNull();
assertThat(adaptor.newMeasure()).isNotNull();

Loading…
Cancel
Save