001 package org.mesopotamia.lang.java; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 import java.util.List; 006 import java.util.logging.Logger; 007 008 import org.mesopotamia.LanguageElement; 009 import org.mesopotamia.MesopotamiaException; 010 import org.mesopotamia.MesopotamiaNode; 011 import org.mesopotamia.NodeData; 012 import org.mesopotamia.RepositoryLanguage; 013 import org.mesopotamia.Scan; 014 import org.mesopotamia.SourceUnit; 015 import org.mesopotamia.lang.java.TypeDefinition.ParameterMatch; 016 import org.mesopotamia.lang.java.ref.Info; 017 import org.mesopotamia.lang.java.ref.MethodInfo; 018 import org.mesopotamia.lang.java.ref.Reference; 019 import org.mesopotamia.lang.java.ref.Scope; 020 import org.mesopotamia.lang.java.ref.TypeInfo; 021 import org.mesopotamia.lang.java.ref.TypeSpecInfo; 022 import org.mesopotamia.lang.java.ref.VariableInfo; 023 import org.w3c.dom.Element; 024 025 import biz.hammurapi.util.CollectionVisitable; 026 import biz.hammurapi.util.Visitor; 027 028 @SuppressWarnings("unchecked") 029 public class NewExpression extends PrimaryExpression implements TypeDefinitionOrAnonymous, Reference<MethodInfo> { 030 private static final Logger logger = Logger.getLogger(NewExpression.class.getName()); 031 032 private Type specType; 033 private int dimensions; 034 035 private List<ArrayInitializer> ArrayInitializers; 036 037 public NewExpression( 038 NodeData xData, 039 Class<?> context, 040 Scan scan, 041 RepositoryLanguage language, 042 Object environment) throws MesopotamiaException { 043 super(xData, context, scan, language, environment); 044 045 Arguments = select(Expression.class, "ELIST/*"); 046 // TypeSpecification = (TypeSpecification) selectSingleElement(TypeSpecification.class, "TYPE"); 047 Fields = select(Field.class, "OBJBLOCK/*"); 048 049 LanguageElement firstChild = getChild(0); 050 if (firstChild instanceof Type) { 051 specType = (Type) firstChild; 052 // if (language.supportsTokenName("TYPE_ARGUMENTS") && specType instanceof LanguageElement) { 053 // TypeArguments = ((LanguageElement) specType).select(TypeArgument.class, "TYPE_ARGUMENTS/TYPE_ARGUMENT"); 054 // } 055 MesopotamiaNode fNode = firstChild.getNode(); 056 List<MesopotamiaNode> siblings = fNode.getParent().getChildren(); 057 int nextSiblingPosition = fNode.getPosition()+1; 058 if (siblings.size()>nextSiblingPosition) { 059 MesopotamiaNode nextSibling = siblings.get(nextSiblingPosition); 060 while ("ARRAY_DECLARATOR".equals(nextSibling.getTypeName())) { 061 ++dimensions; 062 siblings = nextSibling.getChildren(); 063 if (siblings.isEmpty()) { 064 break; 065 } 066 nextSibling = siblings.get(0); 067 } 068 } 069 } 070 071 ArrayInitializers = select(ArrayInitializer.class, "ARRAY_INIT/*"); 072 } 073 074 public void toDom(Element holder) { 075 super.toDom(holder); 076 077 // Serialize attributes 078 // setElement(holder, "TypeArguments", TypeArguments); 079 setElement(holder, "Arguments", Arguments); 080 // setElement(holder, "TypeSpecification", TypeSpecification); 081 } 082 083 // Attributes 084 // private List<TypeArgument> TypeArguments = emptyList; 085 086 private List<Expression> Arguments; 087 088 // private TypeSpecification TypeSpecification; 089 090 private List<Field> Fields; 091 092 // Accessors 093 // public List<TypeArgument> getTypeArguments() { 094 // return TypeArguments; 095 // } 096 097 public List<Expression> getArguments() { 098 return Arguments; 099 } 100 101 // public TypeSpecification getTypeSpecification() { 102 // return TypeSpecification; 103 // } 104 105 /** 106 * @return List of fields for anonymous classes 107 */ 108 public List<Field> getFields() { 109 return Fields; 110 } 111 112 public Type getSpecificationType() { 113 return specType; 114 } 115 116 public int getDimensions() { 117 return dimensions; 118 } 119 120 public List<ArrayInitializer> getArrayInitializer() { 121 return ArrayInitializers; 122 } 123 124 protected void acceptChildren(Visitor visitor) { 125 // Visiting non-text attributes 126 // new CollectionVisitable(TypeArguments, false).accept(visitor); 127 new CollectionVisitable(Arguments, false).accept(visitor); 128 new CollectionVisitable(ArrayInitializers, false).accept(visitor); 129 new CollectionVisitable(Fields, false).accept(visitor); 130 } 131 132 public MethodInfo findMethod(String name, String[] parameterTypes) { 133 MethodInfo candidate = findTypeMethod(name, parameterTypes); 134 135 if (candidate!=null) { 136 return candidate; // Does Java look for more specific methods in enclosed scope? 137 } 138 139 Scope ec = findParent(Scope.class); 140 return ec==null ? null : ec.findMethod(name, parameterTypes); 141 } 142 143 public TypeInfo findType(String name) { 144 TypeInfo ret = findNestedType(name); 145 if (ret!=null) { 146 return ret; 147 } 148 149 Scope ec = findParent(Scope.class); 150 return ec==null ? null : ec.findType(name); 151 } 152 153 public VariableInfo findVariable(String name) { 154 VariableInfo ret = findTypeVariable(name); 155 if (ret!=null) { 156 return ret; 157 } 158 159 Scope ec = findParent(Scope.class); 160 return ec==null ? null : ec.findVariable(name); 161 } 162 163 public boolean isKindOf(String superFcn) { 164 TypeSpecInfo tsi = getTypeSpecInfo(); 165 if (tsi!=null) { 166 TypeInfo ti = TypeSpecification.toTypeInfo(tsi, findParent(Scope.class)); 167 if (ti!=null) { 168 return ti.isKindOf(superFcn); 169 } 170 } 171 return JAVA_LANG_OBJECT.equals(superFcn); 172 } 173 174 public String getFcn() { 175 if (!fcnCalculated) { 176 super.getFcn(); 177 SourceUnit su = getSourceUnit(); 178 if (su instanceof JavaSourceUnit) { 179 ((JavaSourceUnit) su).registerLocalOrAnonymous(fcn, this); 180 } 181 } 182 183 return fcn; 184 } 185 186 public TypeInfo findNestedType(String name) { 187 for (Field field: getFields()) { 188 if (field instanceof TypeDefinition) { 189 final TypeDefinition td = (TypeDefinition) field; 190 if (td.getName().equals(name)) { 191 return td; 192 } 193 } 194 } 195 196 TypeSpecInfo tsi = getTypeSpecInfo(); 197 if (tsi==null || tsi.getTypeInfo()==null) { 198 return null; 199 } 200 TypeInfo ti = TypeSpecification.toTypeInfo(tsi, findParent(Scope.class)); 201 return ti==null ? null : ti.findNestedType(name); 202 } 203 204 public MethodInfo findTypeMethod(String name, String[] parameterTypes) { 205 List<TypeSpecInfo> pTypes=new ArrayList<TypeSpecInfo>(); 206 boolean pTypesResolved = true; 207 for (int i=0; parameterTypes!=null && i<parameterTypes.length; ++i) { 208 if (parameterTypes[i]==null) { 209 StringBuffer sig = new StringBuffer(); 210 for (String pt: parameterTypes) { 211 sig.append(sig.length()==0 ? "(" : ", "); 212 sig.append(pt); 213 } 214 sig.append(")"); 215 logger.warning("Could not resolve method "+name+sig.toString()+" argument "+i+" type ["+getLocation()+"]"); 216 pTypes.add(null); 217 pTypesResolved = false; 218 } else { 219 int dimensions=0; 220 String typeName = parameterTypes[i]; 221 while (typeName.endsWith(TypeSpecInfo.ARRAY_BRACKETS)) { 222 ++dimensions; 223 typeName=typeName.substring(0, typeName.length()-TypeSpecInfo.ARRAY_BRACKETS.length()); 224 } 225 final TypeInfo ptInfo = findType(typeName); 226 if (ptInfo==null) { 227 logger.warning("Type "+ptInfo+" not found"); 228 return null; 229 } 230 final int d = dimensions; 231 pTypes.add(new TypeSpecInfo() { 232 233 public int getDimensions() { 234 return d; 235 } 236 237 public TypeInfo getTypeInfo() { 238 return ptInfo; 239 } 240 241 }); 242 } 243 } 244 245 MethodInfo pnumMatch = null; 246 MethodInfo candidate = null; 247 for (Field field: getFields()) { 248 if (field instanceof MethodDefinition) { 249 MethodDefinition method = (MethodDefinition) field; 250 if (!method.getName().equals(name)) { 251 continue; 252 } 253 254 List<TypeSpecInfo> mTypes = method.getParameterTypes(); 255 ParameterMatch matchResult = TypeDefinition.match(mTypes, pTypes); 256 if (matchResult == ParameterMatch.FULL_MATCH) { 257 return method; 258 } else if (matchResult == ParameterMatch.MATCH) { 259 candidate = TypeDefinition.selectMoreSpecific(candidate, method); 260 } else if (!pTypesResolved && pnumMatch==null) { 261 pnumMatch = method; 262 } 263 } 264 } 265 266 TypeSpecInfo tsi = getTypeSpecInfo(); 267 if (tsi==null || tsi.getTypeInfo()==null) { 268 return candidate==null ? pnumMatch : candidate; 269 } 270 TypeInfo ti = TypeSpecification.toTypeInfo(tsi, findParent(Scope.class)); 271 if (ti==null) { 272 return candidate==null ? pnumMatch : candidate; 273 } 274 275 if (candidate==null && !pTypesResolved) { 276 return pnumMatch; 277 } 278 279 return TypeDefinition.selectMoreSpecific(candidate, ti.findTypeMethod(name, parameterTypes)); 280 } 281 282 public VariableInfo findTypeVariable(String name) { 283 for (Field field: getFields()) { 284 if (field instanceof VariableDefinition) { 285 final VariableDefinition vd = (VariableDefinition) field; 286 if (vd.getName().equals(name)) { 287 return vd; 288 } 289 } 290 } 291 292 TypeSpecInfo tsi = getTypeSpecInfo(); 293 if (tsi==null || tsi.getTypeInfo()==null) { 294 return null; 295 } 296 TypeInfo ti = TypeSpecification.toTypeInfo(tsi, findParent(Scope.class)); 297 return ti==null ? null : ti.findTypeVariable(name); 298 } 299 300 301 public MethodInfo findConstructor(String[] argumentTypes) { 302 // TODO ??? 303 return null; 304 } 305 306 public TypeInfo getDeclaringType() { 307 return null; 308 } 309 310 public List<String> getModifiers() { 311 return emptyList; 312 } 313 314 public String getName() { 315 return null; 316 } 317 318 @Override 319 public TypeSpecInfo getTypeSpecInfo() { 320 final Info info; 321 if (specType instanceof Identifier) { 322 Scope es = findParent(Scope.class); 323 info = ((Identifier) specType).getInfo(es); 324 } else { 325 info = specType.getInfo(); 326 } 327 328 return new TypeSpecInfo() { 329 330 public int getDimensions() { 331 return dimensions; 332 } 333 334 public TypeInfo getTypeInfo() { 335 return info instanceof TypeInfo ? (TypeInfo) info : null; 336 } 337 338 }; 339 } 340 341 public MethodInfo getInfo() { 342 Scope scope = findParent(Scope.class); 343 if (scope == null) { 344 return null; 345 } 346 347 List<Expression> args = getArguments(); 348 String[] argumentTypes = new String[args.size()]; 349 Iterator<Expression> it = args.iterator(); 350 for (int i=0; it.hasNext(); ++i) { 351 argumentTypes[i] = TypeSpecification.toString(it.next().getTypeSpecInfo()); 352 } 353 354 TypeInfo ti = TypeSpecification.toTypeInfo(getTypeSpecInfo(), scope); 355 return ti==null ? null : ti.findConstructor(argumentTypes); 356 } 357 }