gradle / gradle

Adaptable, fast automation for all

Home Page:https://gradle.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Checkstyle task should allow spec-based filtering

technoir42 opened this issue · comments

Not sure if I precisely described it in the title but see this example:

apply plugin: 'com.android.application'
apply plugin: 'checkstyle'

android {
    ...

    android.applicationVariants.all { variant ->
        task "checkstyle${variant.name.capitalize()}"(type: Checkstyle) {
            showViolations true
            dependsOn variant.javaCompile
            classpath = project.fileTree(variant.javaCompile.destinationDir)

            source variant.javaCompile.source // Contains files from both build and src 
            exclude '**/generated/source/**'
        }
    }
}

As I see Checkstyle is SourceTask that uses FileTree.matching(PatternFilterable) under the hood to get input files.

Expected Behavior

All files under generated/source/ are excluded from checkstyle task.

Current Behavior

Doesn't work:
exclude '**/generated/source/**'
exclude '**/build/**'

Works:
exclude '**/R.java'
exclude '**/com/**' (com is located under generated/source)

Steps to Reproduce (for bugs)

  1. Clone the repo from https://github.com/technoir3/gradle-exclude-subdirectory-bug
  2. Run ./gradlew checkstyleDebug
  3. Notice the failures even though **/generated/source/** is listed in exclude patterns

Your Environment

Gradle 4.3
Android Gradle Plugin 3.0.0

Looks at the code it seems that the value you set for classpath is just passed along to CheckstyleInvoker without filtering. You might just have to the files you assign as FileTree:

classpath = fileTree(dir: variant.javaCompile.destinationDir, excludes: ['**/generated/source/**'])

@bmuschko I tried changing classpath like you suggested but that didn't make any difference.

I'd like to point out that when I println the file set that CheckstyleInvoker passes to Ant the output contains files that should instead be filtered out:

source variant.javaCompile.source
exclude '**/generated/source/**'

println it.source.files

Outputs:

[/Users/sergey/dev/projects/checkstyle-test/app/src/main/java/com/sch/gradle/test/MainActivity.java,
/Users/sergey/dev/projects/checkstyle-test/app/build/generated/source/r/debug/android/support/coreutils/R.java,
/Users/sergey/dev/projects/checkstyle-test/app/build/generated/source/r/debug/android/support/v7/appcompat/R.java,
...

This is because regex-based matching is done on the relative path, i.e. the path following the root directory of each tree. generated/source is part of that root directory and thus not available for matching. Changing this would be a major breaking change.

However, you can also do programatic matching and inspect any detail of the tree element you want, e.g. the absolute path.

exclude { element -> element.file.path.contains('generated/source' ) }

@oehme thanks for the workaround though it doesn't seem to work for the checkstyle task:

Cannot add include/exclude specs to Ant node. Only include/exclude patterns are currently supported.

Does this mean there is currently no way to exclude the whole generated/source subtree from the checkstyle?

You're right. Whenever we invoke Ant we can't use spec-based tree filtering. A better solution would be calling Checkstyle directly without Ant in the middle. Until we have that, let me try finding a workaround for you:

What you can try is using the filter {} method instead which will basically turn the tree into a flat list of files. This may make Checkstyle slower depending on how well it handles lots of individual input files vs. a single input tree. But it's definitely worth a try:

source variant.javaCompile.source.filter { file -> file.path... }

Files can be filtered out based on absolute paths in checkstyle.xml configuration.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
    "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
    "https://checkstyle.org/dtds/configuration_1_3.dtd">

<module name="Checker">
  <module name="BeforeExecutionExclusionFileFilter">
    <property name="fileNamePattern" value="/generated/source/"/>
  </module>
</module>

Then you can configure checkstyle plugin in gradle to use your checkstyle.xml file. You can configure it to fetch checkstyle.xml from url:

checkstyle {
  toolVersion = "8.30"
  config = resources.text.fromUri("https://<your page>/checkstyle.xml")
}

Or you can use file:

resources.text.fromFile("checkstyle.xml")
commented

This issue has been automatically marked as stale because it has not had recent activity. Given the limited bandwidth of the team, it will be automatically closed if no further activity occurs. If you're interested in how we try to keep the backlog in a healthy state, please read our blog post on how we refine our backlog. If you feel this is something you could contribute, please have a look at our Contributor Guide. Thank you for your contribution.

commented

This issue has been automatically closed due to inactivity. If you can reproduce this on a recent version of Gradle or if you have a good use case for this feature, please feel free to reopen the issue with steps to reproduce, a quick explanation of your use case or a high-quality pull request.