/** * @param candidate candidate * @param bestSoFar previously found best match */ private JavaSymbol selectBest( Env env, JavaSymbol.TypeJavaSymbol site, List<JavaType> argTypes, JavaSymbol candidate, JavaSymbol bestSoFar, boolean autoboxing) { // TODO get rid of null check if (candidate.kind >= JavaSymbol.ERRONEOUS || !isInheritedIn(candidate, site) || candidate.type == null) { return bestSoFar; } JavaSymbol.MethodJavaSymbol methodJavaSymbol = (JavaSymbol.MethodJavaSymbol) candidate; boolean isVarArgs = methodJavaSymbol.isVarArgs(); boolean usesTypeParameter = usesTypeParameter(methodJavaSymbol); if (!isArgumentsAcceptable( argTypes, ((JavaType.MethodJavaType) candidate.type).argTypes, isVarArgs, autoboxing, usesTypeParameter)) { return bestSoFar; } // TODO ambiguity, errors, ... if (!isAccessible(env, site, candidate)) { return new AccessErrorJavaSymbol(candidate, Symbols.unknownType); } JavaSymbol mostSpecific = selectMostSpecific(candidate, bestSoFar); if (mostSpecific.isKind(JavaSymbol.AMBIGUOUS)) { // same signature, we keep the first symbol found (overrides the other one). mostSpecific = bestSoFar; } return mostSpecific; }
@Override public void visitFormalTypeParameter(String name) { JavaSymbol.TypeVariableJavaSymbol typeVariableSymbol = new JavaSymbol.TypeVariableJavaSymbol(name, symbol); ((TypeVariableJavaType) typeVariableSymbol.type).bounds = Lists.newArrayList(); if (symbol.isTypeSymbol()) { JavaSymbol.TypeJavaSymbol typeJavaSymbol = (JavaSymbol.TypeJavaSymbol) symbol; typeJavaSymbol.typeParameters.enter(typeVariableSymbol); typeJavaSymbol.addTypeParameter((TypeVariableJavaType) typeVariableSymbol.type); } else if (symbol.isMethodSymbol()) { JavaSymbol.MethodJavaSymbol methodSymbol = (JavaSymbol.MethodJavaSymbol) symbol; methodSymbol.typeParameters.enter(typeVariableSymbol); methodSymbol.addTypeParameter((TypeVariableJavaType) typeVariableSymbol.type); } }
/** @return true, if signature of m1 is more specific than signature of m2 */ private boolean isSignatureMoreSpecific(JavaSymbol m1, JavaSymbol m2) { List<JavaType> m1ArgTypes = ((JavaType.MethodJavaType) m1.type).argTypes; List<JavaType> m2ArgTypes = ((JavaType.MethodJavaType) m2.type).argTypes; JavaSymbol.MethodJavaSymbol methodJavaSymbol = (JavaSymbol.MethodJavaSymbol) m1; if (methodJavaSymbol.isVarArgs()) { m1ArgTypes = expandVarArgsToFitSize(m1ArgTypes, m2ArgTypes.size()); } boolean usesTypeParameter = usesTypeParameter(methodJavaSymbol); return isArgumentsAcceptable( m1ArgTypes, m2ArgTypes, ((JavaSymbol.MethodJavaSymbol) m2).isVarArgs(), false, usesTypeParameter); }
/** * Check if a methodTree is overriden. * * @return true if overriden, null if it cannot be decided (method symbol not resolved or lack of * bytecode for super types). */ @CheckForNull public Boolean isOverriding() { if (isStatic() || isPrivate()) { return false; } if (isAnnotatedOverride()) { return true; } if (symbol == null) { return null; } JavaSymbol.MethodJavaSymbol methodJavaSymbol = symbol.overriddenSymbol(); if (methodJavaSymbol != null) { return methodJavaSymbol.isUnknown() ? null : true; } return false; }
@Override public MethodVisitor visitMethod( int flags, String name, String desc, @Nullable String signature, @Nullable String[] exceptions) { Preconditions.checkNotNull(name); Preconditions.checkNotNull(desc); if (!BytecodeCompleter.isSynthetic(flags)) { Preconditions.checkState( (flags & Opcodes.ACC_BRIDGE) == 0, "bridge method not marked as synthetic in class " + className); // TODO(Godin): according to JVMS 4.7.24 - parameter can be marked as synthetic MethodJavaType type = new MethodJavaType( convertAsmTypes(org.objectweb.asm.Type.getArgumentTypes(desc)), convertAsmType(org.objectweb.asm.Type.getReturnType(desc)), getCompletedClassSymbolsType(exceptions), classSymbol); final JavaSymbol.MethodJavaSymbol methodSymbol = new JavaSymbol.MethodJavaSymbol( bytecodeCompleter.filterBytecodeFlags(flags), name, type, classSymbol); classSymbol.members.enter(methodSymbol); if (signature != null) { SignatureReader signatureReader = new SignatureReader(signature); signatureReader.accept(new TypeParameterDeclaration(methodSymbol)); signatureReader.accept(new ReadMethodSignature(methodSymbol)); } methodSymbol.parameters = new Scope(methodSymbol); for (int i = 0; i < type.argTypes.size(); i += 1) { methodSymbol.parameters.enter( new JavaSymbol.VariableJavaSymbol(0, "arg" + i, methodSymbol)); } // checks for annotations on the method and its parameters return new BytecodeMethodVisitor(methodSymbol, this); } return null; }
/** * Check if a methodTree is overriden. * * @return true if overriden, null if it cannot be decided (method symbol not resolved or lack of * bytecode for super types). */ @CheckForNull public Boolean isOverriding() { if (isStatic() || isPrivate()) { return false; } if (isAnnotatedOverride()) { return true; } if (symbol == null) { return null; } return symbol.overriddenSymbol() != null; }