JDK-8208609 : Update --module-source-path to allow explicit source paths for specific modules
  • Type: CSR
  • Component: tools
  • Sub-Component: javac
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 12
  • Submitted: 2018-07-31
  • Updated: 2020-05-25
  • Resolved: 2018-08-30
Related Reports
CSR :  
Relates :  
Description
Summary
-------

Update the `--module-source-path` option in javac and javadoc to support an additional form 
that allows a user to specify an arbitrary explicit source path for a module.

Problem
-------

The current form of the `--module-source-path` option was designed at a time
when the design idiom was to provide a single non-repeatable option that described 
the paths for all modules together.  In addition, the module source path needs to 
provide so-called "leaky" semantics (i.e. standard classpath semantics) for the file 
system components that provide the source for any one individual module, while providing the
appropriate strong encapsulation between modules. As a result, the current form
of the value for the `--module-source-path` option is a rudimentary pattern, that
is based on the assumption that for any file system component that contains source 
code for a module, the file path for that component contains a directory named for
the module.

While that assumption is often true, and can be made true for any new software,
there are some important use-cases where it may not be true: these cases typically
involving existing code whose project layout does not have the requisite property.  

There is currently no way to support such cases from the command-line, although
such cases can be supported when using the `javax.tools` API. (See JDK-8173914)

It would be good to support such cases. 

Users may also find it preferable to provide an explicit path for each module in any
compilation, instead of using the existing pattern-based form.


Solution
--------

Leverage the syntax designed for the `--patch-module` option, which went through
a similar design evolution. That form is sufficiently distinct from the form of the 
existing `--module-source-path` option that it can be supported as an addition to
the existing form, instead of a replacement.

It is sufficient to change the support in javac; javadoc simply delegates any analysis
of the `--module-source-path` option to an internal copy of javac.


Specification
-------------

A new term, the _module-pattern form_ is introduced, to described the existing form
of the `--module_source-path` option (see _The Module-Pattern Form_, below).

A new form, called the _module-specific form_ is introduced, to allow an explicit
search path to be given for any specific module. This form is:

*  _module-name_  `=`  _file-path_  ( _path-separator_  _file-path_ )*

For reference, this is the same form currently used for the `--patch-module` option.

Multiple instances of the `--module-source-path` option may be given, each one using
either the module-pattern form or the module-specific form, subject to the following
limitations:

* the module-pattern form may be used at most once
* the module-specific form may be used at most once for any given module

If the module-specific form is used for any module, the associated search path
overrides any path that might otherwise have been inferred from the module-pattern form.

The module-specific form is just provided as a way to provide a source path for
a specific module. There is no change to the way that the module source path
for any and all modules is interpreted by the module system.

The module-specific form is recommended for use when it is convenient to do so,
and especially when only a few modules are involved.

### Compatibility

The module-pattern form is a series of items separated by the path separator character.
Each item consists of an initial file path, optionally followed by a `*` (representing the module name), 
optionally followed by an additional relative file path, for use when the package root
for the module source code is not an immediate subdirectory of the module-named
directory.  There are additional rules permitting the use of braces (`{` `}`) to allow a 
more concise representation when separate items have a lot of text in common.
For the purposes of this specification, it is sufficient to note that the items in the
module-pattern form of the `--module-source-path` option all begin with an initial file path.

In contrast, the module-specific form always begins "_module-name_`=`", where the 
_module-name_ is a dotted identifier.  It is highly unlikely that any existing module-pattern
form would begin with a dotted identifier followed by `=`, and so a simple lexical
check can be used to disambiguate the two forms.  In the unlikely event that an existing
usage should begin with "_dotted-identifier_`=`", it can trivially adjusted by prefixing it
with `./` or `.\` depending on the file separator character for the platform. 

### The Module-Pattern Form

The module-pattern form was introduced in JDK-8142968, but was not formally defined there.

The module-pattern form is defined by the following rules, which are applied in order:

1.  The argument is considered to be a series of segments 
    separated by the path separator character (`;` on Windows, 
    and `:` otherwise).

2.  Each segment containing curly braces of the form

    _string1_ `{` _alt1_ ( `,` _alt2_ )* } _string2_

    is considered to be replaced by a series of segments
    formed by "expanding" the braces:
    
    _string1_  _alt1_  _string2_  
    _string1_  _alt2_  _string2_  
    _etc_ 

    The braces may be nested.
    
    This rule is applied for all such usages of braces.

3.  Each segment must have at most one asterisk (`*`). 
    If a segment does not contain an asterisk, it is considered
    to be as though the file separator character and an asterisk
    are appended.

4.  For any module _M_, the source path for that module is
    formed from the series of segments obtained by substituting
    the module name _M_ for the asterisk in each segment.
Comments
Thanks for the information and heads-up, Jonathan. For my build tool, I tend to stick to use solely the CLI/ToolProvider SPI for the time being. I.e. projects with a pattern-form incompatible directory layout that want to target Java 11 at runtime would be required to use JDK 12+ and the `--release 11` option.
25-05-2020

> Suggest the Jigsaw team consider backporting this functionality to the 11 update train. I second this suggestion -- as current and future build tools could make good use it. Background: I'm writing such a build tool [Bach.java] and want to support well-known directory tree structure out of the box, meaning user shouldn't be forced to move their existing source files into a structure that matches the rules of pattern form described above. Seeing this feature in javac/javadoc 11 could help to migrate more projects to the modular world. Or at least make exploring the modular world easier on existing code bases. [Bach.java]: https://github.com/sormuras/bach
25-05-2020

[~cstein] If you can use the JavaCompiler API in your build tool, the functionality is already available there, by setting the Location for each module in the file manager. I know the API is not the command line, but nevertheless, the underlying functionality is available.
24-05-2020

After chatting with Jon, voting to Approve. Suggest the Jigsaw team consider backporting this functionality to the 11 update train.
30-08-2018