/* 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;
/**
@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()))
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"!)
}
}
else {
- cname = resolveClassName(MemberResolver.javaToJvmName(cname));
+ cname = resolveClassName(MemberResolver.javaToJvmName(cname), expr.getLineNumber());
cname = MemberResolver.jvmToJavaName(cname);
}
reason = String.format("line %d: %s", lineNumber, s);
}
- public CompileError(String s) {
+ private CompileError(String s) {
reason = s;
lex = null;
}
*/
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)
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());
}
}
return method;
}
catch (NotFoundException e) {
- throw new CompileError(e.toString());
+ throw new CompileError(e.toString(), md.getLineNumber());
}
}
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)
return bytecode;
}
catch (NotFoundException e) {
- throw new CompileError(e.toString());
+ throw new CompileError(e.toString(), -1);
}
}
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());
}
@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());
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,
}
@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,
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);
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);
}
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)
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;
}
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;
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();
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)) {
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;
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();
}
className = jvmJavaLangObject;
}
else
- setType(cc);
+ setType(cc, cc.getLinesCount());
Declarator decl
= new Declarator(exprType, className, arrayDim,
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)
return 8;
}
- protected void compileUnwrapValue(CtClass type, Bytecode code)
+ protected void compileUnwrapValue(CtClass type, Bytecode code, int lineNumber)
throws CompileError
{
if (type == CtClass.voidType) {
}
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;
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;
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);
}
}
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;
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;
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)) {
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;
int nargs = getMethodArgsLength(args);
atMethodArgs(args, new int[nargs], new int[nargs],
new String[nargs]);
- setReturnType(descriptor);
+ setReturnType(descriptor, target.getLineNumber());
addNullIfVoid();
}
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;
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);
String elementClass;
if (type == CLASS) {
- elementClass = resolveClassName(jvmClassname);
+ elementClass = resolveClassName(jvmClassname, lineNumber);
bytecode.addAnewarray(MemberResolver.jvmToJavaName(elementClass));
}
else {
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 == '.') {
}
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());
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);
}
/*
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
}
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);
}
/*
}
throw new CompileError("Method " + methodName
- + " is private");
+ + " is private", declClass.getLinesCount() - 1);
}
/*
}
throw new CompileError("the called constructor is private in "
- + declClass.getName());
+ + declClass.getName(), declClass.getLinesCount() - 1);
}
private boolean isEnclosing(CtClass outer, CtClass inner) {
}
}
- 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;
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;
}
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);
atFieldRead(f, is_static,expr.getLineNumber() );
else {
cexpr.accept(this);
- setFieldType(f.getFieldInfo2());
+ setFieldType(f.getFieldInfo2(), expr.getLineNumber());
}
}
*/
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);
*
* @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;
}
arrayDim = dim;
- exprType = MemberResolver.descToType(c);
+ exprType = MemberResolver.descToType(c, lineNumber);
if (c == 'L')
className = type.substring(i + 1, type.indexOf(';', i + 1));
* 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);
}
}
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 {
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)
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)
* 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;
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;
i = j + 1;
}
else {
- int t = descToType(c);
+ int t = descToType(c, lineNumber);
int at = argTypes[n];
if (t != at)
if (t == INT
* 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
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.
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 :
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);
cc = lookupClass0(name, notCheckInner);
}
catch (NotFoundException e) {
- cc = searchImports(name);
+ cc = searchImports(name, lineNumber);
}
cache.put(name, cc.getName());
return ht;
}
- private CtClass searchImports(String orgName)
+ private CtClass searchImports(String orgName, int lineNumber)
throws CompileError
{
if (orgName.indexOf('.') < 0) {
}
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)
/* 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 {
}
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)
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) {
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;
case '[' :
return CLASS;
default :
- fatal();
+ fatal(lineNumber);
return VOID; // never reach here
}
}
* @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;
}
* 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
* 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);
s = "Object";
else
try {
- s = MemberResolver.getTypeName(type);
+ s = MemberResolver.getTypeName(type, lineNumber);
}
catch (CompileError e) {
s = "?";
/* 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
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);
throws CompileError
{
CtField f = fieldAccess(left);
- atFieldRead(f);
+ atFieldRead(f, expr.getLineNumber());
int fType = exprType;
int fDim = arrayDim;
String cname = className;
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);
}
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);
}
/**
* 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);
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;
}
}
}
- 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;
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();
}
arrayDim = dim;
- exprType = MemberResolver.descToType(c);
+ exprType = MemberResolver.descToType(c, lineNumber);
if (c == 'L')
className = type.substring(i + 1, type.indexOf(';', i + 1));
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;
}
@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);
}
}
}
}
@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))
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);
}
}
}
@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))
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();
}
}
}
@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);
}
}
}
}
@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]);
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);
}
}
}
}
@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);
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);
}
}
}
"}"), "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() {",
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);
}