Browse Source

line numbers for undefined ids & more

pull/484/head
akuznetsov 4 months ago
parent
commit
9777bae93c

+ 4
- 4
src/main/javassist/compiler/CodeGen.java View File

@@ -184,7 +184,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
/* Expands a simple class name to java.lang.*.
* For example, this converts Object into java/lang/Object.
*/
protected abstract String resolveClassName(String jvmClassName)
protected abstract String resolveClassName(String jvmClassName, int lineNumber)
throws CompileError;

/**
@@ -802,7 +802,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
@Override
public void atDeclarator(Declarator d) throws CompileError {
d.setLocalVar(getMaxLocals());
d.setClassName(resolveClassName(d.getClassName()));
d.setClassName(resolveClassName(d.getClassName(), d.getLineNumber()));

int size;
if (is2word(d.getType(), d.getArrayDim()))
@@ -1656,7 +1656,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
int i = cname.indexOf("[L");
if (i >= 0) {
String name = cname.substring(i + 2, cname.length() - 1);
String name2 = resolveClassName(name);
String name2 = resolveClassName(name, expr.getLineNumber());
if (!name.equals(name2)) {
/* For example, to obtain String[].class,
* "[Ljava.lang.String;" (not "[Ljava/lang/String"!)
@@ -1673,7 +1673,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
}
}
else {
cname = resolveClassName(MemberResolver.javaToJvmName(cname));
cname = resolveClassName(MemberResolver.javaToJvmName(cname), expr.getLineNumber());
cname = MemberResolver.jvmToJavaName(cname);
}


+ 1
- 1
src/main/javassist/compiler/CompileError.java View File

@@ -37,7 +37,7 @@ public class CompileError extends Exception {
reason = String.format("line %d: %s", lineNumber, s);
}

public CompileError(String s) {
private CompileError(String s) {
reason = s;
lex = null;
}

+ 13
- 15
src/main/javassist/compiler/Javac.java View File

@@ -95,7 +95,8 @@ public class Javac {
*/
public CtMember compile(String src) throws CompileError {
int startLine = gen.thisClass.getLinesCount();
Parser p = new Parser(new Lex(src, startLine));
Lex lex = new Lex(src, startLine);
Parser p = new Parser(lex);
ASTList mem = p.parseMember1(stable);
try {
if (mem instanceof FieldDecl)
@@ -107,11 +108,8 @@ public class Javac {
decl.getClassFile2());
return cb;
}
catch (BadBytecode bb) {
throw new CompileError(bb.getMessage());
}
catch (CannotCompileException e) {
throw new CompileError(e.getMessage());
catch (BadBytecode | CannotCompileException bb) {
throw new CompileError(bb.getMessage(), lex.getLineNumber());
}
}

@@ -186,7 +184,7 @@ public class Javac {
return method;
}
catch (NotFoundException e) {
throw new CompileError(e.toString());
throw new CompileError(e.toString(), md.getLineNumber());
}
}

@@ -222,7 +220,7 @@ public class Javac {
Stmnt s = p.parseStatement(stb);
if (p.hasMore())
throw new CompileError(
"the method/constructor body must be surrounded by {}");
"the method/constructor body must be surrounded by {}", s.getLineNumber());

boolean callSuper = false;
if (method instanceof CtConstructor)
@@ -234,7 +232,7 @@ public class Javac {
return bytecode;
}
catch (NotFoundException e) {
throw new CompileError(e.toString());
throw new CompileError(e.toString(), -1);
}
}

@@ -446,7 +444,7 @@ public class Javac {

ProceedHandler h = new ProceedHandler() {
@Override
public void doit(JvstCodeGen gen, Bytecode b, ASTList args)
public void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber)
throws CompileError
{
ASTree expr = new Member(m, texpr.getLineNumber());
@@ -459,7 +457,7 @@ public class Javac {
}

@Override
public void setReturnType(JvstTypeChecker check, ASTList args)
public void setReturnType(JvstTypeChecker check, ASTList args, int lineNumber)
throws CompileError
{
ASTree expr = new Member(m, texpr.getLineNumber());
@@ -492,7 +490,7 @@ public class Javac {

ProceedHandler h = new ProceedHandler() {
@Override
public void doit(JvstCodeGen gen, Bytecode b, ASTList args)
public void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber)
throws CompileError
{
Expr expr = Expr.make(TokenId.MEMBER,
@@ -503,7 +501,7 @@ public class Javac {
}

@Override
public void setReturnType(JvstTypeChecker check, ASTList args)
public void setReturnType(JvstTypeChecker check, ASTList args, int lineNumber)
throws CompileError
{
Expr expr = Expr.make(TokenId.MEMBER,
@@ -538,14 +536,14 @@ public class Javac {

ProceedHandler h = new ProceedHandler() {
@Override
public void doit(JvstCodeGen gen, Bytecode b, ASTList args)
public void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber)
throws CompileError
{
gen.compileInvokeSpecial(texpr, methodIndex, descriptor, args);
}

@Override
public void setReturnType(JvstTypeChecker c, ASTList args)
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
c.compileInvokeSpecial(texpr, classname, methodname, descriptor, args);

+ 23
- 23
src/main/javassist/compiler/JvstCodeGen.java View File

@@ -147,7 +147,7 @@ public class JvstCodeGen extends MemberCodeGen {
if (arrayDim != 1 || exprType != CLASS)
throw new CompileError("invalid type for " + paramArrayName, expr.getLineNumber());

atAssignParamList(paramTypeList, bytecode);
atAssignParamList(paramTypeList, bytecode, expr.getLineNumber());
if (!doDup)
bytecode.addOpcode(POP);
}
@@ -155,7 +155,7 @@ public class JvstCodeGen extends MemberCodeGen {
super.atFieldAssign(expr, op, left, right, doDup);
}

protected void atAssignParamList(CtClass[] params, Bytecode code)
protected void atAssignParamList(CtClass[] params, Bytecode code, int lineNumber)
throws CompileError
{
if (params == null)
@@ -167,7 +167,7 @@ public class JvstCodeGen extends MemberCodeGen {
code.addOpcode(DUP);
code.addIconst(i);
code.addOpcode(AALOAD);
compileUnwrapValue(params[i], code);
compileUnwrapValue(params[i], code, lineNumber);
code.addStore(varNo, params[i]);
varNo += is2word(exprType, arrayDim) ? 2 : 1;
}
@@ -201,10 +201,10 @@ public class JvstCodeGen extends MemberCodeGen {
protected void atCastToRtype(CastExpr expr) throws CompileError {
expr.getOprand().accept(this);
if (exprType == VOID || isRefType(exprType) || arrayDim > 0)
compileUnwrapValue(returnType, bytecode);
compileUnwrapValue(returnType, bytecode, expr.getLineNumber());
else if (returnType instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType)returnType;
int destType = MemberResolver.descToType(pt.getDescriptor());
int destType = MemberResolver.descToType(pt.getDescriptor(), expr.getLineNumber());
atNumCastExpr(exprType, destType);
exprType = destType;
arrayDim = 0;
@@ -219,7 +219,7 @@ public class JvstCodeGen extends MemberCodeGen {
if (isRefType(exprType) || arrayDim > 0)
return; // Object type. do nothing.

CtClass clazz = resolver.lookupClass(exprType, arrayDim, className);
CtClass clazz = resolver.lookupClass(exprType, arrayDim, className, expr.getLineNumber());
if (clazz instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType)clazz;
String wrapper = pt.getWrapperName();
@@ -249,7 +249,7 @@ public class JvstCodeGen extends MemberCodeGen {
if (method instanceof Member) {
String name = ((Member)method).get();
if (procHandler != null && name.equals(proceedName)) {
procHandler.doit(this, bytecode, (ASTList)expr.oprand2());
procHandler.doit(this, bytecode, (ASTList)expr.oprand2(), expr.getLineNumber());
return;
}
else if (name.equals(cflowName)) {
@@ -364,7 +364,7 @@ public class JvstCodeGen extends MemberCodeGen {
for (int k = 0; k < n; ++k) {
CtClass p = params[k];
regno += bytecode.addLoad(regno, p);
setType(p);
setType(p, a.getLineNumber());
types[i] = exprType;
dims[i] = arrayDim;
cnames[i] = className;
@@ -420,7 +420,7 @@ public class JvstCodeGen extends MemberCodeGen {
atMethodArgs(args, new int[nargs], new int[nargs],
new String[nargs]);
bytecode.addInvokespecial(methodIndex, descriptor);
setReturnType(descriptor, false, false);
setReturnType(descriptor, false, false, target.getLineNumber());
addNullIfVoid();
}

@@ -569,7 +569,7 @@ public class JvstCodeGen extends MemberCodeGen {
className = jvmJavaLangObject;
}
else
setType(cc);
setType(cc, cc.getLinesCount());

Declarator decl
= new Declarator(exprType, className, arrayDim,
@@ -593,7 +593,7 @@ public class JvstCodeGen extends MemberCodeGen {
while ((c = typeDesc.charAt(dim)) == '[')
++dim;

int type = MemberResolver.descToType(c);
int type = MemberResolver.descToType(c, -1);
String cname = null;
if (type == CLASS) {
if (dim == 0)
@@ -653,7 +653,7 @@ public class JvstCodeGen extends MemberCodeGen {
return 8;
}

protected void compileUnwrapValue(CtClass type, Bytecode code)
protected void compileUnwrapValue(CtClass type, Bytecode code, int lineNumber)
throws CompileError
{
if (type == CtClass.voidType) {
@@ -662,7 +662,7 @@ public class JvstCodeGen extends MemberCodeGen {
}

if (exprType == VOID)
throw new CompileError("invalid type for " + returnCastName);
throw new CompileError("invalid type for " + returnCastName, lineNumber);

if (type instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType)type;
@@ -671,34 +671,34 @@ public class JvstCodeGen extends MemberCodeGen {
code.addCheckcast(wrapper);
code.addInvokevirtual(wrapper, pt.getGetMethodName(),
pt.getGetMethodDescriptor());
setType(type);
setType(type, lineNumber);
}
else {
code.addCheckcast(type);
setType(type);
setType(type, lineNumber);
}
}

/* Sets exprType, arrayDim, and className;
* If type is void, then this method does nothing.
*/
public void setType(CtClass type) throws CompileError {
setType(type, 0);
public void setType(CtClass type, int lineNumber) throws CompileError {
setType(type, 0, lineNumber);
}

private void setType(CtClass type, int dim) throws CompileError {
private void setType(CtClass type, int dim, int lineNumber) throws CompileError {
if (type.isPrimitive()) {
CtPrimitiveType pt = (CtPrimitiveType)type;
exprType = MemberResolver.descToType(pt.getDescriptor());
exprType = MemberResolver.descToType(pt.getDescriptor(), lineNumber);
arrayDim = dim;
className = null;
}
else if (type.isArray())
try {
setType(type.getComponentType(), dim + 1);
setType(type.getComponentType(), dim + 1, lineNumber);
}
catch (NotFoundException e) {
throw new CompileError("undefined type: " + type.getName());
throw new CompileError("undefined type: " + type.getName(), lineNumber);
}
else {
exprType = CLASS;
@@ -714,9 +714,9 @@ public class JvstCodeGen extends MemberCodeGen {
if (type instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType)type;
atNumCastExpr(exprType,
MemberResolver.descToType(pt.getDescriptor()));
MemberResolver.descToType(pt.getDescriptor(), type.getLinesCount() - 1));
}
else
throw new CompileError("type mismatch");
throw new CompileError("type mismatch", type.getLinesCount() - 1);
}
}

+ 12
- 12
src/main/javassist/compiler/JvstTypeChecker.java View File

@@ -127,7 +127,7 @@ public class JvstTypeChecker extends TypeChecker {
compileUnwrapValue(returnType, expr.getLineNumber());
else if (returnType instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType)returnType;
int destType = MemberResolver.descToType(pt.getDescriptor());
int destType = MemberResolver.descToType(pt.getDescriptor(), expr.getLineNumber());
exprType = destType;
arrayDim = 0;
className = null;
@@ -139,7 +139,7 @@ public class JvstTypeChecker extends TypeChecker {
if (CodeGen.isRefType(exprType) || arrayDim > 0)
return; // Object type. do nothing.

CtClass clazz = resolver.lookupClass(exprType, arrayDim, className);
CtClass clazz = resolver.lookupClass(exprType, arrayDim, className, expr.getLineNumber());
if (clazz instanceof CtPrimitiveType) {
exprType = CLASS;
arrayDim = 0;
@@ -158,7 +158,7 @@ public class JvstTypeChecker extends TypeChecker {
if (codeGen.procHandler != null
&& name.equals(codeGen.proceedName)) {
codeGen.procHandler.setReturnType(this,
(ASTList)expr.oprand2());
(ASTList)expr.oprand2(), expr.getLineNumber());
return;
}
else if (name.equals(JvstCodeGen.cflowName)) {
@@ -223,7 +223,7 @@ public class JvstTypeChecker extends TypeChecker {
int n = params.length;
for (int k = 0; k < n; ++k) {
CtClass p = params[k];
setType(p);
setType(p, a.getLineNumber());
types[i] = exprType;
dims[i] = arrayDim;
cnames[i] = className;
@@ -254,7 +254,7 @@ public class JvstTypeChecker extends TypeChecker {
int nargs = getMethodArgsLength(args);
atMethodArgs(args, new int[nargs], new int[nargs],
new String[nargs]);
setReturnType(descriptor);
setReturnType(descriptor, target.getLineNumber());
addNullIfVoid();
}

@@ -263,29 +263,29 @@ public class JvstTypeChecker extends TypeChecker {
if (type == CtClass.voidType)
addNullIfVoid();
else
setType(type);
setType(type, lineNumber);
}

/* Sets exprType, arrayDim, and className;
* If type is void, then this method does nothing.
*/
public void setType(CtClass type) throws CompileError {
setType(type, 0);
public void setType(CtClass type, int lineNumber) throws CompileError {
setType(type, 0, lineNumber);
}

private void setType(CtClass type, int dim) throws CompileError {
private void setType(CtClass type, int dim, int lineNumber) throws CompileError {
if (type.isPrimitive()) {
CtPrimitiveType pt = (CtPrimitiveType)type;
exprType = MemberResolver.descToType(pt.getDescriptor());
exprType = MemberResolver.descToType(pt.getDescriptor(), lineNumber);
arrayDim = dim;
className = null;
}
else if (type.isArray())
try {
setType(type.getComponentType(), dim + 1);
setType(type.getComponentType(), dim + 1, lineNumber);
}
catch (NotFoundException e) {
throw new CompileError("undefined type: " + type.getName());
throw new CompileError("undefined type: " + type.getName(), lineNumber);
}
else {
exprType = CLASS;

+ 25
- 25
src/main/javassist/compiler/MemberCodeGen.java View File

@@ -254,7 +254,7 @@ public class MemberCodeGen extends CodeGen {

decl.setLocalVar(var);

CtClass type = resolver.lookupClassByJvmName(decl.getClassName());
CtClass type = resolver.lookupClassByJvmName(decl.getClassName(), st.getLineNumber());
decl.setClassName(MemberResolver.javaToJvmName(type.getName()));
bc.addExceptionHandler(start, end, bc.currentPc(), type);
bc.growStack(1);
@@ -373,7 +373,7 @@ public class MemberCodeGen extends CodeGen {

String elementClass;
if (type == CLASS) {
elementClass = resolveClassName(jvmClassname);
elementClass = resolveClassName(jvmClassname, lineNumber);
bytecode.addAnewarray(MemberResolver.jvmToJavaName(elementClass));
}
else {
@@ -515,7 +515,7 @@ public class MemberCodeGen extends CodeGen {
int op = e.getOperator();
if (op == MEMBER) { // static method
targetClass
= resolver.lookupClass(((Symbol)e.oprand1()).get(), false);
= resolver.lookupClass(((Symbol)e.oprand1()).get(), false, expr.getLineNumber());
isStatic = true;
}
else if (op == '.') {
@@ -552,15 +552,15 @@ public class MemberCodeGen extends CodeGen {
}

if (arrayDim > 0)
targetClass = resolver.lookupClass(javaLangObject, true);
targetClass = resolver.lookupClass(javaLangObject, true, expr.getLineNumber());
else if (exprType == CLASS /* && arrayDim == 0 */)
targetClass = resolver.lookupClassByJvmName(className);
targetClass = resolver.lookupClassByJvmName(className, expr.getLineNumber());
else
badMethod();
badMethod(e.getLineNumber());
}
}
else
badMethod();
badMethod(expr.getLineNumber());
}
else
fatal(expr.getLineNumber());
@@ -569,8 +569,8 @@ public class MemberCodeGen extends CodeGen {
aload0pos, cached);
}

private static void badMethod() throws CompileError {
throw new CompileError("bad method");
private static void badMethod(int lineNumber) throws CompileError {
throw new CompileError("bad method", lineNumber);
}

/*
@@ -645,7 +645,7 @@ public class MemberCodeGen extends CodeGen {
if (mname.equals(MethodInfo.nameInit)) {
isSpecial = true;
if (declClass != targetClass)
throw new CompileError("no such constructor: " + targetClass.getName());
throw new CompileError("no such constructor: " + targetClass.getName(), targetClass.getLinesCount() - 1);

if (declClass != thisClass && AccessFlag.isPrivate(acc)) {
if (declClass.getClassFile().getMajorVersion() < ClassFile.JAVA_8
@@ -701,12 +701,12 @@ public class MemberCodeGen extends CodeGen {
}
else
if (isStatic)
throw new CompileError(mname + " is not static");
throw new CompileError(mname + " is not static", targetClass.getLinesCount() - 1);
else
bytecode.addInvokevirtual(declClass, mname, desc);
}

setReturnType(desc, isStatic, popTarget);
setReturnType(desc, isStatic, popTarget, targetClass.getLinesCount() - 1);
}

/*
@@ -729,7 +729,7 @@ public class MemberCodeGen extends CodeGen {
}

throw new CompileError("Method " + methodName
+ " is private");
+ " is private", declClass.getLinesCount() - 1);
}

/*
@@ -752,7 +752,7 @@ public class MemberCodeGen extends CodeGen {
}

throw new CompileError("the called constructor is private in "
+ declClass.getName());
+ declClass.getName(), declClass.getLinesCount() - 1);
}

private boolean isEnclosing(CtClass outer, CtClass inner) {
@@ -785,12 +785,12 @@ public class MemberCodeGen extends CodeGen {
}
}

void setReturnType(String desc, boolean isStatic, boolean popTarget)
void setReturnType(String desc, boolean isStatic, boolean popTarget, int lineNumber)
throws CompileError
{
int i = desc.indexOf(')');
if (i < 0)
badMethod();
badMethod(lineNumber);

char c = desc.charAt(++i);
int dim = 0;
@@ -803,13 +803,13 @@ public class MemberCodeGen extends CodeGen {
if (c == 'L') {
int j = desc.indexOf(';', i + 1);
if (j < 0)
badMethod();
badMethod(lineNumber);

exprType = CLASS;
className = desc.substring(i + 1, j);
}
else {
exprType = MemberResolver.descToType(c);
exprType = MemberResolver.descToType(c, lineNumber);
className = null;
}

@@ -843,7 +843,7 @@ public class MemberCodeGen extends CodeGen {
int fi;
if (op == '=') {
FieldInfo finfo = f.getFieldInfo2();
setFieldType(finfo);
setFieldType(finfo, expr.getLineNumber());
AccessorMaker maker = isAccessibleField(f, finfo, expr.getLineNumber());
if (maker == null)
fi = addFieldrefInfo(f, finfo);
@@ -926,7 +926,7 @@ public class MemberCodeGen extends CodeGen {
atFieldRead(f, is_static,expr.getLineNumber() );
else {
cexpr.accept(this);
setFieldType(f.getFieldInfo2());
setFieldType(f.getFieldInfo2(), expr.getLineNumber());
}
}

@@ -946,7 +946,7 @@ public class MemberCodeGen extends CodeGen {
*/
private int atFieldRead(CtField f, boolean isStatic, int lineNumber) throws CompileError {
FieldInfo finfo = f.getFieldInfo2();
boolean is2byte = setFieldType(finfo);
boolean is2byte = setFieldType(finfo, lineNumber);
AccessorMaker maker = isAccessibleField(f, finfo, lineNumber);
if (maker != null) {
MethodInfo minfo = maker.getFieldGetter(finfo, isStatic);
@@ -996,7 +996,7 @@ public class MemberCodeGen extends CodeGen {
*
* @return true if the field type is long or double.
*/
private boolean setFieldType(FieldInfo finfo) throws CompileError {
private boolean setFieldType(FieldInfo finfo, int lineNumber) throws CompileError {
String type = finfo.getDescriptor();

int i = 0;
@@ -1008,7 +1008,7 @@ public class MemberCodeGen extends CodeGen {
}

arrayDim = dim;
exprType = MemberResolver.descToType(c);
exprType = MemberResolver.descToType(c, lineNumber);

if (c == 'L')
className = type.substring(i + 1, type.indexOf(';', i + 1));
@@ -1201,7 +1201,7 @@ public class MemberCodeGen extends CodeGen {
* For example, this converts Object into java/lang/Object.
*/
@Override
protected String resolveClassName(String jvmName) throws CompileError {
return resolver.resolveJvmClassName(jvmName);
protected String resolveClassName(String jvmName, int lineNumber) throws CompileError {
return resolver.resolveJvmClassName(jvmName, lineNumber);
}
}

+ 37
- 35
src/main/javassist/compiler/MemberResolver.java View File

@@ -50,8 +50,8 @@ public class MemberResolver implements TokenId {

public ClassPool getClassPool() { return classPool; }

private static void fatal() throws CompileError {
throw new CompileError("fatal");
private static void fatal(int lineNumber) throws CompileError {
throw new CompileError("fatal", lineNumber);
}

public static class Method {
@@ -85,7 +85,7 @@ public class MemberResolver implements TokenId {
if (current != null && clazz == currentClass)
if (current.getName().equals(methodName)) {
int res = compareSignature(current.getDescriptor(),
argTypes, argDims, argClassNames);
argTypes, argDims, argClassNames, currentClass.getLinesCount() - 1);
if (res != NO) {
Method r = new Method(clazz, current, res);
if (res == YES)
@@ -116,7 +116,7 @@ public class MemberResolver implements TokenId {
if (minfo.getName().equals(methodName)
&& (minfo.getAccessFlags() & AccessFlag.BRIDGE) == 0) {
int res = compareSignature(minfo.getDescriptor(),
argTypes, argDims, argClassNames);
argTypes, argDims, argClassNames, clazz.getLinesCount() - 1);
if (res != NO) {
Method r = new Method(clazz, minfo, res);
if (res == YES)
@@ -192,7 +192,7 @@ public class MemberResolver implements TokenId {
* of parameter types that do not exactly match.
*/
private int compareSignature(String desc, int[] argTypes,
int[] argDims, String[] argClassNames)
int[] argDims, String[] argClassNames, int lineNumber)
throws CompileError
{
int result = YES;
@@ -240,9 +240,9 @@ public class MemberResolver implements TokenId {

String cname = desc.substring(i, j);
if (!cname.equals(argClassNames[n])) {
CtClass clazz = lookupClassByJvmName(argClassNames[n]);
CtClass clazz = lookupClassByJvmName(argClassNames[n], lineNumber);
try {
if (clazz.subtypeOf(lookupClassByJvmName(cname)))
if (clazz.subtypeOf(lookupClassByJvmName(cname, lineNumber)))
result++;
else
return NO;
@@ -255,7 +255,7 @@ public class MemberResolver implements TokenId {
i = j + 1;
}
else {
int t = descToType(c);
int t = descToType(c, lineNumber);
int at = argTypes[n];
if (t != at)
if (t == INT
@@ -273,7 +273,7 @@ public class MemberResolver implements TokenId {
* Only used by fieldAccess() in MemberCodeGen and TypeChecker.
*
* @param jvmClassName a JVM class name. e.g. java/lang/String
* @see #lookupClass(String, boolean)
* @see #lookupClass(String, boolean, int)
*/
public CtField lookupFieldByJvmName2(String jvmClassName, Symbol fieldSym,
ASTree expr) throws NoFieldException
@@ -281,7 +281,7 @@ public class MemberResolver implements TokenId {
String field = fieldSym.get();
CtClass cc = null;
try {
cc = lookupClass(jvmToJavaName(jvmClassName), true);
cc = lookupClass(jvmToJavaName(jvmClassName), true, expr.getLineNumber());
}
catch (CompileError e) {
// EXPR might be part of a qualified class name.
@@ -313,55 +313,56 @@ public class MemberResolver implements TokenId {
public CtField lookupField(String className, Symbol fieldName)
throws CompileError
{
CtClass cc = lookupClass(className, false);
CtClass cc = lookupClass(className, false, fieldName.getLineNumber());
try {
return cc.getField(fieldName.get());
}
catch (NotFoundException e) {}
throw new CompileError("no such field: " + fieldName.get());
throw new CompileError("no such field: " + fieldName.get(), fieldName.getLineNumber());
}

public CtClass lookupClassByName(ASTList name) throws CompileError {
return lookupClass(Declarator.astToClassName(name, '.'), false);
return lookupClass(Declarator.astToClassName(name, '.'), false, name.getLineNumber());
}

public CtClass lookupClassByJvmName(String jvmName) throws CompileError {
return lookupClass(jvmToJavaName(jvmName), false);
public CtClass lookupClassByJvmName(String jvmName, int lineNumber) throws CompileError {
return lookupClass(jvmToJavaName(jvmName), false, lineNumber);
}

public CtClass lookupClass(Declarator decl) throws CompileError {
return lookupClass(decl.getType(), decl.getArrayDim(),
decl.getClassName());
decl.getClassName(), decl.getLineNumber());
}

/**
* @param classname jvm class name.
* @param classname jvm class name.
* @param lineNumber
*/
public CtClass lookupClass(int type, int dim, String classname)
public CtClass lookupClass(int type, int dim, String classname, int lineNumber)
throws CompileError
{
String cname = "";
CtClass clazz;
if (type == CLASS) {
clazz = lookupClassByJvmName(classname);
clazz = lookupClassByJvmName(classname, lineNumber);
if (dim > 0)
cname = clazz.getName();
else
return clazz;
}
else
cname = getTypeName(type);
cname = getTypeName(type, lineNumber);

while (dim-- > 0)
cname += "[]";

return lookupClass(cname, false);
return lookupClass(cname, false, lineNumber);
}

/*
* type cannot be CLASS
*/
static String getTypeName(int type) throws CompileError {
static String getTypeName(int type, int lineNumber) throws CompileError {
String cname = "";
switch (type) {
case BOOLEAN :
@@ -392,22 +393,23 @@ public class MemberResolver implements TokenId {
cname = "void";
break;
default :
fatal();
fatal(lineNumber);
}

return cname;
}

/**
* @param name a qualified class name. e.g. java.lang.String
* @param name a qualified class name. e.g. java.lang.String
* @param lineNumber
*/
public CtClass lookupClass(String name, boolean notCheckInner)
public CtClass lookupClass(String name, boolean notCheckInner, int lineNumber)
throws CompileError
{
Map<String,String> cache = getInvalidNames();
String found = cache.get(name);
if (found == INVALID)
throw new CompileError("no such class: " + name);
throw new CompileError("no such class: " + name, lineNumber);
else if (found != null)
try {
return classPool.get(found);
@@ -419,7 +421,7 @@ public class MemberResolver implements TokenId {
cc = lookupClass0(name, notCheckInner);
}
catch (NotFoundException e) {
cc = searchImports(name);
cc = searchImports(name, lineNumber);
}

cache.put(name, cc.getName());
@@ -454,7 +456,7 @@ public class MemberResolver implements TokenId {
return ht;
}

private CtClass searchImports(String orgName)
private CtClass searchImports(String orgName, int lineNumber)
throws CompileError
{
if (orgName.indexOf('.') < 0) {
@@ -476,7 +478,7 @@ public class MemberResolver implements TokenId {
}

getInvalidNames().put(orgName, INVALID);
throw new CompileError("no such class: " + orgName);
throw new CompileError("no such class: " + orgName, lineNumber);
}

private CtClass lookupClass0(String classname, boolean notCheckInner)
@@ -513,10 +515,10 @@ public class MemberResolver implements TokenId {
/* Expands a simple class name to java.lang.*.
* For example, this converts Object into java/lang/Object.
*/
public String resolveJvmClassName(String jvmName) throws CompileError {
public String resolveJvmClassName(String jvmName, int lineNumber) throws CompileError {
if (jvmName == null)
return null;
return javaToJvmName(lookupClassByJvmName(jvmName).getName());
return javaToJvmName(lookupClassByJvmName(jvmName, lineNumber).getName());
}

public static CtClass getSuperclass(CtClass c) throws CompileError {
@@ -527,7 +529,7 @@ public class MemberResolver implements TokenId {
}
catch (NotFoundException e) {}
throw new CompileError("cannot find the super class of "
+ c.getName());
+ c.getName(), c.getLinesCount() - 1);
}

public static CtClass getSuperInterface(CtClass c, String interfaceName)
@@ -540,7 +542,7 @@ public class MemberResolver implements TokenId {
return intfs[i];
} catch (NotFoundException e) {}
throw new CompileError("cannot find the super interface " + interfaceName
+ " of " + c.getName());
+ " of " + c.getName(), c.getLinesCount() - 1);
}

public static String javaToJvmName(String classname) {
@@ -551,7 +553,7 @@ public class MemberResolver implements TokenId {
return classname.replace('/', '.');
}

public static int descToType(char c) throws CompileError {
public static int descToType(char c, int lineNumber) throws CompileError {
switch (c) {
case 'Z' :
return BOOLEAN;
@@ -575,7 +577,7 @@ public class MemberResolver implements TokenId {
case '[' :
return CLASS;
default :
fatal();
fatal(lineNumber);
return VOID; // never reach here
}
}

+ 2
- 2
src/main/javassist/compiler/ProceedHandler.java View File

@@ -25,6 +25,6 @@ import javassist.compiler.ast.ASTList;
* @see javassist.compiler.JvstCodeGen#setProceedHandler(ProceedHandler, String)
*/
public interface ProceedHandler {
void doit(JvstCodeGen gen, Bytecode b, ASTList args) throws CompileError;
void setReturnType(JvstTypeChecker c, ASTList args) throws CompileError;
void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber) throws CompileError;
void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber) throws CompileError;
}

+ 28
- 28
src/main/javassist/compiler/TypeChecker.java View File

@@ -73,14 +73,14 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
* into a String object.
*/
protected static String argTypesToString(int[] types, int[] dims,
String[] cnames) {
String[] cnames, int lineNumber) {
StringBuilder sbuf = new StringBuilder();
sbuf.append('(');
int n = types.length;
if (n > 0) {
int i = 0;
while (true) {
typeToString(sbuf, types[i], dims[i], cnames[i]);
typeToString(sbuf, types[i], dims[i], cnames[i], lineNumber);
if (++i < n)
sbuf.append(',');
else
@@ -97,7 +97,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
* into a String object.
*/
protected static StringBuilder typeToString(StringBuilder sbuf,
int type, int dim, String cname) {
int type, int dim, String cname, int lineNumber) {
String s;
if (type == CLASS)
s = MemberResolver.jvmToJavaName(cname);
@@ -105,7 +105,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
s = "Object";
else
try {
s = MemberResolver.getTypeName(type);
s = MemberResolver.getTypeName(type, lineNumber);
}
catch (CompileError e) {
s = "?";
@@ -156,8 +156,8 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
/* Expands a simple class name to java.lang.*.
* For example, this converts Object into java/lang/Object.
*/
protected String resolveClassName(String jvmName) throws CompileError {
return resolver.resolveJvmClassName(jvmName);
protected String resolveClassName(String jvmName, int lineNumber) throws CompileError {
return resolver.resolveJvmClassName(jvmName, lineNumber);
}

@Override
@@ -168,7 +168,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
CtClass clazz = resolver.lookupClassByName(expr.getClassName());
String cname = clazz.getName();
ASTList args = expr.getArguments();
atMethodCallCore(clazz, MethodInfo.nameInit, args);
atMethodCallCore(clazz, MethodInfo.nameInit, args, expr.getLineNumber());
exprType = CLASS;
arrayDim = 0;
className = MemberResolver.javaToJvmName(cname);
@@ -294,7 +294,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
throws CompileError
{
CtField f = fieldAccess(left);
atFieldRead(f);
atFieldRead(f, expr.getLineNumber());
int fType = exprType;
int fDim = arrayDim;
String cname = className;
@@ -682,7 +682,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
if (op == MEMBER) // static method
targetClass
= resolver.lookupClass(((Symbol)e.oprand1()).get(),
false);
false, e.getLineNumber());
else if (op == '.') {
ASTree target = e.oprand1();
String classFollowedByDotSuper = isDotSuper(target);
@@ -707,26 +707,26 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
}

if (arrayDim > 0)
targetClass = resolver.lookupClass(javaLangObject, true);
targetClass = resolver.lookupClass(javaLangObject, true, e.getLineNumber());
else if (exprType == CLASS /* && arrayDim == 0 */)
targetClass = resolver.lookupClassByJvmName(className);
targetClass = resolver.lookupClassByJvmName(className, e.getLineNumber());
else
badMethod();
badMethod(e.getLineNumber());
}
}
else
badMethod();
badMethod(expr.getLineNumber());
}
else
fatal(expr.getLineNumber());

MemberResolver.Method minfo
= atMethodCallCore(targetClass, mname, args);
= atMethodCallCore(targetClass, mname, args, expr.getLineNumber());
expr.setMethod(minfo);
}

private static void badMethod() throws CompileError {
throw new CompileError("bad method");
private static void badMethod(int lineNumber) throws CompileError {
throw new CompileError("bad method", lineNumber);
}

/**
@@ -754,7 +754,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
* and the MethodInfo of that method. Never null.
*/
public MemberResolver.Method atMethodCallCore(CtClass targetClass,
String mname, ASTList args)
String mname, ASTList args, int lineNumber)
throws CompileError
{
int nargs = getMethodArgsLength(args);
@@ -768,18 +768,18 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
mname, types, dims, cnames);
if (found == null) {
String clazz = targetClass.getName();
String signature = argTypesToString(types, dims, cnames);
String signature = argTypesToString(types, dims, cnames, lineNumber);
String msg;
if (mname.equals(MethodInfo.nameInit))
msg = "cannot find constructor " + clazz + signature;
else
msg = mname + signature + " not found in " + clazz;

throw new CompileError(msg);
throw new CompileError(msg, lineNumber);
}

String desc = found.info.getDescriptor();
setReturnType(desc);
setReturnType(desc, lineNumber);
return found;
}

@@ -801,10 +801,10 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
}
}

void setReturnType(String desc) throws CompileError {
void setReturnType(String desc, int lineNumber) throws CompileError {
int i = desc.indexOf(')');
if (i < 0)
badMethod();
badMethod(lineNumber);

char c = desc.charAt(++i);
int dim = 0;
@@ -817,22 +817,22 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
if (c == 'L') {
int j = desc.indexOf(';', i + 1);
if (j < 0)
badMethod();
badMethod(lineNumber);

exprType = CLASS;
className = desc.substring(i + 1, j);
}
else {
exprType = MemberResolver.descToType(c);
exprType = MemberResolver.descToType(c, lineNumber);
className = null;
}
}

private void atFieldRead(ASTree expr) throws CompileError {
atFieldRead(fieldAccess(expr));
atFieldRead(fieldAccess(expr), expr.getLineNumber());
}

private void atFieldRead(CtField f) throws CompileError {
private void atFieldRead(CtField f, int lineNumber) throws CompileError {
FieldInfo finfo = f.getFieldInfo2();
String type = finfo.getDescriptor();

@@ -845,7 +845,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
}

arrayDim = dim;
exprType = MemberResolver.descToType(c);
exprType = MemberResolver.descToType(c, lineNumber);

if (c == 'L')
className = type.substring(i + 1, type.indexOf(';', i + 1));
@@ -1007,7 +1007,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
protected void atFieldPlusPlus(ASTree oprand) throws CompileError
{
CtField f = fieldAccess(oprand);
atFieldRead(f);
atFieldRead(f, oprand.getLineNumber());
int t = exprType;
if (t == INT || t == BYTE || t == CHAR || t == SHORT)
exprType = INT;

+ 5
- 5
src/main/javassist/expr/Cast.java View File

@@ -163,26 +163,26 @@ public class Cast extends Expr {
}

@Override
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
if (gen.getMethodArgsLength(args) != 1)
throw new CompileError(Javac.proceedName
+ "() cannot take more than one parameter "
+ "for cast");
+ "for cast", lineNumber);

gen.atMethodArgs(args, new int[1], new int[1], new String[1]);
bytecode.addOpcode(Opcode.CHECKCAST);
bytecode.addIndex(index);
gen.setType(retType);
gen.setType(retType, lineNumber);
}

@Override
public void setReturnType(JvstTypeChecker c, ASTList args)
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
c.atMethodArgs(args, new int[1], new int[1], new String[1]);
c.setType(retType);
c.setType(retType, lineNumber);
}
}
}

+ 10
- 10
src/main/javassist/expr/FieldAccess.java View File

@@ -259,12 +259,12 @@ public class FieldAccess extends Expr {
}

@Override
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
if (args != null && !gen.isParamListName(args))
throw new CompileError(Javac.proceedName
+ "() cannot take a parameter for field reading");
+ "() cannot take a parameter for field reading", lineNumber);

int stack;
if (isStatic(opcode))
@@ -282,14 +282,14 @@ public class FieldAccess extends Expr {
bytecode.add(opcode);
bytecode.addIndex(index);
bytecode.growStack(stack);
gen.setType(fieldType);
gen.setType(fieldType, lineNumber);
}

@Override
public void setReturnType(JvstTypeChecker c, ASTList args)
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
c.setType(fieldType);
c.setType(fieldType, lineNumber);
}
}

@@ -309,13 +309,13 @@ public class FieldAccess extends Expr {
}

@Override
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
if (gen.getMethodArgsLength(args) != 1)
throw new CompileError(Javac.proceedName
+ "() cannot take more than one parameter "
+ "for field writing");
+ "for field writing", lineNumber);

int stack;
if (isStatic(opcode))
@@ -335,16 +335,16 @@ public class FieldAccess extends Expr {
bytecode.add(opcode);
bytecode.addIndex(index);
bytecode.growStack(stack);
gen.setType(CtClass.voidType);
gen.setType(CtClass.voidType, lineNumber);
gen.addNullIfVoid();
}

@Override
public void setReturnType(JvstTypeChecker c, ASTList args)
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
c.atMethodArgs(args, new int[1], new int[1], new String[1]);
c.setType(CtClass.voidType);
c.setType(CtClass.voidType, lineNumber);
c.addNullIfVoid();
}
}

+ 5
- 5
src/main/javassist/expr/Instanceof.java View File

@@ -167,26 +167,26 @@ public class Instanceof extends Expr {
}

@Override
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
if (gen.getMethodArgsLength(args) != 1)
throw new CompileError(Javac.proceedName
+ "() cannot take more than one parameter "
+ "for instanceof");
+ "for instanceof", lineNumber);

gen.atMethodArgs(args, new int[1], new int[1], new String[1]);
bytecode.addOpcode(Opcode.INSTANCEOF);
bytecode.addIndex(index);
gen.setType(CtClass.booleanType);
gen.setType(CtClass.booleanType, lineNumber);
}

@Override
public void setReturnType(JvstTypeChecker c, ASTList args)
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
c.atMethodArgs(args, new int[1], new int[1], new String[1]);
c.setType(CtClass.booleanType);
c.setType(CtClass.booleanType, lineNumber);
}
}
}

+ 5
- 5
src/main/javassist/expr/NewArray.java View File

@@ -270,13 +270,13 @@ public class NewArray extends Expr {
}

@Override
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
int num = gen.getMethodArgsLength(args);
if (num != dimension)
throw new CompileError(Javac.proceedName
+ "() with a wrong number of parameters");
+ "() with a wrong number of parameters", lineNumber);

gen.atMethodArgs(args, new int[num],
new int[num], new String[num]);
@@ -291,14 +291,14 @@ public class NewArray extends Expr {
bytecode.growStack(1 - dimension);
}

gen.setType(arrayType);
gen.setType(arrayType, lineNumber);
}

@Override
public void setReturnType(JvstTypeChecker c, ASTList args)
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
c.setType(arrayType);
c.setType(arrayType, lineNumber);
}
}
}

+ 5
- 5
src/main/javassist/expr/NewExpr.java View File

@@ -250,7 +250,7 @@ public class NewExpr extends Expr {
}

@Override
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
bytecode.addOpcode(NEW);
@@ -258,15 +258,15 @@ public class NewExpr extends Expr {
bytecode.addOpcode(DUP);
gen.atMethodCallCore(newType, MethodInfo.nameInit, args,
false, true, -1, null);
gen.setType(newType);
gen.setType(newType, lineNumber);
}

@Override
public void setReturnType(JvstTypeChecker c, ASTList args)
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
c.atMethodCallCore(newType, MethodInfo.nameInit, args);
c.setType(newType);
c.atMethodCallCore(newType, MethodInfo.nameInit, args, lineNumber);
c.setType(newType, lineNumber);
}
}
}

+ 14
- 0
src/test/javassist/LineNumberTest.java View File

@@ -13,6 +13,20 @@ public class LineNumberTest extends TestCase {
"}"), "line 3: syntax error near \" return\n}\"");
}

public void testUndevField() {
doTestCompile(String.join("\n",
"public void run() {",
" foo = 5;",
"}"), "line 2: no such field: foo");
}

public void testUndevMethod() {
doTestCompile(String.join("\n",
"public void run() {",
" foo();",
"}"), "line 2: foo() not found in javassist.LineNumberCompileTest2");
}

public void testException() {
doTestRuntime(String.join("\n",
"public void run() {",

+ 2
- 2
src/test/javassist/compiler/CompTest.java View File

@@ -105,11 +105,11 @@ public class CompTest extends TestCase {

public void testArgTypesToString() {
String s;
s = TypeChecker.argTypesToString(new int[0], new int[0], new String[0]);
s = TypeChecker.argTypesToString(new int[0], new int[0], new String[0], 0);
assertEquals("()", s);
s = TypeChecker.argTypesToString(new int[] { TokenId.INT, TokenId.CHAR, TokenId.CLASS },
new int[] { 0, 1, 0 },
new String[] { null, null, "String" });
new String[] { null, null, "String" }, 0);
assertEquals("(int,char[],String)", s);
}


Loading…
Cancel
Save