/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * This file was originally derived from the Polyglot extensible compiler framework. * * (C) Copyright 2000-2007 Polyglot project group, Cornell University * (C) Copyright IBM Corporation 2007-2012. */ package polyglot.types; import java.util.*; import polyglot.main.Reporter; import polyglot.util.CollectionUtil; import polyglot.util.InternalCompilerError; import x10.util.CollectionFactory; /** * 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<QName> nocache; protected final static Collection<String> report_topics = CollectionUtil.list(Reporter.types, Reporter.resolver, Reporter.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 = CollectionFactory.newHashSet(); } public Package findPackage(QName name) throws SemanticException { return inner.findPackage(name); } public boolean packageExists(QName name) { return inner.packageExists(name); } /** * Find a type by name. */ public List<Type> find(QName name) throws SemanticException { Reporter reporter = ts.extensionInfo().getOptions().reporter; if (reporter.should_report(report_topics, 3)) reporter.report(3, "MemberCR.find(" + name + ")"); if (nocache.contains(name)) { throw new NoClassException(name.toString()); } List<Type> n = ts.systemResolver().check(name); if (n != null) { return n; } SemanticException error = null; // First, just try the long name. try { if (reporter.should_report(report_topics, 2)) reporter.report(2, "MCR: loading " + name + " from " + inner); return inner.find(name); } catch (SemanticException e) { if (reporter.should_report(report_topics, 2)) reporter.report(2, "MCR: " + e.getMessage()); if (name.qualifier() == null) { 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. QName prefix = name.qualifier(); Name suffix = name.name(); // We should have thrown an exception above if prefix is null. assert prefix != null; // 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 (reporter.should_report(report_topics, 2)) reporter.report(2, "MCR: loading prefix " + prefix); n = find(prefix); List<Type> result = new ArrayList<Type>(); for (Type q : n) { result.addAll(findMember(q, suffix)); } return result; } catch (SemanticException e) { } if (install) { nocache.add(name); } throw error; } /** * Find a single type by name. */ public Type findOne(QName name) throws SemanticException { List<Type> res = find(name); if (res == null || res.size() != 1) throw new InternalCompilerError("Unexpected result when looking up "+name+": "+res); return res.get(0); } protected List<Type> findMember(Type container, Name name) throws SemanticException { if (container instanceof ClassType) { ClassType ct = (ClassType) container; Reporter reporter = ts.extensionInfo().getOptions().reporter; if (reporter.should_report(report_topics, 2)) reporter.report(2, "MCR: found prefix " + ct); // Uncomment if we should search superclasses // return ct.resolver().find(name); Type n = ct.memberTypeMatching(ts.MemberTypeMatcher(ct, name, ts.emptyContext())); if (n != null) { if (reporter.should_report(report_topics, 2)) reporter.report(2, "MCR: found member of " + ct + ": " + n); return CollectionUtil.<Type>list(n); } } throw new NoClassException(container.fullName() + "." + name); } }