List of usage examples for org.objectweb.asm Opcodes ACC_STATIC
int ACC_STATIC
To view the source code for org.objectweb.asm Opcodes ACC_STATIC.
Click Source Link
From source file:org.codehaus.groovy.runtime.callsite.CallSiteGenerator.java
License:Apache License
public static byte[] genPogoMetaMethodSite(CachedMethod cachedMethod, ClassWriter cw, String name) { String internalName = name.replace('.', '/'); classHeader(cw, internalName, "org/codehaus/groovy/runtime/callsite/PogoMetaMethodSite"); cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "__constructor__", "Ljava/lang/reflect/Constructor;", null, null);/* ww w.j a v a 2 s. c o m*/ genConstructor(cw, "org/codehaus/groovy/runtime/callsite/PogoMetaMethodSite", internalName); genCallXxxWithArray(cw, "Current", "org/codehaus/groovy/runtime/callsite/PogoMetaMethodSite", cachedMethod, "groovy/lang/GroovyObject"); genCallXxxWithArray(cw, "", "org/codehaus/groovy/runtime/callsite/PogoMetaMethodSite", cachedMethod, "java/lang/Object"); genCallWithFixedParams(cw, "Current", "org/codehaus/groovy/runtime/callsite/PogoMetaMethodSite", cachedMethod, "groovy/lang/GroovyObject"); genCallWithFixedParams(cw, "", "org/codehaus/groovy/runtime/callsite/PogoMetaMethodSite", cachedMethod, "java/lang/Object"); cw.visitEnd(); return cw.toByteArray(); }
From source file:org.codehaus.groovy.runtime.callsite.CallSiteGenerator.java
License:Apache License
public static byte[] genPojoMetaMethodSite(CachedMethod cachedMethod, ClassWriter cw, String name) { String internalName = name.replace('.', '/'); classHeader(cw, internalName, "org/codehaus/groovy/runtime/callsite/PojoMetaMethodSite"); cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "__constructor__", "Ljava/lang/reflect/Constructor;", null, null);/*w ww .j a v a 2s .co m*/ genConstructor(cw, "org/codehaus/groovy/runtime/callsite/PojoMetaMethodSite", internalName); genCallXxxWithArray(cw, "", "org/codehaus/groovy/runtime/callsite/PojoMetaMethodSite", cachedMethod, "java/lang/Object"); genCallWithFixedParams(cw, "", "org/codehaus/groovy/runtime/callsite/PojoMetaMethodSite", cachedMethod, "java/lang/Object"); cw.visitEnd(); return cw.toByteArray(); }
From source file:org.codehaus.groovy.runtime.callsite.CallSiteGenerator.java
License:Apache License
public static byte[] genStaticMetaMethodSite(CachedMethod cachedMethod, ClassWriter cw, String name) { String internalName = name.replace('.', '/'); classHeader(cw, internalName, "org/codehaus/groovy/runtime/callsite/StaticMetaMethodSite"); cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "__constructor__", "Ljava/lang/reflect/Constructor;", null, null);// w ww.j a va 2 s . c om genConstructor(cw, "org/codehaus/groovy/runtime/callsite/StaticMetaMethodSite", internalName); genCallXxxWithArray(cw, "", "org/codehaus/groovy/runtime/callsite/StaticMetaMethodSite", cachedMethod, "java/lang/Object"); genCallXxxWithArray(cw, "Static", "org/codehaus/groovy/runtime/callsite/StaticMetaMethodSite", cachedMethod, "java/lang/Class"); genCallWithFixedParams(cw, "", "org/codehaus/groovy/runtime/callsite/StaticMetaMethodSite", cachedMethod, "java/lang/Object"); genCallWithFixedParams(cw, "Static", "org/codehaus/groovy/runtime/callsite/StaticMetaMethodSite", cachedMethod, "java/lang/Class"); cw.visitEnd(); return cw.toByteArray(); }
From source file:org.codehaus.groovy.tools.javac.JavaStubGenerator.java
License:Apache License
private static void printModifiers(PrintWriter out, int modifiers) { if ((modifiers & Opcodes.ACC_PUBLIC) != 0) out.print("public "); if ((modifiers & Opcodes.ACC_PROTECTED) != 0) out.print("protected "); if ((modifiers & Opcodes.ACC_PRIVATE) != 0) out.print("private "); if ((modifiers & Opcodes.ACC_STATIC) != 0) out.print("static "); if ((modifiers & Opcodes.ACC_SYNCHRONIZED) != 0) out.print("synchronized "); if ((modifiers & Opcodes.ACC_FINAL) != 0) out.print("final "); if ((modifiers & Opcodes.ACC_ABSTRACT) != 0) out.print("abstract "); }
From source file:org.codehaus.groovy.transform.CategoryASTTransformation.java
License:Apache License
/** * Property invocations done on 'this' reference are transformed so that the invocations at runtime are * done on the additional parameter 'self' *//* ww w . j a va 2 s . com*/ public void visit(ASTNode[] nodes, final SourceUnit source) { if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof ClassNode)) { source.getErrorCollector() .addError(new SyntaxErrorMessage(new SyntaxException( "@Category can only be added to a ClassNode but got: " + (nodes.length == 2 ? nodes[1] : "nothing"), nodes[0].getLineNumber(), nodes[0].getColumnNumber()), source)); } AnnotationNode annotation = (AnnotationNode) nodes[0]; ClassNode parent = (ClassNode) nodes[1]; ClassNode targetClass = getTargetClass(source, annotation); thisExpression.setType(targetClass); final LinkedList<Set<String>> varStack = new LinkedList<Set<String>>(); if (!ensureNoInstanceFieldOrProperty(source, parent)) return; Set<String> names = new HashSet<String>(); for (FieldNode field : parent.getFields()) { names.add(field.getName()); } for (PropertyNode field : parent.getProperties()) { names.add(field.getName()); } varStack.add(names); final Reference parameter = new Reference(); final ClassCodeExpressionTransformer expressionTransformer = new ClassCodeExpressionTransformer() { protected SourceUnit getSourceUnit() { return source; } private void addVariablesToStack(Parameter[] params) { Set<String> names = new HashSet<String>(varStack.getLast()); for (Parameter param : params) { names.add(param.getName()); } varStack.add(names); } @Override public void visitCatchStatement(CatchStatement statement) { varStack.getLast().add(statement.getVariable().getName()); super.visitCatchStatement(statement); varStack.getLast().remove(statement.getVariable().getName()); } @Override public void visitMethod(MethodNode node) { addVariablesToStack(node.getParameters()); super.visitMethod(node); varStack.removeLast(); } @Override public void visitBlockStatement(BlockStatement block) { Set<String> names = new HashSet<String>(varStack.getLast()); varStack.add(names); super.visitBlockStatement(block); varStack.remove(names); } @Override public void visitClosureExpression(ClosureExpression ce) { addVariablesToStack(getParametersSafe(ce)); super.visitClosureExpression(ce); varStack.removeLast(); } @Override public void visitDeclarationExpression(DeclarationExpression expression) { if (expression.isMultipleAssignmentDeclaration()) { TupleExpression te = expression.getTupleExpression(); List<Expression> list = te.getExpressions(); for (Expression arg : list) { VariableExpression ve = (VariableExpression) arg; varStack.getLast().add(ve.getName()); } } else { VariableExpression ve = expression.getVariableExpression(); varStack.getLast().add(ve.getName()); } super.visitDeclarationExpression(expression); } @Override public void visitForLoop(ForStatement forLoop) { Expression exp = forLoop.getCollectionExpression(); exp.visit(this); Parameter loopParam = forLoop.getVariable(); if (loopParam != null) { varStack.getLast().add(loopParam.getName()); } super.visitForLoop(forLoop); } @Override public void visitExpressionStatement(ExpressionStatement es) { // GROOVY-3543: visit the declaration expressions so that declaration variables get added on the varStack Expression exp = es.getExpression(); if (exp instanceof DeclarationExpression) { exp.visit(this); } super.visitExpressionStatement(es); } @Override public Expression transform(Expression exp) { if (exp instanceof VariableExpression) { VariableExpression ve = (VariableExpression) exp; if (ve.getName().equals("this")) return thisExpression; else { if (!varStack.getLast().contains(ve.getName())) { return new PropertyExpression(thisExpression, ve.getName()); } } } else if (exp instanceof PropertyExpression) { PropertyExpression pe = (PropertyExpression) exp; if (pe.getObjectExpression() instanceof VariableExpression) { VariableExpression vex = (VariableExpression) pe.getObjectExpression(); if (vex.isThisExpression()) { pe.setObjectExpression(thisExpression); return pe; } } } else if (exp instanceof ClosureExpression) { ClosureExpression ce = (ClosureExpression) exp; ce.getVariableScope().putReferencedLocalVariable((Parameter) parameter.get()); addVariablesToStack(hasImplicitParameter(ce) ? params(param(ClassHelper.OBJECT_TYPE, "it")) : getParametersSafe(ce)); ce.getCode().visit(this); varStack.removeLast(); } return super.transform(exp); } }; for (MethodNode method : parent.getMethods()) { if (!method.isStatic()) { method.setModifiers(method.getModifiers() | Opcodes.ACC_STATIC); final Parameter[] origParams = method.getParameters(); final Parameter[] newParams = new Parameter[origParams.length + 1]; Parameter p = new Parameter(targetClass, "$this"); p.setClosureSharedVariable(true); newParams[0] = p; parameter.set(p); System.arraycopy(origParams, 0, newParams, 1, origParams.length); method.setParameters(newParams); expressionTransformer.visitMethod(method); } } new VariableScopeVisitor(source, true).visitClass(parent); }
From source file:org.codehaus.groovy.transform.LogASTTransformation.java
License:Apache License
private int lookupLogFieldModifiers(AnnotatedNode targetClass, AnnotationNode logAnnotation) { int modifiers = getVisibility(logAnnotation, targetClass, ClassNode.class, Opcodes.ACC_PRIVATE); return Opcodes.ACC_FINAL | Opcodes.ACC_TRANSIENT | Opcodes.ACC_STATIC | modifiers; }
From source file:org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.java
License:Apache License
/** * A helper method that can be used to evaluate expressions as found in annotation * parameters. For example, it will evaluate a constant, be it referenced directly as * an integer or as a reference to a field. * <p>/*from w w w.ja va 2 s . com*/ * If this method throws an exception, then the expression cannot be evaluated on its own. * * @param expr the expression to be evaluated * @param config the compiler configuration * @return the result of the expression */ public static Object evaluateExpression(Expression expr, CompilerConfiguration config) { String className = "Expression$" + UUID.randomUUID().toString().replace('-', '$'); ClassNode node = new ClassNode(className, Opcodes.ACC_PUBLIC, OBJECT_TYPE); ReturnStatement code = new ReturnStatement(expr); addGeneratedMethod(node, "eval", Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, code); CompilerConfiguration copyConf = new CompilerConfiguration(config); CompilationUnit cu = new CompilationUnit(copyConf); cu.addClassNode(node); cu.compile(Phases.CLASS_GENERATION); List<GroovyClass> classes = cu.getClasses(); Class<?> aClass = cu.getClassLoader().defineClass(className, classes.get(0).getBytes()); try { return aClass.getMethod("eval").invoke(null); } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { throw new GroovyBugError(e); } }
From source file:org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.java
License:Apache License
@Override public void visitMethodCallExpression(final MethodCallExpression call) { String name = call.getMethodAsString(); if (name == null) { addStaticTypeError("cannot resolve dynamic method name at compile time.", call.getMethod()); return;/* w w w . java2 s. c om*/ } if (extension.beforeMethodCall(call)) { extension.afterMethodCall(call); return; } typeCheckingContext.pushEnclosingMethodCall(call); Expression objectExpression = call.getObjectExpression(); objectExpression.visit(this); call.getMethod().visit(this); // if the call expression is a spread operator call, then we must make sure that // the call is made on a collection type if (call.isSpreadSafe()) { //TODO check if this should not be change to iterator based call logic ClassNode expressionType = getType(objectExpression); if (!implementsInterfaceOrIsSubclassOf(expressionType, Collection_TYPE) && !expressionType.isArray()) { addStaticTypeError("Spread operator can only be used on collection types", objectExpression); return; } else { // type check call as if it was made on component type ClassNode componentType = inferComponentType(expressionType, int_TYPE); MethodCallExpression subcall = callX(castX(componentType, EmptyExpression.INSTANCE), name, call.getArguments()); subcall.setLineNumber(call.getLineNumber()); subcall.setColumnNumber(call.getColumnNumber()); subcall.setImplicitThis(call.isImplicitThis()); visitMethodCallExpression(subcall); // the inferred type here should be a list of what the subcall returns ClassNode subcallReturnType = getType(subcall); ClassNode listNode = LIST_TYPE.getPlainNodeReference(); listNode.setGenericsTypes( new GenericsType[] { new GenericsType(wrapTypeIfNecessary(subcallReturnType)) }); storeType(call, listNode); // store target method storeTargetMethod(call, subcall.getNodeMetaData(DIRECT_METHOD_CALL_TARGET)); typeCheckingContext.popEnclosingMethodCall(); return; } } Expression callArguments = call.getArguments(); ArgumentListExpression argumentList = InvocationWriter.makeArgumentList(callArguments); checkForbiddenSpreadArgument(argumentList); // for arguments, we need to visit closures *after* the method has been chosen ClassNode receiver = getType(objectExpression); visitMethodCallArguments(receiver, argumentList, false, null); ClassNode[] args = getArgumentTypes(argumentList); boolean isCallOnClosure = isClosureCall(name, objectExpression, callArguments); try { boolean callArgsVisited = false; if (isCallOnClosure) { // this is a closure.call() call if (isThisExpression(objectExpression)) { // isClosureCall() check verified earlier that a field exists FieldNode field = typeCheckingContext.getEnclosingClassNode().getDeclaredField(name); GenericsType[] genericsTypes = field.getType().getGenericsTypes(); if (genericsTypes != null) { ClassNode closureReturnType = genericsTypes[0].getType(); Object data = field.getNodeMetaData(CLOSURE_ARGUMENTS); if (data != null) { Parameter[] parameters = (Parameter[]) data; typeCheckClosureCall(callArguments, args, parameters); } storeType(call, closureReturnType); } } else if (objectExpression instanceof VariableExpression) { Variable variable = findTargetVariable((VariableExpression) objectExpression); if (variable instanceof ASTNode) { Object data = ((ASTNode) variable).getNodeMetaData(CLOSURE_ARGUMENTS); if (data != null) { Parameter[] parameters = (Parameter[]) data; typeCheckClosureCall(callArguments, args, parameters); } ClassNode type = getType(((ASTNode) variable)); if (type != null && type.equals(CLOSURE_TYPE)) { GenericsType[] genericsTypes = type.getGenericsTypes(); type = OBJECT_TYPE; if (genericsTypes != null) { if (!genericsTypes[0].isPlaceholder()) { type = genericsTypes[0].getType(); } } } if (type != null) { storeType(call, type); } } } else if (objectExpression instanceof ClosureExpression) { // we can get actual parameters directly Parameter[] parameters = ((ClosureExpression) objectExpression).getParameters(); typeCheckClosureCall(callArguments, args, parameters); ClassNode data = getInferredReturnType(objectExpression); if (data != null) { storeType(call, data); } } int nbOfArgs; if (callArguments instanceof ArgumentListExpression) { ArgumentListExpression list = (ArgumentListExpression) callArguments; nbOfArgs = list.getExpressions().size(); } else { // todo : other cases nbOfArgs = 0; } storeTargetMethod(call, nbOfArgs == 0 ? CLOSURE_CALL_NO_ARG : nbOfArgs == 1 ? CLOSURE_CALL_ONE_ARG : CLOSURE_CALL_VARGS); } else { // method call receivers are : // - possible "with" receivers // - the actual receiver as found in the method call expression // - any of the potential receivers found in the instanceof temporary table // in that order List<Receiver<String>> receivers = new LinkedList<>(); List<Receiver<String>> owners = makeOwnerList(objectExpression); addReceivers(receivers, owners, call.isImplicitThis()); List<MethodNode> mn = null; Receiver<String> chosenReceiver = null; for (Receiver<String> currentReceiver : receivers) { ClassNode receiverType = currentReceiver.getType(); mn = findMethod(receiverType, name, args); // if the receiver is "this" or "implicit this", then we must make sure that the compatible // methods are only static if we are in a static context // if we are not in a static context but the current receiver is a static class, we must // ensure that all methods are either static or declared by the current receiver or a superclass if (!mn.isEmpty() && (call.isImplicitThis() || isThisExpression(objectExpression)) && (typeCheckingContext.isInStaticContext || (receiverType.getModifiers() & Opcodes.ACC_STATIC) != 0)) { // we create separate method lists just to be able to print out // a nice error message to the user // a method is accessible if it is static, or if we are not in a static context and it is // declared by the current receiver or a superclass List<MethodNode> accessibleMethods = new LinkedList<>(); List<MethodNode> inaccessibleMethods = new LinkedList<>(); for (final MethodNode node : mn) { if (node.isStatic() || (!typeCheckingContext.isInStaticContext && implementsInterfaceOrIsSubclassOf(receiverType, node.getDeclaringClass()))) { accessibleMethods.add(node); } else { inaccessibleMethods.add(node); } } mn = accessibleMethods; if (accessibleMethods.isEmpty()) { // choose an arbitrary method to display an error message MethodNode node = inaccessibleMethods.get(0); ClassNode owner = node.getDeclaringClass(); addStaticTypeError("Non static method " + owner.getName() + "#" + node.getName() + " cannot be called from static context", call); } } if (!mn.isEmpty()) { chosenReceiver = currentReceiver; break; } } if (mn.isEmpty() && typeCheckingContext.getEnclosingClosure() != null && args.length == 0) { // add special handling of getDelegate() and getOwner() if ("getDelegate".equals(name)) { mn = Collections.singletonList(GET_DELEGATE); } else if ("getOwner".equals(name)) { mn = Collections.singletonList(GET_OWNER); } else if ("getThisObject".equals(name)) { mn = Collections.singletonList(GET_THISOBJECT); } } if (mn.isEmpty()) { mn = extension.handleMissingMethod(receiver, name, argumentList, args, call); } if (mn.isEmpty()) { addNoMatchingMethodError(receiver, name, args, call); } else { if (areCategoryMethodCalls(mn, name, args)) { addCategoryMethodCallError(call); } mn = disambiguateMethods(mn, chosenReceiver != null ? chosenReceiver.getType() : null, args, call); if (mn.size() == 1) { MethodNode directMethodCallCandidate = mn.get(0); if (call.getNodeMetaData(DYNAMIC_RESOLUTION) == null && !directMethodCallCandidate.isStatic() && objectExpression instanceof ClassExpression && !"java.lang.Class" .equals(directMethodCallCandidate.getDeclaringClass().getName())) { ClassNode owner = directMethodCallCandidate.getDeclaringClass(); addStaticTypeError("Non static method " + owner.getName() + "#" + directMethodCallCandidate.getName() + " cannot be called from static context", call); } if (chosenReceiver == null) { chosenReceiver = Receiver.make(directMethodCallCandidate.getDeclaringClass()); } ClassNode returnType = getType(directMethodCallCandidate); if (isUsingGenericsOrIsArrayUsingGenerics(returnType)) { visitMethodCallArguments(chosenReceiver.getType(), argumentList, true, directMethodCallCandidate); ClassNode irtg = inferReturnTypeGenerics(chosenReceiver.getType(), directMethodCallCandidate, callArguments, call.getGenericsTypes()); returnType = (irtg != null && implementsInterfaceOrIsSubclassOf(irtg, returnType) ? irtg : returnType); callArgsVisited = true; } if (directMethodCallCandidate == GET_DELEGATE && typeCheckingContext.getEnclosingClosure() != null) { DelegationMetadata md = getDelegationMetadata( typeCheckingContext.getEnclosingClosure().getClosureExpression()); returnType = typeCheckingContext.getEnclosingClassNode(); if (md != null) { returnType = md.getType(); } } if (typeCheckMethodsWithGenericsOrFail(chosenReceiver.getType(), args, mn.get(0), call)) { returnType = adjustWithTraits(directMethodCallCandidate, chosenReceiver.getType(), args, returnType); storeType(call, returnType); storeTargetMethod(call, directMethodCallCandidate); String data = chosenReceiver.getData(); if (data != null) { // the method which has been chosen is supposed to be a call on delegate or owner // so we store the information so that the static compiler may reuse it call.putNodeMetaData(IMPLICIT_RECEIVER, data); } // if the object expression is a closure shared variable, we will have to perform a second pass if (objectExpression instanceof VariableExpression) { VariableExpression var = (VariableExpression) objectExpression; if (var.isClosureSharedVariable()) { SecondPassExpression<ClassNode[]> wrapper = new SecondPassExpression<>(call, args); typeCheckingContext.secondPassExpressions.add(wrapper); } } } } else { addAmbiguousErrorMessage(mn, name, args, call); } } } // adjust typing for explicit math methods which have special handling - operator variants handled elsewhere if (NUMBER_OPS.containsKey(name) && isNumberType(receiver) && argumentList.getExpressions().size() == 1 && isNumberType(getType(argumentList.getExpression(0)))) { ClassNode right = getType(argumentList.getExpression(0)); ClassNode resultType = getMathResultType(NUMBER_OPS.get(name), receiver, right, name); if (resultType != null) { storeType(call, resultType); } } // now that a method has been chosen, we are allowed to visit the closures MethodNode target = call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET); if (!callArgsVisited) { visitMethodCallArguments(receiver, argumentList, true, target); } if (target != null) { List<Expression> argExpressions = argumentList.getExpressions(); Parameter[] parameters = target.getParameters(); for (int i = 0; i < argExpressions.size() && i < parameters.length; i += 1) { Expression arg = argExpressions.get(i); ClassNode aType = getType(arg), pType = parameters[i].getType(); if (CLOSURE_TYPE.equals(aType) && CLOSURE_TYPE.equals(pType) && !isAssignableTo(aType, pType)) { addNoMatchingMethodError(receiver, name, getArgumentTypes(argumentList), call); call.removeNodeMetaData(DIRECT_METHOD_CALL_TARGET); } } } inferMethodReferenceType(call, receiver, argumentList); } finally { typeCheckingContext.popEnclosingMethodCall(); extension.afterMethodCall(call); } }
From source file:org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.java
License:Apache License
protected List<MethodNode> findMethod(ClassNode receiver, final String name, final ClassNode... args) { if (isPrimitiveType(receiver)) receiver = getWrapper(receiver); List<MethodNode> methods; if (!receiver.isInterface() && "<init>".equals(name)) { methods = addGeneratedMethods(receiver, new ArrayList<>(receiver.getDeclaredConstructors())); if (methods.isEmpty()) { MethodNode node = new ConstructorNode(Opcodes.ACC_PUBLIC, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT); node.setDeclaringClass(receiver); methods = Collections.singletonList(node); if (receiver.isArray()) { // No need to check the arguments against an array constructor: it just needs to exist. The array is // created through coercion or by specifying its dimension(s), anyway, and would not match an // arbitrary number of parameters. return methods; }/*from www. ja va 2 s . co m*/ } } else { methods = findMethodsWithGenerated(receiver, name); if (receiver.isInterface()) { collectAllInterfaceMethodsByName(receiver, name, methods); methods.addAll(OBJECT_TYPE.getMethods(name)); if ("call".equals(name) && isFunctionalInterface(receiver)) { MethodNode sam = findSAM(receiver); MethodNode callMethodNode = new MethodNode("call", sam.getModifiers(), sam.getReturnType(), sam.getParameters(), sam.getExceptions(), sam.getCode()); callMethodNode.setDeclaringClass(sam.getDeclaringClass()); callMethodNode.setSourcePosition(sam); methods.addAll(Collections.singletonList(callMethodNode)); } } // TODO: investigate the trait exclusion a bit further, needed otherwise // CallMethodOfTraitInsideClosureAndClosureParamTypeInference fails saying // not static method can't be called from a static context if (typeCheckingContext.getEnclosingClosure() == null || (receiver.getOuterClass() != null && !receiver.getName().endsWith("$Trait$Helper"))) { // not in a closure or within an inner class ClassNode parent = receiver; while (parent.getOuterClass() != null && !parent.isStaticClass()) { parent = parent.getOuterClass(); methods.addAll(findMethodsWithGenerated(parent, name)); } } if (methods.isEmpty()) { addArrayMethods(methods, receiver, name, args); } if (methods.isEmpty() && (args == null || args.length == 0)) { // check if it's a property String pname = extractPropertyNameFromMethodName("get", name); if (pname == null) { pname = extractPropertyNameFromMethodName("is", name); } if (pname != null) { // we don't use property exists there because findMethod is called on super clases recursively PropertyNode property = null; ClassNode curNode = receiver; while (property == null && curNode != null) { property = curNode.getProperty(pname); ClassNode svCur = curNode; while (property == null && svCur.getOuterClass() != null && !svCur.isStaticClass()) { svCur = svCur.getOuterClass(); property = svCur.getProperty(pname); if (property != null) { receiver = svCur; break; } } curNode = curNode.getSuperClass(); } if (property != null) { MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC, property.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT); if (property.isStatic()) { node.setModifiers(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC); } node.setDeclaringClass(receiver); return Collections.singletonList(node); } } } else if (methods.isEmpty() && args != null && args.length == 1) { // maybe we are looking for a setter ? String pname = extractPropertyNameFromMethodName("set", name); if (pname != null) { ClassNode curNode = receiver; PropertyNode property = null; while (property == null && curNode != null) { property = curNode.getProperty(pname); curNode = curNode.getSuperClass(); } if (property != null) { ClassNode type = property.getOriginType(); if (implementsInterfaceOrIsSubclassOf(wrapTypeIfNecessary(args[0]), wrapTypeIfNecessary(type))) { MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC, VOID_TYPE, new Parameter[] { new Parameter(type, "arg") }, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT); if (property.isStatic()) { node.setModifiers(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC); } node.setDeclaringClass(receiver); return Collections.singletonList(node); } } } } } if (methods.isEmpty()) { // look at the interfaces, there's a chance that a method is not implemented and we should not hide the // error from the compiler collectAllInterfaceMethodsByName(receiver, name, methods); } // lookup in DGM methods too findDGMMethodsByNameAndArguments(getTransformLoader(), receiver, name, args, methods); methods = filterMethodsByVisibility(methods); List<MethodNode> chosen = chooseBestMethod(receiver, methods, args); if (!chosen.isEmpty()) return chosen; // GROOVY-5566 if (receiver instanceof InnerClassNode && ((InnerClassNode) receiver).isAnonymous() && methods.size() == 1 && args != null && "<init>".equals(name)) { MethodNode constructor = methods.get(0); if (constructor.getParameters().length == args.length) { return methods; } } if (receiver.equals(CLASS_Type) && receiver.getGenericsTypes() != null) { List<MethodNode> result = findMethod(receiver.getGenericsTypes()[0].getType(), name, args); if (!result.isEmpty()) return result; } if (GSTRING_TYPE.equals(receiver)) return findMethod(STRING_TYPE, name, args); if (isBeingCompiled(receiver)) { chosen = findMethod(GROOVY_OBJECT_TYPE, name, args); if (!chosen.isEmpty()) return chosen; } return EMPTY_METHODNODE_LIST; }
From source file:org.codehaus.groovy.transform.trait.TraitComposer.java
License:Apache License
private static void applyTrait(final ClassNode trait, final ClassNode cNode, final TraitHelpersTuple helpers, SourceUnit unit) {/*from w w w .j a v a 2 s. c om*/ ClassNode helperClassNode = helpers.getHelper(); ClassNode fieldHelperClassNode = helpers.getFieldHelper(); ClassNode staticFieldHelperClassNode = helpers.getStaticFieldHelper(); Map<String, ClassNode> genericsSpec = GenericsUtils.createGenericsSpec(trait, GenericsUtils.createGenericsSpec(cNode)); for (MethodNode methodNode : helperClassNode.getAllDeclaredMethods()) { String name = methodNode.getName(); Parameter[] helperMethodParams = methodNode.getParameters(); int nParams = helperMethodParams.length; if (nParams > 0 && !methodNode.isAbstract() && ((methodNode.getModifiers() & Opcodes.ACC_STATIC) != 0) && (!name.contains("$") || (methodNode.getModifiers() & Opcodes.ACC_SYNTHETIC) == 0)) { ArgumentListExpression argList = new ArgumentListExpression(); argList.addExpression(new VariableExpression("this")); Parameter[] origParams = new Parameter[nParams - 1]; Parameter[] params = new Parameter[nParams - 1]; System.arraycopy(methodNode.getParameters(), 1, params, 0, params.length); MethodNode originalMethod = trait.getMethod(name, params); Map<String, ClassNode> methodGenericsSpec = Optional.ofNullable(originalMethod) .map(m -> GenericsUtils.addMethodGenerics(m, genericsSpec)).orElse(genericsSpec); for (int i = 1; i < nParams; i += 1) { Parameter parameter = helperMethodParams[i]; ClassNode originType = parameter.getOriginType(); ClassNode fixedType = correctToGenericsSpecRecurse(methodGenericsSpec, originType); Parameter newParam = new Parameter(fixedType, parameter.getName()); List<AnnotationNode> copied = new LinkedList<>(); List<AnnotationNode> notCopied = new LinkedList<>(); GeneralUtils.copyAnnotatedNodeAnnotations(parameter, copied, notCopied); newParam.addAnnotations(copied); params[i - 1] = newParam; origParams[i - 1] = parameter; argList.addExpression(new VariableExpression(newParam)); } createForwarderMethod(trait, cNode, methodNode, originalMethod, helperClassNode, methodGenericsSpec, helperMethodParams, origParams, params, argList, unit); } } MethodCallExpression staticInitCall = new MethodCallExpression(new ClassExpression(helperClassNode), Traits.STATIC_INIT_METHOD, new ArgumentListExpression(new ClassExpression(cNode))); MethodNode staticInitMethod = new MethodNode(Traits.STATIC_INIT_METHOD, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, ClassHelper.VOID_TYPE, new Parameter[] { new Parameter(ClassHelper.CLASS_Type, "clazz") }, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE); staticInitMethod.setDeclaringClass(helperClassNode); staticInitCall.setMethodTarget(staticInitMethod); cNode.addStaticInitializerStatements( Collections.<Statement>singletonList(new ExpressionStatement(staticInitCall)), false); if (fieldHelperClassNode != null && !cNode.declaresInterface(fieldHelperClassNode)) { // we should implement the field helper interface too cNode.addInterface(fieldHelperClassNode); // implementation of methods List<MethodNode> declaredMethods = new LinkedList<>(); for (MethodNode declaredMethod : fieldHelperClassNode.getAllDeclaredMethods()) { if (declaredMethod.getName().endsWith(Traits.DIRECT_GETTER_SUFFIX)) { declaredMethods.add(0, declaredMethod); } else { declaredMethods.add(declaredMethod); } } if (staticFieldHelperClassNode != null) { for (MethodNode declaredMethod : staticFieldHelperClassNode.getAllDeclaredMethods()) { if (declaredMethod.getName().endsWith(Traits.DIRECT_GETTER_SUFFIX)) { declaredMethods.add(0, declaredMethod); } else { declaredMethods.add(declaredMethod); } } } for (MethodNode methodNode : declaredMethods) { String fieldName = methodNode.getName(); if (fieldName.endsWith(Traits.DIRECT_GETTER_SUFFIX) || fieldName.endsWith(Traits.DIRECT_SETTER_SUFFIX)) { int suffixIdx = fieldName.lastIndexOf("$"); fieldName = fieldName.substring(0, suffixIdx); String operation = methodNode.getName().substring(suffixIdx + 1); boolean getter = "get".equals(operation); ClassNode returnType = correctToGenericsSpecRecurse(genericsSpec, methodNode.getReturnType()); int fieldMods = 0; int isStatic = 0; boolean publicField = true; FieldNode helperField = null; fieldMods = 0; isStatic = 0; // look first for field with encoded modifier information for (Integer mod : Traits.FIELD_PREFIXES) { helperField = fieldHelperClassNode.getField(String.format("$0x%04x", mod) + fieldName); if (helperField != null) { if ((mod & Opcodes.ACC_STATIC) != 0) isStatic = Opcodes.ACC_STATIC; fieldMods = fieldMods | mod; break; } } if (helperField == null) { // look for possible legacy fields (trait compiled pre 2.4.8) helperField = fieldHelperClassNode .getField(Traits.FIELD_PREFIX + Traits.PUBLIC_FIELD_PREFIX + fieldName); if (helperField == null) { publicField = false; helperField = fieldHelperClassNode .getField(Traits.FIELD_PREFIX + Traits.PRIVATE_FIELD_PREFIX + fieldName); } if (helperField == null) { publicField = true; // try to find a static one helperField = fieldHelperClassNode .getField(Traits.STATIC_FIELD_PREFIX + Traits.PUBLIC_FIELD_PREFIX + fieldName); if (helperField == null) { publicField = false; helperField = fieldHelperClassNode.getField( Traits.STATIC_FIELD_PREFIX + Traits.PRIVATE_FIELD_PREFIX + fieldName); } fieldMods = fieldMods | Opcodes.ACC_STATIC; isStatic = Opcodes.ACC_STATIC; } fieldMods = fieldMods | (publicField ? Opcodes.ACC_PUBLIC : Opcodes.ACC_PRIVATE); } if (getter) { // add field if (helperField != null) { List<AnnotationNode> copied = new LinkedList<>(); List<AnnotationNode> notCopied = new LinkedList<>(); GeneralUtils.copyAnnotatedNodeAnnotations(helperField, copied, notCopied); FieldNode fieldNode = cNode.addField(fieldName, fieldMods, returnType, null); fieldNode.addAnnotations(copied); // getInitialExpression above will be null if not in same source unit // so instead set within (static) initializer if (fieldNode.isFinal()) { String baseName = fieldNode.isStatic() ? Traits.STATIC_INIT_METHOD : Traits.INIT_METHOD; StaticMethodCallExpression mce = callX(helperClassNode, baseName + fieldNode.getName(), args(varX("this"))); if (helperClassNode.hasPossibleStaticMethod(mce.getMethod(), mce.getArguments())) { Statement stmt = stmt( assignX(varX(fieldNode.getName(), fieldNode.getType()), mce)); if (isStatic == 0) { cNode.addObjectInitializerStatements(stmt); } else { List<Statement> staticStatements = new ArrayList<Statement>(); staticStatements.add(stmt); cNode.addStaticInitializerStatements(staticStatements, true); } } } } } Parameter[] newParams; if (getter) { newParams = Parameter.EMPTY_ARRAY; } else { ClassNode originType = methodNode.getParameters()[0].getOriginType(); ClassNode fixedType = originType.isGenericsPlaceHolder() ? ClassHelper.OBJECT_TYPE : correctToGenericsSpecRecurse(genericsSpec, originType); newParams = new Parameter[] { new Parameter(fixedType, "val") }; } Expression fieldExpr = varX(cNode.getField(fieldName)); boolean finalSetter = !getter && (fieldMods & Opcodes.ACC_FINAL) != 0; Statement body = getter ? returnS(fieldExpr) : (finalSetter ? null : stmt(new BinaryExpression(fieldExpr, Token.newSymbol(Types.EQUAL, 0, 0), varX(newParams[0])))); // add getter/setter even though setter not strictly needed for final fields // but add empty body for setter for legacy compatibility MethodNode impl = new MethodNode(methodNode.getName(), Opcodes.ACC_PUBLIC | isStatic, returnType, newParams, ClassNode.EMPTY_ARRAY, body); AnnotationNode an = new AnnotationNode(COMPILESTATIC_CLASSNODE); impl.addAnnotation(an); cNode.addTransform(StaticCompileTransformation.class, an); cNode.addMethod(impl); } } } cNode.addObjectInitializerStatements( new ExpressionStatement(new MethodCallExpression(new ClassExpression(helperClassNode), Traits.INIT_METHOD, new ArgumentListExpression(new VariableExpression("this"))))); }