所有子包的IntelliJ IDEA @ParametersAreNonnullByDefault

时间:2016-10-17 10:37:42

标签: java android-studio intellij-idea nullable non-nullable

我使用IntelliJ的空检查机制来防止nullpointer崩溃。 我使用this answer默认将所有Java方法参数设置为@NonNull。

创建 package-info.java 后,用于在Java中定义package annotations。作为该软件包的直接后代的所有java文件都在我的Android Studio项目中具有默认@NonNull参数的方法。

enter image description here

显而易见的问题是我需要为该软件包中的所有Java类定义 @ParametersAreNonnullByDefault ,即包括所有子包

如何定义@ParametersAreNonnullByDefault以便向下传播到所有子包java文件?我想默认使用@NonNull注释我的所有内部代码方法。

enter image description here

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

  import javax.annotation.ParametersAreNonnullByDefault;

1 个答案:

答案 0 :(得分:8)

问题在于我无法强迫Android Studio尊重所有子包中的 @ParametersAreNonnullByDefault (即递归显示 com.company.name 中的所有java文件)

我编写了一个 gradle脚本,以检查是否在每个子包文件夹中生成了 package-info.java 文件,并在必要时创建它。该脚本在 assembleDebug 任务之前运行。

事实证明,可以对项目中的所有Java类强制执行 @ParametersAreNonnullByDefault 注释。

下载来源here。请务必使用您的包名称替换第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

Checkstyle规则:

<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&amp;生成包信息文件的扩展版本可以找到androidTest文件夹here

Findbugs&amp;棉绒:

使用findbugs&amp ;; 可以正常工作棉绒。