I’m writing a plugin for a new language (let’s call it Base Plugin). I have the basics rules for this language, wrote the grammar and manage to use it to analyse files with Sonarqube server.
Now I would like to create a new plugin (let’s call it Extending Plugin) that adds some rules using extensions. However the injected objects are alwaysnull.
// Imports to make sure I'm using the good packages
import org.sonar.api.batch.ScannerSide;
import org.sonarsource.api.sonarlint.SonarLintSide;
@SonarLintSide
@ScannerSide
// @ExtensionPoint annotation is not required, right ?
public interface MyExtensionPoint {
void call(String str);
}
Then in the extending plugin I did:
@SonarLintSide
@ScannerSide
public class MyExtensionPointImpl implements MyExtensionPoint {
@Override
public void call(final String str) {
System.err.println(str);
}
}
And registered the extension in the extending plugin declaration:
public class ExtendingPluginPlugin implements Plugin{
@Override
public void define(final Context context) {
context.addExtension(MyExtensionPointImpl.class);
// ... registering other extensions that are working well
}
}
Now in the base plugin, trying to inject a MyExtensionPoint in the Sensor always get null:
public class BaseSquidSensor implements Sensor {
// Constructor with less arguments...
public BaseSquidSensor (final CheckFactory checkFactory,
final Configuration settings,
@Nullable MyExtensionPoint[] myExtensionPoints){
// Injected myExtensionPoints is always null...
}
//....
}
basePlugin will make your two plugins share the same classloader. This is not always good. Another option is to put your interface MyExtensionPoint in the package org.sonar.plugins.<plugin key>.api. By convention all classes in this package are visible to all other plugins.
But as I said using basePlugin is only needed when the extension point is not in the API. In fact I will check but to me no custom rule plugin should use basePlugin.
I am now getting an java.lang.ArrayStoreException: org.sonar.plugins.mysql.api.grammar.SqlGrammar
when running the scanner. This indicates that wrong type argument is provided, but it works in unit test. So my only guess is a runtime class resolution issue.
The target line is simply (invoked in the Extending plugin):
subscribeTo(SqlGrammar.FILE_INPUT);
with signature
public void subscribeTo(final AstNodeType... astNodeTypes) {
SqlGrammar is obviously a GrammarRuleKey which extends AstNodeType, so I’m not sure why it throws an exception. SqlGrammar is defined in the base plugin.
The Extending plugin has a provided Maven dependency to the Base plugin, so I assume that Sonarqube provides the good Jar…
Inspect the content of your extending plugin JAR, and be sure the extended plugin is not packaged. If you are using the Maven scope “provided” it should not be the case.
Is AstNodeType also in the org.sonar.plugins.mysql.api package?
Base plugin JAR is not within the extended plugin. AstNodeType is part of org.sonarsource.sslr:sslr-core in com.sonar.sslr.api package. It is included in my extending plugin with compile scope. This might be the issue.
I’m not sure I can switch it to provided. Will Sonarqube provide it ?
SonarQube won’t provide it. If this library should be part of your plugin API. You can use the Maven shade plugin to relocate classes in the right package.