KickJava   Java API By Example, From Geeks To Geeks.

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


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
28 import java.util.*;
29
30 import org.aspectj.compiler.base.*;
31
32 public class SemanticGroup extends CompilerObject {
33     protected String JavaDoc name;
34     protected SemanticMap map;
35     protected List members;
36
37     public SemanticGroup(SemanticMap map, SemanticObject o) {
38         this(map, o.getName());
39         members.add(o);
40     }
41
42     public SemanticGroup(SemanticMap map, String JavaDoc name) {
43         this(map, name, new LinkedList());
44     }
45
46     private SemanticGroup(SemanticMap map, String JavaDoc name, List members) {
47         super(map.getCompiler());
48         this.map = map;
49         this.name = name;
50         this.members = members;
51     }
52
53     public Collection getMembers() {
54         return members;
55     }
56
57     public String JavaDoc getName() {
58         return name;
59     }
60
61     public SemanticGroup makeInheritedCopy(SemanticMap newMap) {
62         SemanticGroup ret = new SemanticGroup(newMap, name);
63         ret.inheritFrom(this);
64         return ret;
65     }
66
67     public void inheritFrom(SemanticGroup otherGroup) {
68         if (otherGroup == null || otherGroup == this) {
69 // getCompiler().showError(
70
// "INTERNAL: " + this + " inheriting from " + otherGroup);
71
return;
72         }
73
74         boolean skipObject = !map.getType().isInterface() &&
75             otherGroup.map.getType().isInterface();
76
77         for(Iterator i = otherGroup.members.iterator(); i.hasNext(); ) {
78             SemanticObject so = (SemanticObject)i.next();
79             if (skipObject && so.getDeclaringType().isObject()) continue;
80             //System.out.println("should inherit? " + so + " in Type + " +map.getType());
81
//System.out.println(" --> " + so.isInherited(map.getType()));
82
if (so.isInherited(map.getType())) {
83                 addSO(so, inheritMode);
84             }
85         }
86     }
87
88     private static abstract class Mode {
89         abstract SemanticObject handleConflict(Type inType, SemanticObject currentSO, SemanticObject newSO);
90     }
91
92     private static final Mode inheritMode = new Mode() {
93         SemanticObject handleConflict(Type inType, SemanticObject currentSO, SemanticObject newSO) {
94             if (currentSO.checkOverride(inType, newSO)) {
95                 return currentSO;
96             } else {
97                 return null;
98             }
99         }
100     };
101
102     private static final Mode addMode = new Mode() {
103         SemanticObject handleConflict(Type inType, SemanticObject currentSO, SemanticObject newSO) {
104             newSO.showConflictError(currentSO, "defined in same type");
105             return null;
106         }
107     };
108
109     private static final Mode introduceMode = new Mode() {
110         SemanticObject handleConflict(Type inType, SemanticObject currentSO, SemanticObject newSO) {
111             if (currentSO.isAbstract() && !newSO.isAbstract()) {
112                 //currentSO.replaceContentsWith(newSO);
113
return currentSO;
114             }
115             if (newSO.isAbstract()) { return newSO; }
116
117             if (newSO.dominates(currentSO)) { return currentSO; }
118             if (currentSO.dominates(newSO)) { return newSO; }
119
120             newSO.showConflictError(currentSO, "introduced member");
121             return newSO;
122         }
123     };
124
125     private SemanticObject addSO(SemanticObject newSO, Mode mode) {
126         for(Iterator i = members.iterator(); i.hasNext(); ) {
127             SemanticObject currentSO = (SemanticObject)i.next();
128
129             //XXX there is a nasty inefficiency that this hides
130
if (currentSO == newSO) return newSO;
131
132             // this means that these both effectively name the same member
133
if (currentSO.conflictsWith(newSO)) {
134                 SemanticObject removeSO = mode.handleConflict(map.getType(), currentSO, newSO);
135                 if (removeSO != null) {
136                     if (removeSO == currentSO) {
137                         i.remove();
138                         members.add(newSO);
139                         return currentSO;
140                     } else if (removeSO == newSO) {
141                         return newSO;
142                     }
143                 }
144                 return null;
145             }
146         }
147         members.add(newSO);
148         return null;
149     }
150
151     public void addDeclaredSO(SemanticObject newSO) {
152         addSO(newSO, addMode);
153     }
154
155     public SemanticObject addIntroducedSO(SemanticObject newSO) {
156         return addSO(newSO, introduceMode);
157     }
158
159     private boolean containsMissingTypes(Exprs exprs) {
160         if (exprs == null) return false;
161
162         for (int i=0; i < exprs.size(); i++) {
163             if (exprs.get(i).getType().isMissing()) {
164                 return true;
165             }
166         }
167
168         return false;
169     }
170
171
172     private boolean isAccessible(SemanticObject o, ASTObject fromWhere) {
173         return o.isAccessible(fromWhere) &&
174             map.getType().isAccessible(fromWhere);
175     }
176
177     public SemanticObject resolve(ASTObject fromWhere, Exprs params, boolean showError) {
178         SemanticObject foundSemanticObject = null;
179         List possibleSemanticObjects = null;
180
181         for(Iterator i = members.iterator(); i.hasNext(); ) {
182             SemanticObject object = (SemanticObject)i.next();
183
184             if (object.isApplicable(params) && isAccessible(object, fromWhere)) {
185                 if (foundSemanticObject == null) {
186                     foundSemanticObject = object;
187                 } else if (object.isMoreSpecificThan(foundSemanticObject)) {
188 // System.out.println(prettyIdString(name, params) +
189
// " replacing " + foundSemanticObject.toShortString() +
190
// " with more specific " + object.toShortString());
191
foundSemanticObject = object;
192                 } else if (foundSemanticObject.isMoreSpecificThan(object)) {
193 // System.out.println(prettyIdString(name, params) +
194
// " not replacing " + foundSemanticObject.toShortString() +
195
// " with less specific " + object.toShortString());
196
continue;
197                 } else if (containsMissingTypes(params)) {
198                     return map.getNotFoundSemanticObject();
199                 } else {
200                     // no clear most specific object
201
if (possibleSemanticObjects == null) possibleSemanticObjects = new ArrayList();
202                     possibleSemanticObjects.add(foundSemanticObject);
203                     possibleSemanticObjects.add(object);
204                 }
205             }
206         }
207
208         if (foundSemanticObject == null) {
209             //System.out.println("not found in group: " + name);
210
if (showError && !containsMissingTypes(params)) showNotFoundError(fromWhere, params);
211             return map.getNotFoundSemanticObject();
212         }
213
214         if (possibleSemanticObjects != null) {
215             for (Iterator i = possibleSemanticObjects.iterator(); i.hasNext(); ) {
216                 SemanticObject possibleSemanticObject = (SemanticObject)i.next();
217                 if (!foundSemanticObject.isMoreSpecificThan(possibleSemanticObject)) {
218                     if (showError && !containsMissingTypes(params)) getCompiler().showError(
219                             fromWhere,
220                             "two applicable and accessible " + map.getSemanticObjectTypeName() +
221                             "s are equally specific: " + possibleSemanticObject.toShortString() + " and " +
222                             foundSemanticObject.toShortString() + " in "
223                             + map.getType().getPrettyString()
224                     );
225                     return map.getNotFoundSemanticObject();
226                 }
227             }
228         }
229         return foundSemanticObject;
230     }
231
232     private void showNotFoundError(ASTObject fromWhere, Exprs params) {
233         String JavaDoc message;
234         String JavaDoc kind = map.getSemanticObjectTypeName();
235         if (kind.equals("constructor")) {
236             message = prettyIdString(map.getType().getPrettyString(), params);
237         } else {
238             message = prettyIdString(name, params);
239         }
240
241         message = getExplanationString(message, fromWhere, params);
242         getCompiler().showError(fromWhere, message);
243     }
244
245     private String JavaDoc prettyIdString(String JavaDoc id, Exprs args) {
246         if (args == null) return id;
247
248         StringBuffer JavaDoc message = new StringBuffer JavaDoc();
249         if (id.equals("new")) {
250             id = map.getType().getPrettyString();
251         }
252         message.append(id);
253         if (args != null) {
254             message.append("(");
255             for(int i=0; i<args.size(); i++) {
256                 if (i > 0) message.append(", ");
257                 message.append(args.get(i).getType().getString());
258             }
259             message.append(")");
260         }
261         return message.toString();
262     }
263
264
265     private String JavaDoc getExplanationString(String JavaDoc message, ASTObject fromWhere, Exprs parameters) {
266         if (!map.getType().isAccessible(fromWhere)) {
267             return "declaring type " + map.getType().getPrettyString() +
268                    " is not accessible here";
269         }
270         
271         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(message);
272         String JavaDoc shortString = null;
273         int notAccessibleMethods = 0;
274         int notApplicableMethods = 0;
275
276         buf.append(" not found in " + map.getType().getPrettyString());
277
278         if (fromWhere == null) return buf.toString();
279
280         for(Iterator i = members.iterator(); i.hasNext(); ) {
281             SemanticObject object = (SemanticObject)i.next();
282
283             if (object.isApplicable(parameters)) {
284                 if (!isAccessible(object, fromWhere)) {
285                     if (notAccessibleMethods == 0) {
286                         shortString =
287                             object.toShortString() + " has " +
288                             object.getModifiers().getAccessValueString() + " access";
289                     }
290                     buf.append("\n inaccessible " + map.getSemanticObjectTypeName() +
291                                " found: " + object.toShortString()
292                                +" from "+fromWhere.getLexicalType().toShortString());
293                     notAccessibleMethods += 1;
294                 }
295             } else if (object.isAlmostApplicable(parameters)) {
296                 if (notAccessibleMethods == 0 && notApplicableMethods == 0) {
297                     shortString =
298                         message + " doesn't match expected formals for " + object.toShortString();
299                 }
300
301                 buf.append("\n not applicable " + map.getSemanticObjectTypeName() +
302                             " found: " + object.toShortString());
303                 notApplicableMethods += 1;
304             }
305         }
306         if (shortString != null && (notAccessibleMethods == 1 || notApplicableMethods <= 1)) {
307             return shortString;
308         }
309
310         return buf.toString();
311     }
312     
313     public boolean isEmpty() {
314         return members.size() == 0;
315     }
316     
317     public String JavaDoc toString() {
318         return "group(" + name + ": " + members + ")";
319     }
320 }
321
Popular Tags