KickJava   Java API By Example, From Geeks To Geeks.

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


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.*;
30 import org.aspectj.compiler.base.cst.*;
31 // to get the passes for introductions
32
import org.aspectj.compiler.crosscuts.*;
33 import org.aspectj.compiler.base.bcg.CodeBuilder;
34
35 /**
36   * @grammar modifiers resultType id(formals) throws body
37   * @child TypeD resultTypeD @after modifiers
38   * @property String id @after resultTypeD
39   */

40 public class MethodDec extends CodeDec {
41     //!!! temporary work-around
42
public MethodDec(SourceLocation source,Modifiers modifiers, TypeD resultTypeD, String JavaDoc id, Formals formals,
43                      TypeDs _throws, BlockStmt block)
44     {
45         this(source,modifiers, resultTypeD, id, formals, _throws, blockToBody(block));
46     }
47     public MethodDec(SourceLocation source,Modifiers modifiers, Type resultType, String JavaDoc id, Formals formals,
48                      TypeDs _throws, BlockStmt block)
49     {
50         this(source,modifiers, resultType.makeTypeD(), id, formals, _throws, blockToBody(block));
51     }
52
53     public ASTObject postFixAST(final ASTFixerPass fixer) {
54         if (this.isIntroduced()) this.getModifiers().setPublic(true);
55
56         if (getBytecodeTypeDec() instanceof InterfaceDec) {
57             this.getModifiers().setValue(Modifiers.ABSTRACT|Modifiers.PUBLIC);
58             this.setBody(null);
59         }
60         return this;
61     }
62
63     //INTRO from MixinImplementationPass
64
public ASTObject postImplementMixin(MixinImplementationPass fixer) {
65         TypeDec inTypeDec = getBytecodeTypeDec();
66
67         if (!(inTypeDec instanceof InterfaceDec)) return this;
68
69         if (getBody() == null) return this;
70
71         if (isStatic()) {
72             ((InterfaceDec)inTypeDec).addToHelperClass(this);
73             return null;
74         }
75
76
77         this.getModifiers().setFinal(false);
78         this.getModifiers().setPublic(true);
79
80         Set topmostImplementors =
81             Type.filterTopTypes(Type.filterConcreteTypes(inTypeDec.getType().getSubTypes()));
82
83         for (Iterator i = topmostImplementors.iterator(); i.hasNext(); ) {
84             Type implType = (Type)i.next();
85             TypeDec implDec = implType.getTypeDec();
86             //System.out.println("adding: " + this.toShortString() + " to " + implDec);
87

88             // don't implement if I'm already there in some other form
89
if (!shouldImplement(implDec.getType(), this)) continue;
90
91             MethodDec newDec = (MethodDec)fixer.copyToClass(this, implDec);
92 // System.out.println(" really adding");
93
implDec.getBody().add( newDec );
94         }
95
96         this.setBody(null);
97         this.getModifiers().setSynchronized(false);
98         return this;
99     }
100
101
102     boolean shouldImplement(Type onType, Dec dec) {
103         Dec existingDec = onType.findMatchingDec(dec);
104         if (existingDec != null && existingDec != dec) return false;
105         
106         Dec owner = dec.owner;
107         if (owner != null) return shouldImplement(onType, owner);
108         else return true;
109     }
110
111     //INTRO from ScopeWalker
112
public void preScope(ScopeWalker walker) {
113         walker.addMethodDec(this);
114         super.preScope(walker);
115     }
116
117     public Expr getExpr() { return null; }
118
119     public String JavaDoc toShortString() {
120         return addIntroducedFromType(
121             modifiers.toShortString() + " " + resultTypeD.toShortString() + " " +
122                     getDeclaringType().toShortString()+"." + id +
123                     formals.toShortString());
124     }
125
126     public String JavaDoc getKind() { return "method"; }
127
128     public SemanticObject makeCorrespondingSemanticObject() {
129         return new Method(this);
130     }
131
132     public Method getMethod() { return (Method)getCorrespondingSemanticObject(); }
133
134     MethodDec makeSuperCaller() {
135         final AST ast = getAST();
136
137         Modifiers modifiers = ast.makeModifiers(0);
138         if (isProtected()) modifiers.setProtected();
139         if (isPublic()) modifiers.setPublic(true);
140
141         Type resultType = getResultType();
142         Formals formals = (Formals)getFormals().copy();
143         CallExpr superCall = ast.makeSuperCall(getMethod(), formals.makeExprs());
144
145         Stmt stmt;
146         if (resultType.isVoid()) {
147             stmt = ast.makeStmt(superCall);
148         } else {
149             stmt = ast.makeReturn(superCall);
150         }
151
152         MethodDec ret = ast.makeMethod(modifiers, resultType, getId(),
153                 formals, ast.makeBlock(stmt));
154         if (getThrows() != null) {
155             ret.setThrows((TypeDs)getThrows().copy());
156         }
157         return ret;
158     }
159
160     public void checkSpec() {
161         super.checkSpec();
162         if (getModifiers().isAbstract()) {
163             if (getModifiers().isStrict()) {
164                 getModifiers().showError("illegal combination of modifiers: abstract strictfp");
165             } else if (getModifiers().isPrivate()) {
166                 if (!isIntroduced()) {
167                     showError("abstract private method can never be implemented");
168                 }
169             } else if (getModifiers().isStatic()) {
170                 getModifiers().showError("illegal combination of modifiers: abstract static");
171             }
172         }
173         if (isAbstract() || getModifiers().isNative()) {
174             if (getBody() != null) {
175                 showError("abstract or native methods cannot have a body");
176             }
177         } else {
178             if (getBody() == null) {
179                 showError("non-abstract/native methods must have a body");
180             }
181         }
182     }
183
184     void showOverrideError(Type inType, MethodDec other, String JavaDoc message) {
185         if (getDeclaringType() != inType) {
186             inType.getTypeDec().showError("inherited method " + this.toShortString() +
187                 " is incompatible with inherited method " + other.toShortString() +
188                 "; " + message);
189         } else {
190             String JavaDoc overrideKind = "override";
191             if (other.getDeclaringType().isInterface()) {
192                 overrideKind = "implement";
193             }
194             showError(toShortString() + " cannot " + overrideKind + " " +
195                         other.toShortString() + "; " + message);
196         }
197     }
198
199     public boolean isEffectivelyAbstract(Type inType) {
200         return isAbstract() ||
201             (inType.isInterface() && getDeclaringType().isObject());
202     }
203
204     public boolean checkOverride(Type inType, Dec otherDec) {
205         MethodDec other = (MethodDec)otherDec;
206
207 // System.out.println("check override: " + this.toShortString() + ", " +
208
// other.toShortString() + " inherited? " +
209
// (getDeclaringType() != inType));
210

211         // both are inherited
212
if (getDeclaringType() != inType) {
213             if (isEffectivelyAbstract(inType)) {
214                 if (!other.isEffectivelyAbstract(inType)) {
215                     other.internalCheckOverride(inType, this);
216                     return true;
217                 } else {
218                     if (getModifiers().isWeakerThan(other.getModifiers())) {
219                         other.internalCheckOverride(inType, this);
220                         return true;
221                     } else {
222                         this.internalCheckOverride(inType, other);
223                         return false;
224                     }
225                 }
226             } else {
227                 if (other.isEffectivelyAbstract(inType)) {
228                     this.internalCheckOverride(inType, other);
229                     return false;
230                 } else if (this.overrides(other)) {
231                     this.internalCheckOverride(inType, other);
232                     return false;
233                 } else if (other.overrides(this)) {
234                     other.internalCheckOverride(inType, this);
235                     return true;
236                 } else {
237                     showOverrideError(inType, other, "both methods are concrete");
238                     return false;
239                 }
240             }
241         } else {
242             this.internalCheckOverride(inType, other);
243             return false;
244         }
245     }
246
247     private void internalCheckOverride(Type inType, MethodDec other) {
248         if (!getResultType().isEquivalent(other.getResultType())) {
249             showOverrideError(inType, other,
250                         "attempting to use incompatible return type\n" +
251                   "found : " + getResultType().getString() + "\n" +
252                   "required: " + other.getResultType().getString());
253         } else if (other.getModifiers().isFinal()) {
254             showOverrideError(inType, other, "overridden method is final");
255         } else if (other.isStatic() && !this.isStatic()) {
256             showOverrideError(inType, other, "overridden method is static");
257         } else if (this.isStatic() && !other.isStatic()) {
258             showOverrideError(inType, other, "overridden method is non-static");
259         } else if (getModifiers().isWeakerThan(other.getModifiers())) {
260             showOverrideError(inType, other,
261                               "attempting to assign weaker access privileges; was " +
262                               other.getModifiers().toShortString());
263         } else if (_throws != null) {
264             // check that throws clause is not > super's
265
for (int i=0; i<_throws.size(); i++) {
266                 if (!other.canThrow(_throws.get(i).getType())) {
267                     showOverrideError(inType, other,
268                         "overridden method does not throw " +
269                         _throws.get(i).getType().getString());
270                     break;
271                 }
272             }
273         }
274
275         return;
276     }
277
278
279     public boolean overrides(MethodDec other) {
280         for (Iterator i = getDeclaringType().getDirectSuperTypes().iterator(); i.hasNext(); ) {
281             Type type = (Type)i.next();
282             MethodDec dec = (MethodDec)type.findMatchingDec(this);
283             if (dec == null) continue;
284             if (dec == other) return true;
285             if (dec == this) {
286                 getCompiler().internalError(this, "nonsense");
287                 return false;
288             }
289             if (dec.overrides(other)) return true;
290         }
291         return false;
292     }
293
294     public Set getMatchingMethods() {
295         Set ret = new HashSet();
296
297         for (Iterator i = getDeclaringType().getSubTypes().iterator(); i.hasNext(); ) {
298             Type type = (Type)i.next();
299             MethodDec dec = (MethodDec)type.findMatchingDec(this);
300             if (dec != null) ret.add(dec);
301         }
302
303         return ret;
304     }
305     
306     /**
307      * where S(m) = m
308      * +
309      * forall m_sub such that m_sub overrides/implements m, S(m_sub)
310      * +
311      * forall m_super such that m overrides/implements m_super, S(m_super)
312      *
313      * Basically, S(m) walks the type hierarchy of m and picks out all
314      * methods in that hierarchy with the signature of m.
315      */

316     private Set matchingSignatureTypes = null;
317     
318     public Set getMatchingSignatureTypes() {
319         if (matchingSignatureTypes == null) {
320         Set s = new HashSet();
321         addMatchingSignatureTypes(s, getDeclaringType());
322         }
323         return matchingSignatureTypes;
324     }
325     
326     private void addMatchingSignatureTypes(Set s, Type myType) {
327     //Type myType = getDeclaringType();
328
if (s.contains(myType)) {
329         if (matchingSignatureTypes != s) {
330             getCompiler().internalError(this,
331                                 "bad invariant in collecting matching signatures");
332         }
333         return;
334     }
335     
336     matchingSignatureTypes = s;
337     
338     s.add(myType);
339     
340     addMatchingSignaturesIn(s, myType.getDirectSubTypes());
341     addMatchingSignaturesIn(s, myType.getDirectSuperTypes());
342     }
343     
344     private void addMatchingSignaturesIn(Set s, Collection types) {
345     for (Iterator i = types.iterator(); i.hasNext(); ) {
346             Type type = (Type)i.next();
347             // will find a matching dec in this type OR in a super type
348
MethodDec dec = (MethodDec)type.findMatchingDec(this);
349             if (dec != null) {
350                 dec.addMatchingSignatureTypes(s, type);
351             }
352         }
353     }
354     
355 // public MethodDec getRootMethodDec() {
356
// MethodDec ret = null;
357
// for (Iterator i = getDeclaringType().getDirectSuperTypes().iterator(); i.hasNext(); ) {
358
// Type type = (Type)i.next();
359
// MethodDec dec = (MethodDec)type.findMatchingDec(this);
360
// if (dec != null) {
361
// if (ret == null) {
362
// ret = dec;
363
// } else {
364
// return null;
365
// }
366
// }
367
// }
368
// if (ret == null) return this;
369
// else return ret.getRootMethodDec();
370
// }
371

372     /** This refers backdoor method for privileged aspects and
373      * for access from inner classes (for bytecode compilation)
374      */

375     private MethodDec backdoorMethod;
376
377     public MethodDec getBackdoorMethod() {
378         if (backdoorMethod != null) return backdoorMethod;
379
380         final AST ast = getAST();
381         String JavaDoc id = getBytecodeId() + "$ajc$backdoor";
382
383         Modifiers modifiers = ast.makeModifiers(Modifiers.FINAL|Modifiers.PUBLIC);
384         if (isStatic()) modifiers.setStatic(true);
385
386         Formals formals = (Formals)getFormals().copy();
387         Expr thisExpr;
388         if (isStatic()) thisExpr = ast.makeTypeExpr(getBytecodeTypeDec().getType());
389         else thisExpr = ast.makeThis(getBytecodeTypeDec().getType());
390
391         CallExpr innerCall = ast.makeCall(this, thisExpr, formals.makeExprs());
392         Stmt stmt;
393         if (resultTypeD.getType().isEquivalent(getTypeManager().voidType)) {
394             stmt = ast.makeStmt(innerCall);
395         } else {
396             stmt = ast.makeReturn(innerCall);
397         }
398
399         MethodDec ret = ast.makeMethod(modifiers, getResultType(), id, formals,
400                 ast.makeBlock(stmt));
401         ret.getBody().setParsed(true);
402         if (getThrows() != null) {
403             ret.setThrows((TypeDs)getThrows().copy());
404         }
405
406         getDeclaringType().getTypeDec().addToBody(ret);
407
408         backdoorMethod = ret;
409         return backdoorMethod;
410     }
411
412
413     public void unparse(CodeWriter writer) {
414         if (getBytecodeTypeDec() instanceof InterfaceDec && (isPrivate() || isFinal())) {
415             return;
416         }
417
418         writeModifiers(writer);
419         writer.write(resultTypeD);
420         writer.requiredSpace();
421         writer.write(getBytecodeId());
422         writer.write(formals);
423
424         writeNames(writer, "throws", getThrows());
425
426         if (!writer.isOnlySignatures()) {
427             if (body == null) {
428                 writer.closeStmt();
429             } else {
430                 writer.optionalSpace();
431                 writer.write(body);
432             }
433             writer.newLine();
434         }
435     }
436
437     // ------------------------------
438
// bcg
439

440     protected void cgCodeMember(CodeBuilder cb) {
441         cb.setMaxFrame(getFrameSize());
442         cb.enterBlock();
443         Formals f = getFormals();
444         for (int i = 0, len = f.size(); i < len; i++) {
445             cb.enterVar(f.get(i));
446         }
447         getBody().cgTop(cb);
448         cb.exitBlock();
449     }
450
451     private String JavaDoc descriptor;
452     public synchronized String JavaDoc getDescriptor() {
453         if (descriptor == null) {
454             descriptor = "(";
455
456             for (Iterator i = getFormals().iterator(); i.hasNext(); ) {
457                 FormalDec dec = (FormalDec)i.next();
458                 descriptor += dec.getType().getDescriptor();
459             }
460             descriptor += ")";
461             descriptor += getResultType().getDescriptor();
462         }
463         return descriptor;
464     }
465
466     private boolean isDeltaComputed = false;
467     private int stackDelta;
468     public synchronized int getStackDelta() {
469         if (!isDeltaComputed) {
470             stackDelta = getResultType().getSlotCount();
471             if (!isStatic()) stackDelta--;
472             for (Iterator i = getFormals().iterator(); i.hasNext(); ) {
473                 FormalDec dec = (FormalDec)i.next();
474                 stackDelta -= dec.getType().getSlotCount();
475             }
476             isDeltaComputed = true;
477         }
478         return stackDelta;
479     }
480
481     // ------------------------------
482
// INTRO: LocalClassPass.ThreadingWalker
483

484     public void preThreading(LocalClassPass.ThreadingWalker walker) {
485         walker.pushNonConstructorEnv();
486     }
487
488     public ASTObject postThreading(LocalClassPass.ThreadingWalker walker) {
489         walker.popEnv();
490         return this;
491     }
492
493     //BEGIN: Generated from @child and @property
494
protected TypeD resultTypeD;
495     public TypeD getResultTypeD() { return resultTypeD; }
496     public void setResultTypeD(TypeD _resultTypeD) {
497         if (_resultTypeD != null) _resultTypeD.setParent(this);
498         resultTypeD = _resultTypeD;
499     }
500
501     protected String JavaDoc id;
502     public String JavaDoc getId() { return id; }
503     public void setId(String JavaDoc _id) { id = _id; }
504
505     public MethodDec(SourceLocation location, Modifiers _modifiers, TypeD _resultTypeD, String JavaDoc _id, Formals _formals, TypeDs __throws, CodeBody _body) {
506         super(location, _modifiers, _formals, __throws, _body);
507         setResultTypeD(_resultTypeD);
508         setId(_id);
509     }
510     protected MethodDec(SourceLocation source) {
511         super(source);
512     }
513
514     public ASTObject copyWalk(CopyWalker walker) {
515         MethodDec ret = new MethodDec(getSourceLocation());
516         ret.preCopy(walker, this);
517         if (modifiers != null) ret.setModifiers( (Modifiers)walker.process(modifiers) );
518         if (resultTypeD != null) ret.setResultTypeD( (TypeD)walker.process(resultTypeD) );
519         ret.id = id;
520         if (formals != null) ret.setFormals( (Formals)walker.process(formals) );
521         if (_throws != null) ret.setThrows( (TypeDs)walker.process(_throws) );
522         if (body != null) ret.setBody( (CodeBody)walker.process(body) );
523         return ret;
524     }
525
526     public ASTObject getChildAt(int childIndex) {
527         switch(childIndex) {
528         case 0: return modifiers;
529         case 1: return resultTypeD;
530         case 2: return formals;
531         case 3: return _throws;
532         case 4: return body;
533         default: return super.getChildAt(childIndex);
534         }
535     }
536      public String JavaDoc getChildNameAt(int childIndex) {
537         switch(childIndex) {
538         case 0: return "modifiers";
539         case 1: return "resultTypeD";
540         case 2: return "formals";
541         case 3: return "throws";
542         case 4: return "body";
543         default: return super.getChildNameAt(childIndex);
544         }
545     }
546      public void setChildAt(int childIndex, ASTObject child) {
547         switch(childIndex) {
548         case 0: setModifiers((Modifiers)child); return;
549         case 1: setResultTypeD((TypeD)child); return;
550         case 2: setFormals((Formals)child); return;
551         case 3: setThrows((TypeDs)child); return;
552         case 4: setBody((CodeBody)child); return;
553         default: super.setChildAt(childIndex, child); return;
554         }
555     }
556      public int getChildCount() {
557         return 5;
558     }
559
560     public String JavaDoc getDefaultDisplayName() {
561         return "MethodDec(id: "+id+")";
562     }
563
564     //END: Generated from @child and @property
565
}
566
Popular Tags