如何确保我的自定义声纳插件规则可以使用正确的字节码,因此我不知道!对于每种类型?

时间:2016-08-22 04:29:26

标签: sonarqube sonarqube-5.4

我一直在尝试为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方法引用上进行正则表达式匹配,这很容易丢失。

1 个答案:

答案 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类。