Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "JDT Core Programmer Guide/ECJ/Lookups"

(Scopes)
(ModuleBinding: package lookup through a module)
Line 28: Line 28:
 
Since Java 9 also module bindings act as lookups.
 
Since Java 9 also module bindings act as lookups.
  
 +
The current design has been developed in {{bug|547181}}:
  
''TBC''
+
===Declared Packages===
 +
Each module binding stores a flat map of <code>declaredPackages</code>.
 +
* This map is indexed by '''qualified names'''
 +
* Values in this map are <code>PlainPackageBinding</code>
 +
 
 +
The map represents exactly those packages that are declared in this module. It does not take into account possible name clashes with packages declared in another module (<code>SplitPackageBinding</code>, see below).
 +
 
 +
:'''NB:''' ''Much of the complexity of package lookup is necessary to ''admit'' and ''distinguish'' same-named packages in different modules. Interestingly, the JVM will not be able to handle such programs unless a custom <code>Layer</code> implementation is provided.''
 +
 
 +
During compilation, the map <code>declaredPackages</code> is ''eagerly'' filled with all packages mentioned in '''exports''' and '''opens''' directives. This is done as to avoid re-entrant package lookup as we observed before {{bug|547181}} due to crazy traversal of the module graph etc. For automatic modules, which have no such declarations, the structure is filled using a lazy, one-time scan using <code>IModuleAwareNameEnvironment.listPackages()</code>.
 +
 
 +
For explicit modules additional (non-exported) packages may be added lazily, but those have no impact on resolving of references outside this module.
 +
 
 +
===Visible and Accessible Packages===
 +
Additionally, two methods of name <code>getVisiblePackage</code> exist, which will search the current module and all other modules read by it. If more than one visible module declares the requested package, the result will be represented as a <code>SplitPackageBinding</code>. JLS distinguishes visibility and accessibility. The former is defined just by the module graph, whereas the latter, stronger form also takes '''exports''' declarations into account. To query accessibility, the method <code>canAccess(PackageBinding)</code> can be used.
  
 
==PackageBinding==
 
==PackageBinding==

Revision as of 16:59, 1 March 2021

Note.png
During name resolving, several structures are used to identify the binding referenced by a given name.


LookupEnvironment

The central place where the following bindings are globally stored:

  • ModuleBinding (knownModules)
  • PackageBinding (knownPackages, recursively)
    • TypeBinding (knownTypes)

Since Java 9, however, different instances of LookupEnvironment are used, to implement the perspective of one module each. In this situation

  • the root lookup environment represents the unnamed module
  • module-specific lookup environments are found via the environment field of elements of knownModules
  • each lookup environment has a back link root to the root environment
  • fields of LookupEnvironment that are not module specific are documented as either ROOT_ONLY or SHARED (see javadoc of LookupEnvironment#root).

Other "singletons"

The root lookup environment also links a few unique instances:

  • globalOptions : all compiler options in effect
  • nameEnvironment : sometimes called the oracle, since it's an external/opaque entity that can answer sought types and packages.
  • typeRequestor : callback for newly discovered types
  • typeSystem : manages variants of known type bindings (parameterizations, arrays, annotations)
  • verifier :
  • problemReporter : a fall-back problem reporter, which is used for reporting errors that cannot be associated to a particular AST node.
  • classFilePool :

TBC

ModuleBinding

Since Java 9 also module bindings act as lookups.

The current design has been developed in bug 547181:

Declared Packages

Each module binding stores a flat map of declaredPackages.

  • This map is indexed by qualified names
  • Values in this map are PlainPackageBinding

The map represents exactly those packages that are declared in this module. It does not take into account possible name clashes with packages declared in another module (SplitPackageBinding, see below).

NB: Much of the complexity of package lookup is necessary to admit and distinguish same-named packages in different modules. Interestingly, the JVM will not be able to handle such programs unless a custom Layer implementation is provided.

During compilation, the map declaredPackages is eagerly filled with all packages mentioned in exports and opens directives. This is done as to avoid re-entrant package lookup as we observed before bug 547181 due to crazy traversal of the module graph etc. For automatic modules, which have no such declarations, the structure is filled using a lazy, one-time scan using IModuleAwareNameEnvironment.listPackages().

For explicit modules additional (non-exported) packages may be added lazily, but those have no impact on resolving of references outside this module.

Visible and Accessible Packages

Additionally, two methods of name getVisiblePackage exist, which will search the current module and all other modules read by it. If more than one visible module declares the requested package, the result will be represented as a SplitPackageBinding. JLS distinguishes visibility and accessibility. The former is defined just by the module graph, whereas the latter, stronger form also takes exports declarations into account. To query accessibility, the method canAccess(PackageBinding) can be used.

PackageBinding

TBC


Scopes

In addition to the global lookup (which serves source and binary elements), the following AST nodes have their dedicated Scope which performs the initial, location-aware part of name lookup:

  • CompilationUnitDeclaration -> CompilationUnitScope
  • ModuleDeclaration -> ModuleScope
  • TypeDeclaration -> ClassScope
  • AbstractMethodDeclaration -> MethodScope
  • Block -> BlockScope (also used by block-like nodes like ForeachStatement)

A TypeDeclaration may hold additional scopes initializerScope and staticInitializerScope for resolving field initializers (implementation uses MethodScope also here).

Each scope has a parent link to support inside-out searches during resolution. TBC

Back to the top