📄 memberresolver.java
字号:
/* * Javassist, a Java-bytecode translator toolkit. * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved. * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. Alternatively, the contents of this file may be used under * the terms of the GNU Lesser General Public License Version 2.1 or later. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. */package javassist.compiler;import java.util.List;import java.util.Iterator;import javassist.*;import javassist.bytecode.*;import javassist.compiler.ast.*;/* Code generator methods depending on javassist.* classes. */public class MemberResolver implements TokenId { private ClassPool classPool; public MemberResolver(ClassPool cp) { classPool = cp; } public ClassPool getClassPool() { return classPool; } private static void fatal() throws CompileError { throw new CompileError("fatal"); } /** * @param jvmClassName a class name. Not a package name. */ public void recordPackage(String jvmClassName) { String classname = jvmToJavaName(jvmClassName); for (;;) { int i = classname.lastIndexOf('.'); if (i > 0) { classname = classname.substring(0, i); classPool.recordInvalidClassName(classname); } else break; } } public static class Method { public CtClass declaring; public MethodInfo info; public int notmatch; public Method(CtClass c, MethodInfo i, int n) { declaring = c; info = i; notmatch = n; } /** * Returns true if the invoked method is static. */ public boolean isStatic() { int acc = info.getAccessFlags(); return (acc & AccessFlag.STATIC) != 0; } } public Method lookupMethod(CtClass clazz, CtClass currentClass, MethodInfo current, String methodName, int[] argTypes, int[] argDims, String[] argClassNames) throws CompileError { Method maybe = null; // to enable the creation of a recursively called method if (current != null && clazz == currentClass) if (current.getName().equals(methodName)) { int res = compareSignature(current.getDescriptor(), argTypes, argDims, argClassNames); if (res != NO) { Method r = new Method(clazz, current, res); if (res == YES) return r; else maybe = r; } } Method m = lookupMethod(clazz, methodName, argTypes, argDims, argClassNames, maybe != null); if (m != null) return m; else return maybe; } private Method lookupMethod(CtClass clazz, String methodName, int[] argTypes, int[] argDims, String[] argClassNames, boolean onlyExact) throws CompileError { Method maybe = null; List list = clazz.getClassFile2().getMethods(); int n = list.size(); for (int i = 0; i < n; ++i) { MethodInfo minfo = (MethodInfo)list.get(i); if (minfo.getName().equals(methodName)) { int res = compareSignature(minfo.getDescriptor(), argTypes, argDims, argClassNames); if (res != NO) { Method r = new Method(clazz, minfo, res); if (res == YES) return r; else if (maybe == null || maybe.notmatch > res) maybe = r; } } } if (onlyExact) maybe = null; else onlyExact = maybe != null; try { CtClass pclazz = clazz.getSuperclass(); if (pclazz != null) { Method r = lookupMethod(pclazz, methodName, argTypes, argDims, argClassNames, onlyExact); if (r != null) return r; } } catch (NotFoundException e) {} int mod = clazz.getModifiers(); if (Modifier.isAbstract(mod) || Modifier.isInterface(mod)) try { CtClass[] ifs = clazz.getInterfaces(); int size = ifs.length; for (int i = 0; i < size; ++i) { Method r = lookupMethod(ifs[i], methodName, argTypes, argDims, argClassNames, onlyExact); if (r != null) return r; } } catch (NotFoundException e) {} return maybe; } private static final int YES = 0; private static final int NO = -1; /* * Returns YES if actual parameter types matches the given signature. * * argTypes, argDims, and argClassNames represent actual parameters. * * This method does not correctly implement the Java method dispatch * algorithm. * * If some of the parameter types exactly match but others are subtypes of * the corresponding type in the signature, this method returns the number * of parameter types that do not exactly match. */ private int compareSignature(String desc, int[] argTypes, int[] argDims, String[] argClassNames) throws CompileError { int result = YES; int i = 1; int nArgs = argTypes.length; if (nArgs != Descriptor.numOfParameters(desc)) return NO; int len = desc.length(); for (int n = 0; i < len; ++n) { char c = desc.charAt(i++); if (c == ')') return (n == nArgs ? result : NO); else if (n >= nArgs) return NO; int dim = 0; while (c == '[') { ++dim; c = desc.charAt(i++); } if (argTypes[n] == NULL) { if (dim == 0 && c != 'L') return NO; if (c == 'L') i = desc.indexOf(';', i) + 1; } else if (argDims[n] != dim) { if (!(dim == 0 && c == 'L' && desc.startsWith("java/lang/Object;", i))) return NO; // if the thread reaches here, c must be 'L'. i = desc.indexOf(';', i) + 1; result++; if (i <= 0) return NO; // invalid descriptor? } else if (c == 'L') { // not compare int j = desc.indexOf(';', i); if (j < 0 || argTypes[n] != CLASS) return NO; String cname = desc.substring(i, j); if (!cname.equals(argClassNames[n])) { CtClass clazz = lookupClassByJvmName(argClassNames[n]); try { if (clazz.subtypeOf(lookupClassByJvmName(cname))) result++; else return NO; } catch (NotFoundException e) { result++; // should be NO? } } i = j + 1; } else { int t = descToType(c); int at = argTypes[n]; if (t != at) if (t == INT && (at == SHORT || at == BYTE || at == CHAR)) result++; else return NO; } } return NO; } /** * Only used by fieldAccess() in MemberCodeGen and TypeChecker. * * @param jvmClassName a JVM class name. e.g. java/lang/String */ public CtField lookupFieldByJvmName2(String jvmClassName, Symbol fieldSym, ASTree expr) throws NoFieldException { String field = fieldSym.get(); CtClass cc = null; try { cc = lookupClass(jvmToJavaName(jvmClassName), true); } catch (CompileError e) { // EXPR might be part of a qualified class name. throw new NoFieldException(jvmClassName + "/" + field, expr); } try { return cc.getField(field); } catch (NotFoundException e) { // maybe an inner class. jvmClassName = javaToJvmName(cc.getName());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -