KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > compiler > base > ast > NameType


1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This file is part of the compiler and core tools for the AspectJ(tm)
4  * programming language; see http://aspectj.org
5  *
6  * The contents of this file are subject to the Mozilla Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License at
9  * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is AspectJ.
17  *
18  * The Initial Developer of the Original Code is Xerox Corporation. Portions
19  * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
20  * All Rights Reserved.
21  *
22  * Contributor(s):
23  */

24
25 package org.aspectj.compiler.base.ast;
26
27 import java.util.*;
28
29 import org.aspectj.compiler.base.bcg.CodeBuilder;
30 import org.aspectj.compiler.base.*;
31 import java.io.IOException JavaDoc;
32
33 //ASPECT use introduction from crosscuts package
34
import org.aspectj.compiler.crosscuts.ast.*;
35 import org.aspectj.compiler.crosscuts.joinpoints.*;
36
37
38 /**
39  * A unique Type for each class, interface or aspect in the system,
40  * either defined in source or loaded from bytecode.
41  * There is a 1-to-1 mapping between NameTypes and TypeDecs
42  *
43  * Virtually all of the code for validating Types and for looking up decs
44  * efficiently on them is handled by this class.
45  */

46 public class NameType extends org.aspectj.compiler.base.ast.RefType {
47     final SemanticMap fields = new SemanticMap(this, "field");
48
49     final SemanticMap pointcuts = new SemanticMap(this, "pointcut");
50
51     final SemanticMap innerTypes = new SemanticMap(this, "type");
52
53     final SemanticMap methods = new SemanticMap(this, "method");
54
55     //??? having a SemanticMap for constructors simplifies the design, but isn't terribly
56
//??? elegant since constructors don't even really have names...
57
final SemanticMap constructors = new SemanticMap(this, "constructor");
58
59     public NameType(TypeDec typeDec) {
60         super(typeDec.getCompiler());
61         this.dec = typeDec;
62     }
63
64     public TypeDec getTypeDec() { return (TypeDec)dec; }
65
66     public boolean isCoercableTo(Type other) {
67         if (this.isAssignableFrom(other)) return true;
68         if (other.isAssignableFrom(this)) return true;
69         
70         if (! (other instanceof NameType) ) return false;
71
72         // if they are both classes, then a direct relationship is required
73
if (!isInterface() && !other.isInterface()) return false;
74         
75         // if they are both interfaces, then check method compatibility
76
if (isInterface() && other.isInterface()) {
77             return methodsCompatibleWith(other);
78         }
79         
80         // if one is a class and the other is an interface, then check that the
81
// class is not final -- compatible with JLS 5.5
82
// would be nice if spec included method compatibility check here,
83
// but it doesn't
84
if (isInterface()) return !((NameType)other).isFinal();
85         if (other.isInterface()) return !this.isFinal();
86
87         return false;
88     }
89
90
91     /**
92      * Checks to see if all of my methods are compatible with all
93      * of the methods of some other type.
94      */

95     private boolean methodsCompatibleWith(Type other) {
96         for (Iterator i = getMethods().iterator(); i.hasNext(); ) {
97             Method m = (Method)i.next();
98             Method mOther = (Method)other.findMatchingSemanticObject(m);
99             if (mOther != null) {
100                 if (!m.getReturnType().isEquivalent(mOther.getReturnType())) {
101                     return false;
102                 }
103             }
104         }
105         return true;
106     }
107
108
109     public boolean dominates(Type other) {
110         TypeDec t1 = getTypeDec();
111         TypeDec t2 = other.getTypeDec();
112         if (t2 != null && t1 instanceof AspectDec && t2 instanceof AspectDec) {
113             return ((AspectDec)t1).dominates((AspectDec)t2);
114         } else {
115             return super.dominates(other);
116         }
117     }
118
119     public boolean isEffectivelyStatic() {
120         return isStatic() || isPackageMember();
121     }
122
123     public Expr getClassExpr() {
124         if (! getTypeDec().hasGlobalName()) return getAST().makeNull();
125         return new ClassExpr(getAST().getSourceLocation(), this.makeTypeD());
126     }
127
128     public Expr makeObject(Expr expr) { return expr; }
129
130     public Expr fromObject(Expr expr) {
131         return getAST().makeCast(this, expr);
132     }
133
134     public Expr getNullExpr() {
135         return getAST().makeNull();
136     }
137
138     public Type getRefType() { return this; }
139
140     public Type getOutermostType() {
141         return getTypeDec().getOutermostType();
142     }
143
144
145     public PointcutSO getPointcut(String JavaDoc id, ASTObject fromWhere, boolean showError) {
146         ensureFinishedSignature();
147         return (PointcutSO)pointcuts.get(id, fromWhere, null, showError);
148     }
149
150     public Field getField(String JavaDoc id, ASTObject fromWhere, boolean showError) {
151         //System.out.println("get field on " + this + ", " + System.identityHashCode(this));
152
ensureFinishedSignature();
153         return (Field)fields.get(id, fromWhere, null, showError);
154     }
155
156     public Type getInnerType(String JavaDoc id, ASTObject fromWhere, boolean showError) {
157 // System.out.println("get inner type on " + this + ", " + id);
158
// System.out.println(" " + fromWhere + ", " + innerTypes.map.keySet());
159
//??? including this makes some order issues much harder, can I skip it???
160
ensureBuiltTypeGraph();
161         //??? what about null returns from this???
162
Type ret = (Type)innerTypes.get(id, fromWhere, null, showError);
163         //System.out.println(" returning: " + ret);
164
return ret;
165     }
166
167     public Method getMethod(String JavaDoc id, ASTObject fromWhere, Exprs params, boolean showError) {
168         ensureFinishedSignature();
169         //System.out.println(" " + id + " in " + this);
170
Method ret = (Method)methods.get(id, fromWhere, params, showError);
171 // if (ret == getWorld().METHOD_DEC_NOT_FOUND) {
172
// getTypeDec().showError("can't find: " + id);
173
// }
174
// System.out.println(" " + ret);
175
return ret;
176     }
177
178     // currently only used by ReceptionsPointcut and by TypeScope.findMethodLookupType
179
public boolean hasMethodNamed(String JavaDoc id) {
180         ensureFinishedSignature();
181         return methods.hasName(id);
182     }
183
184     public Constructor getConstructor(ASTObject fromWhere, Exprs params, boolean showError) {
185         ensureFinishedSignature();
186
187         return (Constructor)constructors.get("new", fromWhere, params, showError);
188     }
189
190     public SemanticObject findMatchingSemanticObject(SemanticObject o) {
191         if (o instanceof Method) {
192             return methods.findMatchingSemanticObject(o);
193         } else if (o instanceof Constructor) {
194             return constructors.findMatchingSemanticObject(o);
195         } else if (o instanceof Field) {
196             return fields.findMatchingSemanticObject(o);
197         } else {
198             return null;
199         }
200     }
201
202     private void addInheritedMembers(SemanticMap map, Collection bag) {
203         for (Iterator i = map.getAllSemanticObjects().iterator(); i.hasNext(); ) {
204             SemanticObject so = (SemanticObject)i.next();
205             if (so.getDeclaringType() != this) { bag.add(so); }
206         }
207     }
208
209     // currently only used by AdviceWeaver for dealing with synthetic reception points
210
public Collection getInheritedMethods() {
211         List ret = new LinkedList();
212         addInheritedMembers(methods, ret);
213         return ret;
214     }
215
216     public Collection getInheritedMembers() {
217         List ret = new LinkedList();
218         addInheritedMembers(methods, ret);
219         addInheritedMembers(innerTypes, ret);
220         addInheritedMembers(fields, ret);
221         addInheritedMembers(pointcuts, ret);
222         return ret;
223     }
224
225     public Collection getConstructors() {
226         return constructors.getAllSemanticObjects();
227     }
228
229     /** Used by ajdoc. */
230     public Collection getMethods() {
231         return methods.getAllSemanticObjects();
232     }
233     /** Used by ajdoc. */
234     public Collection getFields() {
235         return fields.getAllSemanticObjects();
236     }
237     /** Used by ajdoc. */
238     public Collection getPointcuts() {
239         return pointcuts.getAllSemanticObjects();
240     }
241
242
243     public void addPointcut(PointcutDec pointcut) {
244         pointcuts.addDeclared(pointcut.getCorrespondingSemanticObject());
245     }
246
247     public void addField(FieldDec field) {
248         //System.out.println("adding " + field + " to " + System.identityHashCode(this));
249
fields.addDeclared(field.getCorrespondingSemanticObject());
250     }
251
252     public void addMethod(MethodDec method) {
253         methods.addDeclared(method.getCorrespondingSemanticObject());
254     }
255
256     public void addConstructor(ConstructorDec constructor) {
257         constructors.addDeclared(constructor.getCorrespondingSemanticObject());
258     }
259
260     public NameType getSuperClassType() {
261         return (NameType)getTypeDec().getSuperClassType();
262     }
263
264     public Type getDeclaringType() {
265         return getTypeDec().getDeclaringType();
266     }
267
268     public void addInnerType(TypeDec type) {
269         //System.out.println("adding inner " + type + " to " + this);
270
innerTypes.addDeclared(type.getType());
271     }
272
273     public Collection getInheritedFromTypes() {
274         //??? true for classes
275
return directSuperTypes;
276     }
277
278     private void initializeInheritedTypeMap() {
279         for (Iterator i = getInheritedFromTypes().iterator(); i.hasNext(); ) {
280             NameType superType = (NameType)i.next();
281             superType.ensureBuiltTypeGraph();
282             innerTypes.addInherited(superType.innerTypes);
283         }
284
285  // System.out.println(this.getString() + " inners " +
286
// getInnerTypes() +
287
// " supers " + getInheritedFromTypes());
288
}
289
290
291     private void handleInheritedMembers(NameType superType) {
292         superType.ensureFinishedSignature();
293
294         pointcuts.addInherited(superType.pointcuts);
295         fields.addInherited(superType.fields);
296         methods.addInherited(superType.methods);
297     }
298
299     private void handleInheritedMembers() {
300         NameType superClassType = getSuperClassType();
301         //System.out.println(this + " super: " + superClassType);
302
if (superClassType != null && getInheritedFromTypes().contains(superClassType)) {
303             //System.out.println(" inherited");
304
handleInheritedMembers(superClassType);
305         }
306
307         for (Iterator i = getInheritedFromTypes().iterator(); i.hasNext(); ) {
308             NameType superType = (NameType)i.next();
309             if (superType != superClassType) handleInheritedMembers(superType);
310         }
311     }
312
313     //private String prettyString = null;
314
public String JavaDoc getPrettyString() {
315         String JavaDoc prettyString = null;
316         if (prettyString != null) return prettyString;
317
318 // if (! getTypeDec().hasGlobalName()) {
319
// prettyString = getTypeDec().getDeclaringType().getPrettyString() + "$" +
320
// getTypeDec().getId();
321
// } else {
322
prettyString = getLegalString().replace('$', '.');
323 // }
324

325         return prettyString;
326     }
327
328     private String JavaDoc makeLegalString() {
329         return getTypeDec().getFullName();
330 // String legalName = getTypeDec().getFullName();
331
// if (legalName != null) return legalName;
332
// legalName = getTypeDec().getExtendedId();
333
// String packageName = getTypeDec().getPackageName();
334
// if (packageName != null) {
335
// legalName = packageName+'.'+legalName;
336
// }
337
// return legalName;
338
}
339
340     //private String legalString = null;
341
public String JavaDoc getLegalString() {
342         return makeLegalString();
343 // if (legalString != null) return legalString;
344
// legalString = makeLegalString();
345
// return legalString;
346
}
347
348     public String JavaDoc getSourceString() {
349         TypeDec typeDec = getTypeDec();
350 // if (! typeDec.hasGlobalName()) {
351
// return typeDec.getId();
352
// }
353
return getPrettyString();
354     }
355
356     //!!! should be cleaned up in TypeD
357
public String JavaDoc getString() {
358         return getSourceString(); //+ "%" + System.identityHashCode(this);
359
}
360
361
362     /**
363      * Returns the name of this class minus the package name
364      *
365      * uses '$' as a separator for inners
366      *
367      * java.util.Map.Entry goes to Map$Entry
368      */

369     public String JavaDoc getExtendedId() {
370         return getTypeDec().getExtendedId();
371     }
372
373
374     /**
375      * Returns the simple name of this class, ignoring enclosing types
376      *
377      * java.util.Map.Entry goes to Entry
378      */

379     public String JavaDoc getId() {
380         return getTypeDec().getId();
381     }
382
383     public String JavaDoc getExternalName() {
384         return getClassName();
385     }
386
387     public String JavaDoc getClassName() {
388         return getTypeDec().getFullName();
389     }
390
391     public String JavaDoc getPackageName() {
392         return getTypeDec().getPackageName();
393     }
394
395
396     public void unparse(CodeWriter writer) throws IOException JavaDoc {
397         writer.write(getSourceString());
398     }
399
400     //!!! name should change to getPrettyClassName
401
/**
402      * @return e.g. qualified type name java.util.Map.Entry will be returned as Map.Entry
403      */

404     public String JavaDoc toShortString() {
405         String JavaDoc ret = getTypeDec().getSourceExtendedId();
406         //ret += "%" + System.identityHashCode(this);
407
return ret;
408     }
409
410     public String JavaDoc toString() {
411         return "NameType("+getPrettyString()+")";
412     }
413
414
415     public boolean isInterface() { return getTypeDec() instanceof InterfaceDec; }
416     public boolean isClass() { return getTypeDec() instanceof ClassDec; }
417     public boolean isAspect() { return getTypeDec() instanceof AspectDec; }
418
419     public boolean isInnerType() { return getTypeDec().isInnerType(); }
420
421     public boolean isAnonymous() { return getTypeDec().isLocallyDefined(); }
422
423     public boolean isAbstract() { return isInterface() || getTypeDec().isAbstract(); }
424     public boolean isFinal() { return getTypeDec().isFinal(); }
425
426     public void ensureNoAbstractDecs() {
427         pointcuts.ensureNoAbstracts();
428         methods.ensureNoAbstracts();
429     }
430
431
432     synchronized public void ensureBuiltTypeGraph() {
433         if (builtTypeGraph) return;
434         //if (getTypeDec().fromSource()) {
435
getTypeDec().addToTypeGraph(); //getOutermostTypeDec().addToTypeGraph();
436
//} else {
437
// addToTypeGraph();
438
//}
439
}
440
441     synchronized public void ensureFinishedSignature() {
442         if (builtSignatures) return;
443             // !!! this was a good idea that didn't match up with the structure of the
444
// in particular, NameTypes don't really finish their signatures until they
445
// handle their inherited members. But, they call this method before handling
446
// their inherited members.
447
//// if (!getWorld().collectedTypeDecPlanners) {
448
//// getCompiler().internalError("should have collected type dec planners by now");
449
//// }
450

451         ensureBuiltTypeGraph();
452         //if (getTypeDec().fromSource()) {
453
getTypeDec().buildSignatures(); //getOutermostTypeDec().buildSignatures();
454
}
455
456     /*
457       Here are the important stages in the lifecyle of a NameType
458
459       parse -- produces concrete syntax tree
460       bind names in extends and implements clauses
461       build type graph -- requires parents type graphs built
462       
463       collect and bind introduction planners -- requires type graph
464       implement declare parents -- requires all introduction planners collected
465       add introduced members to type -- requires declare parents implemented
466       bind names in declared members signatures -- requires declare parents implemented
467
468       build type signature??? -- requires built type signature in parents
469                               names bound in declared members
470                               introduced members added to type
471
472       bind names in bodies
473       folding and checking assignments???
474
475       collect advice planners
476
477       ...
478     */

479     private boolean builtTypeGraph = false;
480     public void addToTypeGraph() {
481         if (builtTypeGraph) {
482             getCompiler().internalError("already built type graph " +
483                                         getPrettyString());
484             return;
485         }
486         builtTypeGraph = true;
487         getCompiler().showMessage(" building type graph " + getPrettyString());
488         
489         if (this != getTypeManager().getObjectType()) {
490             addDirectSuperType(getTypeDec().getSuperClassType());
491         }
492
493         for (Iterator i = getTypeDec().getSuperInterfaceTypes().iterator();
494              i.hasNext(); )
495         {
496             NameType superInterfaceType = (NameType)i.next();
497             addDirectSuperType(superInterfaceType);
498         }
499
500         initializeInheritedTypeMap();
501
502         getTypeDec().addInnerTypes();
503     }
504
505     private boolean builtSignatures = false;
506     public void buildSignatures() {
507         if (builtSignatures) {
508             getCompiler().internalError("already built signatures: " +
509                                         getPrettyString());
510             return;
511         }
512         builtSignatures = true;
513         getCompiler().showMessage(" building signatures " + getPrettyString());
514         
515         if (getTypeDec().fromSource()) checkForCircularities();
516
517         getWorld().runTypeDecPlanners(getTypeDec(), TypeDecPlanner.TYPE);
518         
519         getTypeDec().addDecs(this);
520
521         getWorld().runTypeDecPlanners(getTypeDec(), TypeDecPlanner.SIGNATURE);
522         //System.out.println("almost finished: " + this);
523

524         handleInheritedMembers();
525     }
526
527     public Collection getInnerTypes() {
528         return innerTypes.getAllSemanticObjects();
529     }
530
531     public Type getOutermostLexicalType() {
532         return getTypeDec().getOutermostLexicalType();
533     }
534     
535     public Type getOutermostBytecodeType() {
536         return getTypeDec().getOutermostBytecodeType();
537     }
538     
539  
540
541
542     //XXX I hate to do this, but make everything lazy for now
543
private boolean isLazy = true;
544     public void setLazy() { isLazy = true; }
545     
546
547     public void checkForCircularities() {
548         checkForCircularities(new LinkedList());
549     }
550
551     private boolean checkForCircularities(LinkedList list) {
552         if (list.contains(this)) {
553             StringBuffer JavaDoc message = new StringBuffer JavaDoc("cyclic inheritance, ");
554             boolean foundThis = false;
555             for (Iterator i = list.iterator(); i.hasNext(); ) {
556                 Type t = (Type)i.next();
557                 if (t == this) {
558                     foundThis = true;
559                 }
560                 if (foundThis) {
561                     message.append(t.getString());
562                     message.append(" -> ");
563                 }
564             }
565             message.append(getString());
566 // message.append(getString());
567
// while (list.getLast() != this) {
568
// message.append(" <- ");
569
// message.append(((Type)list.removeLast()).getString());
570
// }
571
// message.append(" <- ");
572
// message.append(getString());
573
getTypeDec().showError(message.toString());
574             //??? this makes error handling more robust...
575
directSuperTypes.clear();
576             return true;
577         } else {
578             list.add(this);
579             if (getEnclosingType() != null) {
580                 if (getEnclosingType().checkForCircularities(list)) return true;
581             }
582             
583             for (Iterator i = directSuperTypes.iterator(); i.hasNext(); ) {
584                 NameType superType = (NameType)i.next();
585                 if (superType.checkForCircularities(list)) return true;
586             }
587             list.removeLast();
588             return false;
589         }
590     }
591
592     // ------------------------------
593
// vm internals
594
private String JavaDoc internalName;
595     private String JavaDoc descriptor;
596
597     public synchronized String JavaDoc getInternalName() {
598         if (internalName == null) {
599             internalName = getClassName().replace('.', '/');
600         }
601         return internalName;
602     }
603
604     public synchronized String JavaDoc getDescriptor() {
605         if (descriptor == null) {
606             descriptor = "L" + getInternalName() + ";";
607         }
608         return descriptor;
609     }
610
611     // ------------------------------
612
// ASPECT: Fold
613
final LiteralExpr foldAddOp(LiteralExpr rand1, LiteralExpr rand2) {
614         return getAST().makeLiteral(rand1.getStringValue() + rand2.getStringValue());
615     }
616     final LiteralExpr foldEqualityTestOp(String JavaDoc op, LiteralExpr lit1, LiteralExpr lit2) {
617         final AST ast = getAST();
618         String JavaDoc a = lit1.getStringValue();
619         String JavaDoc b = lit2.getStringValue();
620         if (op == "==") return ast.makeLiteral(a.equals(b));
621         else if (op == "!=") return ast.makeLiteral(! a.equals(b));
622         else throw new RuntimeException JavaDoc("bad op " + op);
623     }
624     final LiteralExpr foldCast(LiteralExpr lit) {
625         return getAST().makeLiteral(lit.getStringValue());
626     }
627
628     // ------------------------------
629
// Dealing with non-package-level types
630

631     // !!! These dispatch to the typeDec. It's probably wrong that
632
// isInner and isPackageMember do so... rather, the typeDec may
633
// want to dispatch here. In particular, it seems more a property
634
// of NameTypes that they're "inner", that is, that their
635
// constructor takes an extra arg and that they have an enclosing
636
// instance. isLocal() is definitely a property of the dec, rather
637
// than the type, though.
638

639     public boolean isInner() {
640         return getTypeDec().isInner();
641     }
642     public NameType getEnclosingInstanceType() {
643         // only if isInner()
644
return (NameType)getDeclaringType();
645     }
646
647     public boolean isLocal() {
648         TypeDec typeDec = getTypeDec();
649         if (typeDec == null) return false; // ???
650
return typeDec.isLocal();
651     }
652     public CodeDec getEnclosingCodeDec() {
653         // only if isLocal()
654
return getTypeDec().getEnclosingCodeDec();
655     }
656
657     public boolean isPackageMember() {
658         return getTypeDec().isPackageMember();
659     }
660     public NameType getEnclosingType() {
661         // only if ! isPackageMember()
662
return (NameType)getDeclaringType();
663     }
664 }
665
Popular Tags