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.buck...@oracle.com
<mailto:alex.buck...@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



Reply via email to