|
|
|
@ -30,44 +30,69 @@ import java.util.Vector; |
|
|
|
|
import java.util.Enumeration; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* OuterValues are used in method scoped classes: If a method |
|
|
|
|
* scoped class uses a local of the surrounding method, the java |
|
|
|
|
* compiler adds the locals to the param list of each constructor |
|
|
|
|
* of the method scoped class. Each invocation of the constructor |
|
|
|
|
* must give the correct values for these locals. |
|
|
|
|
* A list of local variables that a method scoped class inherits |
|
|
|
|
* from its declaring method. |
|
|
|
|
* |
|
|
|
|
* These extra parameters are the outerValues. |
|
|
|
|
* A method scoped class is a class that is declared in a method and |
|
|
|
|
* it can access other (final) local variables declared earlier. To |
|
|
|
|
* realize this the java compiler adds hidden parameters to the |
|
|
|
|
* constructor of the method scoped class, where it passes the values |
|
|
|
|
* of the local varaiables. If a method scoped class has more than |
|
|
|
|
* one constructor, each gets this hidden parameters. These hidden |
|
|
|
|
* parameters are the outerValues, because they are used to transport |
|
|
|
|
* a value of a local variable from an outer method. |
|
|
|
|
* |
|
|
|
|
* The main problem here is, that we don't know immediately if a |
|
|
|
|
* parameter is a standard parameter or a local of the outer |
|
|
|
|
* method. We may shrink this array if we notice a problem later. |
|
|
|
|
* Unfortunately there is no definite way to distinguish this outer |
|
|
|
|
* value parameters from the real parameters, so jode has to do a |
|
|
|
|
* guess: It first assumes that everything is an outer value parameter |
|
|
|
|
* added by the compiler and if this leads to contradiction shrinks |
|
|
|
|
* the count of these parameters. A contradiction can occur, because |
|
|
|
|
* the constructor is called two times with different values. |
|
|
|
|
* |
|
|
|
|
* Every class interested in outer values, may register itself |
|
|
|
|
* as OuterValueListener. It will then be notified every time the |
|
|
|
|
* outer values shrink. |
|
|
|
|
* On the other hand the TransformConstructor class assumes at some |
|
|
|
|
* point that some parameters are outer values. If later a |
|
|
|
|
* contradiction occurs, jode has to give up and complain loudly. |
|
|
|
|
* |
|
|
|
|
* The outer instance of a non static _class_ scoped class is not |
|
|
|
|
* considered as outer value, mainly because it can be changed. With |
|
|
|
|
* jikes method scoped classes also have an outer class instance, but |
|
|
|
|
* that is considered as outer value. |
|
|
|
|
* Every class interested in outer values, may register itself as |
|
|
|
|
* OuterValueListener. It will then be notified every time the outer |
|
|
|
|
* values shrink. Sometimes there are real listener queues: if |
|
|
|
|
* another method scoped class creates instances of the first in its |
|
|
|
|
* constructor by passing some of its own outer value parameter, it |
|
|
|
|
* may first seem that all parameters of the first class's constructor |
|
|
|
|
* are outer values. Because we can't be sure that the parameter from |
|
|
|
|
* the second class's constructor is really an outer value, we have to |
|
|
|
|
* add a listener. If later a constructor invokation for the second |
|
|
|
|
* class is found, where a parameter does not have the right outer |
|
|
|
|
* value, the listener will also shrink the outer values list of the |
|
|
|
|
* first class. |
|
|
|
|
* |
|
|
|
|
* Under jikes anonymous classes that extends class or method scoped |
|
|
|
|
* classes have as last parameter the outer instance of the parent |
|
|
|
|
* class. This should really be the first parameter (just after the |
|
|
|
|
* outerValues), like it is under javac. We mark such classes as |
|
|
|
|
* jikesAnonymousInner. This is done in the initialize() pass. |
|
|
|
|
* A non static _class_ scoped class (i.e. a normal inner class) also |
|
|
|
|
* has a hidden parameter, namely the instance of its outer class. |
|
|
|
|
* This hidden parameter is not considered as outer value though. |
|
|
|
|
* Note that you can even explicitly invoke the constructor with a |
|
|
|
|
* different outer class instance, by using the |
|
|
|
|
* <code>outerInstance.new InnerClass()</code> construct. This |
|
|
|
|
* exception doesn't apply to method scoped classes, though. |
|
|
|
|
* |
|
|
|
|
* Under javac the outer class paramter for anonymous classes that |
|
|
|
|
* extends class scoped classes is at the right position, just before |
|
|
|
|
* the other parameters. |
|
|
|
|
* Anonymous classes can of course also extend class or method scoped |
|
|
|
|
* classes. If they are compiled by jikes the constructor takes as |
|
|
|
|
* last parameter the outer instance of its super class. This should |
|
|
|
|
* really be the first parameter just after the outerValues, as it |
|
|
|
|
* is under javac. We mark such classes as jikesAnonymousInner. This |
|
|
|
|
* is done in the initialize() pass. |
|
|
|
|
* |
|
|
|
|
* @see #shrinkOuterValues |
|
|
|
|
* @see #addOuterValueListener |
|
|
|
|
* @since 1.0.93 */ |
|
|
|
|
* @since 1.0.93 |
|
|
|
|
*/ |
|
|
|
|
public class OuterValues |
|
|
|
|
{ |
|
|
|
|
private ClassAnalyzer clazzAnalyzer; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The outer values. An outer value is either a |
|
|
|
|
* LocalLoadOperator, a ThisOperator, or a OuterLocalOperator. |
|
|
|
|
*/ |
|
|
|
|
private Expression[] head; |
|
|
|
|
private Vector ovListeners; |
|
|
|
|
private boolean jikesAnonymousInner; |
|
|
|
|