1 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 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 name) { 43 this(map, name, new LinkedList()); 44 } 45 46 private SemanticGroup(SemanticMap map, String 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 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 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 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 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 if (currentSO == newSO) return newSO; 131 132 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 foundSemanticObject = object; 192 } else if (foundSemanticObject.isMoreSpecificThan(object)) { 193 continue; 197 } else if (containsMissingTypes(params)) { 198 return map.getNotFoundSemanticObject(); 199 } else { 200 if (possibleSemanticObjects == null) possibleSemanticObjects = new ArrayList(); 202 possibleSemanticObjects.add(foundSemanticObject); 203 possibleSemanticObjects.add(object); 204 } 205 } 206 } 207 208 if (foundSemanticObject == null) { 209 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 message; 234 String 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 prettyIdString(String id, Exprs args) { 246 if (args == null) return id; 247 248 StringBuffer message = new StringBuffer (); 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 getExplanationString(String 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 buf = new StringBuffer (message); 272 String 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 toString() { 318 return "group(" + name + ": " + members + ")"; 319 } 320 } 321 | Popular Tags |