private void createField(ClassNode classNode, String propertyName, boolean isLazy, boolean isStrict) { int modifiers = isLazy ? ACC_PRIVATE | ACC_STATIC | ACC_VOLATILE : ACC_PUBLIC | ACC_FINAL | ACC_STATIC; Expression initialValue = isLazy ? null : ctorX(classNode); final FieldNode fieldNode = classNode.addField(propertyName, modifiers, newClass(classNode), initialValue); createConstructor(classNode, fieldNode, propertyName, isStrict); final BlockStatement body = new BlockStatement(); body.addStatement(isLazy ? lazyBody(classNode, fieldNode) : nonLazyBody(fieldNode)); addGeneratedMethod(classNode, getGetterName(propertyName), ACC_STATIC | ACC_PUBLIC, newClass(classNode), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body); }
@Test public void testVisit_Contract() { try { ASTNode[] badInput = new ASTNode[]{ new ConstantExpression("sample"), new EmptyExpression() }; new SingletonASTTransformation().visit(badInput, null); Assert.fail("Contract Failure"); } catch (Error e) { Assert.assertTrue("Bad error msg: " + e.getMessage(), e.getMessage().contains("ConstantExpression")); Assert.assertTrue("Bad error msg: " + e.getMessage(), e.getMessage().contains("EmptyExpression")); Assert.assertTrue("Bad error msg: " + e.getMessage(), e.getMessage().contains("expecting [AnnotationNode, AnnotatedNode]")); } }
public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode node = (AnnotationNode) nodes[0]; if (parent instanceof ClassNode) { ClassNode classNode = (ClassNode) parent; String propertyName = getMemberStringValue(node, "property", "instance"); boolean isLazy = memberHasValue(node, "lazy", true); boolean isStrict = !memberHasValue(node, "strict", false); createField(classNode, propertyName, isLazy, isStrict); } }
/** * * @param nodes the ast nodes * @param source the source unit for the nodes */ public void visit(ASTNode[] nodes, SourceUnit source) { if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) { throw new RuntimeException( String.format( "Internal error: wrong types: %s / %s. Expected: AnnotationNode / AnnotatedNode", nodes[0].getClass(), nodes[1].getClass()) ); } AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode node = (AnnotationNode) nodes[0]; if (parent instanceof ClassNode) { ClassNode classNode = (ClassNode) parent; final Expression member = node.getMember("lazy"); if(member instanceof ConstantExpression && ((ConstantExpression)member).getValue().equals(true)) createLazy(classNode); else createNonLazy(classNode); } }
private void createNonLazy(ClassNode classNode) { final FieldNode fieldNode = classNode.addField("instance", ACC_PUBLIC|ACC_FINAL|ACC_STATIC, classNode, new ConstructorCallExpression(classNode, new ArgumentListExpression())); createConstructor(classNode, fieldNode); final BlockStatement body = new BlockStatement(); body.addStatement(new ReturnStatement(new FieldExpression(fieldNode))); classNode.addMethod("getInstance", ACC_STATIC|ACC_PUBLIC, classNode, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body); }
private void createConstructor(ClassNode classNode, FieldNode field, String propertyName, boolean isStrict) { final List<ConstructorNode> cNodes = classNode.getDeclaredConstructors(); ConstructorNode foundNoArg = null; for (ConstructorNode cNode : cNodes) { final Parameter[] parameters = cNode.getParameters(); if (parameters == null || parameters.length == 0) { foundNoArg = cNode; break; } } if (isStrict && !cNodes.isEmpty()) { for (ConstructorNode cNode : cNodes) { addError("@Singleton didn't expect to find one or more additional constructors: remove constructor(s) or set strict=false", cNode); } } if (foundNoArg == null) { final BlockStatement body = new BlockStatement(); body.addStatement(ifS( notNullX(varX(field)), throwS( ctorX(make(RuntimeException.class), args(constX("Can't instantiate singleton " + classNode.getName() + ". Use " + classNode.getName() + "." + propertyName)))) )); addGeneratedConstructor(classNode, new ConstructorNode(ACC_PRIVATE, body)); } } }
/** * * @param nodes the ast nodes * @param source the source unit for the nodes */ public void visit(ASTNode[] nodes, SourceUnit source) { if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) { throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class"); } AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode node = (AnnotationNode) nodes[0]; if (parent instanceof ClassNode) { ClassNode classNode = (ClassNode) parent; final Expression member = node.getMember("lazy"); if(member instanceof ConstantExpression && ((ConstantExpression)member).getValue().equals(true)) createLazy(classNode); else createNonLazy(classNode); } }
private void createNonLazy(ClassNode classNode) { final FieldNode fieldNode = classNode.addField("instance", ACC_PUBLIC|ACC_FINAL|ACC_STATIC, classNode, new ConstructorCallExpression(classNode, new ArgumentListExpression())); createConstructor(classNode, fieldNode); final BlockStatement body = new BlockStatement(); body.addStatement(new ReturnStatement(new FieldExpression(fieldNode))); classNode.addMethod("getInstance", ACC_STATIC|ACC_PUBLIC, classNode, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body); }
/** * * @param nodes the ast nodes * @param source the source unit for the nodes */ public void visit(ASTNode[] nodes, SourceUnit source) { if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) { throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class"); } AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode node = (AnnotationNode) nodes[0]; if (parent instanceof ClassNode) { ClassNode classNode = (ClassNode) parent; final Expression member = node.getMember("lazy"); if(member instanceof ConstantExpression && ((ConstantExpression)member).getValue().equals(true)) createLazy(classNode); else createNonLazy(classNode); } }
private void createNonLazy(ClassNode classNode) { final FieldNode fieldNode = classNode.addField("instance", ACC_PUBLIC|ACC_FINAL|ACC_STATIC, classNode.getPlainNodeReference(), new ConstructorCallExpression(classNode, new ArgumentListExpression())); createConstructor(classNode, fieldNode); final BlockStatement body = new BlockStatement(); body.addStatement(new ReturnStatement(new VariableExpression(fieldNode))); classNode.addMethod("getInstance", ACC_STATIC|ACC_PUBLIC, classNode.getPlainNodeReference(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body); }
private void createLazy(ClassNode classNode) { final FieldNode fieldNode = classNode.addField("instance", ACC_PRIVATE|ACC_STATIC|ACC_VOLATILE, classNode, null); createConstructor(classNode, fieldNode); final BlockStatement body = new BlockStatement(); final FieldExpression instanceExpression = new FieldExpression(fieldNode); body.addStatement(new IfStatement( new BooleanExpression(new BinaryExpression(instanceExpression, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)), new ReturnStatement(instanceExpression), new SynchronizedStatement( new ClassExpression(classNode), new IfStatement( new BooleanExpression(new BinaryExpression(instanceExpression, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)), new ReturnStatement(instanceExpression), new ReturnStatement(new BinaryExpression(instanceExpression,Token.newSymbol("=",-1,-1), new ConstructorCallExpression(classNode, new ArgumentListExpression()))) ) ) )); classNode.addMethod("getInstance", ACC_STATIC|ACC_PUBLIC, classNode, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body); }
private void createLazy(ClassNode classNode) { final FieldNode fieldNode = classNode.addField("instance", ACC_PRIVATE|ACC_STATIC|ACC_VOLATILE, classNode, null); createConstructor(classNode, fieldNode); final BlockStatement body = new BlockStatement(); final FieldExpression instanceExpression = new FieldExpression(fieldNode); body.addStatement(new IfStatement( new BooleanExpression(new BinaryExpression(instanceExpression, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)), new ReturnStatement(instanceExpression), new SynchronizedStatement( new ClassExpression(classNode), new IfStatement( new BooleanExpression(new BinaryExpression(instanceExpression, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)), new ReturnStatement(instanceExpression), new ReturnStatement(new BinaryExpression(instanceExpression,Token.newSymbol("=",-1,-1), new ConstructorCallExpression(classNode, new ArgumentListExpression()))) ) ) )); classNode.addMethod("getInstance", ACC_STATIC|ACC_PUBLIC, classNode, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body); }
private void createLazy(ClassNode classNode) { final FieldNode fieldNode = classNode.addField("instance", ACC_PRIVATE|ACC_STATIC|ACC_VOLATILE, classNode.getPlainNodeReference(), null); createConstructor(classNode, fieldNode); final BlockStatement body = new BlockStatement(); final Expression instanceExpression = new VariableExpression(fieldNode); body.addStatement(new IfStatement( new BooleanExpression(new BinaryExpression(instanceExpression, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)), new ReturnStatement(instanceExpression), new SynchronizedStatement( new ClassExpression(classNode), new IfStatement( new BooleanExpression(new BinaryExpression(instanceExpression, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)), new ReturnStatement(instanceExpression), new ReturnStatement(new BinaryExpression(instanceExpression,Token.newSymbol("=",-1,-1), new ConstructorCallExpression(classNode, new ArgumentListExpression()))) ) ) )); classNode.addMethod("getInstance", ACC_STATIC|ACC_PUBLIC, classNode.getPlainNodeReference(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body); }