IntelliJ IDEA @ParametersAreNonnullByDefault for all subpackages

别说谁变了你拦得住时间么 提交于 2019-11-28 04:25:01

问题


I use IntelliJ's null-checking mechanism to prevent nullpointer crashes. I've successfully set up all Java method parameters to be @NonNull by default using this answer.

After creating package-info.java which is used to define package annotations in Java. All java files which are direct descendants of that package have methods with default @NonNull parameters in my Android Studio project.

The obvious problem is that I need to define @ParametersAreNonnullByDefault for all Java classes in that package i.e. including all subpackages.

How can I define @ParametersAreNonnullByDefault so that it propagates down to all subpackage java files? I want to have all of my internal code's method annotated with @NonNull by default.

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

  import javax.annotation.ParametersAreNonnullByDefault;

回答1:


The problem was that I couldn't force Android Studio to respect @ParametersAreNonnullByDefault in all subpackages (i.e. recursively for all java files in com.company.name)

I wrote a gradle script, however, to check whether package-info.java files are generated inside each of the subpackage folders and create it if necessary. The script runs just before assembleDebug task.

So it turns out it is possible to force @ParametersAreNonnullByDefault annotation on all java classes in your project.

Download the source here. Remember to replace line 19 with your package name.

Usage:

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

android {
   compileSdkVersion 24
   buildToolsVersion "24.0.2"

   [...]
}

Remember to include package-info.java files in .gitignore

//File: .gitignore 

package-info.java

Checkstyle rule:

<module name="JavadocPackage"/>

checks whether package-info.java is included in each subpackage.

Source:

/**
 *  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;"
}

Extended version which generates package info files for src main, test & androidTest folders can be found here.

Findbugs & Lint:

It does work with findbugs & lint.



来源:https://stackoverflow.com/questions/40084203/intellij-idea-parametersarenonnullbydefault-for-all-subpackages

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!