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