Experimenting with types modelling.
--- a/src/jdk.compiler/share/classes/com/sun/source/util/TreeBuilder.java Thu Mar 28 11:31:30 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/TreeBuilder.java Fri Mar 29 10:12:18 2019 +0100
@@ -57,8 +57,8 @@
interface Class extends WithModifiers<Class>, WithJavadoc<Class> {
//setters:
- Class superclass(Consumer<Expression> sup);
- Class superinterface(Consumer<Expression> sup);
+ Class superclass(Consumer<Type> sup);
+ Class superinterface(Consumer<Type> sup);
//type parameters?
//adders:
@@ -105,26 +105,47 @@
//TODO...
}
+ //TODO: DeclaredType vs. Type?
+
interface Type {
- void _class(String simpleName); //TODO: type parameters - declaredtype???
-// void _class(String simpleName, Consumer<TypeArgs> targs);
+ default void _class(String className) {
+ _class(N -> N.qualifiedName(className));
+ }
+ default void _class(Consumer<QualifiedName> className) {
+ _class(className, A -> {});
+ }
+ void _class(Consumer<QualifiedName> className, Consumer<TypeArguments> typeArguments);
void _int();
void _float();
void _void();
}
+ interface TypeArguments { //???
+ TypeArguments type(Consumer<Type> t);
+ }
+
+ interface QualifiedName {
+ void select(Consumer<QualifiedName> selected, String name);
+ void ident(String simpleName);
+ void ident(String... components);
+ default void qualifiedName(String qualifiedName) {
+ ident(qualifiedName.split("\\."));
+ }
+ }
+
// interface TypeArgs { //???
// TypeArgs type(Consumer<Type> t);
// TypeArgs _extends(Consumer<Type> t);
// TypeArgs _super(Consumer<Type> t);
// TypeArgs unbound();
// }
-
+//
interface Expression {
void minusminus(Consumer<Expression> expr);
void plus(Consumer<Expression> lhs, Consumer<Expression> rhs);
void cond(Consumer<Expression> cond, Consumer<Expression> truePart, Consumer<Expression> falsePart);
- void ident(String... qnames);
+ void select(Consumer<Expression> selected, String name);
+ void ident(String qnames);
void literal(Object value);
}
@@ -141,7 +162,7 @@
Type::_void,
M -> M.parameter(T -> T._class("Foo"))
.parameter(T -> T._float(), P -> P.name("whatever"))
- .body(B -> B._if(E -> E.minusminus(V -> V.ident("foo", "bar")),
+ .body(B -> B._if(E -> E.minusminus(V -> V.select(S -> S.ident("foo"), "bar")),
Statements::skip,
Statements::skip
)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/TreeBuilderImpl.java Thu Mar 28 11:31:30 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/TreeBuilderImpl.java Fri Mar 29 10:12:18 2019 +0100
@@ -98,13 +98,15 @@
}
@Override
- public Class superclass(Consumer<Expression> sup) {
- throw new UnsupportedOperationException("Not supported yet.");
+ public Class superclass(Consumer<Type> sup) {
+ result.extending = visitType(sup); //TODO: check extending not filled!
+ return this;
}
@Override
- public Class superinterface(Consumer<Expression> sup) {
- throw new UnsupportedOperationException("Not supported yet.");
+ public Class superinterface(Consumer<Type> sup) {
+ result.implementing = result.implementing.append(visitType(sup));
+ return this;
}
@Override
@@ -152,8 +154,15 @@
private JCExpression type;
@Override
- public void _class(String simpleName) {
- throw new UnsupportedOperationException("Not supported yet.");
+ public void _class(Consumer<QualifiedName> className, Consumer<TypeArguments> typeArguments) {
+ JCExpression clazz = visitQualifiedName(className);
+ TypeArgumentsImpl ta = new TypeArgumentsImpl();
+ typeArguments.accept(ta);
+ if (ta.types.isEmpty()) {
+ type = clazz;
+ } else {
+ type = make.TypeApply(clazz, ta.types);
+ }
}
@Override
@@ -173,7 +182,18 @@
}
}
-
+
+ private final class TypeArgumentsImpl implements TypeArguments {
+ private List<JCExpression> types = List.nil();
+ @Override
+ public TypeArguments type(Consumer<Type> t) {
+ TypeImpl type = new TypeImpl();
+ t.accept(type);
+ types = types.append(type.type);
+ return this;
+ }
+ }
+
private final class VariableImpl implements Variable {
private final JCVariableDecl result;
@@ -184,16 +204,7 @@
@Override
public Variable init(Consumer<Expression> init) {
- ExpressionImpl expr = new ExpressionImpl();
-
- init.accept(expr);
-
- if (expr.expr == null) {
- throw new IllegalStateException("Expression not provided!");
- }
-
- result.init = expr.expr;
-
+ result.init = visitExpression(init);
return this;
}
@@ -225,11 +236,9 @@
@Override
public void plus(Consumer<Expression> lhs, Consumer<Expression> rhs) {
- ExpressionImpl left = new ExpressionImpl();
- lhs.accept(left);
- ExpressionImpl right = new ExpressionImpl();
- rhs.accept(right);
- expr = make.Binary(Tag.PLUS, left.expr, right.expr); //XXX: check exprs filled!
+ expr = make.Binary(Tag.PLUS,
+ visitExpression(lhs),
+ visitExpression(rhs));
}
@Override
@@ -238,8 +247,13 @@
}
@Override
- public void ident(String... qnames) {
- expr = make.Ident(names.fromString(qnames[0])); //XXX
+ public void select(Consumer<Expression> selected, String name) {
+ expr = make.Select(visitExpression(selected), names.fromString(name));
+ }
+
+ @Override
+ public void ident(String ident) {
+ expr = make.Ident(names.fromString(ident)); //XXX
}
@Override
@@ -247,4 +261,64 @@
expr = make.Literal(value);
}
}
+
+ private final class QualifiedNameImpl implements QualifiedName {
+
+ private JCExpression expr;
+
+ @Override
+ public void select(Consumer<QualifiedName> selected, String name) {
+ expr = make.Select(visitQualifiedName(selected), names.fromString(name));
+ }
+
+ @Override
+ public void ident(String ident) {
+ expr = make.Ident(names.fromString(ident));
+ }
+
+ @Override
+ public void ident(String... qnames) {
+ expr = make.Ident(names.fromString(qnames[0]));
+ for (int i = 1; i < qnames.length; i++) {
+ expr = make.Select(expr, names.fromString(qnames[i]));
+ }
+ }
+
+ }
+
+ private JCExpression visitExpression(Consumer<Expression> c) {
+ ExpressionImpl expr = new ExpressionImpl();
+
+ c.accept(expr);
+
+ if (expr.expr == null) {
+ throw new IllegalStateException("Expression not provided!");
+ }
+
+ return expr.expr;
+ }
+
+ private JCExpression visitQualifiedName(Consumer<QualifiedName> c) {
+ QualifiedNameImpl expr = new QualifiedNameImpl();
+
+ c.accept(expr);
+
+ if (expr.expr == null) {
+ throw new IllegalStateException("Name not provided!");
+ }
+
+ return expr.expr;
+ }
+
+ private JCExpression visitType(Consumer<Type> c) {
+ TypeImpl type = new TypeImpl();
+
+ c.accept(type);
+
+ if (type.type == null) {
+ throw new IllegalStateException("Expression not provided!");
+ }
+
+ return type.type;
+ }
}
--- a/test/langtools/tools/javac/api/ast/ASTBuilder.java Thu Mar 28 11:31:30 2019 +0100
+++ b/test/langtools/tools/javac/api/ast/ASTBuilder.java Fri Mar 29 10:12:18 2019 +0100
@@ -67,7 +67,7 @@
" int x;" +
"}",
U -> U._class("Test", C -> C.field("x", Type::_int)));
- runTest("class Test {" +
+ runTest("class Test extends Exception implements java.util.List<Map<String, String>>, CharSequence {" +
" int x1 = 2;" +
" int x2 = 2 + x1;" +
"}");
--- a/test/langtools/tools/javac/api/ast/CodeBuilder.java Thu Mar 28 11:31:30 2019 +0100
+++ b/test/langtools/tools/javac/api/ast/CodeBuilder.java Fri Mar 29 10:12:18 2019 +0100
@@ -37,6 +37,8 @@
import java.util.Locale;
import java.util.Set;
+import com.sun.source.tree.MemberSelectTree;
+import com.sun.source.tree.ParameterizedTypeTree;
public class CodeBuilder {
@@ -48,7 +50,21 @@
@Override
public Void visitClass(ClassTree node, Void p) {
result.append(currentBuilder() + "._class(\"" + node.getSimpleName() + "\", ");
- doScan("C", () -> super.visitClass(node, p));
+ doScan("C", () -> {
+// R r = scan(node.getModifiers(), p);
+// r = scanAndReduce(node.getTypeParameters(), p, r);
+ if (node.getExtendsClause() != null) {
+ result.append(currentBuilder() + ".superclass(");
+ handleDeclaredType(node.getExtendsClause());
+ result.append(")");
+ }
+ for (Tree impl : node.getImplementsClause()) {
+ result.append(currentBuilder() + ".superinterface(");
+ handleDeclaredType(impl);
+ result.append(")");
+ }
+ scan(node.getMembers(), p);
+ });
result.append(")");
return null;
}
@@ -83,6 +99,20 @@
}
@Override
+ public Void visitParameterizedType(ParameterizedTypeTree node, Void p) {
+ scan(node.getType(), null);
+ result.append(", ");
+ doScan("A", () -> {
+ for (Tree ta : node.getTypeArguments()) {
+ result.append(currentBuilder() + ".type(");
+ handleDeclaredType(ta);
+ result.append(")");
+ }
+ });
+ return null;
+ }
+
+ @Override
public Void visitLiteral(LiteralTree node, Void p) {
result.append(currentBuilder() + ".literal(" + node.getValue() + ")");
return null;
@@ -104,11 +134,30 @@
}
@Override
+ public Void visitMemberSelect(MemberSelectTree node, Void p) {
+ //TODO: use ident(String...) for "flat" selects
+ result.append(currentBuilder() + ".select(");
+ doScan("E", node.getExpression());
+ result.append(", \"");
+ result.append(node.getIdentifier());
+ result.append("\")");
+ return null;
+ }
+
+ @Override
public Void visitIdentifier(IdentifierTree node, Void p) {
result.append(currentBuilder() + ".ident(\"" + node.getName() + "\")");
return null;
}
+ private void handleDeclaredType(Tree t) {
+ doScan("T", () -> {
+ result.append(currentBuilder() + "._class(");
+ doScan("Q", t);
+ result.append(")");
+ });
+ }
+
private String currentBuilder() {
if (currentBuilder != null) {
String res = currentBuilder;