protected JL5Call_c reconstruct(Receiver target, List arguments, List typeArgs) { if (target != this.target || !CollectionUtil.equals(arguments, this.arguments) || !CollectionUtil.equals(typeArgs, this.typeArguments)) { JL5Call_c n = (JL5Call_c) copy(); n.target = target; n.arguments = TypedList.copyAndCheck(arguments, Expr.class, true); n.typeArguments = TypedList.copyAndCheck(typeArgs, TypeNode.class, false); return n; } return this; }
/** Reconstruct the statement. */ protected For_c reconstruct(List inits, Expr cond, List iters, Stmt body) { if (!CollectionUtil.equals(inits, this.inits) || cond != this.cond || !CollectionUtil.equals(iters, this.iters) || body != this.body) { For_c n = (For_c) copy(); n.inits = TypedList.copyAndCheck(inits, ForInit.class, true); n.cond = cond; n.iters = TypedList.copyAndCheck(iters, ForUpdate.class, true); n.body = body; return n; } return this; }
/** Reconstruct the statement expression. */ protected StmtExpr_c reconstruct(List<Stmt> statements, Expr result) { if (!CollectionUtil.allEqual(statements, this.statements) || result != this.result) { StmtExpr_c n = (StmtExpr_c) copy(); n.statements = TypedList.copyAndCheck(statements, Stmt.class, true); n.result = result; return n; } return this; }
/** Returns true if the procedure has the given formal parameter types. */ public boolean hasFormals( List<Type> otherFormalTypes, List<TypeVariable> otherTypeVariables, List<Type> typeArguments, Context context) { if (isGeneric() != isGeneric(otherTypeVariables)) return false; if (formalTypes().size() != otherFormalTypes.size()) return false; if (isGeneric() && typeVariables().size() != otherTypeVariables.size()) return false; if (!CollectionUtil.allElementwise( this.typeVariables(), otherTypeVariables, new TypeVariableEquals(context))) { return false; } if (!CollectionUtil.allElementwise( this.formalTypes(), otherFormalTypes, new TypeEquals(context))) { return false; } return true; }
/** * Find a type object in the context of the class. * * @param name The name to search for. */ public Named find(Matcher<Named> matcher, Context context) throws SemanticException { Name name = matcher.name(); if (Report.should_report(TOPICS, 2)) Report.report(2, "Looking for " + name + " in " + this); if (!(type instanceof ClassType)) { throw new NoClassException(name.toString(), type); } ClassType type = (ClassType) this.type; Named m = null; QName fullName = null; QName rawName = null; if (type.isGloballyAccessible()) { fullName = QName.make(type.fullName(), name); QName q = ts.getTransformedClassName(type.def()); rawName = QName.make(q.qualifier(), Name.make(q.name() + "$" + name)); } if (fullName != null) { // First check the system resolver. m = ts.systemResolver().check(fullName); // Try the raw class file name. if (m == null) { m = ts.systemResolver().check(rawName); } if (m == null) { // Go to disk, but only if there is no job for the type. // If there is a job, all members should be in the resolver // already. boolean useLoadedResolver = true; if (type instanceof ParsedTypeObject) { ParsedTypeObject pto = (ParsedTypeObject) type; if (pto.job() != null) { useLoadedResolver = false; } } if (useLoadedResolver) { try { m = ts.systemResolver().find(rawName); } catch (SemanticException e) { // Not found; will fall through to error handling code } } } // If we found something, verify that it matches. if (m != null) { try { m = matcher.instantiate(m); } catch (SemanticException e) { // Doesn't match; try again. m = null; } } } // Check if the member was explicitly declared. if (m == null) { m = type.memberTypeMatching(matcher); } // If we found something, make sure it's accessible. if (m instanceof ClassType) { ClassType mt = (ClassType) m; if (!mt.isMember()) { throw new SemanticException( "Class " + mt + " is not a member class, " + " but was found in " + type + "."); } if (!mt.outer().equals((Object) type)) { throw new SemanticException( "Class " + mt + " is not a member class " + " of " + type + "."); } return mt; } if (m instanceof MemberInstance) { MemberInstance<?> mi = (MemberInstance<?>) m; if (!mi.container().equals((Object) type)) { throw new SemanticException("Type " + mi + " is not a member " + " of " + type + "."); } } if (m != null) { if (!canAccess(m, context.currentClassDef(), context)) { throw new SemanticException("Cannot access member type \"" + m + "\"."); } return m; } // If we struck out, try the super types. // Collect all members of the super types. // Use a Set to eliminate duplicates. Set<Named> acceptable = new HashSet<Named>(); if (type.superClass() != null) { Type sup = type.superClass(); if (sup instanceof ClassType) { Resolver r = ts.classContextResolver((ClassType) sup, context); try { Named n = r.find(matcher); acceptable.add(n); } catch (SemanticException e) { } } } for (Iterator<Type> i = type.interfaces().iterator(); i.hasNext(); ) { Type sup = (Type) i.next(); if (sup instanceof ClassType) { Resolver r = ts.classContextResolver((ClassType) sup, context); try { Named n = r.find(matcher); acceptable.add(n); } catch (SemanticException e) { } } } if (acceptable.size() == 0) { throw new NoClassException(name.toString(), type); } else if (acceptable.size() > 1) { Set<Type> containers = new HashSet<Type>(acceptable.size()); for (Named n : acceptable) { if (n instanceof MemberInstance) { MemberInstance<?> mi = (MemberInstance<?>) n; containers.add(mi.container()); } } if (containers.size() == 2) { Iterator<Type> i = containers.iterator(); Type t1 = (Type) i.next(); Type t2 = (Type) i.next(); throw new SemanticException( "Member \"" + name + "\" of " + type + " is ambiguous; it is defined in both " + t1 + " and " + t2 + "."); } else if (containers.size() == 0) { throw new SemanticException("Member \"" + name + "\" of " + type + " is ambiguous."); } else { throw new SemanticException( "Member \"" + name + "\" of " + type + " is ambiguous; it is defined in " + CollectionUtil.listToString(new ArrayList<Type>(containers)) + "."); } } assert acceptable.size() == 1; Named t = acceptable.iterator().next(); if (Report.should_report(TOPICS, 2)) Report.report(2, "Found member type " + t); return t; }
public String signature() { return container + "(" + CollectionUtil.listToString(formalTypes) + ")"; }
/** Loads member classes using a TopLevelResolver that can only handle top-level classes. */ public class MemberClassResolver implements TopLevelResolver { protected TypeSystem ts; protected TopLevelResolver inner; protected boolean allowRawClasses; protected Set<String> nocache; protected static final Collection<String> report_topics = CollectionUtil.list(Report.types, Report.resolver, Report.loader, "mcr"); /** * Create a member class resolver. * * @param ts The type system * @param inner The resolver for top-level classes */ public MemberClassResolver(TypeSystem ts, TopLevelResolver inner, boolean allowRawClasses) { this.ts = ts; this.inner = inner; this.allowRawClasses = allowRawClasses; this.nocache = new HashSet<String>(); } @Override public boolean packageExists(String name) { return inner.packageExists(name); } /** Find a type by name. */ @Override public Named find(String name) throws SemanticException { if (Report.should_report(report_topics, 3)) Report.report(3, "MemberCR.find(" + name + ")"); if (nocache.contains(name)) { throw new NoClassException(name); } Named n = ts.systemResolver().check(name); if (n != null) { return n; } SemanticException error = null; // First, just try the long name. try { if (Report.should_report(report_topics, 2)) Report.report(2, "MCR: loading " + name + " from " + inner); return inner.find(name); } catch (SemanticException e) { if (Report.should_report(report_topics, 2)) Report.report(2, "MCR: " + e.getMessage()); if (StringUtil.isNameShort(name)) { throw e; } error = e; } boolean install = true; // Now try the prefix of the name and look for a member class // within it named with the suffix. String prefix = StringUtil.getPackageComponent(name); String suffix = StringUtil.getShortNameComponent(name); // Try the full name of the prefix first, then the raw class name, // so that encoded type information and source files are preferred // to the raw class file. try { if (Report.should_report(report_topics, 2)) Report.report(2, "MCR: loading prefix " + prefix); n = find(prefix); // This may be called during deserialization; n's // member classes might not be initialized yet. if (n instanceof ParsedTypeObject) { return findMember(n, suffix); } } catch (SemanticException e) { } if (install) { nocache.add(name); } throw error; } protected Named findMember(Named container, String name) throws SemanticException { if (container instanceof ClassType) { ClassType ct = (ClassType) container; if (Report.should_report(report_topics, 2)) Report.report(2, "MCR: found prefix " + ct); // Uncomment if we should search superclasses // return ct.resolver().find(name); Named n = ct.memberClassNamed(name); if (n != null) { if (Report.should_report(report_topics, 2)) Report.report(2, "MCR: found member of " + ct + ": " + n); return n; } } throw new NoClassException(container.fullName() + "." + name); } }