Antlr plugin should preserve package structure

The simplest antlr build seems to always place generated code at the base of build/generated-src/antlr/main/. This causes java errors if a package was defined in the .g files, like this:

@header {
package com.example.foo.antlr;
}

I realize it might be difficult for the Antlr plugin to be aware of that package information, but an alternate solution would be to mirror the source folder structure like resources do:

Thus this .g file:
src/main/antlr/com/example/foo/antlr/Foo.g

Should have generated code placed under a similar package structure:
build/generated-src/antlr/main/com/example/foo/antlr/Foo.java

(I should mention that simply specifying the outputDirectory does not work in the case of multiple .g files with different packages)

I second this.

And what’s worse is that this seems to be a regression. I believe that this used to work in versions of Gradle prior to 2.3/2.4 when the Antlr plugin was significantly changed.

For additional information… putting the grammar file in the proper “package directory structure”… the plugin does find the grammar files, but it flattens the output back out into a root directory rather than honoring the “package directory structure”.

Interestingly (not sure how) compiling the generated sources works out ok. Using Henry’s example…

  1. Foo.g declares package com.example.foo.antlr;
  2. No matter where that file exists under src/main/antlr it is found, but the generated sources end up in ${buildDir}/generated-src/antlr/main rather than in ${buildDir}/generated-src/antlr/main/com/example/foo/antlr
  3. On compile, somehow, the right thing does happen. Not only are the classes compiled, but somehow they get put into ${buildDir}/classes/main/com/example/foo/antlr

The Hibernate build[1] illustrates this if you need a way to reproduce. Hibernate is using Antlr 2, while it would appear that Henry is using Antlr 3 or 4. So that may be a difference too.

Ultimately the issue is in IDEs. If you import the Hibernate project into your IDE it (properly) shows ${buildDir}/generated-src/antlr/main as a source directory, however it shows it being incorrect since the sources are not in their proper directories according to their package statements.

I find it fascinating that the compiled classes end up in the proper directory. I am almost positive javac is not doing that.

[1] http://github.com/hibernate/hibernate-orm

Hey there,

I’m trying to reproduce this and figuring out what’s going on here. thanks for reporting!

Hey there,
this is indeed a regression. At least for Antlr2 the fix seems easy. I created GRADLE-3323 for this.

Please note that even though Gradle is able to compile the generated source files (even though they are not placed in correct folder structure), other tools may not. I had to manually correct the folder structure, because IntelliJ Idea refused to “make” my Gradle project using Antlr 4. Therefore I hope this bug will be fixed also for Antlr 4.

It would be nice if Gradle’s Antlr plugin guessed “package” parameter value from the location of the grammar file, without needing to set “@header” inside the grammar file itself. This is how Maven’s Antlr4 plugin works - you just put your .g file to src/main/antlr4/your/package/ and generated .java files land in your/package/ folder.

The -package parameter works, one has to copy the generated code after.

generateGrammarSource {
  arguments += ["-package", "target.package"]
  
  doLast {
    copy {
      from 'build/generated-src/antlr/main/'
      include '*.*'
      into 'build/generated-src/antlr/main/target/package'
    }
    project.delete fileTree('build/generated-src/antlr/main').include('*.*')
  }
}

This has been fixed in gradle-2.7-rc-1. Please try it out and let us know how it works for you.

Thanks! Works for me.

I have to add

arguments += ["-package", "target.package"]

though, otherwise the files end up in the right folder but the package declaration is missing.

This is normal antlr behaviour as much as I remember so I’d say it’s the proper way to do but might be nice to have a comment on this in the docs.

@creichlin Are you using ANTLR4? Do your grammar files have a

@header {
 package target.package;
} 

in them?

@sterling, Yes and no, thanks for the tip.