diff -r 000000000000 -r 959103a6100f test/tools/javac/lambdaShapes/org/openjdk/tests/separate/SourceModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambdaShapes/org/openjdk/tests/separate/SourceModel.java Wed Apr 27 01:34:52 2016 +0800 @@ -0,0 +1,600 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.tests.separate; + +import java.util.*; +import java.io.StringWriter; +import java.io.PrintWriter; + +public class SourceModel { + + public static final String stdMethodName = "m"; + + public static interface SourceProcessor { + // Called with a generated source file + void process(String name, String content); + } + + public static abstract class Element { + + protected abstract void generate(PrintWriter pw); + + public String toString() { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + generate(pw); + return sw.toString(); + } + } + + public static class AccessFlag extends Element { + private String flag; + + public AccessFlag(String name) { flag = name; } + + protected void generate(PrintWriter pw) { + pw.print(flag); + } + + public String toString() { return flag; } + + public static final AccessFlag PUBLIC = new AccessFlag("public"); + public static final AccessFlag PRIVATE = new AccessFlag("private"); + public static final AccessFlag PROTECTED = new AccessFlag("protected"); + public static final AccessFlag STATIC = new AccessFlag("static"); + public static final AccessFlag FINAL = new AccessFlag("final"); + public static final AccessFlag SYNCHRONIZED = new AccessFlag("synchronized"); + public static final AccessFlag VOLATILE = new AccessFlag("volatile"); + public static final AccessFlag NATIVE = new AccessFlag("native"); + public static final AccessFlag ABSTRACT = new AccessFlag("abstract"); + public static final AccessFlag STRICTFP = new AccessFlag("strictfp"); + public static final AccessFlag DEFAULT = new AccessFlag("default"); + } + + public static class TypeParameter extends Element { + private String parameter; + + public TypeParameter(String str) { + this.parameter = str; + } + + protected void generate(PrintWriter pw) { + pw.print(parameter); + } + } + + public static class TypeArgument extends Element { + private String argument; + + public TypeArgument(String str) { + this.argument = str; + } + + protected void generate(PrintWriter pw) { + pw.print(argument); + } + } + + public static class MethodParameter extends Element { + private String type; + private String name; + + public MethodParameter(String type, String name) { + this.type = type; + this.name = name; + } + + protected void generate(PrintWriter pw) { + pw.printf("%s %s", this.type, this.name); + } + + public String toString() { return type + " " + name; } + } + + public static abstract class Type extends Element { + private String name; + private List accessFlags; + private List parameters; + private List supertypes; + private List methods; + + // methods from superclasses that are required for compilation + // (and thus will be present in stubs) + private Set methodDependencies; + private List typeDependencies; + private boolean fullCompilation; + + protected Type(String name, + List flags, List params, + List ifaces, List methods) { + this.name = name; + this.accessFlags = flags == null ? new ArrayList<>() : flags; + this.parameters = params == null ? new ArrayList<>() : params; + this.supertypes = ifaces == null ? new ArrayList<>() : ifaces; + this.methods = methods == null ? new ArrayList<>() : methods; + this.methodDependencies = new HashSet<>(); + this.typeDependencies = new ArrayList<>(); + } + + public String getName() { return this.name; } + public List getAccessFlags() { return this.accessFlags; } + public List getParameters() { return this.parameters; } + public List getSupertypes() { return this.supertypes; } + public List getMethods() { return this.methods; } + public Set methodDependencies() { + return this.methodDependencies; + } + + public Class getSuperclass() { return null; } + protected abstract void setSuperClass(Extends supertype); + + public void addSuperType(Extends sup) { + assert sup.getType() instanceof Interface : "Must be an interface"; + this.supertypes.add(sup); + } + public void addSuperType(Interface iface) { + this.supertypes.add(new Extends(iface)); + } + + public void addMethod(Method m) { + this.methods.add(m); + } + + public void addAccessFlag(AccessFlag f) { + this.accessFlags.add(f); + } + + // Convenience method for creation. Parameters are interpreted + // according to their type. Class (or Extends with a Class type) is + // considered a superclass (only one allowed). TypeParameters are + // generic parameter names. Interface (or Extends with an Interface + // type) is an implemented supertype. Methods are methods (duh!). + protected void addComponent(Element p) { + if (p instanceof Class) { + setSuperClass(new Extends((Class)p)); + } else if (p instanceof Extends) { + Extends ext = (Extends)p; + if (ext.supertype instanceof Class) { + setSuperClass(ext); + } else if (ext.supertype instanceof Interface) { + addSuperType(ext); + } else { + assert false : "What is this thing?"; + } + } else if (p instanceof Interface) { + addSuperType((Interface)p); + } else if (p instanceof TypeParameter) { + this.parameters.add((TypeParameter)p); + } else if (p instanceof Method) { + addMethod((Method)p); + } else if (p instanceof AccessFlag) { + addAccessFlag((AccessFlag)p); + } else { + assert false : "What is this thing?"; + } + } + + // Find and return the first method that has name 'name' + public Method findMethod(String name) { + for (Method m : methods) { + if (m.name.equals(name)) { + return m; + } + } + return null; + } + + public void addCompilationDependency(Type t) { + typeDependencies.add(t); + } + + public void addCompilationDependency(Method m) { + methodDependencies.add(m); + } + + public boolean isFullCompilation() { + return fullCompilation; + } + + public void setFullCompilation(boolean fullCompilation) { + this.fullCompilation = fullCompilation; + } + + // Convenience method for creating an Extends object using this + // class and specified type arguments. + public Extends with(String ... args) { + return new Extends(this, args); + } + + public abstract void generate(SourceProcessor sp); + public abstract void generateAsDependency( + SourceProcessor sp, Set neededMethods); + + protected void generateName(PrintWriter pw) { + pw.print(this.name); + toJoinedString(this.parameters, ",", "<", ">", ""); + pw.print(toJoinedString(this.parameters, ",", "<", ">", "")); + pw.print(" "); + } + + protected void generateBody(PrintWriter pw, String superSpec) { + pw.print(toJoinedString(this.supertypes, ",", superSpec + " ", " ", "")); + pw.println("{ "); + pw.print(toJoinedString(this.methods, "\n ", "\n ", "\n", "")); + pw.println("}"); + } + + protected void generateAccessFlags(PrintWriter pw) { + pw.print(toJoinedString(this.accessFlags, " ", "", " ")); + } + + protected void generateBodyAsDependency( + PrintWriter pw, Set neededMethods) { + pw.println(" {"); + for (Method m : this.methods) { + if (neededMethods.contains(m)) { + pw.print(" "); + m.generate(pw); + pw.println(); + } + } + pw.println("}"); + } + + public Collection typeDependencies(boolean recursive) { + HashMap dependencies = new HashMap<>(); + Type superclass = getSuperclass(); + if (superclass != null) { + dependencies.put(superclass.getName(), superclass); + if (recursive) { + for (Type t : superclass.typeDependencies(true)) + dependencies.put(t.getName(), t); + } + } + for (Extends e : getSupertypes()) { + dependencies.put(e.getType().getName(), e.getType()); + if (recursive) { + for (Type t : e.getType().typeDependencies(true)) + dependencies.put(t.getName(), t); + } + } + // Do these last so that they override + for (Type t : this.typeDependencies) + dependencies.put(t.getName(), t); + return dependencies.values(); + } + } + + public static class Class extends Type { + private Extends superClass; + + public Class(String name, List flags, + List params, Extends sprClass, + List interfaces, List methods) { + super(name, flags, params, interfaces, methods); + this.superClass = sprClass; + addAccessFlag(AccessFlag.PUBLIC); // should remove this + } + + public Class(String name, Element ... components) { + super(name, null, null, null, null); + this.superClass = null; + + for (Element p : components) { + addComponent(p); + } + addAccessFlag(AccessFlag.PUBLIC); // should remove this + } + + public boolean isAbstract() { + for (AccessFlag flag : getAccessFlags()) { + if (flag == AccessFlag.ABSTRACT) { + return true; + } + } + return false; + } + + @Override + public void setSuperClass(Extends ext) { + assert this.superClass == null : "Multiple superclasses defined"; + assert ext.getType() instanceof Class : "Must be a class"; + this.superClass = ext; + } + + public void setSuperClass(Class c) { + setSuperClass(new Extends(c)); + } + + @Override + public Class getSuperclass() { + return superClass == null ? null : (Class)superClass.supertype; + } + + public void generate(SourceProcessor processor) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + generate(pw); + processor.process(getName(), sw.toString()); + } + + public void generate(PrintWriter pw) { + generateAccessFlags(pw); + pw.print("class "); + generateName(pw); + if (superClass != null) { + pw.print("extends "); + superClass.generate(pw); + pw.print(" "); + } + generateBody(pw, "implements"); + } + + public void generateAsDependency( + SourceProcessor processor, Set neededMethods) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + generateAccessFlags(pw); + pw.print("class "); + generateName(pw); + pw.print(" "); + generateBodyAsDependency(pw, neededMethods); + + processor.process(getName(), sw.toString()); + } + } + + public static class Interface extends Type { + + public Interface(String name, + List flags, List params, + List interfaces, List methods) { + super(name, flags, params, interfaces, methods); + } + + public Interface(String name, Element ... components) { + super(name, null, null, null, null); + for (Element c : components) { + addComponent(c); + } + } + + protected void setSuperClass(Extends ext) { + assert false : "Interfaces cannot have Class supertypes"; + } + + public void generate(SourceProcessor processor) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + generate(pw); + processor.process(getName(), sw.toString()); + } + + public void generate(PrintWriter pw) { + generateAccessFlags(pw); + pw.print("interface "); + generateName(pw); + pw.print(" "); + generateBody(pw, "extends"); + } + + public void generateAsDependency( + SourceProcessor processor, Set neededMethods) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + + generateAccessFlags(pw); + pw.print("interface "); + generateName(pw); + pw.print(" "); + generateBodyAsDependency(pw, neededMethods); + + processor.process(getName(), sw.toString()); + } + } + + /** + * Represents a type extension that might contain type arguments + */ + public static class Extends extends Element { + private final Type supertype; + private final List arguments; + + public Type getType() { return supertype; } + public List getArguments() { + return arguments; + } + + public Extends(Type supertype, String ... args) { + assert supertype != null : "Null supertype"; + this.supertype = supertype; + this.arguments = new ArrayList<>(); + for (String arg : args) { + this.arguments.add(new TypeArgument(arg)); + } + } + + public void generate(PrintWriter pw) { + pw.print(supertype.getName()); + pw.print(toJoinedString(getArguments(), ",", "<", ">", "")); + } + } + + public static abstract class Method extends Element { + private String name; + private String returnType; + private List accessFlags; + private List parameters; + private boolean emitSuppressWarnings; + + protected Method(String ret, String name, Element ... params) { + this.name = name; + this.returnType = ret; + this.accessFlags = new ArrayList<>(); + this.parameters = new ArrayList<>(); + this.emitSuppressWarnings = false; + + for (Element e : params) { + if (e instanceof MethodParameter) { + this.parameters.add((MethodParameter) e); + } else if (e instanceof AccessFlag) { + this.accessFlags.add((AccessFlag) e); + } + } + assert accessFlags.size() + parameters.size() == params.length : + "Non method parameters or access flags in constructor"; + } + + public String getName() { return this.name; } + public String getReturnType() { return this.returnType; } + public List getParameters() { + return this.parameters; + } + public List getAccessFlags() { + return this.accessFlags; + } + public Element[] getElements() { + ArrayList elements = new ArrayList<>(); + elements.addAll(getParameters()); + elements.addAll(getAccessFlags()); + return elements.toArray(new Element[0]); + } + + public void suppressWarnings() { this.emitSuppressWarnings = true; } + + public void generateWarningSuppression(PrintWriter pw) { + if (this.emitSuppressWarnings) { + pw.printf("@SuppressWarnings(\"unchecked\")\n "); + } + } + + protected void generateDecl(PrintWriter pw) { + generateWarningSuppression(pw); + pw.print(toJoinedString(this.accessFlags, " ", "", " ")); + pw.printf("%s %s(", returnType, name); + pw.print(toJoinedString(parameters, ",")); + pw.print(")"); + } + } + + public static class AbstractMethod extends Method { + public AbstractMethod( + String ret, String name, Element ... params) { + super(ret, name, params); + this.getAccessFlags().add(AccessFlag.ABSTRACT); + } + + public void generate(PrintWriter pw) { + generateDecl(pw); + pw.print(";"); + } + + public static AbstractMethod std() { + return new AbstractMethod( + "int", SourceModel.stdMethodName, AccessFlag.PUBLIC); + } + } + + public static class ConcreteMethod extends Method { + protected String body; + + public ConcreteMethod(String ret, String name, + String body, Element ... params) { + super(ret, name, params); + this.body = body; + } + + public void generate(PrintWriter pw) { + generateDecl(pw); + pw.printf(" { %s }", this.body); + } + + public static ConcreteMethod std(String value) { + return new ConcreteMethod( + "int", SourceModel.stdMethodName, "return " + value + ";", + AccessFlag.PUBLIC); + } + } + + // When the default method flag gets moved into the traditional + // access flags location, we can remove this class completely and + // use a ConcreteMethod with an AccessFlag("default") in the constructor + public static class DefaultMethod extends Method { + protected String body; + + public DefaultMethod(String ret, String name, String body, + Element ... params) { + super(ret, name, params); + this.body = body; + this.getAccessFlags().add(AccessFlag.DEFAULT); + } + + public void generate(PrintWriter pw) { + generateDecl(pw); + pw.printf(" { %s }", this.body); + } + + public static DefaultMethod std(String value) { + return new DefaultMethod( + "int", SourceModel.stdMethodName, "return " + value + ";"); + } + } + + private static String toJoinedString(List list, String... p) { + StringBuilder sb = new StringBuilder(); + String sep = ""; + String init = ""; + String end = ""; + String empty = null; + switch (p.length) { + case 4: + empty = p[3]; + /*fall-through*/ + case 3: + end = p[2]; + /*fall-through*/ + case 2: + init = p[1]; + /*fall-through*/ + case 1: + sep = p[0]; + break; + } + if (empty != null && list.isEmpty()) { + return empty; + } else { + sb.append(init); + for (T x : list) { + if (sb.length() != init.length()) { + sb.append(sep); + } + sb.append(x.toString()); + } + sb.append(end); + return sb.toString(); + } + } +}