diff options
author | patriot1burke <patriot1burke@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2003-04-22 13:47:06 +0000 |
---|---|---|
committer | patriot1burke <patriot1burke@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2003-04-22 13:47:06 +0000 |
commit | 069bceaf72fd0d6ffad14ce4e3e00ca91a280bde (patch) | |
tree | b8230a15d3061c64d5a64bf9efa654d0d6311ff2 /src/main/javassist/expr/NewExpr.java | |
parent | f610083ba0adbcb3fe92a504015fb26fb5a42530 (diff) | |
download | javassist-069bceaf72fd0d6ffad14ce4e3e00ca91a280bde.tar.gz javassist-069bceaf72fd0d6ffad14ce4e3e00ca91a280bde.zip |
This commit was generated by cvs2svn to compensate for changes in r2, which
included commits to RCS files with non-trunk default branches.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@6 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main/javassist/expr/NewExpr.java')
-rw-r--r-- | src/main/javassist/expr/NewExpr.java | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/main/javassist/expr/NewExpr.java b/src/main/javassist/expr/NewExpr.java new file mode 100644 index 00000000..73546238 --- /dev/null +++ b/src/main/javassist/expr/NewExpr.java @@ -0,0 +1,224 @@ +/* + * This file is part of the Javassist toolkit. + * + * 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. You may obtain a copy of the License at + * either http://www.mozilla.org/MPL/. + * + * 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. + * + * The Original Code is Javassist. + * + * The Initial Developer of the Original Code is Shigeru Chiba. Portions + * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba. + * All Rights Reserved. + * + * Contributor(s): + * + * The development of this software is supported in part by the PRESTO + * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation. + */ + +package javassist.expr; + +import javassist.*; +import javassist.bytecode.*; +import javassist.compiler.*; +import javassist.compiler.ast.ASTree; +import javassist.compiler.ast.ASTList; + +/** + * Object creation (<tt>new</tt> expression). + */ +public class NewExpr extends Expr { + String newTypeName; + int newPos; + + /** + * Undocumented constructor. Do not use; internal-use only. + */ + NewExpr(int pos, CodeIterator i, CtClass declaring, MethodInfo m, + String type, int np) + { + super(pos, i, declaring, m); + newTypeName = type; + newPos = np; + } + + private int getNameAndType(ConstPool cp) { + String cname; + int pos = currentPos; + int c = iterator.byteAt(pos); + int index = iterator.u16bitAt(pos + 1); + + if (c == INVOKEINTERFACE) + return cp.getInterfaceMethodrefNameAndType(index); + else + return cp.getMethodrefNameAndType(index); + } + + /** + * Returns the method or constructor containing the <tt>new</tt> + * expression represented by this object. + */ + public CtBehavior where() { return super.where(); } + + /** + * Returns the line number of the source line containing the + * <tt>new</tt> expression. + * + * @return -1 if this information is not available. + */ + public int getLineNumber() { + return super.getLineNumber(); + } + + /** + * Returns the source file containing the <tt>new</tt> expression. + * + * @return null if this information is not available. + */ + public String getFileName() { + return super.getFileName(); + } + + /** + * Returns the class of the created object. + */ + private CtClass getCtClass() throws NotFoundException { + return thisClass.getClassPool().get(newTypeName); + } + + /** + * Returns the class name of the created object. + */ + public String getClassName() { + return newTypeName; + } + + /** + * Returns the constructor called for creating the object. + */ + public CtConstructor getConstructor() throws NotFoundException { + ConstPool cp = getConstPool(); + int index = iterator.u16bitAt(currentPos + 1); + String desc = cp.getMethodrefType(index); + return getCtClass().getConstructor(desc); + } + + /** + * Returns the list of exceptions that the expression may throw. + * This list includes both the exceptions that the try-catch statements + * including the expression can catch and the exceptions that + * the throws declaration allows the method to throw. + */ + public CtClass[] mayThrow() { + return super.mayThrow(); + } + + /* + * Returns the parameter types of the constructor. + + public CtClass[] getParameterTypes() throws NotFoundException { + ConstPool cp = getConstPool(); + int index = iterator.u16bitAt(currentPos + 1); + String desc = cp.getMethodrefType(index); + return Descriptor.getParameterTypes(desc, thisClass.getClassPool()); + } + */ + + private int canReplace() throws CannotCompileException { + int op = iterator.byteAt(newPos + 3); + if (op == Opcode.DUP) + return 4; + else if (op == Opcode.DUP_X1 + && iterator.byteAt(newPos + 4) == Opcode.SWAP) + return 5; + else + throw new CannotCompileException( + "sorry, cannot edit NEW followed by no DUP"); + } + + /** + * Replaces the <tt>new</tt> expression with the bytecode derived from + * the given source text. + * + * <p>$0 is available but the value is null. + * + * @param statement a Java statement. + */ + public void replace(String statement) throws CannotCompileException { + final int bytecodeSize = 3; + int pos = newPos; + + int newIndex = iterator.u16bitAt(pos + 1); + + /* delete the preceding NEW and DUP (or DUP_X1, SWAP) instructions. + */ + int end = pos + canReplace(); + for (int i = pos; i < end; ++i) + iterator.writeByte(NOP, i); + + ConstPool constPool = getConstPool(); + pos = currentPos; + int methodIndex = iterator.u16bitAt(pos + 1); // constructor + + String signature = constPool.getMethodrefType(methodIndex); + + Javac jc = new Javac(thisClass); + ClassPool cp = thisClass.getClassPool(); + CodeAttribute ca = iterator.get(); + try { + CtClass[] params = Descriptor.getParameterTypes(signature, cp); + CtClass newType = cp.get(newTypeName); + int paramVar = ca.getMaxLocals(); + jc.recordParams(newTypeName, params, + true, paramVar, withinStatic()); + int retVar = jc.recordReturnType(newType, true); + jc.recordProceed(new ProceedForNew(newType, newIndex, + methodIndex)); + + /* Is $_ included in the source code? + */ + checkResultValue(newType, statement); + + Bytecode bytecode = jc.getBytecode(); + storeStack(params, true, paramVar, bytecode); + jc.compileStmnt(statement); + bytecode.addAload(retVar); + + replace0(pos, bytecode, bytecodeSize); + } + catch (CompileError e) { throw new CannotCompileException(e); } + catch (NotFoundException e) { throw new CannotCompileException(e); } + catch (BadBytecode e) { + throw new CannotCompileException("broken method"); + } + } + + static class ProceedForNew implements ProceedHandler { + CtClass newType; + int newIndex, methodIndex; + + ProceedForNew(CtClass nt, int ni, int mi) { + newType = nt; + newIndex = ni; + methodIndex = mi; + } + + public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) + throws CompileError + { + bytecode.addOpcode(NEW); + bytecode.addIndex(newIndex); + bytecode.addOpcode(DUP); + gen.atMethodCall2(newType, MethodInfo.nameInit, + args, false, true); + gen.setType(newType); + } + } +} |