private JavaSymbol findMemberType( Env env, JavaSymbol.TypeJavaSymbol site, String name, JavaSymbol.TypeJavaSymbol c) { JavaSymbol bestSoFar = symbolNotFound; for (JavaSymbol symbol : c.members().lookup(name)) { if (symbol.kind == JavaSymbol.TYP) { return isAccessible(env, site, symbol) ? symbol : new AccessErrorJavaSymbol(symbol, Symbols.unknownType); } } if (c.getSuperclass() != null) { JavaSymbol symbol = findMemberType(env, site, name, c.getSuperclass().symbol); if (symbol.kind < bestSoFar.kind) { bestSoFar = symbol; } } if (c.getInterfaces() == null) { // Invariant to check that interfaces are not set only when we are looking into the symbol we // are currently completing. // required for generics Preconditions.checkState( c.completing, "interfaces of a symbol not currently completing are not set."); Preconditions.checkState(c == site); } else { for (JavaType interfaceType : c.getInterfaces()) { JavaSymbol symbol = findMemberType(env, site, name, interfaceType.symbol); if (symbol.kind < bestSoFar.kind) { bestSoFar = symbol; } } } return bestSoFar; }
/** Finds field with given name. */ private Resolution findField( Env env, JavaSymbol.TypeJavaSymbol site, String name, JavaSymbol.TypeJavaSymbol c) { Resolution bestSoFar = unresolved(); Resolution resolution = new Resolution(); for (JavaSymbol symbol : c.members().lookup(name)) { if (symbol.kind == JavaSymbol.VAR) { if (isAccessible(env, site, symbol)) { resolution.symbol = symbol; resolution.type = resolveTypeSubstitution(symbol.type, c.type); return resolution; } else { return Resolution.resolution(new AccessErrorJavaSymbol(symbol, Symbols.unknownType)); } } } if (c.getSuperclass() != null) { resolution = findField(env, site, name, c.getSuperclass().symbol); if (resolution.symbol.kind < bestSoFar.symbol.kind) { resolution.type = resolveTypeSubstitution(resolution.symbol.type, c.getSuperclass()); bestSoFar = resolution; } } for (JavaType interfaceType : c.getInterfaces()) { resolution = findField(env, site, name, interfaceType.symbol); if (resolution.symbol.kind < bestSoFar.symbol.kind) { bestSoFar = resolution; } } return bestSoFar; }
/** Is given class a subclass of given base class? */ @VisibleForTesting static boolean isSubClass(JavaSymbol.TypeJavaSymbol c, JavaSymbol base) { // TODO get rid of null check if (c == null) { return false; } // TODO see Javac if (c == base) { // same class return true; } else if ((base.flags() & Flags.INTERFACE) != 0) { // check if class implements base for (JavaType interfaceType : c.getInterfaces()) { if (isSubClass(interfaceType.symbol, base)) { return true; } } // check if superclass implements base return isSubClass(superclassSymbol(c), base); } else { // check if class extends base or its superclass extends base return isSubClass(superclassSymbol(c), base); } }