ESC/Java2
© 2003,2004,2005 David Cok and Joseph Kiniry
© 2005 UCD Dublin
© 2003,2004 Radboud University Nijmegen
© 1999,2000 Compaq Computer Corporation
© 1997,1998,1999 Digital Equipment Corporation
All Rights Reserved

javafe.tc
Class OutsideEnv

java.lang.Object
  extended byjavafe.tc.OutsideEnv

public final class OutsideEnv
extends java.lang.Object

OutsideEnv implements the top-level environment consisting of only the package-member types.

This is the environment outside of any compilation unit (e.g., no import declarations are in effect). It is used to lookup the TypeSig for a given fully-qualified package-member name (P.T). Class-member types are obtained by using the lookup methods of the TypeSig that contains them as members.

Initialization

In order to greatly simplify the front end, there can be at most one such environment during front-end execution. All of OutsideEnv's lookup methods are accordingly static methods. OutsideEnv must be initialized before any of its lookup methods can be called.

At initialization time OutsideEnv is passed a way to determine which fully-qualified package-member-type names exist and a means to read in and parse the files of those types into CompilationUnits. This is done by passing OutsideEnv a TypeReader, which contains exactly this information.

OutsideEnv uses this information to determine which package-member types exist and to create TypeSigs for them when needed by loading their underlying TypeDecls in from the filesystem. (Each java file contains a CompilationUnit, which is a set of TypeDecls.)

Loading CompilationUnits

Loading is actually done lazily for efficiency reasons(*). When a fully-qualified package-member-type name is looked up for the first time, OutsideEnv first checks to see if it exists. If it exists, then a new unloaded TypeSig is returned. Otherwise, null is returned. Future lookups of the same name return the same result, except that for a local package-member-type (see next section), a null result may change to a non-null result.

Only when the new TypeSig's TypeDecl is touched (via TypeSig.getTypeDecl()) for the first time does OutsideEnv load in the CompilationUnit that should contain that type. Errors may be reported via ErrorSet at this time (e.g., I/O error, syntax error, file fails to contain the type, etc.). This loading is otherwise transparent to the users of TypeSig. An special version of lookup is available that defers testing for type existence until loading time; this is useful for dealing with types that are required to exist by the Java language specification.

(*) - Exception: if eagerRead is set (not the default), all loading is done non-lazily.

The avoidSpec flag is used when CompilationUnits are read in to determine if a spec or a non-spec should be read. (Note that non-specs are not always available.)

When CompilationUnits are loaded in, TypeSigs are automatically created for each of their TypeDecls (including recursively).

Local package-member types

A package-member type named T that is contained in a file V.java, T != V, is called a local package-member type. Such types are accessible only from within in the same file. OutsideEnv handles such types as follows:

The existence of local package-member types opens up the possibility of duplicate package-member-type definitions. Should OutsideEnv load two different package-member types with the same name, a fatal error will be reported via ErrorSet. Because files are loaded lazily, some duplicate type errors may not be detected.

Additional source files

A client of OutsideEnv may add additional package-member types to those defined by the information provided at initialization time by using the method addSource. addSource is called with a source file; it attempts to load the CompilationUnit contained in that file. If successful, it adds the package-member types contained in that file to the package-member-type environment and returns the loaded CompilationUnit to the caller.

addSource(GenericFile) is intended primarily for use in handling source files given to a tool as command-line arguments. It can be called only before the first lookup is done. The filenames of the source files passed to addSource are ignored.

Notification

Whenever OutsideEnv successfully loads a CompilationUnit, it notifies the current Listener, if any. Only one Listener at a time is currently supported; setListener(javafe.tc.Listener) is used to set the current Listener.

Because this notification is "asynchronous" (it can occur in the middle of any code that touches a TypeSig's TypeDecl), it is strongly recommended that Listeners take no action other then storing information for later use.

Implementation

Note that the implementation of the functionality described here is spread between this class and that of TypeSig.

See Also:
TypeSig, TypeReader, CompilationUnit, Listener

Field Summary
static boolean avoidSpec
          When we load in types, do we prefer to read specs or non-specs?
static boolean eagerRead
          If true, files are read eagerly, as soon as we look them up.
private static int filesRead
          Count of files read so far.
private static Listener listener
          The Listener to notify when a CompilationUnit is loaded.
static TypeReader reader
          The TypeReader for our underlying Java file space.
 
Constructor Summary
private OutsideEnv()
           
 
Method Summary
static CompilationUnit addSource(GenericFile source)
          Attempt to add the package-member types contained in a source file to the package-member-types environment, returning the CompilationUnit, if any, found in that file.
static CompilationUnit addSource(java.lang.String sourceName)
          Attempt to add the package-member types contained in a named source file to the package-member-types environment, returning the CompilationUnit, if any, found in that file.
static java.util.ArrayList addSources(java.util.ArrayList sources)
          Adds all relevant files from the given package; 'relevant' is defined by the 'findFiles' method of the current reader.
static void clear()
           
private static void describeLookup(java.lang.String N)
          Call lookup on N then describe the results.
static int filesRead()
          Return count of files read so far.
static void init(TypeReader R)
          Initialize ourselves to use TypeReader R for our underlying Java file space.
(package private) static void load(TypeSig sig)
          Attempt to load the TypeDecl of TypeSig sig.
static TypeSig lookup(java.lang.String[] P, java.lang.String T)
          Get the TypeSig for fully-qualified package-member name P.T.
static TypeSig lookupDeferred(java.lang.String[] P, java.lang.String T)
          Like lookup except that checking the existence of the type is deferred until it's TypeDecl is touched for the first time.
static void main(java.lang.String[] args)
          A debugging harness that allows describing the results of calling lookup on a series of package-member-type names.
private static void notify(CompilationUnit justLoaded)
          Send a CompilationUnit-loaded notification event to the current Listener (if any).
static java.util.ArrayList resolveDirSources(java.lang.String dirname)
           
static java.util.ArrayList resolveSources(java.lang.String[] pname)
           
static void setListener(Listener l)
          Set the Listener to be notified about CompilationUnit loading.
private static void setSigs(CompilationUnit cu)
          This routine creates TypeSigs for each TypeDecl member of cu.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

reader

public static TypeReader reader
The TypeReader for our underlying Java file space.


avoidSpec

public static boolean avoidSpec
When we load in types, do we prefer to read specs or non-specs? Defaults to preferring non-specs.


eagerRead

public static boolean eagerRead
If true, files are read eagerly, as soon as we look them up. Defaults to false.


filesRead

private static int filesRead
Count of files read so far.


listener

private static Listener listener
The Listener to notify when a CompilationUnit is loaded. May be null if there is no current Listener (the initial state).

Constructor Detail

OutsideEnv

private OutsideEnv()
Method Detail

filesRead

public static int filesRead()
Return count of files read so far.


init

public static void init(TypeReader R)
Initialize ourselves to use TypeReader R for our underlying Java file space.

Requires:
R is not null, no init method for this class has previously been called.

clear

public static void clear()

lookup

public static TypeSig lookup(java.lang.String[] P,
                             java.lang.String T)
Get the TypeSig for fully-qualified package-member name P.T. Returns null if no such type exists.

This function never results in CompilationUnits being loaded unless eagerRead is set.

Calling this function twice with the same arguments is guaranteed to give back the same answer, except that a null answer may later change to a non-null answer.

Requires:
an init method has already been called

lookupDeferred

public static TypeSig lookupDeferred(java.lang.String[] P,
                                     java.lang.String T)
Like lookup except that checking the existence of the type is deferred until it's TypeDecl is touched for the first time. If eagerRead is set, existence is always checked, with non-existance resulting in an error.

This routine never returns null: if P does not exist in our Java file space, then an unloaded TypeSig is returned; when its TypeDecl is first referenced, an error will be reported.

This function is intended to be used only to load types required to be present by the language specification (e.g., Object).

Requires:
an init method has already been called.

addSource

public static CompilationUnit addSource(GenericFile source)
Attempt to add the package-member types contained in a source file to the package-member-types environment, returning the CompilationUnit, if any, found in that file.

If an error occurs, it will be reported via ErrorSet and null will be returned.

null may also be returned if a file is repeated on the command line.

Note:
Calling addSource twice on the same file may or may not produce a duplicate-type error.
Requires:
no lookup has been done yet using this class.

addSources

public static java.util.ArrayList addSources(java.util.ArrayList sources)
Adds all relevant files from the given package; 'relevant' is defined by the 'findFiles' method of the current reader.


resolveSources

public static java.util.ArrayList resolveSources(java.lang.String[] pname)

addSource

public static CompilationUnit addSource(java.lang.String sourceName)
Attempt to add the package-member types contained in a named source file to the package-member-types environment, returning the CompilationUnit, if any, found in that file.

If an error occurs, it will be reported via ErrorSet and null will be returned.

Note:
Calling addSource twice on the same file may or may not produce a duplicate-type error.
Requires:
no lookup has been done yet using this class.

resolveDirSources

public static java.util.ArrayList resolveDirSources(java.lang.String dirname)

setSigs

private static void setSigs(CompilationUnit cu)
This routine creates TypeSigs for each TypeDecl member of cu.

As a side effect, this sets the sig fields of cu's direct TypeDecl members (aka, the TypeDecls for the package-member types cu contains) to point to TypeSigs that have been loaded with the TypeDecls that point to them.

Requires:
cu must be non-null.

load

static void load(TypeSig sig)
Attempt to load the TypeDecl of TypeSig sig.

This method should be called only from TypeSig.preload.

Tries to load the file that should contain sig. Reports any errors encountered to ErrorSet. If successful, calls sig.load with its TypeDecl.

It is a fatal error if this routine cannot load sig. Later the error may be made non-fatal; in that case TypeSig.preload will be responsible for substituting a wildcard TypeDecl.

Requires:
an init method has already been called.

setListener

public static void setListener(Listener l)
Set the Listener to be notified about CompilationUnit loading.

l may be null if no notification is desired (the initial default). The previous current Listener is replaced. (I.e., only 1 Listener may be in effect at a time.)


notify

private static void notify(CompilationUnit justLoaded)
Send a CompilationUnit-loaded notification event to the current Listener (if any).

Requires:
justLoaded != null, justLoaded must already have the sig fields of its direct TypeDecls adjusted.

main

public static void main(java.lang.String[] args)
A debugging harness that allows describing the results of calling lookup on a series of package-member-type names.


describeLookup

private static void describeLookup(java.lang.String N)
Call lookup on N then describe the results.


ESC/Java2
© 2003,2004,2005 David Cok and Joseph Kiniry
© 2005 UCD Dublin
© 2003,2004 Radboud University Nijmegen
© 1999,2000 Compaq Computer Corporation
© 1997,1998,1999 Digital Equipment Corporation
All Rights Reserved

The ESC/Java2 Project Homepage