List of usage examples for org.eclipse.jdt.core.dom ClassInstanceCreation setAnonymousClassDeclaration
public void setAnonymousClassDeclaration(AnonymousClassDeclaration decl)
From source file:cn.ieclipse.adt.ext.jdt.SourceGenerator.java
License:Apache License
private static void rewriteOnCreate(CompilationUnit unit, String dbName, List<String> tableCreators) { AST ast = unit.getAST();//from www . j a va 2 s . co m TypeDeclaration type = (TypeDeclaration) unit.types().get(0); MethodDeclaration onCreate = getMethod(type, ("onCreate"), null); if (onCreate != null) { Block methodBlock = ast.newBlock(); // mOpenHelper = new // InlineOpenHelper(this.getContext(),"person.db",null,1); Assignment a = ast.newAssignment(); a.setOperator(Assignment.Operator.ASSIGN); a.setLeftHandSide(ast.newSimpleName("mOpenHelper")); ClassInstanceCreation cc = ast.newClassInstanceCreation(); cc.setType(ast.newSimpleType(ast.newSimpleName("SQLiteOpenHelper"))); ThisExpression thisExp = ast.newThisExpression(); MethodInvocation mi = ast.newMethodInvocation(); mi.setName(ast.newSimpleName("getContext")); mi.setExpression(thisExp); cc.arguments().add(mi); StringLiteral sl = ast.newStringLiteral(); sl.setLiteralValue(dbName); cc.arguments().add(sl); cc.arguments().add(ast.newNullLiteral()); cc.arguments().add(ast.newNumberLiteral("1")); a.setRightHandSide(cc); methodBlock.statements().add(ast.newExpressionStatement(a)); AnonymousClassDeclaration acd = ast.newAnonymousClassDeclaration(); cc.setAnonymousClassDeclaration(acd); genInnerSQLiteOpenHelper(acd, ast, tableCreators); a = ast.newAssignment(); a.setOperator(Assignment.Operator.ASSIGN); a.setLeftHandSide(ast.newSimpleName("session")); ClassInstanceCreation cic = ast.newClassInstanceCreation(); cic.setType(ast.newSimpleType(ast.newSimpleName("Session"))); // SingleVariableDeclaration svd = // ast.newSingleVariableDeclaration(); // svd.setName(ast.newSimpleName("mOpenHelper")); cic.arguments().add(ast.newSimpleName("mOpenHelper")); // vdf.setInitializer(cic); a.setRightHandSide(cic); // methodBlock.statements().add(vde); methodBlock.statements().add(ast.newExpressionStatement(a)); ReturnStatement returnStmt = ast.newReturnStatement(); returnStmt.setExpression(ast.newBooleanLiteral(true)); methodBlock.statements().add(returnStmt); onCreate.setBody(methodBlock); } }
From source file:com.google.devtools.j2cpp.translate.AnonymousClassConverter.java
License:Open Source License
/** * Convert the anonymous class into an inner class. Fields are added for * final variables that are referenced, and a constructor is added. * * Note: endVisit is used for a depth-first traversal, to make it easier * to scan their containing nodes for references. */// ww w .j a v a 2 s . com @Override @SuppressWarnings("unchecked") public void endVisit(AnonymousClassDeclaration node) { ASTNode parent = node.getParent(); ClassInstanceCreation newInvocation = null; EnumConstantDeclaration enumConstant = null; List<Expression> parentArguments; String newClassName; ITypeBinding innerType; boolean isStatic = staticParent(node); int modifiers = isStatic ? Modifier.STATIC : 0; if (parent instanceof ClassInstanceCreation) { newInvocation = (ClassInstanceCreation) parent; parentArguments = newInvocation.arguments(); innerType = Types.getTypeBinding(newInvocation); newClassName = innerType.getName(); innerType = RenamedTypeBinding.rename(newClassName, innerType.getDeclaringClass(), innerType, modifiers); } else if (parent instanceof EnumConstantDeclaration) { enumConstant = (EnumConstantDeclaration) parent; parentArguments = enumConstant.arguments(); innerType = Types.getTypeBinding(node); newClassName = Types.getTypeBinding(node).getName(); innerType = RenamedTypeBinding.rename(newClassName, innerType.getDeclaringClass(), innerType, modifiers); } else { throw new AssertionError("unknown anonymous class declaration parent: " + parent.getClass().getName()); } // Create a type declaration for this anonymous class. AST ast = node.getAST(); TypeDeclaration typeDecl = ast.newTypeDeclaration(); if (isStatic) { typeDecl.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD)); } Types.addBinding(typeDecl, innerType); typeDecl.setName(ast.newSimpleName(newClassName)); Types.addBinding(typeDecl.getName(), innerType); typeDecl.setSourceRange(node.getStartPosition(), node.getLength()); Type superType = Types.makeType(Types.mapType(innerType.getSuperclass())); typeDecl.setSuperclassType(superType); for (ITypeBinding interfaceType : innerType.getInterfaces()) { typeDecl.superInterfaceTypes().add(Types.makeType(Types.mapType(interfaceType))); } for (Object bodyDecl : node.bodyDeclarations()) { BodyDeclaration decl = (BodyDeclaration) bodyDecl; typeDecl.bodyDeclarations().add(NodeCopier.copySubtree(ast, decl)); } typeDecl.accept(new InitializationNormalizer()); // Fix up references to external types, if necessary. Set<IVariableBinding> methodVars = getMethodVars(node); final List<ReferenceDescription> references = findReferences(node, methodVars); final List<Expression> invocationArgs = parentArguments; if (!references.isEmpty() || !invocationArgs.isEmpty()) { // is there anything to fix-up? List<IVariableBinding> innerVars = getInnerVars(references); if (!innerVars.isEmpty() || !invocationArgs.isEmpty()) { GeneratedMethodBinding defaultConstructor = addInnerVars(typeDecl, innerVars, references, parentArguments); Types.addBinding(parent, defaultConstructor); for (IVariableBinding var : innerVars) { if (!isConstant(var)) { parentArguments.add(makeFieldRef(var, ast)); } } assert defaultConstructor.getParameterTypes().length == parentArguments.size(); typeDecl.accept(new ASTVisitor() { @Override public void endVisit(SimpleName node) { IVariableBinding var = Types.getVariableBinding(node); if (var != null) { for (ReferenceDescription ref : references) { if (var.isEqualTo(ref.binding)) { if (ref.innerField != null) { setProperty(node, makeFieldRef(ref.innerField, node.getAST())); } else { // In-line constant. Object o = var.getConstantValue(); assert o != null; Expression literal = makeLiteral(o, var.getType().getQualifiedName(), node.getAST()); setProperty(node, literal); } return; } } } } }); } } // If invocation, replace anonymous class invocation with the new constructor. if (newInvocation != null) { newInvocation.setAnonymousClassDeclaration(null); newInvocation.setType(Types.makeType(innerType)); IMethodBinding oldBinding = Types.getMethodBinding(newInvocation); if (oldBinding == null) { oldBinding = newInvocation.resolveConstructorBinding(); } if (oldBinding != null) { GeneratedMethodBinding invocationBinding = new GeneratedMethodBinding(oldBinding); invocationBinding.setDeclaringClass(innerType); Types.addBinding(newInvocation, invocationBinding); } } else { enumConstant.setAnonymousClassDeclaration(null); } // Add type declaration to enclosing type. ITypeBinding outerType = innerType.getDeclaringClass(); if (outerType.isAnonymous()) { // Get outerType node. ASTNode n = parent.getParent(); while (!(n instanceof AnonymousClassDeclaration) && !(n instanceof TypeDeclaration)) { n = n.getParent(); } if (n instanceof AnonymousClassDeclaration) { AnonymousClassDeclaration outerDecl = (AnonymousClassDeclaration) n; outerDecl.bodyDeclarations().add(typeDecl); } } else { AbstractTypeDeclaration outerDecl = (AbstractTypeDeclaration) unit.findDeclaringNode(outerType); outerDecl.bodyDeclarations().add(typeDecl); } Symbols.scanAST(typeDecl); super.endVisit(node); }
From source file:com.motorola.studio.android.generateviewbylayout.codegenerators.AbstractLayoutCodeGenerator.java
License:Apache License
/** * Adds method invocation that instantiates an anonymous class to deal with the event *//*from ww w. j a v a 2s . com*/ @SuppressWarnings("unchecked") protected void addMethodInvocationToListenerHandler(String callerId, String invocationMethod, String classType, String listenerClazzName, List<MethodDeclaration> methodDeclarations) throws JavaModelException { MethodInvocation methodInvocation = onCreateDeclaration.getAST().newMethodInvocation(); SimpleName listenerInvocationName = onCreateDeclaration.getAST().newSimpleName(invocationMethod); SimpleName listenerOptionalName = onCreateDeclaration.getAST().newSimpleName(callerId); FieldAccess fieldAccess = onCreateDeclaration.getAST().newFieldAccess(); fieldAccess.setExpression(onCreateDeclaration.getAST().newThisExpression()); fieldAccess.setName(listenerOptionalName); methodInvocation.setName(listenerInvocationName); methodInvocation.setExpression(fieldAccess); ClassInstanceCreation classInstanceCreation = onCreateDeclaration.getAST().newClassInstanceCreation(); SimpleType listenerType = getListenerSimpleType(classType, listenerClazzName); classInstanceCreation.setType(listenerType); AnonymousClassDeclaration classDeclaration = onCreateDeclaration.getAST().newAnonymousClassDeclaration(); for (MethodDeclaration methodDeclaration : methodDeclarations) { classDeclaration.bodyDeclarations().add(methodDeclaration); } classInstanceCreation.setAnonymousClassDeclaration(classDeclaration); methodInvocation.arguments().add(classInstanceCreation); ExpressionStatement expressionStatement = onCreateDeclaration.getAST() .newExpressionStatement(methodInvocation); insertStatementsAtOnCreateDeclaration(expressionStatement, false); }
From source file:com.motorola.studio.android.generateviewbylayout.codegenerators.RadioButtonCodeGenerator.java
License:Apache License
/** * Creates field with an anonymous class declaration for radio buttons *//*from w w w .jav a2s . c om*/ @SuppressWarnings("unchecked") private IfStatement createOnClickListenerForRadioButtons(LayoutNode node) { IfStatement ifSt; Modifier privateMod = typeDeclaration.getAST().newModifier(ModifierKeyword.PRIVATE_KEYWORD); SimpleType listenerType = getListenerSimpleType(JavaViewBasedOnLayoutModifierConstants.VIEW_CLASS, JavaViewBasedOnLayoutModifierConstants.METHOD_ON_CLICK_LISTENER); VariableDeclarationFragment variableFragment = typeDeclaration.getAST().newVariableDeclarationFragment(); SimpleName varName = variableFragment.getAST() .newSimpleName(JavaViewBasedOnLayoutModifierConstants.HANDLER_ONCLICK_LISTENER); variableFragment.setName(varName); FieldDeclaration declaration = typeDeclaration.getAST().newFieldDeclaration(variableFragment); declaration.modifiers().add(privateMod); declaration.setType(listenerType); ClassInstanceCreation classInstanceCreation = typeDeclaration.getAST().newClassInstanceCreation(); SimpleType listenerType2 = getListenerSimpleType(JavaViewBasedOnLayoutModifierConstants.VIEW_CLASS, JavaViewBasedOnLayoutModifierConstants.METHOD_ON_CLICK_LISTENER); classInstanceCreation.setType(listenerType2); AnonymousClassDeclaration classDeclaration = typeDeclaration.getAST().newAnonymousClassDeclaration(); MethodDeclaration methodDeclaration = addMethodDeclaration(ModifierKeyword.PUBLIC_KEYWORD, JavaViewBasedOnLayoutModifierConstants.METHOD_NAME_ON_CLICK, PrimitiveType.VOID, JavaViewBasedOnLayoutModifierConstants.VIEW_CLASS, JavaViewBasedOnLayoutModifierConstants.VIEW_VARIABLE_NAME); Block block = typeDeclaration.getAST().newBlock(); ifSt = createElseIfForEachRadioButtonId(node); block.statements().add(ifSt); methodDeclaration.setBody(block); classDeclaration.bodyDeclarations().add(methodDeclaration); classInstanceCreation.setAnonymousClassDeclaration(classDeclaration); variableFragment.setInitializer(classInstanceCreation); typeDeclaration.bodyDeclarations().add(declaration); return ifSt; }
From source file:de.dentrassi.varlink.generator.JdtGenerator.java
License:Open Source License
@SuppressWarnings("unchecked") private void createImpl(final AST ast, final CompilationUnit cu, final Interface iface, final String name) { // create type final String implName = name + "Impl"; final TypeDeclaration td = ast.newTypeDeclaration(); cu.types().add(td);// w ww . ja va 2s . c o m td.setName(ast.newSimpleName(implName)); make(td, PUBLIC_KEYWORD); final Type parentType = ast.newSimpleType(ast.newName(name)); td.superInterfaceTypes().add(parentType); // create factory createImplFactory(ast, td); // create fields createField(td, "de.dentrassi.varlink.spi.Connection", "connection", PRIVATE_KEYWORD, FINAL_KEYWORD); createField(td, "de.dentrassi.varlink.internal.VarlinkImpl", "varlink", PRIVATE_KEYWORD, FINAL_KEYWORD); // create constructor final MethodDeclaration ctor = ast.newMethodDeclaration(); td.bodyDeclarations().add(ctor); ctor.setConstructor(true); ctor.setName(ast.newSimpleName(implName)); make(ctor, PRIVATE_KEYWORD); createParameter(ctor, "de.dentrassi.varlink.spi.Connection", "connection", FINAL_KEYWORD); createParameter(ctor, "de.dentrassi.varlink.internal.VarlinkImpl", "varlink", FINAL_KEYWORD); // constructor body { final Block body = ast.newBlock(); ctor.setBody(body); createThisAssignment(body, "connection"); createThisAssignment(body, "varlink"); } // error mapper { final MethodDeclaration md = ast.newMethodDeclaration(); make(md, PUBLIC_KEYWORD); td.bodyDeclarations().add(md); md.setName(ast.newSimpleName("checkError")); createParameter(md, "de.dentrassi.varlink.spi.CallResponse", "response", FINAL_KEYWORD); final Block body = ast.newBlock(); md.setBody(body); final MethodInvocation mi = ast.newMethodInvocation(); mi.setExpression(ast.newName("de.dentrassi.varlink.spi.Errors")); mi.setName(ast.newSimpleName("checkErrors")); mi.arguments().add(ast.newSimpleName("response")); final ExpressionMethodReference ref = ast.newExpressionMethodReference(); ref.setExpression(ast.newThisExpression()); ref.setName(ast.newSimpleName("mapError")); mi.arguments().add(ref); body.statements().add(ast.newExpressionStatement(mi)); } { final MethodDeclaration md = ast.newMethodDeclaration(); make(md, PUBLIC_KEYWORD); td.bodyDeclarations().add(md); md.setName(ast.newSimpleName("mapError")); createParameter(md, "java.lang.String", "error", FINAL_KEYWORD); createParameter(md, "de.dentrassi.varlink.spi.CallResponse", "response", FINAL_KEYWORD); md.setReturnType2(ast.newSimpleType(ast.newName("java.lang.RuntimeException"))); final Block body = ast.newBlock(); md.setBody(body); final SwitchStatement sw = ast.newSwitchStatement(); body.statements().add(sw); sw.setExpression(ast.newSimpleName("error")); errors(iface).forEach(error -> { final String errorName = errorTypeName(error); final String fullErrorName = iface.getName() + "." + errorName; final SwitchCase sc = ast.newSwitchCase(); sc.setExpression(JdtHelper.newStringLiteral(ast, fullErrorName)); sw.statements().add(sc); final FieldAccess fa = ast.newFieldAccess(); fa.setExpression(ast.newThisExpression()); fa.setName(ast.newSimpleName("varlink")); final MethodInvocation fromJson = ast.newMethodInvocation(); fromJson.setExpression(fa); fromJson.setName(ast.newSimpleName("fromJson")); // type name final TypeLiteral typeLiteral = ast.newTypeLiteral(); typeLiteral.setType(ast.newSimpleType(ast.newName(errorName + ".Parameters"))); fromJson.arguments().add(typeLiteral); // parameters final MethodInvocation parameters = ast.newMethodInvocation(); parameters.setExpression(ast.newSimpleName("response")); parameters.setName(ast.newSimpleName("getParameters")); fromJson.arguments().add(parameters); // new exception final ClassInstanceCreation cic = ast.newClassInstanceCreation(); cic.setType(ast.newSimpleType(ast.newName(errorName))); cic.arguments().add(fromJson); // return final ReturnStatement ret = ast.newReturnStatement(); ret.setExpression(cic); sw.statements().add(ret); }); { final SwitchCase sc = ast.newSwitchCase(); sc.setExpression(null); sw.statements().add(sc); final ReturnStatement ret = ast.newReturnStatement(); ret.setExpression(ast.newNullLiteral()); sw.statements().add(ret); } } // async creator /* * @Override public Async async() { return new Async() { * * @Override public CompletableFuture<List<Netdev>> list() { return * executeList(); } }; } */ { final MethodDeclaration md = ast.newMethodDeclaration(); td.bodyDeclarations().add(md); md.setName(ast.newSimpleName("async")); addSimpleAnnotation(md, "Override"); make(md, PUBLIC_KEYWORD); md.setReturnType2(ast.newSimpleType(ast.newName("Async"))); final Block body = ast.newBlock(); md.setBody(body); // inner class final ReturnStatement ret = ast.newReturnStatement(); body.statements().add(ret); final ClassInstanceCreation cic = ast.newClassInstanceCreation(); cic.setType(ast.newSimpleType(ast.newName("Async"))); ret.setExpression(cic); final AnonymousClassDeclaration acc = ast.newAnonymousClassDeclaration(); cic.setAnonymousClassDeclaration(acc); forMethods(ast, iface, (m, amd) -> { acc.bodyDeclarations().add(amd); amd.setName(ast.newSimpleName(m.getName())); make(amd, PUBLIC_KEYWORD); makeAsync(amd); final Block asyncBody = ast.newBlock(); amd.setBody(asyncBody); final ReturnStatement asyncRet = ast.newReturnStatement(); asyncBody.statements().add(asyncRet); final MethodInvocation mi = ast.newMethodInvocation(); mi.setName(ast.newSimpleName(internalMethodName(m.getName()))); for (final String argName : m.getParameters().keySet()) { mi.arguments().add(ast.newSimpleName(argName)); } asyncRet.setExpression(mi); }); } // internal methods forMethods(ast, iface, (m, md) -> { make(md, PROTECTED_KEYWORD); td.bodyDeclarations().add(md); md.setName(ast.newSimpleName(internalMethodName(m.getName()))); makeAsync(md); createInternalMethod(td, m, md); }); }
From source file:de.dentrassi.varlink.generator.JdtGenerator.java
License:Open Source License
@SuppressWarnings("unchecked") private void createInternalMethod(final TypeDeclaration parentTypeDeclaration, final MethodInformation m, final MethodDeclaration md) { final AST ast = md.getAST(); final Block body = ast.newBlock(); md.setBody(body);// w w w . ja v a 2 s . c o m /* * return this.connection.call(CallRequest.of("io.systemd.network.List")) * .thenApply(cr -> { check(cr); * * final Iterator<JsonElement> i = cr.getParameters().values().iterator(); * * return asList( this.varlink .fromJson( Netdev[].class, i.next())); }); } */ // add arguments if (!m.getParameters().isEmpty()) { // code: Map<String,Object> parameters = new HashMap<> (); final VariableDeclarationFragment parameters = ast.newVariableDeclarationFragment(); parameters.setName(ast.newSimpleName("parameters")); final VariableDeclarationStatement decl = ast.newVariableDeclarationStatement(parameters); body.statements().add(decl); final ParameterizedType map = ast.newParameterizedType(ast.newSimpleType(ast.newName("java.util.Map"))); map.typeArguments().add(ast.newSimpleType(ast.newName("java.lang.String"))); map.typeArguments().add(ast.newSimpleType(ast.newName("java.lang.Object"))); decl.setType(map); final ClassInstanceCreation init = ast.newClassInstanceCreation(); init.setType(ast.newParameterizedType(ast.newSimpleType(ast.newName("java.util.HashMap")))); init.arguments().add(ast.newNumberLiteral(Integer.toString(m.getParameters().size()))); parameters.setInitializer(init); for (final String argName : m.getParameters().keySet()) { final MethodInvocation mi = ast.newMethodInvocation(); mi.setExpression(ast.newSimpleName("parameters")); mi.setName(ast.newSimpleName("put")); mi.arguments().add(JdtHelper.newStringLiteral(ast, argName)); mi.arguments().add(ast.newSimpleName(argName)); } } // return final ReturnStatement ret = ast.newReturnStatement(); body.statements().add(ret); final MethodInvocation mi = ast.newMethodInvocation(); mi.setName(ast.newSimpleName("call")); final FieldAccess fa = ast.newFieldAccess(); fa.setExpression(ast.newThisExpression()); fa.setName(ast.newSimpleName("connection")); mi.setExpression(fa); final MethodInvocation cr = ast.newMethodInvocation(); cr.setExpression(ast.newName("de.dentrassi.varlink.spi.CallRequest")); cr.setName(ast.newSimpleName("of")); cr.arguments().add(newStringLiteral(ast, m.getInterface().getName() + "." + toUpperFirst(m.getName()))); if (!m.getParameters().isEmpty()) { cr.arguments().add(ast.newSimpleName("parameters")); } mi.arguments().add(cr); final MethodInvocation thenApply = ast.newMethodInvocation(); thenApply.setName(ast.newSimpleName("thenApply")); thenApply.setExpression(mi); // add transformation final LambdaExpression le = ast.newLambdaExpression(); le.setParentheses(false); thenApply.arguments().add(le); final VariableDeclarationFragment p = ast.newVariableDeclarationFragment(); p.setName(ast.newSimpleName("result")); le.parameters().add(p); final Block transform = ast.newBlock(); le.setBody(transform); { // check result final MethodInvocation check = ast.newMethodInvocation(); check.setName(ast.newSimpleName("checkError")); transform.statements().add(ast.newExpressionStatement(check)); check.arguments().add(ast.newSimpleName("result")); } if (m.getReturnTypes().isEmpty()) { final ReturnStatement transformRet = ast.newReturnStatement(); transformRet.setExpression(ast.newNullLiteral()); transform.statements().add(transformRet); } else { final int returns = m.getReturnTypes().size(); if (returns > 0) { // return this.varlink.fromJson(DriveCondition.class, result.getParameters()); // return this.varlink.fromJson(DriveCondition.class, // result.getFirstParameter()); final FieldAccess varlink = ast.newFieldAccess(); varlink.setExpression(ast.newThisExpression()); varlink.setName(ast.newSimpleName("varlink")); final MethodInvocation fromJson = ast.newMethodInvocation(); fromJson.setExpression(varlink); fromJson.setName(ast.newSimpleName("fromJson")); // FIXME: add to parent { final ParameterizedType ttt = ast .newParameterizedType(ast.newSimpleType(ast.newName(TYPE_TOKEN_TYPE_NAME))); ttt.typeArguments().add(m.createMainReturnType(ast)); final ClassInstanceCreation tt = ast.newClassInstanceCreation(); tt.setType(JdtHelper.copyNode(ast, ttt)); final AnonymousClassDeclaration decl = ast.newAnonymousClassDeclaration(); tt.setAnonymousClassDeclaration(decl); final MethodInvocation getType = ast.newMethodInvocation(); getType.setExpression(tt); getType.setName(ast.newSimpleName("getType")); final VariableDeclarationFragment vdf = ast.newVariableDeclarationFragment(); vdf.setName(ast.newSimpleName(m.getName() + "_returnTypeToken")); vdf.setInitializer(getType); final FieldDeclaration fd = ast.newFieldDeclaration(vdf); fd.setType(ast.newSimpleType(ast.newName("java.lang.reflect.Type"))); make(fd, PRIVATE_KEYWORD, FINAL_KEYWORD, STATIC_KEYWORD); parentTypeDeclaration.bodyDeclarations().add(fd); } fromJson.arguments().add(ast.newSimpleName(m.getName() + "_returnTypeToken")); // json fragment final MethodInvocation fragment = ast.newMethodInvocation(); if (returns == 1) { fragment.setName(ast.newSimpleName("getFirstParameter")); } else { fragment.setName(ast.newSimpleName("getParameters")); } fragment.setExpression(ast.newSimpleName("result")); fromJson.arguments().add(fragment); // return final ReturnStatement transformRet = ast.newReturnStatement(); transformRet.setExpression(fromJson); transform.statements().add(transformRet); } // FIXME: handle return type // FIXME: handle n } // set return ret.setExpression(thenApply); }
From source file:de.dentrassi.varlink.generator.JdtGenerator.java
License:Open Source License
@SuppressWarnings("unchecked") private void createInterface(final AST ast, final CompilationUnit cu, final Interface iface, final String name) { final TypeDeclaration td = ast.newTypeDeclaration(); cu.types().add(td);// ww w . j a v a 2 s . c om td.setInterface(true); td.setName(ast.newSimpleName(name)); make(td, PUBLIC_KEYWORD); final NormalAnnotation ann = JdtHelper.addAnnotation(td, "de.dentrassi.varlink.spi.Interface"); { final MemberValuePair mvpName = ast.newMemberValuePair(); ann.values().add(mvpName); mvpName.setName(ast.newSimpleName("name")); mvpName.setValue(JdtHelper.newStringLiteral(ast, iface.getName())); } { final MemberValuePair mvpFactory = ast.newMemberValuePair(); ann.values().add(mvpFactory); mvpFactory.setName(ast.newSimpleName("factory")); final TypeLiteral fn = ast.newTypeLiteral(); fn.setType(ast.newSimpleType(ast.newName(name + "Impl.Factory"))); mvpFactory.setValue(fn); } // create types createTypes(td, iface); // create errors createErrors(td, iface); /* * * public interface Async { public CompletableFuture<List<Netdev>> list(); } * * public interface Sync { public List<Netdev> list(); } * * public Async async(); * * public default Sync sync() { return new Sync() { * * @Override public List<Netdev> list() { return Syncer.await(async().list()); } * }; } */ // create async { // public interface Async { ... } final TypeDeclaration async = ast.newTypeDeclaration(); td.bodyDeclarations().add(async); async.setInterface(true); make(async, PUBLIC_KEYWORD); async.setName(ast.newSimpleName("Async")); forMethods(ast, iface, (m, md) -> { make(md, PUBLIC_KEYWORD); async.bodyDeclarations().add(md); makeAsync(md); }); // public Async async(); final MethodDeclaration md = ast.newMethodDeclaration(); td.bodyDeclarations().add(md); md.setName(ast.newSimpleName("async")); make(md, PUBLIC_KEYWORD); final Type rt = ast.newSimpleType(ast.newSimpleName("Async")); md.setReturnType2(rt); } // create sync { // public interface Sync { ... } final TypeDeclaration sync = ast.newTypeDeclaration(); td.bodyDeclarations().add(sync); sync.setInterface(true); make(sync, PUBLIC_KEYWORD); sync.setName(ast.newSimpleName("Sync")); // methods forMethods(ast, iface, (m, md) -> { make(md, PUBLIC_KEYWORD); sync.bodyDeclarations().add(md); }); { final MethodDeclaration smd = ast.newMethodDeclaration(); smd.setName(ast.newSimpleName("sync")); make(smd, PUBLIC_KEYWORD, DEFAULT_KEYWORD); td.bodyDeclarations().add(smd); final Block body = ast.newBlock(); smd.setBody(body); final ReturnStatement ret = ast.newReturnStatement(); body.statements().add(ret); final ClassInstanceCreation cic = ast.newClassInstanceCreation(); cic.setType(ast.newSimpleType(ast.newName("Sync"))); ret.setExpression(cic); smd.setReturnType2(ast.newSimpleType(ast.newName("Sync"))); final AnonymousClassDeclaration acc = ast.newAnonymousClassDeclaration(); cic.setAnonymousClassDeclaration(acc); forMethods(ast, iface, (m, md) -> { make(md, PUBLIC_KEYWORD); acc.bodyDeclarations().add(md); final Block mbody = ast.newBlock(); md.setBody(mbody); // return Syncer.await(async().list()); final MethodInvocation await = ast.newMethodInvocation(); await.setExpression(ast.newName("de.dentrassi.varlink.spi.Syncer")); await.setName(ast.newSimpleName("await")); final MethodInvocation asyncCall = ast.newMethodInvocation(); asyncCall.setName(ast.newSimpleName("async")); final MethodInvocation mcall = ast.newMethodInvocation(); mcall.setName(ast.newSimpleName(m.getName())); mcall.setExpression(asyncCall); await.arguments().add(mcall); // add arguments for (final String argName : m.getParameters().keySet()) { mcall.arguments().add(ast.newSimpleName(argName)); } if (m.getReturnTypes().isEmpty()) { mbody.statements().add(ast.newExpressionStatement(await)); } else { final ReturnStatement rs = ast.newReturnStatement(); rs.setExpression(await); mbody.statements().add(rs); } }); } } }
From source file:edu.umd.cs.findbugs.plugin.eclipse.quickfix.CreateDoPrivilegedBlockResolution.java
License:Open Source License
private ClassInstanceCreation createPrivilegedActionCreation(ASTRewrite rewrite, ClassInstanceCreation classLoaderCreation) { AST ast = rewrite.getAST();// w w w. ja v a2 s.co m ClassInstanceCreation privilegedActionCreation = ast.newClassInstanceCreation(); ParameterizedType privilegedActionType = createPrivilegedActionType(rewrite, classLoaderCreation); AnonymousClassDeclaration anonymousClassDeclaration = createAnonymousClassDeclaration(rewrite, classLoaderCreation); privilegedActionCreation.setType(privilegedActionType); privilegedActionCreation.setAnonymousClassDeclaration(anonymousClassDeclaration); return privilegedActionCreation; }
From source file:java5totext.input.JDTVisitor.java
License:Open Source License
@Override public void endVisit(org.eclipse.jdt.core.dom.ClassInstanceCreation node) { ClassInstanceCreation element = (ClassInstanceCreation) this.binding.get(node); this.initializeNode(element, node); MethodDeclaration anonymousConstructor = null; if (this.binding.get(node.getAnonymousClassDeclaration()) != null) { AnonymousClassDeclaration anoDecl = (AnonymousClassDeclaration) this.binding .get(node.getAnonymousClassDeclaration()); element.setAnonymousClassDeclaration(anoDecl); anonymousConstructor = this.factory.createMethodDeclaration(); anonymousConstructor.setProxy(true); anonymousConstructor.setName(""); anoDecl.getBodyDeclarations().add(anonymousConstructor); }/* www . j a v a 2 s.c o m*/ if (this.binding.get(node.getType()) != null) element.setType((NamedElementRef) this.binding.get(node.getType())); for (Iterator<?> i = node.arguments().iterator(); i.hasNext();) { Expression itElement = (Expression) this.binding.get(i.next()); if (itElement != null) element.getArguments().add(itElement); } if (this.binding.get(node.getExpression()) != null) element.setExpression((Expression) this.binding.get(node.getExpression())); NamedElementRef constructorRef = this.factory.createNamedElementRef(); element.setMethod(constructorRef); //if it is an anonymous class declaration we directly use the anonymous constructor if (anonymousConstructor != null) { constructorRef.setElement(anonymousConstructor); } else JDTVisitorUtils.manageBindingRef(constructorRef, node, this); /*original code for this method ClassInstanceCreation element= (ClassInstanceCreation)binding.get(node); if (binding.get(node.getAnonymousClassDeclaration()) != null) element.setAnonymousClassDeclaration((AnonymousClassDeclaration)binding.get(node.getAnonymousClassDeclaration())); if (binding.get(node.getType()) != null) element.setType((NamedElementRef)binding.get(node.getType())); for (Iterator i=node.arguments().iterator() ;i.hasNext();){ Expression itElement= (Expression) this.binding.get(i.next()); if (itElement != null) element.getArguments().add(itElement); } if (binding.get(node.getExpression()) != null) element.setExpression((Expression)binding.get(node.getExpression())); NamedElementRef constructorRef= this.factory.createNamedElementRef(); element.setMethod(constructorRef); JDTVisitorUtils.manageBindingRef(constructorRef, node, this); */ }
From source file:org.decojer.cavaj.transformers.TrExpressions.java
License:Open Source License
private boolean transformOperations(@Nonnull final BB bb) { while (bb.getOps() > 0) { if (isStackUnderflow(bb)) { if (!mitigateStackUnderflow(bb)) { return false; }//w w w. j av a2s . c o m if (bb.isRemoved()) { // is also a possible form of stack underflow mitigation return true; } // something has been mitigated...may be not to the full extend, try again continue; } final Op op = bb.removeOp(0); switch (op.getOptype()) { case ADD: { bb.push(newInfixExpressionPop(InfixExpression.Operator.PLUS, bb, op)); break; } case ALOAD: { final ArrayAccess arrayAccess = setOp(getAst().newArrayAccess(), op); arrayAccess.setIndex(wrap(bb.pop())); arrayAccess.setArray(wrap(bb.pop(), Priority.ARRAY_INDEX)); bb.push(arrayAccess); break; } case AND: { bb.push(newInfixExpressionPop(InfixExpression.Operator.AND, bb, op)); break; } case ARRAYLENGTH: { final Expression expression = bb.pop(); if (expression instanceof Name) { // annotationsVisible.length bb.push(setOp( getAst().newQualifiedName((Name) wrap(expression), getAst().newSimpleName("length")), op)); break; } // FieldAccess or MethodInvocation: // this.code.length, getInterfaces().length final FieldAccess fieldAccess = setOp(getAst().newFieldAccess(), op); fieldAccess.setExpression(wrap(expression, Priority.MEMBER_ACCESS)); fieldAccess.setName(getAst().newSimpleName("length")); bb.push(fieldAccess); break; } case ASTORE: { final Expression rightOperand = bb.pop(); final Expression indexExpression = bb.pop(); final Expression arrayRefExpression = bb.pop(); if (arrayRefExpression instanceof ArrayCreation) { final ArrayCreation arrayCreation = (ArrayCreation) arrayRefExpression; ArrayInitializer arrayInitializer = arrayCreation.getInitializer(); if (arrayInitializer == null) { arrayInitializer = setOp(getAst().newArrayInitializer(), op); arrayCreation.setInitializer(arrayInitializer); // TODO for higher performance and for full array creation removement we // could defer the 0-fill and rewrite to the final A/STORE phase final Object sizeExpression = arrayCreation.dimensions().get(0); final Number size = sizeExpression instanceof Expression ? getNumberValue((Expression) sizeExpression) : null; assert size != null; final T t = peekT(op); assert t != null; // not all indexes may be set, null/0/false in JVM 7 are not set, fill for (int i = size.intValue(); i-- > 0;) { arrayInitializer.expressions().add(newLiteral(t, null, getM(), op)); } arrayCreation.dimensions().clear(); } final Number numberValue = getNumberValue(indexExpression); assert numberValue != null; arrayInitializer.expressions().set(numberValue.intValue(), wrap(rightOperand)); break; } final ArrayAccess arrayAccess = setOp(getAst().newArrayAccess(), op); arrayAccess.setArray(wrap(arrayRefExpression, Priority.ARRAY_INDEX)); arrayAccess.setIndex(wrap(indexExpression)); final Assignment assignment = newAssignment(Assignment.Operator.ASSIGN, arrayAccess, rightOperand, op); // TODO a = a +/- 1 => a++ / a-- // TODO a = a <op> expr => a <op>= expr // inline assignment, DUP(_X1) -> PUT if (!bb.isStackEmpty() && bb.peek() == rightOperand) { bb.pop(); bb.push(assignment); break; } bb.addStmt(setOp(getAst().newExpressionStatement(assignment), op)); break; } case CAST: { final CAST cop = (CAST) op; final CastExpression castExpression = setOp(getAst().newCastExpression(), op); castExpression.setType(newType(cop.getToT(), getM())); castExpression.setExpression(wrap(bb.pop(), Priority.TYPE_CAST)); bb.push(castExpression); break; } case CMP: { // pseudo expression for following JCND, not really the correct // answer for -1, 0, 1 bb.push(newInfixExpressionPop(InfixExpression.Operator.LESS_EQUALS, bb, op)); break; } case DIV: { bb.push(newInfixExpressionPop(InfixExpression.Operator.DIVIDE, bb, op)); break; } case DUP: { final DUP cop = (DUP) op; switch (cop.getKind()) { // for all following variants: don't change op without copying! case DUP: bb.push(bb.peek()); break; case DUP_X1: { final Expression e1 = bb.pop(); final Expression e2 = bb.pop(); bb.push(e1); bb.push(e2); bb.push(e1); break; } case DUP_X2: { final Expression e1 = bb.pop(); final Expression e2 = bb.pop(); if (!isWide(e2)) { final Expression e3 = bb.pop(); bb.push(e1); bb.push(e3); bb.push(e2); bb.push(e1); break; } bb.push(e1); bb.push(e2); bb.push(e1); break; } case DUP2: { final Expression e1 = bb.peek(); if (!isWide(e1)) { final Expression e2 = bb.peek(1); bb.push(e2); bb.push(e1); break; } bb.push(e1); break; } case DUP2_X1: { final Expression e1 = bb.pop(); if (!isWide(e1)) { final Expression e2 = bb.pop(); final Expression e3 = bb.pop(); bb.push(e2); bb.push(e1); bb.push(e3); bb.push(e2); bb.push(e1); break; } final Expression e3 = bb.pop(); bb.push(e1); bb.push(e3); bb.push(e1); break; } case DUP2_X2: { final Expression e1 = bb.pop(); if (!isWide(e1)) { final Expression e2 = bb.pop(); final Expression e3 = bb.pop(); if (!isWide(e3)) { final Expression e4 = bb.pop(); bb.push(e2); bb.push(e1); bb.push(e4); bb.push(e3); bb.push(e2); bb.push(e1); break; } bb.push(e2); bb.push(e1); bb.push(e3); bb.push(e2); bb.push(e1); break; } final Expression e3 = bb.pop(); if (!isWide(e3)) { final Expression e4 = bb.pop(); bb.push(e1); bb.push(e4); bb.push(e3); bb.push(e1); break; } bb.push(e1); bb.push(e3); bb.push(e1); break; } default: log.warn(getM() + ": Unknown DUP type '" + cop.getKind() + "'!"); } break; } case FILLARRAY: { final FILLARRAY cop = (FILLARRAY) op; final T t = peekT(op); final T componentT = t.getComponentT(); assert componentT != null; Expression expression = bb.pop(); if (!(expression instanceof ArrayCreation)) { // LOAD 0, NEWARRAY, STORE 0, LOAD 0, FILLARRAY <end> // TODO Dalvik: if STORE x / LOAD x are compressed then we shouldn't need this: expression = setOp(getAst().newArrayCreation(), op); ((ArrayCreation) expression).setType((ArrayType) newType(t, getM())); } final ArrayInitializer arrayInitializer = setOp(getAst().newArrayInitializer(), op); final Object[] values = cop.getValues(); assert values != null; for (final Object value : values) { arrayInitializer.expressions().add(newLiteral(componentT, value, getM(), op)); } ((ArrayCreation) expression).setInitializer(arrayInitializer); bb.push(expression); break; } case GET: { final GET cop = (GET) op; if (rewriteCachedClassLiteral(bb, cop)) { break; } final F f = cop.getF(); if (f.isStatic()) { // Eclipse AST expects a Name for f.getT(), not a Type: // is OK - f.getT() cannot be generic bb.push(setOp(getAst().newQualifiedName(newTypeName(f.getT(), getM()), newSimpleName(f.getName(), getAst())), op)); break; } final FieldAccess fieldAccess = setOp(getAst().newFieldAccess(), op); fieldAccess.setExpression(wrap(bb.pop(), Priority.MEMBER_ACCESS)); fieldAccess.setName(newSimpleName(f.getName(), getAst())); bb.push(fieldAccess); break; } case GOTO: { // not really necessary, but important for // 1) correct opPc blocks // 2) line numbers // TODO put line number anywhere? // remember as pseudo statement? but problem with boolean ops break; } case INC: { final INC cop = (INC) op; final int value = cop.getValue(); if (value == 1 || value == -1) { // ++ / -- if (rewriteInlinePrefixIncDec(bb, cop) || rewriteInlinePostfixIncDec(bb, cop)) { break; } if (bb.isStackEmpty()) { bb.addStmt(setOp(getAst().newExpressionStatement(newPrefixExpression( cop.getValue() == 1 ? PrefixExpression.Operator.INCREMENT : PrefixExpression.Operator.DECREMENT, getVarExpression(cop.getReg(), cop.getPc(), op), op)), op)); break; } log.warn(getM() + ": Inline ++/--!"); break; } if (rewriteInlineRegAssignment(bb, cop)) { break; } if (bb.isStackEmpty()) { bb.addStmt(setOp( getAst().newExpressionStatement(newAssignment( value >= 0 ? Assignment.Operator.PLUS_ASSIGN : Assignment.Operator.MINUS_ASSIGN, getVarExpression(cop.getReg(), cop.getPc(), op), newLiteral(cop.getT(), value >= 0 ? value : -value, getCfg().getM(), op), op)), op)); break; } log.warn(getM() + ": Inline INC with value '" + value + "'!"); break; } case INSTANCEOF: { final INSTANCEOF cop = (INSTANCEOF) op; final InstanceofExpression instanceofExpression = setOp(getAst().newInstanceofExpression(), op); instanceofExpression.setLeftOperand(wrap(bb.pop(), Priority.INSTANCEOF)); instanceofExpression.setRightOperand(newType(cop.getT(), getM())); bb.push(instanceofExpression); break; } case INVOKE: { final INVOKE cop = (INVOKE) op; final M m = cop.getM(); // read method invokation arguments, handle varargs final List<Expression> arguments = Lists.newArrayList(); final int params = m.getParamTs().length; if (params > 0) { if (m.isVarargs()) { final Expression array = bb.pop(); if (array instanceof ArrayCreation) { final ArrayInitializer initializer = ((ArrayCreation) array).getInitializer(); if (initializer != null) { for (final Expression e : (List<Expression>) initializer.expressions()) { // wrap() in addAll(), DUP could happen with receiver & argument arguments.add(e); } Collections.reverse(arguments); } } else { // can happen if forwarded as variable arguments.add(array); } } else { arguments.add(bb.pop()); } // now add remaining parameters that cannot be varargs for (int i = params - 1; i-- > 0;) { arguments.add(bb.pop()); } Collections.reverse(arguments); } final Expression methodExpression; if (cop.isDirect()) { final Expression expression = bb.pop(); if (m.isConstructor()) { methodExpression = null; final T ownerT = m.getT(); if (expression instanceof ThisExpression) { enumConstructor: if (ownerT != null && ownerT.is(Enum.class) && !getCfg().getCu().check(DFlag.IGNORE_ENUM)) { if (arguments.size() < 2) { log.warn(getM() + ": Super constructor invocation '" + m + "' for enum has less than 2 arguments!"); break enumConstructor; } if (!m.getParamTs()[0].is(String.class)) { log.warn(getM() + ": Super constructor invocation '" + m + "' for enum must contain string literal as first parameter!"); break enumConstructor; } if (m.getParamTs()[1] != T.INT) { log.warn(getM() + ": Super constructor invocation '" + m + "' for enum must contain number literal as first parameter!"); break enumConstructor; } arguments.remove(0); arguments.remove(0); } if (ownerT != null && ownerT.is(getCfg().getT())) { final ConstructorInvocation constructorInvocation = getAst() .newConstructorInvocation(); wrapAddAll(constructorInvocation.arguments(), arguments); bb.addStmt(setOp(constructorInvocation, op)); break; } if (arguments.size() == 0) { // implicit super callout, more checks possible but not necessary break; } final SuperConstructorInvocation superConstructorInvocation = getAst() .newSuperConstructorInvocation(); wrapAddAll(superConstructorInvocation.arguments(), arguments); bb.addStmt(setOp(superConstructorInvocation, op)); break; } if (expression instanceof ClassInstanceCreation) { if (ownerT != null && ownerT.isInner() && !getCfg().getCu().check(DFlag.IGNORE_CONSTRUCTOR_THIS)) { // inner class constructor invocation has synthetic this reference // as first argument: remove if (arguments.size() == 0) { log.warn(getM() + ": Inner class constructor invocation has no synthetic this reference as first argument! No arguments given."); } else if (!(arguments.get(0) instanceof ThisExpression)) { log.warn(getM() + ": Inner class constructor invocation has no synthetic this reference as first argument! Wrong first argument: " + arguments.get(0)); } else { arguments.remove(0); } } wrapAddAll(((ClassInstanceCreation) expression).arguments(), arguments); // normally there was a DUP in advance, don't use: // basicBlock.pushExpression(classInstanceCreation); break; } log.warn(getM() + ": Constructor expects expression class 'ThisExpression' or 'ClassInstanceCreation' but is '" + expression.getClass() + "' with value: " + expression); break; } if (expression instanceof ThisExpression && !m.getAf(AF.PRIVATE)) { final SuperMethodInvocation superMethodInvocation = getAst().newSuperMethodInvocation(); superMethodInvocation.setName(newSimpleName(m.getName(), getAst())); wrapAddAll(superMethodInvocation.arguments(), arguments); methodExpression = superMethodInvocation; } else { // could be private method call in same object, nothing special in syntax, // just used together with "this." final MethodInvocation methodInvocation = getAst().newMethodInvocation(); methodInvocation.setExpression(wrap(expression, Priority.METHOD_CALL)); methodInvocation.setName(newSimpleName(m.getName(), getAst())); wrapAddAll(methodInvocation.arguments(), arguments); methodExpression = methodInvocation; } } else if (m.isDynamic()) { final Object[] bsArgs = cop.getBsArgs(); if (isLambdaBootstrapMethod(cop.getBsM()) && bsArgs != null && bsArgs.length > 1 && bsArgs[1] instanceof M) { final M dynamicM = (M) bsArgs[1]; if (dynamicM.isSynthetic()) { // is lambda final LambdaExpression lambdaExpression = getAst().newLambdaExpression(); // init lambda parameters final T[] paramTs = dynamicM.getParamTs(); final A[][] paramAss = dynamicM.getParamAss(); // first m.paramTs.length parameters are for outer capture inits for (int i = m.getParamTs().length; i < paramTs.length; ++i) { lambdaExpression.parameters().add(newSingleVariableDeclaration(dynamicM, paramTs, paramAss, i, this.cfg.getT())); } // init lambda body final CFG lambdaCfg = dynamicM.getCfg(); assert lambdaCfg != null; if (lambdaCfg.getBlock() == null) { // if synthetics are not decompiled... // lambda methods are synthetic: init block, could later add more // checks and alternatives here if obfuscators play with these flags lambdaCfg.setBlock((Block) lambdaExpression.getBody()); lambdaCfg.decompile(); } else if (lambdaCfg.getBlock().getParent() instanceof MethodDeclaration) { // if synthetics are decompiled...but not for re-decompilation: // don't show this recognized (normally synthetic) method // declaration lambdaCfg.getBlock().delete(); // delete from parent dynamicM.setAstNode(null); // is our new lambda body lambdaExpression.setBody(lambdaCfg.getBlock()); } methodExpression = lambdaExpression; } else { // is a method reference, 4 different variants possible if (dynamicM.isConstructor()) { final CreationReference methodReference = getAst().newCreationReference(); final T ownerT = dynamicM.getT(); assert ownerT != null; methodReference.setType(newType(ownerT, getM())); methodExpression = methodReference; } else if (dynamicM.isStatic()) { final TypeMethodReference methodReference = getAst().newTypeMethodReference(); final T ownerT = dynamicM.getT(); assert ownerT != null; methodReference.setType(newType(ownerT, getM())); methodReference.setName(newSimpleName(dynamicM.getName(), getAst())); methodExpression = methodReference; } else { assert arguments .size() == 1 : "expression method reference doesn't have 1 argument"; final ExpressionMethodReference methodReference = getAst() .newExpressionMethodReference(); methodReference.setExpression(arguments.get(0)); methodReference.setName(newSimpleName(dynamicM.getName(), getAst())); methodExpression = methodReference; } // TODO is in bytecode via lambda, we could let it be or recognize this // pattern and shorten down to getAst().newSuperMethodReference(); } } else { final MethodInvocation methodInvocation = getAst().newMethodInvocation(); methodInvocation.setName(newSimpleName(m.getName(), getAst())); wrapAddAll(methodInvocation.arguments(), arguments); methodExpression = methodInvocation; } } else if (m.isStatic()) { final MethodInvocation methodInvocation = getAst().newMethodInvocation(); methodInvocation.setExpression(newTypeName(m.getT(), getM())); methodInvocation.setName(newSimpleName(m.getName(), getAst())); wrapAddAll(methodInvocation.arguments(), arguments); methodExpression = methodInvocation; } else { if (rewriteStringAppend(bb, cop)) { break; } final MethodInvocation methodInvocation = getAst().newMethodInvocation(); final Expression expression = bb.pop(); // TODO need this for switch(this.ordinal) rewrites, delete later? // if (!(expression instanceof ThisExpression)) { methodInvocation.setExpression(wrap(expression, Priority.METHOD_CALL)); // } methodInvocation.setName(newSimpleName(m.getName(), getAst())); wrapAddAll(methodInvocation.arguments(), arguments); methodExpression = methodInvocation; } setOp(methodExpression, op); final T returnT = m.getReturnT(); if (returnT == T.VOID) { bb.addStmt(setOp(setOp(getAst().newExpressionStatement(methodExpression), op), op)); break; } assert methodExpression != null; bb.push(methodExpression); break; } case JCMP: { final JCMP cop = (JCMP) op; // invert all operators and switch out edge predicates final InfixExpression.Operator operator; switch (cop.getCmpType()) { case T_EQ: operator = InfixExpression.Operator.EQUALS; break; case T_GE: operator = InfixExpression.Operator.GREATER_EQUALS; break; case T_GT: operator = InfixExpression.Operator.GREATER; break; case T_LE: operator = InfixExpression.Operator.LESS_EQUALS; break; case T_LT: operator = InfixExpression.Operator.LESS; break; case T_NE: operator = InfixExpression.Operator.NOT_EQUALS; break; default: log.warn(getM() + ": Unknown cmp type '" + cop.getCmpType() + "'!"); operator = null; } final IfStatement ifStatement = getAst().newIfStatement(); ifStatement.setExpression(newInfixExpressionPop(operator, bb, op)); bb.addStmt(setOp(ifStatement, op)); break; } case JCND: { final JCND cop = (JCND) op; Expression expression = bb.pop(); // check preceding CMP if (expression instanceof InfixExpression && ((InfixExpression) expression).getOperator() == InfixExpression.Operator.LESS_EQUALS) { // preceding compare expression (CMP result: -1 / 0 / 1) final InfixExpression.Operator operator; switch (cop.getCmpType()) { case T_EQ: operator = InfixExpression.Operator.EQUALS; break; case T_GE: operator = InfixExpression.Operator.GREATER_EQUALS; break; case T_GT: operator = InfixExpression.Operator.GREATER; break; case T_LE: operator = InfixExpression.Operator.LESS_EQUALS; break; case T_LT: operator = InfixExpression.Operator.LESS; break; case T_NE: operator = InfixExpression.Operator.NOT_EQUALS; break; default: log.warn(getM() + ": Unknown cmp type '" + cop.getCmpType() + "'!"); operator = null; } ((InfixExpression) expression).setOperator(operator); } else if (peekT(op).isRef()) { final InfixExpression.Operator operator; switch (cop.getCmpType()) { case T_EQ: operator = InfixExpression.Operator.EQUALS; break; case T_NE: operator = InfixExpression.Operator.NOT_EQUALS; break; default: log.warn(getM() + ": Unknown cmp type '" + cop.getCmpType() + "' for null-expression!"); operator = null; } expression = newInfixExpression(operator, expression, newLiteral(T.REF, null, getM(), op), op); } else if (peekT(op).is(T.BOOLEAN)) { // "!a" or "a == 0"? switch (cop.getCmpType()) { case T_EQ: // "== 0" means "is false" expression = not(expression); break; case T_NE: // "!= 0" means "is true" break; default: log.warn(getM() + ": Unknown cmp type '" + cop.getCmpType() + "' for boolean expression '" + expression + "'!"); } } else { final InfixExpression.Operator operator; switch (cop.getCmpType()) { case T_EQ: operator = InfixExpression.Operator.EQUALS; break; case T_GE: operator = InfixExpression.Operator.GREATER_EQUALS; break; case T_GT: operator = InfixExpression.Operator.GREATER; break; case T_LE: operator = InfixExpression.Operator.LESS_EQUALS; break; case T_LT: operator = InfixExpression.Operator.LESS; break; case T_NE: operator = InfixExpression.Operator.NOT_EQUALS; break; default: log.warn(getM() + ": Unknown cmp type '" + cop.getCmpType() + "' for 0-expression!"); operator = null; } expression = newInfixExpression(operator, expression, newLiteral(T.INT, 0, getM(), op), op); } final IfStatement ifStatement = getAst().newIfStatement(); ifStatement.setExpression(wrap(expression)); bb.addStmt(setOp(ifStatement, op)); break; } case JSR: { // <finally> till JVM 6 (50), we don't really push something at the sub BB, we // rewrite this or catch the stack underflow for the STORE break; } case LOAD: { final LOAD cop = (LOAD) op; /* * final V v = getCfg().getFrameVar(cop.getReg(), cop.getPc()); if (v == null || * v.getName() == null) { // temporary local final Expression expression = * bb.get(cop.getReg()); if (expression != null) { bb.push(bb.get(cop.getReg())); * break; } } */ // must not access method parameters for fieldInits... fieldInitCheck: if (isFieldInit()) { if (!getM().isConstructor()) { setFieldInit(false); break fieldInitCheck; } final R r = getCfg().getInFrame(op).load(cop.getReg()); if (r == null) { break fieldInitCheck; } if (!r.isMethodParam()) { setFieldInit(false); break fieldInitCheck; } if (cop.getReg() == 0) { break fieldInitCheck; // this } // only synthetic parameters are allowed final T ownerT = getM().getT(); if (ownerT != null && ownerT.isInner() && !getCfg().getCu().check(DFlag.IGNORE_CONSTRUCTOR_THIS)) { if (cop.getReg() == 1 && r.getT().is(getM().getParamTs()[0])) { break fieldInitCheck; } } setFieldInit(false); } bb.push(getVarExpression(cop.getReg(), cop.getPc(), op)); break; } case MONITOR: { final MONITOR cop = (MONITOR) op; switch (cop.getKind()) { case ENTER: { final SynchronizedStatement synchronizedStatement = setOp(getAst().newSynchronizedStatement(), op); synchronizedStatement.setExpression(wrap(bb.pop())); bb.addStmt(setOp(synchronizedStatement, op)); break; } case EXIT: { // for now: same as ENTER, blocks don't work here, // use getOp() to distinguish in control flow analysis final SynchronizedStatement synchronizedStatement = setOp(getAst().newSynchronizedStatement(), op); synchronizedStatement.setExpression(wrap(bb.pop())); bb.addStmt(setOp(synchronizedStatement, op)); break; } default: log.warn(getM() + ": Unknown monitor kind '" + cop.getKind() + "'!"); } break; } case MUL: { bb.push(newInfixExpressionPop(InfixExpression.Operator.TIMES, bb, op)); break; } case NEG: { bb.push(newPrefixExpression(PrefixExpression.Operator.MINUS, bb.pop(), op)); break; } case NEW: { final NEW cop = (NEW) op; final ClassInstanceCreation classInstanceCreation = setOp(getAst().newClassInstanceCreation(), op); final String thisName = getCfg().getT().getName(); final T newT = cop.getT(); final String newName = newT.getName(); // check for valid inner anonymous anonymous: if (newT.validateQualifierName(thisName)) { try { // anonymous classes typically use a number postfix, try it Integer.parseInt(newName.substring(thisName.length() + 1)); if (newT.isDeclaration()) { // anonymous inner can only have a single interface // (with generic super "Object") or a super class final T[] interfaceTs = newT.getInterfaceTs(); switch (interfaceTs.length) { case 0: { final T superT = newT.getSuperT(); assert superT != null; classInstanceCreation.setType(newType(superT, getM())); break; } case 1: { final T interfaceT = interfaceTs[0]; assert interfaceT != null; classInstanceCreation.setType(newType(interfaceT, getM())); break; } default: break anonymous; } final AnonymousClassDeclaration anonymousClassDeclaration = setOp( getAst().newAnonymousClassDeclaration(), op); newT.setAstNode(anonymousClassDeclaration); classInstanceCreation.setAnonymousClassDeclaration(anonymousClassDeclaration); bb.push(classInstanceCreation); break; } } catch (final NumberFormatException e) { // no int } } classInstanceCreation.setType(newType(newT, getM())); bb.push(classInstanceCreation); break; } case NEWARRAY: { final NEWARRAY cop = (NEWARRAY) op; final ArrayCreation arrayCreation = setOp(getAst().newArrayCreation(), op); arrayCreation.setType((ArrayType) newType(cop.getT(), getM())); for (int i = cop.getDimensions(); i-- > 0;) { arrayCreation.dimensions().add(0, wrap(bb.pop())); } bb.push(arrayCreation); break; } case OR: { bb.push(newInfixExpressionPop(InfixExpression.Operator.OR, bb, op)); break; } case POP: { final POP cop = (POP) op; switch (cop.getKind()) { case POP2: { final Expression e = bb.pop(); if (Expressions.isStatementExpression(e)) { bb.addStmt(setOp(getAst().newExpressionStatement(wrap(e)), op)); } else if (e instanceof SimpleName) { // exception or simple literal break; } else if (isBoolean(e) && !(e instanceof BooleanLiteral)) { if (getCfg().getT().isAtLeast(Version.JVM_4)) { log.warn(getM() + ": Boolean expression POP in '" + cop + "' for >= JVM 5 code! Rewriting to empty if."); } final IfStatement ifStatement = getAst().newIfStatement(); ifStatement.setExpression(wrap(e)); ifStatement.setThenStatement(getAst().newEmptyStatement()); bb.addStmt(setOp(ifStatement, op)); } if (isWide(e)) { break; } // fall through for second pop iff none-wide } case POP: { final Expression e = bb.pop(); if (Expressions.isStatementExpression(e)) { bb.addStmt(setOp(getAst().newExpressionStatement(wrap(e)), op)); } else if (e instanceof SimpleName) { // exception or simple literal break; } else if (isBoolean(e) && !(e instanceof BooleanLiteral)) { if (getCfg().getT().isAtLeast(Version.JVM_4)) { log.warn(getM() + ": Boolean expression POP in '" + cop + "' for >= JVM 5 code! Rewriting to empty if."); } final IfStatement ifStatement = getAst().newIfStatement(); ifStatement.setExpression(wrap(e)); ifStatement.setThenStatement(getAst().newEmptyStatement()); bb.addStmt(setOp(ifStatement, op)); } break; } default: log.warn(getM() + ": Unknown POP type '" + cop.getKind() + "'!"); } break; } case PUSH: { final PUSH cop = (PUSH) op; final T t = getCfg().getOutFrame(op).peek().getT(); assert t != null; bb.push(newLiteral(t, cop.getValue(), getCfg().getM(), op)); break; } case PUT: { final PUT cop = (PUT) op; final F f = cop.getF(); final Expression rightOperand = bb.pop(); assert rightOperand != null; if (rewriteFieldInit(bb, f, rightOperand)) { // was a constructor or initializer field init, done break; } Expression leftOperand; if (f.isStatic()) { leftOperand = getAst().newQualifiedName(newTypeName(f.getT(), getM()), newSimpleName(f.getName(), getAst())); } else { final FieldAccess fieldAccess = getAst().newFieldAccess(); fieldAccess.setExpression(wrap(bb.pop(), Priority.MEMBER_ACCESS)); fieldAccess.setName(newSimpleName(f.getName(), getAst())); leftOperand = fieldAccess; } assert leftOperand != null; final Assignment assignment = newAssignment(Assignment.Operator.ASSIGN, leftOperand, rightOperand, op); // TODO a = a +/- 1 => a++ / a-- // TODO a = a <op> expr => a <op>= expr // inline assignment, DUP(_X1) -> PUT if (!bb.isStackEmpty() && bb.peek() == rightOperand) { bb.pop(); bb.push(assignment); break; } if (!bb.isStackEmpty() && rightOperand instanceof InfixExpression && (((InfixExpression) rightOperand).getOperator() == InfixExpression.Operator.PLUS || ((InfixExpression) rightOperand) .getOperator() == InfixExpression.Operator.MINUS)) { // if i'm an peek-1 or peek+1 expression, than we can post-inc/dec // TODO more checks! bb.push(newPostfixExpression( ((InfixExpression) rightOperand).getOperator() == InfixExpression.Operator.PLUS ? PostfixExpression.Operator.INCREMENT : PostfixExpression.Operator.DECREMENT, bb.pop(), op)); break; } bb.addStmt(setOp(getAst().newExpressionStatement(assignment), op)); break; } case REM: { bb.push(newInfixExpressionPop(InfixExpression.Operator.REMAINDER, bb, op)); break; } case RET: { // TODO break; } case RETURN: { final RETURN cop = (RETURN) op; final ReturnStatement returnStatement = getAst().newReturnStatement(); if (cop.getT() != T.VOID) { returnStatement.setExpression(wrap(bb.pop())); } bb.addStmt(setOp(returnStatement, op)); break; } case SHL: { bb.push(newInfixExpressionPop(InfixExpression.Operator.LEFT_SHIFT, bb, op)); break; } case SHR: { final SHR cop = (SHR) op; bb.push(newInfixExpressionPop(cop.isUnsigned() ? InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED : InfixExpression.Operator.RIGHT_SHIFT_SIGNED, bb, op)); break; } case STORE: { final STORE cop = (STORE) op; final Expression rightOperand = bb.pop(); // handle exception name expression exceptionNameExpression: if (rightOperand instanceof SimpleName) { // should be an uninitialized, temporary exception name expression final ASTNode parent = rightOperand.getParent(); if (!(parent instanceof VariableDeclarationFragment)) { break exceptionNameExpression; } assert ((SimpleName) rightOperand).getIdentifier().equals(Expressions.EXCEPTION_NAME_TMP); // also renames the parent temporary throwable declaration name, // later used for creating catch control statements ((SimpleName) rightOperand).setIdentifier(getVarName(cop.getReg(), cop.getPc() + 1)); break; // STORE end } // handle inline assignments via DUP -> STORE final boolean isInlineAssignment = !bb.isStackEmpty() && bb.peek() == rightOperand; // handle variable declaration assignments final V v = getCfg().getFrameVar(cop.getReg(), cop.getPc() + 1); if (v == null /* tmp hack */ || v.getName() == null) { // temporary local // bb.set(cop.getReg(), rightOperand); // break; // TODO else not really necessary later if this is sure } else { // TODO if () int i = 0 else int i = 1 ??? if (!isInlineAssignment && v.getPcs()[0] /* TODO */ == cop.getPc() + 1) { final VariableDeclarationFragment variableDeclarationFragment = getAst() .newVariableDeclarationFragment(); variableDeclarationFragment.setName(newSimpleName(v.getName(), getAst())); variableDeclarationFragment.setInitializer(wrap(rightOperand, Priority.ASSIGNMENT)); final VariableDeclarationStatement variableDeclarationStatement = getAst() .newVariableDeclarationStatement(variableDeclarationFragment); variableDeclarationStatement.setType(newType(v.getT(), getM())); bb.addStmt(setOp(variableDeclarationStatement, op)); break; } } final Assignment assignment = newAssignment(Assignment.Operator.ASSIGN, getVarExpression(cop.getReg(), cop.getPc() + 1, op), rightOperand, op); if (isInlineAssignment) { bb.pop(); bb.push(assignment); break; } if (!rewriteStorePreIncDec(bb, assignment)) { bb.addStmt(setOp(getAst().newExpressionStatement(assignment), op)); } break; } case SUB: { bb.push(newInfixExpressionPop(InfixExpression.Operator.MINUS, bb, op)); break; } case SWAP: { final Expression e1 = bb.pop(); final Expression e2 = bb.pop(); bb.push(e1); bb.push(e2); break; } case SWITCH: { final SWITCH cop = (SWITCH) op; final Expression switchExpression = bb.pop(); assert switchExpression != null; if (rewriteSwitchEnum(bb, cop, switchExpression)) { break; } if (rewriteSwitchString(bb, cop, switchExpression)) { break; } final T t = peekT(op); if (t == T.CHAR) { rewriteSwitchChar(bb); } final SwitchStatement switchStatement = getAst().newSwitchStatement(); switchStatement.setExpression(wrap(switchExpression)); bb.addStmt(setOp(switchStatement, op)); break; } case THROW: { final Expression exceptionExpression = bb.pop(); assert exceptionExpression != null; final ThrowStatement throwStatement = getAst().newThrowStatement(); throwStatement.setExpression(wrap(exceptionExpression)); bb.addStmt(setOp(throwStatement, op)); break; } case XOR: { final Expression rightOperand = bb.pop(); // "a ^ -1" => "~a" if (rightOperand instanceof NumberLiteral && ((NumberLiteral) rightOperand).getToken().equals("-1")) { bb.push(newPrefixExpression(PrefixExpression.Operator.COMPLEMENT, bb.pop(), op)); break; } // "a ^ true" => "!a" (found in JVM 1.2 boolean expressions) if (rightOperand instanceof BooleanLiteral && getBooleanValue(rightOperand) == Boolean.TRUE) { bb.push(newPrefixExpression(PrefixExpression.Operator.NOT, bb.pop(), op)); break; } bb.push(newInfixExpression(InfixExpression.Operator.XOR, bb.pop(), rightOperand, op)); break; } default: throw new DecoJerException("Unknown intermediate vm operation '" + op + "'!"); } } return true; }