Where do empty compilation units belong?

Jonathan Gibbons jonathan.gibbons at oracle.com
Mon Nov 26 23:22:53 UTC 2018



On 11/26/2018 01:44 PM, Alex Buckley wrote:
> // Adding compiler-dev since the parsing of files into compilation 
> units is not a Jigsaw issue.
>
> On 11/20/2018 9:14 PM, Jayaprakash Artanareeswaran wrote:
>> "jigsaw-dev" <jigsaw-dev-bounces at openjdk.java.net> wrote on 21/11/2018
>> 01:56:42 AM:
>>  > Jon points out that `OrdinaryCompilationUnit` will match an empty 
>> stream
>>  > of tokens (I dislike the syntax-driven optionality here, but it's
>>  > longstanding) so the file D.java could be regarded as a 
>> compilation unit
>>  > with no package declaration, no import declarations, and no type
>>  > declarations.
>>  >
>>  > Per JLS 7.4.2, such a compilation unit is in an unnamed package, and
>>  > must be associated with an unnamed module.
>>  >
>>  > I would prefer 7.4.2 to say only that a compilation unit with no 
>> package
>>  > declarations _and at least one type declaration_ is in an unnamed
>>  > package (and must be associated with an unnamed module; 7.3 should
>>  > enumerate that possibility). A compilation unit with no package
>>  > declarations _and no type declarations_ would be deemed 
>> unobservable by
>>  > 7.3, and all these questions about what to do with empty files would
>>  > disappear.
>>
>> That would be perfect and make things unambiguous. But for now, the
>> paragraph above is good enough for me.
>
> Unfortunately, import declarations can have side effects (compile-time 
> errors) so to be sure that the "no package or type decl === 
> unobservable" rule is suitable for a file containing just an import 
> decl, we would have to do a case analysis of how javac and ecj handle 
> the eight combinations of the three parts allowed in an ordinary 
> compilation unit. That's overkill for the situation involving empty 
> files that keeps coming up and that I really want to clarify. I don't 
> think anyone loves that an ordinary compilation unit matches the empty 
> stream, so let's define away that scenario. As Jon said, an empty file 
> doesn't present anything to be checked; there is no compilation unit 
> there, so let's be unambiguous about that.
>
> We can rule out the empty stream in 7.3 with grammar or with 
> semantics. Usually a semantic description is clearest (gives everyone 
> the proper terminology and concepts) but in this case we don't want 
> the description to wrestle with "consists of one, two, or three parts" 
> when the grammar allows zero. So, a new grammatical description is 
> appropriate, and straightforward:
>
>   OrdinaryCompilationUnit:
>     PackageDeclaration {ImportDeclaration} {TypeDeclaration}
>     ImportDeclaration {ImportDeclaration} {TypeDeclaration}
>     TypeDeclaration {TypeDeclaration}
>
> The "three parts, each of which is optional" description is still 
> accurate. The package decl part is optional (as long as you have the 
> import decls part and/or the type decls part); the import decls part 
> is optional (as long as you have either the package decl part or ...) 
> ... you get the picture.
>
> I would leave 7.4.2 alone; an ordinary compilation unit with no 
> package or type decls but with import decls is part of the unnamed 
> package (and thus unnamed module) as before, and compilers can handle 
> that, I think.
>
> Any comments?
>
> Alex

That seems good to me.

To summarize the javac behavior ...

  * javac accepts/ignores an empty file
  * javac treats import-only compilation units as in the unnamed
    package, which is not allowed in a named module
  * javac enforces file naming constraints when declaring a public class
  * javac uses file naming constraints when looking on the (module)
    source path for a file for a class


Attached is a toy class to generate combinations of package, import and 
type declarations. You can use the source-launcher feature to run it.

-- Jon



More information about the jigsaw-dev mailing list