Codenarc unable to resolve groovy classes - gradle

I am using codenarc 1.4 with gradle to test groovy code in a Jenkins shared library, but when running it outputs errors saying it was unable to resolve groovy.lang.Closure though this doesn't seem to prevent the checks being run.
An example of the code that's hitting the problem is
interface IStepExecutor {
int sh(String command)
void dir(String path, Closure commands)
...
when codenarc is run the following error is produced:
file:/.../IStepExecutor.groovy: 8: unable to resolve class Closure
# line 8, column 27.
void dir(String path, Closure commands)
^
The codenarc parts of my gradle config is as follows:
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.5.7'
testCompile "org.spockframework:spock-core:1.3-groovy-2.5"
}
codenarc {
toolVersion = "1.4"
}
codenarcMain {
configFile = file("config/codenarc/CodeNarcMain.groovy")
source = 'src'
compilationClasspath += files('src/')
}
codenarcTest {
configFile = file("config/codenarc/CodeNarcMain.groovy")
source = 'src'
compilationClasspath += files('src/')
}
I can stop the error messages by adding an import groovy.lang.Closure but that causes the UnnecessaryGroovyImport rule to error. Is there a way to prevent these errors being reported without removing the UnnecessaryGroovyImport rule?

I'm also using CodeNarc with Gradle for Jenkins shared library tests and found adding the following to my Gradle configuration fixed a similar issue:
codenarcMain {
compilationClasspath = sourceSets.main.compileClasspath + sourceSets.main.output
}
codenarcTest {
compilationClasspath = codenarcMain.compilationClasspath + sourceSets.test.compileClasspath + sourceSets.test.output
}
I found this in a comment on a CodeNarc issue on GitHub.
I think the problem is something to do with each file being compiled in isolation for static analysis which is different from the normal compilation steps in Gradle. I'm very new to this though so maybe misunderstanding it.

Related

gradle protobuf plugin not functioning

I am using the below mentioned protobuf gradle plugin in one project where its working fine but when I referenced the same plugin in a different project, 'gradle clean' is consistently giving me the error copied below:
relevant parts of build.grade (v3.4)
apply plugin: 'com.google.protobuf'
buildscript {
repositories {
mavenCentral()
mavenLocal()
jcenter()
}
dependencies {
// classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.9"
// classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.4'
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0'
}
}
def grpcVersion = '1.1.2'
dependencies {
compile "io.grpc:grpc-netty:${grpcVersion}"
compile "io.grpc:grpc-protobuf:${grpcVersion}"
compile "io.grpc:grpc-stub:${grpcVersion}"
}
protobuf {
protoc {
Artifact = 'com.google.protobuf:protoc:3.2.0'
}
plugins {
grpc {
Artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
}
}
generateProtoTasks {
all()*.plugins {
grpc {
// To generate deprecated interfaces and static bindService method,
// turn the enable_deprecated option to true below:
option 'enable_deprecated=false'
}
}
}
}
error when I run gradle clean
* What went wrong:
Could not compile build file '/xyz/xyz/build.gradle'.
> startup failed:
build file '/xyz/xyz/build.gradle': 102: you tried to assign a value to the class 'org.gradle.api.component.Artifact'
# line 102, column 9.
Artifact = 'com.google.protobuf:protoc:3.2.0'
^
build file '/xyz/xyz/build.gradle': 106: you tried to assign a value to the class 'org.gradle.api.component.Artifact'
# line 106, column 13.
Artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
I have tried protobuf plugins 0.8.0. and 0.8.1 but both give the same error. v0.8.0 works as is in a different project. Any thoughts on how to troubleshoot this further would be appreciated.
It should be artifact, not Artifact. The latter is a class that you try to assign to which will not work, the former is a property you assign to.

How to run JBoss TattleTale from inside Gradle build

I am in love with JBoss TattleTale. Typically, in my Ant builds, I follow the docs to define the Tattletale tasks and then run them like so:
<taskdef name="report"
classname="org.jboss.tattletale.ant.ReportTask"
classpathref="tattletale.lib.path.id"/>
...
<tattletale:report source="${src.dir]" destination="${dest.dir}"/>
I am now converting my builds over to Gradle and am struggling to figure out how to get Tattletale running in Gradle. There doesn't appear to be a Gradle-Tattletale plugin, and I'm not experienced enough with Gradle to contribute one. But I also know that Gradle can run any Ant plugin and can also executing stuff from the system shell; I'm just not sure how to do this in Gradle because there aren't any docs on this (yet).
So I ask: How do I run the Tattletale ReportTask from inside a Gradle build?
Update
Here is what the Gradle/Ant docs show as an example:
task loadfile << {
def files = file('../antLoadfileResources').listFiles().sort()
files.each { File file ->
if (file.isFile()) {
ant.loadfile(srcFile: file, property: file.name)
println " *** $file.name ***"
println "${ant.properties[file.name]}"
}
}
}
However, no where in here do I see how/where to customize this for Tattletale and its ReportTask.
The following is adapted from https://github.com/roguePanda/tycho-gen/blob/master/build.gradle
It bypasses ant and directly invokes the Tattletale Java class.
It was changed to process a WAR, and mandates a newer javassist in order to handle Java 8 features such as lambdas.
configurations {
tattletale
}
configurations.tattletale {
resolutionStrategy {
force 'org.javassist:javassist:3.20.0-GA'
}
}
dependencies {
// other dependencies here...
tattletale "org.jboss.tattletale:tattletale:1.2.0.Beta2"
}
task createTattletaleProperties {
ext.props = [reports:"*", enableDot:"true"]
ext.destFile = new File(buildDir, "tattletale.properties")
inputs.properties props
outputs.file destFile
doLast {
def properties = new Properties()
properties.putAll(props)
destFile.withOutputStream { os ->
properties.store(os, null)
}
}
}
task tattletale(type: JavaExec, dependsOn: [createTattletaleProperties, war]) {
ext.outputDir = new File(buildDir, "reports/tattletale")
outputs.dir outputDir
inputs.files configurations.runtime.files
inputs.file war.archivePath
doFirst {
outputDir.mkdirs()
}
main = "org.jboss.tattletale.Main"
classpath = configurations.tattletale
systemProperties "jboss-tattletale.properties": createTattletaleProperties.destFile
args([configurations.runtime.files, war.archivePath].flatten().join("#"))
args outputDir
}
The previous answers either are incomplete or excessively complicated. What I did was use the ant task from gradle which works fine. Let's assume your tattletale jars are beneath rootDir/tools/...
ant.taskdef(name: "tattleTaleTask", classname: "org.jboss.tattletale.ant.ReportTask", classpath: "${rootDir}/tools/tattletale-1.1.2.Final/tattletale-ant.jar:${rootDir}/tools/tattletale-1.1.2.Final/tattletale.jar:${rootDir}/tools/tattletale-1.1.2.Final/javassist.jar")
sources = "./src:./src2:./etcetera"
ant.tattleTaleTask(
source: sources,
destination: "tattleTaleReport",
classloader: "org.jboss.tattletale.reporting.classloader.NoopClassLoaderStructure",
profiles: "java5, java6",
reports: "*",
excludes: "notthisjar.jar,notthisjareither.jar,etcetera.jar"
){
}
So the above code will generate the report beneath ./tattleTaleReport. It's that simple. The annoyance is that the source variable only accepts directories so if there are jars present in those directories you do not wish to scan you need to add them to the excludes parameter.

Why my dependency is printed twice?

I have the following fairly simple build.gradle build script:
repositories {
mavenCentral()
}
configurations { libs }
dependencies {
libs 'org.hibernate:hibernate-core:4.3.5.Final'
}
configurations.libs.files { println it }
When I run it with gradlew build (I'm using Gradle 1.12, latest at the moment) I get the following:
DefaultExternalModuleDependency{group='org.hibernate', name='hibernate-core', version='4.3.5.Final', configuration='default'}
DefaultExternalModuleDependency{group='org.hibernate', name='hibernate-core', version='4.3.5.Final', configuration='default'}
These seem to be the same dependencies, but I don't get it why there are 2 of them when I have added just a single one.
Does anyone know why? Did I do something wrong? Or is there something I don't understand?
The Configuration#files method expects a predicate. (For API details, see Configuration in the Gradle Build Language Reference.) If you instead pass it a closure containing a println statement, (seemingly) strange things will happen. You probably want something like the following instead:
// configurations should only be resolved in
// the execution phase, so let's declare a task
task printLibs {
doLast {
configurations.libs.each { println it }
}
}

Add source file extension in gradle

I am trying to tell gradle that files with the *.dsl extension should be compiled as groovy files, so I have added a source set with the inclusion pattern and changed the compile task includes property:
sourceSets {
...
dsl_scripts {
groovy {
include '**/*.dsl'
}
}
}
compileDsl_scriptsGroovy.includes = ['**/*.dsl']
But when I run the build under a debug mode it skips all *.dsl files with the following message:
Skipping task ':compileDsl_scriptsGroovy' as it has no source files
The following line successfully outputs all the files I try to compile:
println sourceSets.dsl_scripts.allSource.matching({include '**/*.dsl'}).getFiles()
What do I do wrong?
EDIT:
I found the following snippet in gradle sources:
FileCollection groovyJavaOnly = spec.getSource().filter(new Spec<File>() {
public boolean isSatisfiedBy(File element) {
return element.getName().endsWith(".groovy") || element.getName().endsWith(".java");
}
});
spec.setSource(new SimpleFileCollection(groovyJavaOnly.getFiles()));
Is it possible to override?
It seems to be a gradle bug http://issues.gradle.org/browse/GRADLE-2372

gradle checkstyle error:Expected file collection to contain exactly one file, however, it contains 14 files

I am using Java 8 with Gradle and trying to add the Google checkstyle rules into the build, but what I get is this error:
"Expected file collection to contain exactly one file, however, it contains 14 files."
My configuration is:
apply plugin: 'checkstyle'
configurations {
checkstyleConfig
}
def versions = [
checkstyle: '8.8',
]
dependencies {
checkstyleConfig "com.puppycrawl.tools:checkstyle:${versions.checkstyle}"
}
checkstyle {
toolVersion = "${versions.checkstyle}"
config = resources.text.fromArchiveEntry(configurations.checkstyleConfig, 'google_checks.xml')
}
The issue here is that configurations.checkstyleConfig includes multiple JAR files: com.puppycrawl.tools:checkstyle, as well as all of its transitive dependencies. Debugging the issue locally, I see that these dependencies are being included:
antlr:antlr:2.7.7
com.google.code.findbugs:jsr305:1.3.9
com.google.errorprone:error_prone_annotations:2.1.3
com.google.guava:guava:23.6-jre
com.google.j2objc:j2objc-annotations:1.1
com.puppycrawl.tools:checkstyle:8.8
commons-beanutils:commons-beanutils:1.9.3
commons-cli:commons-cli:1.4
commons-collections:commons-collections:3.2.2
commons-logging:commons-logging:1.2
net.sf.saxon:Saxon-HE:9.8.0-7
org.antlr:antlr4-runtime:4.7.1
org.checkerframework:checker-compat-qual:2.0.0
org.codehaus.mojo:animal-sniffer-annotations:1.14
The fix for this is fortunately very simple. All you need to do is exclude the transitive dependencies from the Checkstyle dependency, and the rest of your script will work the way you want it to:
dependencies {
checkstyleConfig("com.puppycrawl.tools:checkstyle:${versions.checkstyle}") { transitive = false }
}
btw, for future reference, there's no need to add a new configuration to use this, it's just a matter of filtering the checkstyle dependency from the existing configuration used by the plgin.
This is the config I use:
checkstyle {
config = resources.text.fromArchiveEntry(
configurations.checkstyle.find { it.name.contains('checkstyle') },
'google_checks.xml'
)
}
For anyone interested, this is the Kotlin DSL variant of the config from #thiago answer:
checkstyle {
config = resources.text.fromArchiveEntry(
configurations.checkstyle.get().find { it.name.contains("checkstyle") }!!,
"google_checks.xml"
)
}

Resources