Package, import and type declarations are allowed now in module-info.java by spec
Alex Buckley
alex.buckley at oracle.com
Mon Mar 14 22:21:14 UTC 2016
The JLS doesn't know what the string "module-info.class" means or what a
"JAR root" is. It only knows about Unicode input matching the
CompilationUnit production. Nothing is mandated about the filesystem
layout of files containing CompilationUnit productions that include a
PackageDeclaration. For clarity, we could extend 7.6's compiler guidance
to cover a file called module-info.java, but technically the guidance is
already broad enough to allow a compiler to "do the right thing".
Alex
On 3/14/2016 9:08 AM, Paul Benedict wrote:
> Alex, you wrote: "The JLS doesn't prevent javac from rejecting a package
> declaration or an import declaration in a file called module-info.java."
>
> It seems that a package declaration, in this context, should be
> prohibited syntax because module-info.class is always in the JAR root
> which has no package.
>
> Cheers,
> Paul
>
> On Wed, Mar 9, 2016 at 4:02 PM, Alex Buckley <alex.buckley at oracle.com
> <mailto:alex.buckley at oracle.com>> wrote:
>
> The JLS doesn't prevent javac from rejecting a package declaration
> or an import declaration in a file called module-info.java.
>
> In fact, since a package declaration or import declaration must be
> followed by a type declaration, and since a type declaration cannot
> use a hyphen, javac is free to take the optional rule from JLS 7.6
> -- filename must align with type declaration -- and develop it
> further: rejecting a package declaration or import declaration in
> module-info.java because the filename cannot possibly align with any
> type declaration.
>
> I can't speak to what a particular EA build of javac is doing with a
> particular option. javac options are irrelevant to the JLS. If a
> compiler accepts the Java language circa SE 9, then a module
> declaration is a valid compilation unit. What's the name of the file
> containing such a compilation unit? Anything the compiler likes.
>
> Alex
>
> On 3/9/2016 5:14 AM, Georgiy Rakov wrote:
>
> Hi Alex,
>
> if I understand correctly you mean about following assertions
> from JLS 7.6:
>
> If and only if packages are stored in a file system (§7.2
>
> <http://docs.oracle.com/javase/specs/jls/se8/html/jls-7.html#jls-7.2>),
> the host system may choose to enforce the restriction that
> it is a
> compile-time error if a type is not found in a file under a
> name
> composed of the type name plus an extension (such as |.java|or
> |.jav|) if either of the following is true:
>
> *
>
> The type is referred to by code in other compilation
> units of
> the package in which the type is declared.
>
> *
>
> The type is declared |public|(and therefore is potentially
> accessible from code in other packages).
>
> Literally these assertion doesn't make presented behavior
> corresponding
> to spec because the declared type is neither public nor being
> referred
> to from other sources being compiled.
>
> Nevertheless following sources doesn't compile either despite
> the fact
> that no types are declared there at all.
> Namely when only package is specified:
>
> mod\module-info.java:
> module mod {
> exports pkg;
> }
>
> mod\pkg\module-info.java:
> package pkg;
>
> then compiling it by following command line with javac from [2]:
>
> javac -modulesourcepath . mod\module-info.java
> mod\pkg\module-info.java
>
> causes following output:
>
> mod\pkg\module-info.java:1: error: expected 'module
> package pkg;
> ^
> 1 error
>
> When only import statment is specified:
>
> mod\module-info.java:
> module mod {
> exports pkg;
> }
>
> mod\pkg\module-info.java:
> import java.util.List;
>
> then compiling it by following command line with javac from [2]:
>
> javac -modulesourcepath . mod\module-info.java
> mod\pkg\module-info.java
>
> causes following output:
>
> mod\pkg\module-info.java:1: error: expected 'module'
> import java.util.List;
> ^
> 1 error
>
> Please see minimized test cases attached in tests23.zip. In order to
> reproduce, please:
>
> 1. Unzip the attached archive to some dir on Windows machined, say
> directory A;
> 2. Rename A\test2\test_bat to A\test2\test.bat and
> A\test3\test_bat to
> A\test3\test.bat;
> 3. Modify these two test.bat files by changing JDK_HOME variable to
> point to your jigsaw JDK 9 installation directory;
> 4. Run test.bat files in turn.
>
> BTW: javac behavior [2] currently differs depending on whether
> sources
> are compiled "in module" mode or not. By "module mode" I mean
> specifying
> modulesourcepath option. For instance without modulesourcepath
> option
> module declarations are not recognized as valid grammar while import
> declarations contained within module-info.java compile successfully.
> This can be seen by experimenting with test3 from the attached
> testcases. Now javac from [2] even can throw exception in
> "non-module"
> mode, please see https://bugs.openjdk.java.net/browse/JDK-8150733.
>
> Could you please tell if spec will specify somehow two modes of
> processing java-sources, now it [1] doesn't.
>
> [1] http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html
> [2]
> http://download.java.net/java/jigsaw/archive/106/binaries/jigsaw-jdk-9-ea+106_windows-x86_bin.zip
>
> Thanks,
> Georgiy.
>
> On 26.02.2016 21:26, Alex Buckley wrote:
>
> On 2/26/2016 8:37 AM, Georgiy Rakov wrote:
>
> current spec [1] now contains following assertions
> related to grammar:
>
> A compilation unit (JLS 7.3) may contain a module
> declaration, in
> which case the filename of the compilation unit is
> typically
> |module-info.java|.
>
> CompilationUnit:
> [PackageDeclaration] {ImportDeclaration}
> {TypeDeclaration}
> ModuleDeclaration
>
> These assertions allows to specify any of import,
> package or type
> declarations in any compilation unit, for instance
> module-info.java is
> allowed to contain any of the mentioned declarations.
> However currently
> javac in the latest jigsaw build [2] reports an error on
> such cases
> provided they are compiled in module mode. For example
> if we have
> following directory structure:
>
> mod\module-info.java:
> module mod {
> exports pkg;
> }
>
> mod\pkg\module-info.java:
> package pkg;
>
> class C {
> }
>
> then compiling it by following command line with javac
> from [2]:
>
> javac -modulesourcepath . mod\module-info.java
> mod\pkg\module-info.java
>
> causes following output:
>
> mod\pkg\module-info.java:1: error: expected 'module'
> package pkg;
> ^
> 1 error
>
>
> javac is merely choosing to implement the rule at the end of
> JLS 7.6
> that a type declaration (optionally preceded by package/import
> declarations) must be provided in a suitably named file.
>
> Perhaps I should say "a variant of the rule" because 7.6 as
> written
> concerns a public type and your example has a package-access
> type.
> Still, bottom line, javac is free to require that a
> compilation unit
> which starts with a package declaration _must not_ be in a
> file called
> foo-bar.java -- the hyphen indicates a name that can't
> possibly align
> with the type declared in the compilation unit.
>
> The error message for mod\pkg\module-info.java could be a
> bit more
> helpful, but that's a quality-of-implementation detail.
>
> Conversely, a compilation unit that contains a module
> declaration
> _may_ be in a file called module-info.java, or in a file called
> foo-bar.java, or in a file called mod_decl.JAV. The
> "typically" in [1]
> is meant to indicate that the sub-clause on filename is
> non-normative.
> This is akin to how a compilation unit that contains a
> package-access
> type declaration for class C _may_ be in a file D.java.
>
> Alex
>
>
>
More information about the jigsaw-dev
mailing list