Experimenting with types modelling. jlahoda-tree-builder
authorjlahoda
Fri, 29 Mar 2019 10:12:18 +0100
branchjlahoda-tree-builder
changeset 57296 464cc8d22d94
parent 57295 5497ee9d40f4
child 57297 ad0be596956b
Experimenting with types modelling.
src/jdk.compiler/share/classes/com/sun/source/util/TreeBuilder.java
src/jdk.compiler/share/classes/com/sun/tools/javac/api/TreeBuilderImpl.java
test/langtools/tools/javac/api/ast/ASTBuilder.java
test/langtools/tools/javac/api/ast/CodeBuilder.java
--- 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;