7

nullpointer のクラッシュを防ぐために、IntelliJ のnull チェック メカニズムを使用します。この回答を使用して、デフォルトですべてのJavaメソッドパラメータを @NonNull に設定することに成功しました。

Javaでパッケージアノテーションを定義するために使用されるpackage-info.javaを作成した後。そのパッケージの直接の子孫であるすべての Java ファイルには、私の Android Studio プロジェクトにデフォルトの @NonNull パラメータを持つメソッドがあります。

ここに画像の説明を入力

明らかな問題は、そのパッケージ内のすべての Java クラス、つまりすべてのサブパッケージを含む@ParametersAreNonnullByDefaultを定義する必要があることです。

@ParametersAreNonnullByDefault を定義して、すべてのサブパッケージ Java ファイルに伝達されるようにするにはどうすればよいですか? デフォルトで、内部コードのすべてのメソッドに @NonNull アノテーションを付けたいと考えています。

ここに画像の説明を入力

/**
  * File: package-info.java
  * Make all method parameters @NonNull by default
  */
  @ParametersAreNonnullByDefault
  package com.intive.nearbyplaces.main;

  import javax.annotation.ParametersAreNonnullByDefault;
4

1 に答える 1

9

問題は、すべてのサブパッケージで Android Studio に @ParametersAreNonnullByDefault を強制的に適用させることができなかったことです(つまり、 com.company.nameのすべての Java ファイルに対して再帰的に) 。

ただし、各サブパッケージ フォルダー内にpackage-info.javaファイルが生成されているかどうかを確認し、必要に応じて作成するgradle スクリプトを作成しました。このスクリプトは、 assembleDebugタスクの直前に実行されます。

したがって、プロジェクト内のすべての Java クラスに@ParametersAreNonnullByDefaultアノテーションを強制できることがわかりました。

ソースはこちらからダウンロードしてください。19 行目をパッケージ名に置き換えることを忘れないでください。

使用法:

apply plugin: 'com.android.application'
apply from: 'nonnull.gradle'

android {
   compileSdkVersion 24
   buildToolsVersion "24.0.2"

   [...]
}

.gitignoreにpackage-info.javaファイルを含めることを忘れないでください

//File: .gitignore 

package-info.java

チェックスタイル ルール:

<module name="JavadocPackage"/>

package-info.java が各サブパッケージに含まれているかどうかを確認します。

ソース:

/**
 *  File: nonnull.gradle
 *
 *  Generates package-info.java for appropriate packages
 *  inside src/main/java folder.
 *
 *  This is a workaround to define @ParametersAreNonnullByDefault for all Java classes in a package
 *  i.e. including all subpackages (note: edit package name in line no. 19).
 */
task generateNonNullJavaFiles(dependsOn: "assembleDebug", type: Copy) {
    group = "Copying"
    description = "Generate package-info.java classes"

    def infoFileContentHeader = getFileContentHeader();
    def infoFileContentFooter = getFileContentFooter();

    def sourceDir = file( "${projectDir}" + File.separatorChar + "src" + File.separatorChar +
            "main" + File.separatorChar + "java" + File.separatorChar +
            "com" + File.separatorChar + "company" + File.separatorChar + "name" )
    sourceDir.eachDirRecurse { dir ->
        def infoFilePath = dir.getAbsolutePath() + File.separatorChar + "package-info.java"

        if (!file(infoFilePath).exists()) {
            def infoFileContentPackage = getFileContentPackage(dir.getAbsolutePath());
            new File(infoFilePath).write(infoFileContentHeader +
                    infoFileContentPackage + infoFileContentFooter)
            println "[dir] " + infoFilePath + "  created";
        }
    }
    println "[SUCCESS] NonNull generator: package-info.java files checked"
}

def getFileContentPackage(path) {
    def mainSrcPhrase = "src" + File.separatorChar + "main" + File.separatorChar +
            "java" + File.separatorChar
    def mainSrcPhraseIndex = path.indexOf(mainSrcPhrase)
    def output = path.substring(mainSrcPhraseIndex)

    // Win hotfix
    if (System.properties['os.name'].toLowerCase().contains('windows')) {
        output = output.replace("\\", "/")
        mainSrcPhrase = mainSrcPhrase.replace("\\", "/")
    }

    return "package " + output.replaceAll(mainSrcPhrase, "").replaceAll(
            "/", ".") + ";\n"
}

def getFileContentHeader() {
    return  "/** javadoc goes here \n */\n" +
            "@ParametersAreNonnullByDefault\n" +
            "@ReturnValuesAreNonnullByDefault\n"
}

def getFileContentFooter() {
    return  "\n" +
            "import javax.annotation.ParametersAreNonnullByDefault;\n" +
            "\n" +
            "import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault;"
}

src main、test & androidTest フォルダーのパッケージ情報ファイルを生成する拡張バージョンは、こちらにあります

Findbugs & Lint:

findbugs と lint で動作します

于 2016-10-17T16:34:23.757 に答える