2016-08-22 9 views
2

私は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を参照し、静的なMAX、MIN、ASC、またはDESCのSQLビルダーメソッドを使用して、AutoLongColumnを探してください。これは、注文目的で使用されている識別子フィールドを停止するためです。

残念ながら、maven 'test'クラスパスに必要なライブラリがありますが、タイプを取得しようとすると、それらは単に!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. 

} 

は、私は、パズルのいくつかの重要な部分が欠けてると確信している、と私は間違っているつもりだどこ誰かが私に言うことができる場合、私は感謝します。

EDIT:私はアナライザ用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

分析するコードを共有してもよろしいですか?そこに何かが隠されているかもしれません。 – benzonico

+1

また、あなたが使用しているソナーのJavaアナライザのバージョンを正確に知りたいかもしれません。 – benzonico

+0

質問に更新を追加しました。 – tzrlk

答えて

2

利用可能な型を取得する方法は、必要なjarファイルをディレクトリにコピーしてから、ファイルのリストに変換して渡すことですそれをテストベリファイアに送信します。

<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> 

この実行はtarget/dependencyディレクトリにジョダ時の瓶を置く:

は例えば、我々はジョダ-時間の使用法を見つけるためにしようとしているふりをすることができます。次に、あなたは(私たちは、あなたの検証「JodaCheckを」という名前と仮定している)、そのディレクトリ内のjarファイルを列挙してください、そして、あなたのテストの検証にそれらを追加します。

// 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クラスが使用可能であることが示されます。

+0

注意しなければならないこと:これには正当な理由があります:テストするタイプがあなたのプロジェクトの一部ではない可能性があるため、プロジェクトに依存性を追加したくない場合もあります(クラスの最終的な競合のためにテストでも)カスタムルールプロジェクト(JPAのテストなど) – benzonico

関連する問題