private boolean checkTypeArgs(AST node, boolean seenTypeArgs) { if (isType(IDENT, node) && seenTypeArgs) { throw new ASTRuntimeException(node, "Unexpected type arguments found prior to: " + qualifiedName(node)); } if (isType(DOT, node)) { AST next = node.getFirstChild(); while (next != null && !isType(TYPE_ARGUMENTS, next)) { seenTypeArgs |= checkTypeArgs(next, seenTypeArgs); seenTypeArgs |= isType(TYPE_ARGUMENTS, next.getFirstChild()) || isType(TYPE_ARGUMENTS, next.getNextSibling()); next = next.getNextSibling(); } } return seenTypeArgs; }
private int getBoundType(AST node) { if (node == null) return -1; if (isType(TYPE_UPPER_BOUNDS, node)) return TYPE_UPPER_BOUNDS; if (isType(TYPE_LOWER_BOUNDS, node)) return TYPE_LOWER_BOUNDS; throw new ASTRuntimeException(node, "Unexpected node type: " + getTokenName(node) + " found when expecting type: " + getTokenName(TYPE_UPPER_BOUNDS) + " or type: " + getTokenName(TYPE_LOWER_BOUNDS)); }
protected ClassNode makeTypeWithArguments(AST rootNode) { ClassNode basicType = makeType(rootNode); AST node = rootNode.getFirstChild(); if (node == null || isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) return basicType; if (!isType(DOT, node)) { node = node.getFirstChild(); if (node == null) return basicType; return addTypeArguments(basicType, node); } else { node = node.getFirstChild(); while (node != null && !isType(TYPE_ARGUMENTS, node)) node = node.getNextSibling(); return node == null ? basicType : addTypeArguments(basicType, node); } }
public static String qualifiedName(AST qualifiedNameNode) { if (isType(IDENT, qualifiedNameNode)) { return qualifiedNameNode.getText(); } if (isType(DOT, qualifiedNameNode)) { AST node = qualifiedNameNode.getFirstChild(); StringBuilder buffer = new StringBuilder(); boolean first = true; while (node != null && !isType(TYPE_ARGUMENTS, node)) { if (first) { first = false; } else { buffer.append("."); } buffer.append(qualifiedName(node)); node = node.getNextSibling(); } return buffer.toString(); } else { return qualifiedNameNode.getText(); } }
private void processAnnotations(List<AnnotationNode> annotations, AST node) { AST child = node.getFirstChild(); while (child != null) { if (isType(ANNOTATION, child)) annotations.add(annotation(child)); child = child.getNextSibling(); } }
protected Parameter[] parameters(AST parametersNode) { AST node = parametersNode.getFirstChild(); firstParam = false; firstParamIsVarArg = false; if (node == null) { if (isType(IMPLICIT_PARAMETERS, parametersNode)) return Parameter.EMPTY_ARRAY; return null; } else { List<Parameter> parameters = new ArrayList<Parameter>(); AST firstParameterNode = null; do { firstParam = (firstParameterNode == null); if (firstParameterNode == null) firstParameterNode = node; parameters.add(parameter(node)); node = node.getNextSibling(); } while (node != null); verifyParameters(parameters, firstParameterNode); Parameter[] answer = new Parameter[parameters.size()]; parameters.toArray(answer); return answer; } }
protected ClosureExpression closureExpression(AST node) { AST paramNode = node.getFirstChild(); Parameter[] parameters = null; AST codeNode = paramNode; if (isType(PARAMETERS, paramNode) || isType(IMPLICIT_PARAMETERS, paramNode)) { parameters = parameters(paramNode); codeNode = paramNode.getNextSibling(); } Statement code = statementListNoChild(codeNode, node); ClosureExpression closureExpression = new ClosureExpression(parameters, code); configureAST(closureExpression, node); return closureExpression; }
if (isType(TYPE, node)) { node = node.getFirstChild(); if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) { answer = ClassHelper.make(qualifiedName(node)); } else if (isPrimitiveTypeLiteral(node)) { answer = ClassHelper.make(node.getText()); } else if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) { AST child = node.getFirstChild(); answer = buildName(child).makeArray(); if (isType(INDEX_OP, nextSibling) || isType(ARRAY_DECLARATOR, node)) { answer = answer.makeArray(); configureAST(answer, node);
protected GenericsType[] makeGenericsType(AST rootNode) { AST typeParameter = rootNode.getFirstChild(); LinkedList ret = new LinkedList(); assertNodeType(TYPE_PARAMETER, typeParameter); while (isType(TYPE_PARAMETER, typeParameter)) { AST typeNode = typeParameter.getFirstChild(); ClassNode type = makeType(typeParameter); GenericsType gt = new GenericsType(type, makeGenericsBounds(typeNode, TYPE_UPPER_BOUNDS), null); configureAST(gt, typeParameter); ret.add(gt); typeParameter = typeParameter.getNextSibling(); } return (GenericsType[]) ret.toArray(GenericsType.EMPTY_ARRAY); }
protected void packageDef(AST packageDef) { List<AnnotationNode> annotations = new ArrayList<AnnotationNode>(); AST node = packageDef.getFirstChild(); if (isType(ANNOTATIONS, node)) { processAnnotations(annotations, node); node = node.getNextSibling(); } String name = qualifiedName(node); // TODO should we check package node doesn't already exist? conflict? PackageNode packageNode = setPackage(name, annotations); configureAST(packageNode, packageDef); }
protected void throwsList(AST node, List<ClassNode> list) { String name; if (isType(DOT, node)) { name = qualifiedName(node); } else { name = identifier(node); } ClassNode exception = ClassHelper.make(name); configureAST(exception, node); list.add(exception); AST next = node.getNextSibling(); if (next != null) throwsList(next, list); }
protected List arraySizeExpression(AST node) { List list; Expression size = null; if (isType(ARRAY_DECLARATOR, node)) { AST right = node.getNextSibling(); if (right != null) { size = expression(right); } else { size = ConstantExpression.EMPTY_EXPRESSION; } AST child = node.getFirstChild(); if (child == null) { throw new ASTRuntimeException(node, "No expression for the array constructor call"); } list = arraySizeExpression(child); } else { size = expression(node); list = new ArrayList(); } list.add(size); return list; }
private ClosureListExpression closureListExpression(AST node) { isClosureListExpressionAllowedHere(node); AST exprNode = node.getFirstChild(); List<Expression> list = new LinkedList<Expression>(); while (exprNode != null) { if (isType(EXPR, exprNode)) { Expression expr = expression(exprNode); configureAST(expr, exprNode); list.add(expr); } else { assertNodeType(EMPTY_STAT, exprNode); list.add(EmptyExpression.INSTANCE); } exprNode = exprNode.getNextSibling(); } ClosureListExpression cle = new ClosureListExpression(list); configureAST(cle, node); return cle; }
protected Statement tryStatement(AST tryStatementNode) { AST tryNode = tryStatementNode.getFirstChild(); Statement tryStatement = statement(tryNode); Statement finallyStatement = EmptyStatement.INSTANCE; AST node = tryNode.getNextSibling(); // let's do the catch nodes List<CatchStatement> catches = new ArrayList<CatchStatement>(); for (; isType(LITERAL_catch, node); node = node.getNextSibling()) { final List<CatchStatement> catchStatements = catchStatement(node); catches.addAll(catchStatements); } if (isType(LITERAL_finally, node)) { finallyStatement = statement(node); node = node.getNextSibling(); } if (finallyStatement instanceof EmptyStatement && catches.isEmpty()) { throw new ASTRuntimeException(tryStatementNode, "A try statement must have at least one catch or finally block."); } TryCatchStatement tryCatchStatement = new TryCatchStatement(tryStatement, finallyStatement); configureAST(tryCatchStatement, tryStatementNode); for (CatchStatement statement : catches) { tryCatchStatement.addCatch(statement); } return tryCatchStatement; }
protected Statement whileStatement(AST whileNode) { AST node = whileNode.getFirstChild(); assertNodeType(EXPR, node); // TODO remove this once we support declarations in the while condition if (isType(VARIABLE_DEF, node.getFirstChild())) { throw new ASTRuntimeException(whileNode, "While loop condition contains a declaration; this is currently unsupported."); } BooleanExpression booleanExpression = booleanExpression(node); node = node.getNextSibling(); Statement block; if (isType(SEMI, node)) { block = EmptyStatement.INSTANCE; } else { block = statement(node); } WhileStatement whileStatement = new WhileStatement(booleanExpression, block); configureAST(whileStatement, whileNode); return whileStatement; }
protected ClassNode makeType(AST typeNode) { ClassNode answer = ClassHelper.DYNAMIC_TYPE; AST node = typeNode.getFirstChild(); if (node != null) { if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) { answer = makeType(node).makeArray(); } else { checkTypeArgs(node, false); answer = ClassHelper.make(qualifiedName(node)); if (answer.isUsingGenerics()) { ClassNode newAnswer = ClassHelper.makeWithoutCaching(answer.getName()); newAnswer.setRedirect(answer); answer = newAnswer; } } configureAST(answer, node); } return answer; }
protected Expression methodPointerExpression(AST node) { AST exprNode = node.getFirstChild(); Expression objectExpression = expression(exprNode); AST mNode = exprNode.getNextSibling(); Expression methodName; if (isType(DYNAMIC_MEMBER, mNode)) { methodName = expression(mNode); } else { methodName = new ConstantExpression(identifier(mNode)); } configureAST(methodName, mNode); MethodPointerExpression methodPointerExpression = new MethodPointerExpression(objectExpression, methodName); configureAST(methodPointerExpression, node); return methodPointerExpression; }
protected void enumDef(AST enumNode) { assertNodeType(ENUM_DEF, enumNode); List<AnnotationNode> annotations = new ArrayList<AnnotationNode>(); AST node = enumNode.getFirstChild(); int modifiers = Opcodes.ACC_PUBLIC; if (isType(MODIFIERS, node)) { modifiers = modifiers(node, annotations, modifiers); node = node.getNextSibling(); } String name = identifier(node); node = node.getNextSibling(); ClassNode[] interfaces = interfaces(node); node = node.getNextSibling(); boolean syntheticPublic = ((modifiers & Opcodes.ACC_SYNTHETIC) != 0); modifiers &= ~Opcodes.ACC_SYNTHETIC; String enumName = (classNode != null ? name : dot(getPackageName(), name)); ClassNode enumClass = EnumHelper.makeEnumNode(enumName, modifiers, interfaces, classNode); enumClass.setSyntheticPublic(syntheticPublic); ClassNode oldNode = classNode; enumClass.addAnnotations(annotations); classNode = enumClass; configureAST(classNode, enumNode); assertNodeType(OBJBLOCK, node); objectBlock(node); classNode = oldNode; output.addClass(enumClass); }
protected AnnotationNode annotation(AST annotationNode) { annotationBeingDef = true; AST node = annotationNode.getFirstChild(); String name = qualifiedName(node); AnnotationNode annotatedNode = new AnnotationNode(ClassHelper.make(name)); configureAST(annotatedNode, annotationNode); while (true) { node = node.getNextSibling(); if (isType(ANNOTATION_MEMBER_VALUE_PAIR, node)) { AST memberNode = node.getFirstChild(); String param = identifier(memberNode); Expression expression = expression(memberNode.getNextSibling()); if (annotatedNode.getMember(param) != null) { throw new ASTRuntimeException(memberNode, "Annotation member '" + param + "' has already been associated with a value"); } annotatedNode.setMember(param, expression); } else { break; } } annotationBeingDef = false; return annotatedNode; }
private GenericsType makeGenericsArgumentType(AST typeArgument) { GenericsType gt; AST rootNode = typeArgument.getFirstChild(); if (isType(WILDCARD_TYPE, rootNode)) { ClassNode base = ClassHelper.makeWithoutCaching("?"); if (rootNode.getNextSibling() != null) { int boundType = getBoundType(rootNode.getNextSibling()); ClassNode[] gts = makeGenericsBounds(rootNode, boundType); if (boundType == TYPE_UPPER_BOUNDS) { gt = new GenericsType(base, gts, null); } else { gt = new GenericsType(base, null, gts[0]); } } else { gt = new GenericsType(base, null, null); } gt.setName("?"); gt.setWildcard(true); } else { ClassNode argument = makeTypeWithArguments(rootNode); gt = new GenericsType(argument); } configureAST(gt, typeArgument); return gt; }