我一直在尝试为Sonarqube~5.4编写一个自定义规则插件,虽然我已经实现并运行了一些规则,但依赖于标准库以外类型的规则依赖于各种类型杂技字符串匹配。
我使用sonar-packaging-maven-plugin
进行打包:
<plugin>
<groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
<artifactId>sonar-packaging-maven-plugin</artifactId>
<version>1.16</version>
<configuration>
<pluginClass>${project.groupId}.sonar.BravuraRulesPlugin</pluginClass>
<pluginKey>SonarPluginBravura</pluginKey>
<skipDependenciesPackaging>false</skipDependenciesPackaging>
<basePlugin>java</basePlugin>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>sonar-plugin</goal>
</goals>
</execution>
</executions>
</plugin>
我正在使用以下帮助扩展程序(kotlin)运行各种检查:
fun <T : JavaFileScanner> T.verify() {
val workDir = System.getProperty("user.dir");
val folder = Paths.get(workDir, "src/test/samples", this.javaClass.simpleName);
Files.list(folder).forEach { sample ->
try {
if (sample.toString().endsWith(".clean.java")) {
JavaCheckVerifier.verifyNoIssue(sample.toString(), this);
} else {
JavaCheckVerifier.verify(sample.toString(), this);
}
} catch (error: Exception) {
throw VerificationFailedException(sample, error);
}
}
};
class VerificationFailedException(path: Path, error: Exception)
: Exception("Failed to verify $path.", error);
我为规则创建了一个IssuableSubscriptionVisitor
子类,并访问Tree.Kind.METHOD_INVOCATION
,寻找使用传递AutoLongColumn
的静态MAX,MIN,ASC或DESC sql构建器方法。这是为了停止用于订购目的的标识符字段。
不幸的是,即使我在maven上有必要的图书馆&#39; test&#39; classpath,当我尝试获取任何类型时,它们只显示为!unknown!
。
override fun visitNode(tree: Tree) {
if (tree !is MethodInvocationTree) {
return;
}
val methodSelect = tree.methodSelect();
if (methodSelect !is IdentifierTree || methodSelect.name() !in setOf("MAX", "MIN", "ASC", "DESC")) {
return;
}
val firstArg = statement.arguments().first();
if (firstArg !is MethodInvocationTree) {
return;
}
val firstArgSelect = firstArg.methodSelect();
if (firstArgSelect !is MemberSelectExpressionTree) {
return;
}
if (firstArgSelect.type is UnknownType) {
throw TableFlipException("(ノಥ益ಥ)ノ ┻━┻");
}
// It never gets here.
}
我确定我错过了一些重要的谜题,如果有人能告诉我哪里出错了,我会很感激。
编辑:我使用org.sonarsource.java:sonar-java-plugin:3.14
作为分析器,而我无法发布分析目标的所有代码(商业IP及其他所有内容) ,这里的结构与关键部分完全相同:
import static com.library.UtilClass.MAX;
...
query.SELECT(biggestId = MAX(address._id())) // Noncompliant
.FROM(address)
.WHERE(address.user_id().EQ(userId)
.AND(address.type_id().EQ(typeId)));
...
address.id()
的类型是com.library.Identifier
,包裹了很长时间。我希望能够访问所有方法调用,检查它们是否与com.library.UtilCLass.MAX
匹配,如果匹配,请确保第一个参数不是com.library.Identifier
。如果没有类型信息,我必须在_id
方法引用上进行正则表达式匹配,这很容易丢失。
答案 0 :(得分:2)
因此,事实证明获得类型可用的方法是使用maven(或您正在使用的任何工具)将所需的jar复制到目录中,然后将批次转换为文件列表,并传递到测试验证者。
例如,假装我们试图找到 joda-time 的用法:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy-libs</id>
<phase>generate-test-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.4</version>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<executions>
</plugin>
此执行会将joda-time jar放入target/dependency
目录。接下来,确保枚举该目录中的jar,并将它们添加到测试验证中(我们假设您将验证者命名为“JodaCheck”):
// Not at all necessary, but it makes the code later on a lot easier to read.
fun <T> Stream<T>.toList(): List<T> = this.collect({
mutableListOf()
}, { list, item ->
list.add(item)
}, { list, otherList ->
list.addAll(otherList)
})
...
val workDir = System.getProperty("user.dir")
val sampleFile = Paths.get(workDir, "src/test/samples/JodaSample.java").toString()
val dependencies = Files.list(Paths.get(workDir, "target/dependency"))
.map { it.toFile() }.toList()
JavaCheckVerifier.verify(sampleFile, JodaChecker(), dependencies)
完成后,通过测试调试将显示分析期间可以使用joda-time类。