/** * If we are in a constructor, that is static compiled, but in a class, that is not, it may happen * that init code from object initializers, fields or properties is added into the constructor * code. The backend assumes a purely static contructor, so it may fail if it encounters dynamic * code here. Thus we make this kind of code fail */ private void checkForConstructorWithCSButClassWithout(MethodNode node) { if (!(node instanceof ConstructorNode)) return; Object meta = node.getNodeMetaData(STATIC_COMPILE_NODE); if (!Boolean.TRUE.equals(meta)) return; ClassNode clz = typeCheckingContext.getEnclosingClassNode(); meta = clz.getNodeMetaData(STATIC_COMPILE_NODE); if (Boolean.TRUE.equals(meta)) return; if (clz.getObjectInitializerStatements().isEmpty() && clz.getFields().isEmpty() && clz.getProperties().isEmpty()) { return; } addStaticTypeError( "Cannot statically compile constructor implicitly including non static elements from object initializers, properties or fields.", node); }
/** Adds special accessors for private constants so that inner classes can retrieve them. */ @SuppressWarnings("unchecked") private void addPrivateFieldsAccessors(ClassNode node) { Set<ASTNode> accessedFields = (Set<ASTNode>) node.getNodeMetaData(StaticTypesMarker.PV_FIELDS_ACCESS); if (accessedFields == null) return; Map<String, MethodNode> privateConstantAccessors = (Map<String, MethodNode>) node.getNodeMetaData(PRIVATE_FIELDS_ACCESSORS); if (privateConstantAccessors != null) { // already added return; } int acc = -1; privateConstantAccessors = new HashMap<String, MethodNode>(); final int access = Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC; for (FieldNode fieldNode : node.getFields()) { if (accessedFields.contains(fieldNode)) { acc++; Parameter param = new Parameter(node.getPlainNodeReference(), "$that"); Expression receiver = fieldNode.isStatic() ? new ClassExpression(node) : new VariableExpression(param); Statement stmt = new ExpressionStatement(new PropertyExpression(receiver, fieldNode.getName())); MethodNode accessor = node.addMethod( "pfaccess$" + acc, access, fieldNode.getOriginType(), new Parameter[] {param}, ClassNode.EMPTY_ARRAY, stmt); privateConstantAccessors.put(fieldNode.getName(), accessor); } } node.setNodeMetaData(PRIVATE_FIELDS_ACCESSORS, privateConstantAccessors); }