test/tools/javac/lambdaShapes/org/openjdk/tests/separate/SourceModel.java

changeset 0
959103a6100f
child 2525
2eb010b6cb22
equal deleted inserted replaced
-1:000000000000 0:959103a6100f
1 /*
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package org.openjdk.tests.separate;
27
28 import java.util.*;
29 import java.io.StringWriter;
30 import java.io.PrintWriter;
31
32 public class SourceModel {
33
34 public static final String stdMethodName = "m";
35
36 public static interface SourceProcessor {
37 // Called with a generated source file
38 void process(String name, String content);
39 }
40
41 public static abstract class Element {
42
43 protected abstract void generate(PrintWriter pw);
44
45 public String toString() {
46 StringWriter sw = new StringWriter();
47 PrintWriter pw = new PrintWriter(sw);
48 generate(pw);
49 return sw.toString();
50 }
51 }
52
53 public static class AccessFlag extends Element {
54 private String flag;
55
56 public AccessFlag(String name) { flag = name; }
57
58 protected void generate(PrintWriter pw) {
59 pw.print(flag);
60 }
61
62 public String toString() { return flag; }
63
64 public static final AccessFlag PUBLIC = new AccessFlag("public");
65 public static final AccessFlag PRIVATE = new AccessFlag("private");
66 public static final AccessFlag PROTECTED = new AccessFlag("protected");
67 public static final AccessFlag STATIC = new AccessFlag("static");
68 public static final AccessFlag FINAL = new AccessFlag("final");
69 public static final AccessFlag SYNCHRONIZED = new AccessFlag("synchronized");
70 public static final AccessFlag VOLATILE = new AccessFlag("volatile");
71 public static final AccessFlag NATIVE = new AccessFlag("native");
72 public static final AccessFlag ABSTRACT = new AccessFlag("abstract");
73 public static final AccessFlag STRICTFP = new AccessFlag("strictfp");
74 public static final AccessFlag DEFAULT = new AccessFlag("default");
75 }
76
77 public static class TypeParameter extends Element {
78 private String parameter;
79
80 public TypeParameter(String str) {
81 this.parameter = str;
82 }
83
84 protected void generate(PrintWriter pw) {
85 pw.print(parameter);
86 }
87 }
88
89 public static class TypeArgument extends Element {
90 private String argument;
91
92 public TypeArgument(String str) {
93 this.argument = str;
94 }
95
96 protected void generate(PrintWriter pw) {
97 pw.print(argument);
98 }
99 }
100
101 public static class MethodParameter extends Element {
102 private String type;
103 private String name;
104
105 public MethodParameter(String type, String name) {
106 this.type = type;
107 this.name = name;
108 }
109
110 protected void generate(PrintWriter pw) {
111 pw.printf("%s %s", this.type, this.name);
112 }
113
114 public String toString() { return type + " " + name; }
115 }
116
117 public static abstract class Type extends Element {
118 private String name;
119 private List<AccessFlag> accessFlags;
120 private List<TypeParameter> parameters;
121 private List<Extends> supertypes;
122 private List<Method> methods;
123
124 // methods from superclasses that are required for compilation
125 // (and thus will be present in stubs)
126 private Set<Method> methodDependencies;
127 private List<Type> typeDependencies;
128 private boolean fullCompilation;
129
130 protected Type(String name,
131 List<AccessFlag> flags, List<TypeParameter> params,
132 List<Extends> ifaces, List<Method> methods) {
133 this.name = name;
134 this.accessFlags = flags == null ? new ArrayList<>() : flags;
135 this.parameters = params == null ? new ArrayList<>() : params;
136 this.supertypes = ifaces == null ? new ArrayList<>() : ifaces;
137 this.methods = methods == null ? new ArrayList<>() : methods;
138 this.methodDependencies = new HashSet<>();
139 this.typeDependencies = new ArrayList<>();
140 }
141
142 public String getName() { return this.name; }
143 public List<AccessFlag> getAccessFlags() { return this.accessFlags; }
144 public List<TypeParameter> getParameters() { return this.parameters; }
145 public List<Extends> getSupertypes() { return this.supertypes; }
146 public List<Method> getMethods() { return this.methods; }
147 public Set<Method> methodDependencies() {
148 return this.methodDependencies;
149 }
150
151 public Class getSuperclass() { return null; }
152 protected abstract void setSuperClass(Extends supertype);
153
154 public void addSuperType(Extends sup) {
155 assert sup.getType() instanceof Interface : "Must be an interface";
156 this.supertypes.add(sup);
157 }
158 public void addSuperType(Interface iface) {
159 this.supertypes.add(new Extends(iface));
160 }
161
162 public void addMethod(Method m) {
163 this.methods.add(m);
164 }
165
166 public void addAccessFlag(AccessFlag f) {
167 this.accessFlags.add(f);
168 }
169
170 // Convenience method for creation. Parameters are interpreted
171 // according to their type. Class (or Extends with a Class type) is
172 // considered a superclass (only one allowed). TypeParameters are
173 // generic parameter names. Interface (or Extends with an Interface
174 // type) is an implemented supertype. Methods are methods (duh!).
175 protected void addComponent(Element p) {
176 if (p instanceof Class) {
177 setSuperClass(new Extends((Class)p));
178 } else if (p instanceof Extends) {
179 Extends ext = (Extends)p;
180 if (ext.supertype instanceof Class) {
181 setSuperClass(ext);
182 } else if (ext.supertype instanceof Interface) {
183 addSuperType(ext);
184 } else {
185 assert false : "What is this thing?";
186 }
187 } else if (p instanceof Interface) {
188 addSuperType((Interface)p);
189 } else if (p instanceof TypeParameter) {
190 this.parameters.add((TypeParameter)p);
191 } else if (p instanceof Method) {
192 addMethod((Method)p);
193 } else if (p instanceof AccessFlag) {
194 addAccessFlag((AccessFlag)p);
195 } else {
196 assert false : "What is this thing?";
197 }
198 }
199
200 // Find and return the first method that has name 'name'
201 public Method findMethod(String name) {
202 for (Method m : methods) {
203 if (m.name.equals(name)) {
204 return m;
205 }
206 }
207 return null;
208 }
209
210 public void addCompilationDependency(Type t) {
211 typeDependencies.add(t);
212 }
213
214 public void addCompilationDependency(Method m) {
215 methodDependencies.add(m);
216 }
217
218 public boolean isFullCompilation() {
219 return fullCompilation;
220 }
221
222 public void setFullCompilation(boolean fullCompilation) {
223 this.fullCompilation = fullCompilation;
224 }
225
226 // Convenience method for creating an Extends object using this
227 // class and specified type arguments.
228 public Extends with(String ... args) {
229 return new Extends(this, args);
230 }
231
232 public abstract void generate(SourceProcessor sp);
233 public abstract void generateAsDependency(
234 SourceProcessor sp, Set<Method> neededMethods);
235
236 protected void generateName(PrintWriter pw) {
237 pw.print(this.name);
238 toJoinedString(this.parameters, ",", "<", ">", "");
239 pw.print(toJoinedString(this.parameters, ",", "<", ">", ""));
240 pw.print(" ");
241 }
242
243 protected void generateBody(PrintWriter pw, String superSpec) {
244 pw.print(toJoinedString(this.supertypes, ",", superSpec + " ", " ", ""));
245 pw.println("{ ");
246 pw.print(toJoinedString(this.methods, "\n ", "\n ", "\n", ""));
247 pw.println("}");
248 }
249
250 protected void generateAccessFlags(PrintWriter pw) {
251 pw.print(toJoinedString(this.accessFlags, " ", "", " "));
252 }
253
254 protected void generateBodyAsDependency(
255 PrintWriter pw, Set<Method> neededMethods) {
256 pw.println(" {");
257 for (Method m : this.methods) {
258 if (neededMethods.contains(m)) {
259 pw.print(" ");
260 m.generate(pw);
261 pw.println();
262 }
263 }
264 pw.println("}");
265 }
266
267 public Collection<Type> typeDependencies(boolean recursive) {
268 HashMap<String,Type> dependencies = new HashMap<>();
269 Type superclass = getSuperclass();
270 if (superclass != null) {
271 dependencies.put(superclass.getName(), superclass);
272 if (recursive) {
273 for (Type t : superclass.typeDependencies(true))
274 dependencies.put(t.getName(), t);
275 }
276 }
277 for (Extends e : getSupertypes()) {
278 dependencies.put(e.getType().getName(), e.getType());
279 if (recursive) {
280 for (Type t : e.getType().typeDependencies(true))
281 dependencies.put(t.getName(), t);
282 }
283 }
284 // Do these last so that they override
285 for (Type t : this.typeDependencies)
286 dependencies.put(t.getName(), t);
287 return dependencies.values();
288 }
289 }
290
291 public static class Class extends Type {
292 private Extends superClass;
293
294 public Class(String name, List<AccessFlag> flags,
295 List<TypeParameter> params, Extends sprClass,
296 List<Extends> interfaces, List<Method> methods) {
297 super(name, flags, params, interfaces, methods);
298 this.superClass = sprClass;
299 addAccessFlag(AccessFlag.PUBLIC); // should remove this
300 }
301
302 public Class(String name, Element ... components) {
303 super(name, null, null, null, null);
304 this.superClass = null;
305
306 for (Element p : components) {
307 addComponent(p);
308 }
309 addAccessFlag(AccessFlag.PUBLIC); // should remove this
310 }
311
312 public boolean isAbstract() {
313 for (AccessFlag flag : getAccessFlags()) {
314 if (flag == AccessFlag.ABSTRACT) {
315 return true;
316 }
317 }
318 return false;
319 }
320
321 @Override
322 public void setSuperClass(Extends ext) {
323 assert this.superClass == null : "Multiple superclasses defined";
324 assert ext.getType() instanceof Class : "Must be a class";
325 this.superClass = ext;
326 }
327
328 public void setSuperClass(Class c) {
329 setSuperClass(new Extends(c));
330 }
331
332 @Override
333 public Class getSuperclass() {
334 return superClass == null ? null : (Class)superClass.supertype;
335 }
336
337 public void generate(SourceProcessor processor) {
338 StringWriter sw = new StringWriter();
339 PrintWriter pw = new PrintWriter(sw);
340 generate(pw);
341 processor.process(getName(), sw.toString());
342 }
343
344 public void generate(PrintWriter pw) {
345 generateAccessFlags(pw);
346 pw.print("class ");
347 generateName(pw);
348 if (superClass != null) {
349 pw.print("extends ");
350 superClass.generate(pw);
351 pw.print(" ");
352 }
353 generateBody(pw, "implements");
354 }
355
356 public void generateAsDependency(
357 SourceProcessor processor, Set<Method> neededMethods) {
358 StringWriter sw = new StringWriter();
359 PrintWriter pw = new PrintWriter(sw);
360 generateAccessFlags(pw);
361 pw.print("class ");
362 generateName(pw);
363 pw.print(" ");
364 generateBodyAsDependency(pw, neededMethods);
365
366 processor.process(getName(), sw.toString());
367 }
368 }
369
370 public static class Interface extends Type {
371
372 public Interface(String name,
373 List<AccessFlag> flags, List<TypeParameter> params,
374 List<Extends> interfaces, List<Method> methods) {
375 super(name, flags, params, interfaces, methods);
376 }
377
378 public Interface(String name, Element ... components) {
379 super(name, null, null, null, null);
380 for (Element c : components) {
381 addComponent(c);
382 }
383 }
384
385 protected void setSuperClass(Extends ext) {
386 assert false : "Interfaces cannot have Class supertypes";
387 }
388
389 public void generate(SourceProcessor processor) {
390 StringWriter sw = new StringWriter();
391 PrintWriter pw = new PrintWriter(sw);
392 generate(pw);
393 processor.process(getName(), sw.toString());
394 }
395
396 public void generate(PrintWriter pw) {
397 generateAccessFlags(pw);
398 pw.print("interface ");
399 generateName(pw);
400 pw.print(" ");
401 generateBody(pw, "extends");
402 }
403
404 public void generateAsDependency(
405 SourceProcessor processor, Set<Method> neededMethods) {
406 StringWriter sw = new StringWriter();
407 PrintWriter pw = new PrintWriter(sw);
408
409 generateAccessFlags(pw);
410 pw.print("interface ");
411 generateName(pw);
412 pw.print(" ");
413 generateBodyAsDependency(pw, neededMethods);
414
415 processor.process(getName(), sw.toString());
416 }
417 }
418
419 /**
420 * Represents a type extension that might contain type arguments
421 */
422 public static class Extends extends Element {
423 private final Type supertype;
424 private final List<TypeArgument> arguments;
425
426 public Type getType() { return supertype; }
427 public List<TypeArgument> getArguments() {
428 return arguments;
429 }
430
431 public Extends(Type supertype, String ... args) {
432 assert supertype != null : "Null supertype";
433 this.supertype = supertype;
434 this.arguments = new ArrayList<>();
435 for (String arg : args) {
436 this.arguments.add(new TypeArgument(arg));
437 }
438 }
439
440 public void generate(PrintWriter pw) {
441 pw.print(supertype.getName());
442 pw.print(toJoinedString(getArguments(), ",", "<", ">", ""));
443 }
444 }
445
446 public static abstract class Method extends Element {
447 private String name;
448 private String returnType;
449 private List<AccessFlag> accessFlags;
450 private List<MethodParameter> parameters;
451 private boolean emitSuppressWarnings;
452
453 protected Method(String ret, String name, Element ... params) {
454 this.name = name;
455 this.returnType = ret;
456 this.accessFlags = new ArrayList<>();
457 this.parameters = new ArrayList<>();
458 this.emitSuppressWarnings = false;
459
460 for (Element e : params) {
461 if (e instanceof MethodParameter) {
462 this.parameters.add((MethodParameter) e);
463 } else if (e instanceof AccessFlag) {
464 this.accessFlags.add((AccessFlag) e);
465 }
466 }
467 assert accessFlags.size() + parameters.size() == params.length :
468 "Non method parameters or access flags in constructor";
469 }
470
471 public String getName() { return this.name; }
472 public String getReturnType() { return this.returnType; }
473 public List<MethodParameter> getParameters() {
474 return this.parameters;
475 }
476 public List<AccessFlag> getAccessFlags() {
477 return this.accessFlags;
478 }
479 public Element[] getElements() {
480 ArrayList<Element> elements = new ArrayList<>();
481 elements.addAll(getParameters());
482 elements.addAll(getAccessFlags());
483 return elements.toArray(new Element[0]);
484 }
485
486 public void suppressWarnings() { this.emitSuppressWarnings = true; }
487
488 public void generateWarningSuppression(PrintWriter pw) {
489 if (this.emitSuppressWarnings) {
490 pw.printf("@SuppressWarnings(\"unchecked\")\n ");
491 }
492 }
493
494 protected void generateDecl(PrintWriter pw) {
495 generateWarningSuppression(pw);
496 pw.print(toJoinedString(this.accessFlags, " ", "", " "));
497 pw.printf("%s %s(", returnType, name);
498 pw.print(toJoinedString(parameters, ","));
499 pw.print(")");
500 }
501 }
502
503 public static class AbstractMethod extends Method {
504 public AbstractMethod(
505 String ret, String name, Element ... params) {
506 super(ret, name, params);
507 this.getAccessFlags().add(AccessFlag.ABSTRACT);
508 }
509
510 public void generate(PrintWriter pw) {
511 generateDecl(pw);
512 pw.print(";");
513 }
514
515 public static AbstractMethod std() {
516 return new AbstractMethod(
517 "int", SourceModel.stdMethodName, AccessFlag.PUBLIC);
518 }
519 }
520
521 public static class ConcreteMethod extends Method {
522 protected String body;
523
524 public ConcreteMethod(String ret, String name,
525 String body, Element ... params) {
526 super(ret, name, params);
527 this.body = body;
528 }
529
530 public void generate(PrintWriter pw) {
531 generateDecl(pw);
532 pw.printf(" { %s }", this.body);
533 }
534
535 public static ConcreteMethod std(String value) {
536 return new ConcreteMethod(
537 "int", SourceModel.stdMethodName, "return " + value + ";",
538 AccessFlag.PUBLIC);
539 }
540 }
541
542 // When the default method flag gets moved into the traditional
543 // access flags location, we can remove this class completely and
544 // use a ConcreteMethod with an AccessFlag("default") in the constructor
545 public static class DefaultMethod extends Method {
546 protected String body;
547
548 public DefaultMethod(String ret, String name, String body,
549 Element ... params) {
550 super(ret, name, params);
551 this.body = body;
552 this.getAccessFlags().add(AccessFlag.DEFAULT);
553 }
554
555 public void generate(PrintWriter pw) {
556 generateDecl(pw);
557 pw.printf(" { %s }", this.body);
558 }
559
560 public static DefaultMethod std(String value) {
561 return new DefaultMethod(
562 "int", SourceModel.stdMethodName, "return " + value + ";");
563 }
564 }
565
566 private static <T> String toJoinedString(List<T> list, String... p) {
567 StringBuilder sb = new StringBuilder();
568 String sep = "";
569 String init = "";
570 String end = "";
571 String empty = null;
572 switch (p.length) {
573 case 4:
574 empty = p[3];
575 /*fall-through*/
576 case 3:
577 end = p[2];
578 /*fall-through*/
579 case 2:
580 init = p[1];
581 /*fall-through*/
582 case 1:
583 sep = p[0];
584 break;
585 }
586 if (empty != null && list.isEmpty()) {
587 return empty;
588 } else {
589 sb.append(init);
590 for (T x : list) {
591 if (sb.length() != init.length()) {
592 sb.append(sep);
593 }
594 sb.append(x.toString());
595 }
596 sb.append(end);
597 return sb.toString();
598 }
599 }
600 }

mercurial