1 /* 2 * Copyright (c) 2015, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package sampleapi.generator; 25 26 import java.io.File; 27 import java.io.FileWriter; 28 import java.io.InputStream; 29 import java.io.FileInputStream; 30 import java.io.IOException; 31 import java.util.ArrayList; 32 import java.util.Hashtable; 33 import javax.xml.parsers.DocumentBuilderFactory; 34 import javax.xml.parsers.DocumentBuilder; 35 import javax.xml.parsers.ParserConfigurationException; 36 import org.xml.sax.SAXException; 37 import org.w3c.dom.Document; 38 import org.w3c.dom.Element; 39 import org.w3c.dom.Text; 40 import org.w3c.dom.Node; 41 import org.w3c.dom.NodeList; 42 43 import com.sun.source.util.JavacTask; 44 import com.sun.tools.javac.api.JavacTool; 45 import com.sun.tools.javac.api.JavacTaskImpl; 46 import com.sun.tools.javac.util.Context; 47 import com.sun.tools.javac.util.Name; 48 import com.sun.tools.javac.util.Names; 49 import com.sun.tools.javac.util.List; 50 import com.sun.tools.javac.util.ListBuffer; 51 import com.sun.tools.javac.tree.TreeMaker; 52 import com.sun.tools.javac.tree.JCTree; 53 import com.sun.tools.javac.tree.JCTree.*; 54 import com.sun.tools.javac.code.Flags; 55 import com.sun.tools.javac.code.Type; 56 import com.sun.tools.javac.code.TypeTag; 57 import com.sun.tools.javac.code.TypeMetadata; 58 import com.sun.tools.javac.code.Symbol; 59 import com.sun.tools.javac.code.Symtab; 60 61 import sampleapi.util.*; 62 import sampleapi.SampleApi.Fault; 63 64 public class PackageGenerator { 65 66 String packageName; 67 String packageDirName; 68 69 ArrayList<JCCompilationUnit> topLevels; 70 Hashtable<String, Integer> nameIndex; 71 Hashtable<String, JCClassDecl> idBases; 72 Hashtable<String, JCAnnotation> idAnnos; 73 74 TreeMaker make; 75 Names names; 76 Symtab syms; 77 DocumentBuilderFactory factory; 78 Documentifier documentifier; 79 boolean fx = false; 80 81 public PackageGenerator() { 82 JavacTool jt = JavacTool.create(); 83 JavacTask task = jt.getTask(null, null, null, null, null, null); 84 Context ctx = ((JavacTaskImpl)task).getContext(); 85 86 make = TreeMaker.instance(ctx); 87 names = Names.instance(ctx); 88 syms = Symtab.instance(ctx); 89 factory = DocumentBuilderFactory.newInstance(); 90 91 documentifier = Documentifier.instance(ctx); 92 } 93 94 String dataSetName; 95 96 public void processDataSet(String dsName) throws Fault { 97 dataSetName = dsName; 98 topLevels = new ArrayList<>(); 99 nameIndex = new Hashtable<>(); 100 idBases = new Hashtable<>(); 101 idAnnos = new Hashtable<>(); 102 103 String dsPath = "res/xml/" + dsName + ".xml"; 104 105 try { 106 InputStream is = getClass().getResourceAsStream("/" + dsPath); 107 if (is == null) 108 is = new FileInputStream(dsPath); 109 110 DocumentBuilder builder = factory.newDocumentBuilder(); 111 Document document = builder.parse(is); 112 113 Element rootElement = document.getDocumentElement(); 114 packageName = rootElement.getAttribute("package"); 115 fx = "fx".equals(rootElement.getAttribute("style")); 116 packageDirName = packageName.replace('.', '/'); 117 118 // process nodes (toplevels) 119 NodeList nodeList = rootElement.getChildNodes(); 120 for (int i = 0; i < nodeList.getLength(); i++) { 121 Node node = nodeList.item(i); 122 123 if (!(node instanceof Element)) 124 continue; 125 processTopLevel((Element)node); 126 } 127 } catch (ParserConfigurationException | SAXException | IOException e) { 128 throw new Fault("Error parsing dataset " + dsName); 129 } 130 131 fx = false; 132 } 133 134 public void generate(File outDir) throws Fault { 135 if (dataSetName == null) 136 throw new Fault("No Data Set processed"); 137 138 try { 139 File pkgDir = new File(outDir, packageDirName); 140 pkgDir.mkdirs(); 141 142 for (JCCompilationUnit decl : topLevels) { 143 JCClassDecl classDecl = (JCClassDecl)decl.getTypeDecls().get(0); 144 File outFile = new File(pkgDir, 145 classDecl.getSimpleName().toString() + ".java"); 146 FileWriter writer = new FileWriter(outFile); 147 writer.write(decl.toString()); 148 writer.flush(); 149 writer.close(); 150 } 151 152 // package-info 153 File outFile = new File(pkgDir, "package-info.java"); 154 FileWriter writer = new FileWriter(outFile); 155 writer.write("/**\n"); 156 writer.write(documentifier.getDocGenerator().getPackageComment()); 157 writer.write("*/\n"); 158 writer.write("package " + packageName + ";"); 159 writer.flush(); 160 writer.close(); 161 } catch (IOException e) { 162 throw new Fault("Error writing output"); 163 } 164 } 165 166 // levels' processing methods 167 168 void processTopLevel(Element tlTag) { 169 String kind = tlTag.getTagName(); 170 171 if (kind.equals("annodecl")) { 172 // decls stored separately, does not affect bases 173 String declId = tlTag.getAttribute("id"); 174 if (!declId.startsWith("@")) 175 declId = "@" + declId; 176 idAnnos.put(declId, processAnnoDecl(tlTag)); 177 return; 178 } 179 180 ListBuffer<JCTree>[] bases = processBases(tlTag, null); 181 182 for (JCTree base : bases[0]) { // [0] - bases namely 183 JCPackageDecl pkg = make.PackageDecl( 184 List.<JCAnnotation>nil(), 185 make.QualIdent( 186 new Symbol.PackageSymbol( 187 names.fromString(packageName), 188 null))); 189 ListBuffer<JCTree> topLevelParts = new ListBuffer<>(); 190 topLevelParts.append(pkg); 191 topLevelParts.appendList(bases[1]); // [1] imports 192 topLevelParts.append(base); 193 194 JCCompilationUnit topLevel = make.TopLevel(topLevelParts.toList()); 195 documentifier.documentify(topLevel, fx); 196 topLevels.add(topLevel); 197 } 198 } 199 200 ListBuffer<JCTree>[] processBases(Element baseTag, Hashtable<String, Integer> scope) { 201 String kind = baseTag.getTagName(); 202 String baseName = baseTag.getAttribute("basename"); 203 String typeParam = baseTag.getAttribute("tparam"); 204 String baseId = baseTag.getAttribute("id"); 205 206 long kindFlag = 0; 207 switch (kind) { 208 case "class": 209 // no flags for class 210 break; 211 case "interface": 212 kindFlag |= Flags.INTERFACE; 213 break; 214 case "enum": 215 kindFlag |= Flags.ENUM; 216 break; 217 case "annotation": 218 kindFlag |= Flags.ANNOTATION | Flags.INTERFACE; 219 break; 220 } 221 222 // go through other nodes; add modifiers to multiplier 223 NodeList nodes = baseTag.getChildNodes(); 224 ListBuffer<JCTree> bases = new ListBuffer<>(); 225 ListBuffer<JCTree> members = new ListBuffer<>(); 226 ListBuffer<JCTree> imports = new ListBuffer<>(); 227 JCExpression extType = null; 228 ListBuffer<JCExpression> implTypes = new ListBuffer<>(); 229 SimpleMultiplier multiply = new SimpleMultiplier(); 230 for (int i = 0; i < nodes.getLength(); i++) { 231 Node node = nodes.item(i); 232 233 if (!(node instanceof Element)) 234 continue; 235 236 switch (((Element)node).getTagName()) { 237 case "modifier": 238 multiply.addAxis(((Element)node).getTextContent()); 239 break; 240 case "anno": 241 multiply.addAxis(((Element)node).getTextContent()); 242 break; 243 case "member": 244 // process members here 245 members.appendList(processMembers((Element)node, baseName, kind)); 246 break; 247 case "extend": 248 String classId = ((Element)node).getAttribute("id"); // this pkg 249 String classRef = ((Element)node).getAttribute("ref"); // external 250 if (classId.length() !=0 && 251 idBases.containsKey(classId)) { 252 // if have base, take methods from base members 253 JCClassDecl baseDecl = idBases.get(classId); 254 extType = make.Type( 255 getTypeByName( 256 baseDecl.getSimpleName().toString())); 257 members.appendList(processMethods(baseDecl.getMembers(), false)); 258 } else if (classRef.length() !=0) { 259 extType = make.Type(getTypeByName(classRef)); 260 } 261 break; 262 case "implement": 263 String interfaceId = ((Element)node).getAttribute("id"); 264 String interfaceRef = ((Element)node).getAttribute("ref"); 265 if (interfaceId.length() != 0 && 266 idBases.containsKey(interfaceId)) { 267 JCClassDecl baseDecl = idBases.get(interfaceId); 268 implTypes.add( 269 make.Type( 270 getTypeByName( 271 baseDecl.getSimpleName().toString()))); 272 members.appendList(processMethods(baseDecl.getMembers(), true)); 273 } else if (interfaceRef.length() != 0) { 274 implTypes.add(make.Type(getTypeByName(interfaceRef))); 275 } 276 break; 277 case "import": 278 imports.append( 279 make.Import( 280 make.Ident(names.fromString(((Element)node).getTextContent())), 281 false)); 282 } 283 } 284 285 // process modifiers through multiplier 286 multiply.initIterator(); 287 while (multiply.hasNext()) { 288 ArrayList<String> tuple = multiply.getNext(); 289 290 long declFlags = kindFlag; 291 ListBuffer<JCAnnotation> annos = new ListBuffer<>(); 292 for (String modifier : tuple) { 293 if (modifier.startsWith("@") && idAnnos.containsKey(modifier)) 294 annos.add(idAnnos.get(modifier)); // it's anno 295 else 296 declFlags |= getFlagByName(modifier); // it's modifier 297 } 298 299 String declName = (scope == null) 300 ? getUniqName(baseName) 301 : baseName + getUniqIndex(scope, baseName); 302 JCClassDecl baseDecl = make.ClassDef( 303 make.Modifiers(declFlags, annos.toList()), 304 names.fromString(declName), 305 processTypeParams(typeParam), // type params 306 extType, // ext 307 implTypes.toList(), // impl 308 members.toList()); // members 309 310 // fix constructors names 311 fixConstructorNames(baseDecl); 312 313 bases.append(baseDecl); 314 315 // for non-empty ids store first base occurence from multiplied sequence 316 if (baseId.length() != 0) { 317 idBases.put(baseId, baseDecl); 318 baseId = ""; 319 } 320 } 321 322 return new ListBuffer[] { bases, imports }; 323 } 324 325 List<JCTypeParameter> processTypeParams(String typeParams) { 326 327 if (typeParams == null || typeParams.length() == 0) 328 return List.<JCTypeParameter>nil(); // empty 329 330 String[] typeVarsArr = typeParams.split(","); 331 ListBuffer<JCTypeParameter> typeParamsDecls = new ListBuffer<>(); 332 333 for (String typeVar : typeVarsArr) { 334 typeParamsDecls.add( 335 make.TypeParameter(names.fromString(typeVar), 336 List.<JCExpression>nil())); 337 } 338 339 return typeParamsDecls.toList(); 340 } 341 342 ListBuffer<JCTree> processMembers(Element memberTag, String name, String kind) { 343 ListBuffer<JCTree> members = new ListBuffer<>(); 344 NodeList nodes = memberTag.getChildNodes(); 345 Hashtable<String, Integer> scope = new Hashtable<>(); 346 for (int i = 0; i < nodes.getLength(); i++) { 347 Node node = nodes.item(i); 348 349 if (!(node instanceof Element)) 350 continue; 351 352 switch (((Element)node).getTagName()) { 353 case "field": 354 members.appendList(processFields((Element)node, scope)); 355 break; 356 case "serialfield": 357 members.append(processSerialFields((Element)node)); 358 break; 359 case "constant": 360 members.appendList(processConstants((Element)node, scope)); 361 break; 362 case "constructor": 363 members.appendList(processMethods((Element)node, scope, true, true)); 364 break; 365 case "method": 366 boolean needBody = kind.equals("class") || kind.equals("enum"); 367 members.appendList(processMethods((Element)node, scope, needBody, false)); 368 break; 369 case "class": 370 case "interface": 371 case "enum": 372 case "annotation": 373 members.appendList(processBases((Element)node, scope)[0]); 374 break; 375 } 376 } 377 378 return members; 379 } 380 381 ListBuffer<JCTree> processFields(Element fieldsNode, Hashtable<String, Integer> scope) { 382 String kind = fieldsNode.getTagName(); 383 String baseName = fieldsNode.getAttribute("basename"); 384 385 ListBuffer<JCTree> fields = new ListBuffer<>(); 386 NodeList nodes = fieldsNode.getChildNodes(); 387 SimpleMultiplier multiply = new SimpleMultiplier(); // for modifiers 388 String[] types = new String[] {}; 389 for (int i = 0; i < nodes.getLength(); i++) { 390 Node node = nodes.item(i); 391 392 if (!(node instanceof Element)) 393 continue; 394 395 // parse type and modifiers 396 switch (((Element)node).getTagName()) { 397 case "modifier": 398 multiply.addAxis(((Element)node).getTextContent()); 399 break; 400 case "anno": 401 multiply.addAxis(((Element)node).getTextContent()); 402 case "type": 403 types = ((Element)node).getTextContent().split("\\|"); 404 break; 405 } 406 } 407 408 // process through modifiers and types 409 multiply.initIterator(); 410 while (multiply.hasNext()) { 411 ArrayList<String> tuple = multiply.getNext(); 412 413 long declFlags = 0; 414 ListBuffer<JCAnnotation> annos = new ListBuffer<>(); 415 for (String modifier : tuple) { 416 if (modifier.startsWith("@") && idAnnos.containsKey(modifier)) 417 annos.add(idAnnos.get(modifier)); // it's anno 418 else 419 declFlags |= getFlagByName(modifier); // it's modifier 420 } 421 422 423 for (String type : types) { 424 String declName = baseName + getUniqIndex(scope, baseName); 425 426 Type initType = getTypeByName(type); 427 JCExpression initExpr = null; 428 if ((declFlags & Flags.STATIC) != 0) // static to be initialized 429 initExpr = make.Literal(initType.isPrimitive() ? 430 initType.getTag() : 431 TypeTag.BOT, 432 "String".equals(type) 433 ? new String("blah-blah-blah") 434 : new Integer(0)); 435 436 JCVariableDecl fieldDecl = make.VarDef( 437 make.Modifiers(declFlags, annos.toList()), 438 names.fromString(declName), 439 make.Type(getTypeByName(type)), 440 initExpr); 441 442 fields.append(fieldDecl); 443 } 444 } 445 446 return fields; 447 } 448 449 JCTree processSerialFields(Element sfNode) { 450 String baseName = sfNode.getAttribute("basename"); 451 String[] fieldTypes = sfNode.getTextContent().split(","); 452 453 ListBuffer<JCExpression> serialFields = new ListBuffer<>(); 454 Hashtable<String, Integer> scope = new Hashtable<>(); 455 456 for (String fType : fieldTypes) { 457 String fieldName = baseName + getUniqIndex(scope, baseName); 458 serialFields.add( 459 make.NewClass( 460 null, 461 null, 462 make.Type(getTypeByName("ObjectStreamField")), 463 List.from( 464 new JCTree.JCExpression[] { 465 make.Literal(fieldName), 466 make.Ident(names.fromString(fType + ".class")) 467 }), 468 null)); 469 } 470 471 JCTree sfDecl = make.VarDef( 472 make.Modifiers( 473 Flags.PRIVATE | Flags.STATIC | Flags.FINAL), 474 names.fromString("serialPersistentFields"), 475 make.TypeArray( 476 make.Type(getTypeByName("ObjectStreamField"))), 477 make.NewArray( 478 null, 479 List.<JCExpression>nil(), 480 serialFields.toList())); 481 482 return sfDecl; 483 } 484 485 ListBuffer<JCTree> processConstants(Element constNode, Hashtable<String, Integer> scope) { 486 String baseName = constNode.getAttribute("basename"); 487 int count = 1; 488 try { 489 count = Integer.parseInt(constNode.getAttribute("count")); 490 } catch (Exception e) {} // nothing to do, will use count = 1 491 492 long declFlags = Flags.PUBLIC | Flags.STATIC | Flags.FINAL | Flags.ENUM; 493 ListBuffer<JCTree> fields = new ListBuffer<>(); 494 495 for (int i = 0; i < count; i++) { 496 String declName = baseName + 497 ((count == 1) ? "" : getUniqIndex(scope, baseName)); 498 499 JCVariableDecl constDecl = make.VarDef( 500 make.Modifiers(declFlags), 501 names.fromString(declName), 502 null, // no need for type in enum decl 503 null); // no init 504 505 fields.append(constDecl); 506 } 507 return fields; 508 } 509 510 ListBuffer<JCTree> processMethods(Element methodsNode, Hashtable<String, Integer> scope, boolean needBody, boolean isConstructor) { 511 String kind = methodsNode.getTagName(); 512 String baseName = methodsNode.getAttribute("basename"); 513 String name = methodsNode.getAttribute("name"); 514 String methodTypeParam = methodsNode.getAttribute("tparam"); 515 516 ListBuffer<JCTree> methods = new ListBuffer<>(); 517 NodeList nodes = methodsNode.getChildNodes(); 518 SimpleMultiplier multiply = new SimpleMultiplier(); // for modifiers 519 String[] types = new String[0]; 520 String[] params = new String[] { "none" }; // default - no params 521 ListBuffer<Type> throwTypes = new ListBuffer<>(); 522 for (int i = 0; i < nodes.getLength(); i++) { 523 Node node = nodes.item(i); 524 525 if (!(node instanceof Element)) 526 continue; 527 528 // parse type and modifiers 529 switch (((Element)node).getTagName()) { 530 case "modifier": 531 multiply.addAxis(((Element)node).getTextContent()); 532 break; 533 case "anno": 534 multiply.addAxis(((Element)node).getTextContent()); 535 break; 536 case "type": 537 types = ((Element)node).getTextContent().split("\\|"); 538 break; 539 case "param": 540 params = ((Element)node).getTextContent().split("\\|"); 541 break; 542 case "throw": 543 throwTypes.add( 544 getTypeByName(((Element)node).getTextContent())); 545 break; 546 547 } 548 } 549 550 // constructor? 551 if (isConstructor) { 552 baseName = "constructor"; 553 types = new String[] { "" }; 554 } 555 556 // direct name not indexed 557 boolean isDirectName = false; 558 if (name.length() > 0) { 559 baseName = name; 560 isDirectName = true; 561 } 562 563 // process through modifiers and types 564 multiply.initIterator(); 565 while (multiply.hasNext()) { 566 ArrayList<String> tuple = multiply.getNext(); 567 568 long declFlags = 0; 569 ListBuffer<JCAnnotation> annos = new ListBuffer<>(); 570 for (String modifier : tuple) { 571 if (modifier.startsWith("@") && idAnnos.containsKey(modifier)) 572 annos.add(idAnnos.get(modifier)); // it's anno 573 else 574 declFlags |= getFlagByName(modifier); // it's modifier 575 } 576 577 for (String type : types) { 578 String declName = baseName 579 + ((isConstructor || isDirectName) 580 ? "" : getUniqIndex(scope, baseName)); 581 582 JCBlock body = null; 583 if (needBody && (declFlags & Flags.ABSTRACT) == 0) { // create body 584 List<JCStatement> bodyStatements = List.<JCStatement>nil(); 585 if (!type.equals("") && !type.equals("void")) { // create return statement 586 Type retType = getTypeByName(type); 587 bodyStatements = List.<JCStatement>of( 588 make.Return( 589 make.Literal( 590 retType.isPrimitive() ? 591 retType.getTag() : 592 TypeTag.BOT, 593 new Integer(0)))); 594 } 595 body = make.Block(0, bodyStatements); 596 } 597 598 // same method by different params (if they exist) 599 for (String param : params) { 600 601 JCMethodDecl methodDecl = 602 make.MethodDef( 603 make.Modifiers(declFlags, annos.toList()), 604 names.fromString(declName), 605 isConstructor ? null : make.Type(getTypeByName(type)), 606 processTypeParams(methodTypeParam), // type params 607 null, // no receiver 608 processParams(param), // formal params 609 make.Types(throwTypes.toList()), // throws 610 body, 611 null); // no default value YET 612 613 methods.append(methodDecl); 614 } 615 } 616 } 617 618 return methods; 619 } 620 621 JCAnnotation processAnnoDecl(Element annoDeclNode) { 622 String annoId = annoDeclNode.getAttribute("id"); 623 624 ListBuffer<JCExpression> args = new ListBuffer<>(); 625 String className = ""; 626 627 NodeList nodes = annoDeclNode.getChildNodes(); 628 for (int i = 0; i < nodes.getLength(); i++) { 629 Node node = nodes.item(i); 630 631 if (!(node instanceof Element)) 632 continue; 633 634 switch (((Element)node).getTagName()) { 635 case "class": 636 className = ((Element)node).getTextContent(); 637 break; 638 case "arg": 639 String argName = ((Element)node).getAttribute("name"); 640 String argValue = ((Element)node).getAttribute("value"); 641 642 JCExpression arg; 643 if (argName.length() == 0) 644 arg = make.Ident(names.fromString(argValue)); 645 else 646 arg = make.Assign( 647 make.Ident(names.fromString(argName)), 648 make.Ident(names.fromString(argValue))); 649 650 args.add(arg); 651 break; 652 } 653 } 654 655 return make.Annotation( 656 make.Ident(names.fromString(className)), 657 args.toList()); 658 } 659 660 ListBuffer<JCTree> processMethods(List<JCTree> tree, boolean needBody) { 661 // for "extends" clause; returns methods only 662 ListBuffer<JCTree> methods = new ListBuffer<>(); 663 for (JCTree memberDecl : tree) { 664 if (memberDecl instanceof JCMethodDecl) { 665 JCMethodDecl methodDecl = (JCMethodDecl)memberDecl; 666 JCTree retTypeTree = methodDecl.getReturnType(); 667 668 // skip constructors 669 if (retTypeTree == null) 670 continue; 671 672 if (needBody) { 673 // here we need to 'implement' interface declared methods 674 Type retType = retTypeTree.type; 675 676 List<JCStatement> bodyStatements = List.<JCStatement>nil(); 677 if (retType.getTag() != TypeTag.VOID) 678 bodyStatements = List.<JCStatement>of( 679 make.Return( 680 make.Literal( 681 retType.isPrimitive() ? 682 retType.getTag() : 683 TypeTag.BOT, 684 new Integer(0)))); 685 686 JCBlock body = make.Block(0, bodyStatements); 687 688 methodDecl = make.MethodDef( 689 methodDecl.getModifiers(), 690 methodDecl.getName(), 691 (JCExpression)methodDecl.getReturnType(), 692 methodDecl.getTypeParameters(), 693 methodDecl.getReceiverParameter(), 694 methodDecl.getParameters(), 695 methodDecl.getThrows(), 696 body, 697 (JCExpression)methodDecl.getDefaultValue()); 698 } 699 700 methods.add(methodDecl); 701 } 702 } 703 return methods; 704 } 705 706 void fixConstructorNames(JCClassDecl baseDecl) { 707 ListBuffer<JCTree> newMembers = new ListBuffer<>(); 708 List<JCTree> members = baseDecl.getMembers(); 709 Name name = baseDecl.getSimpleName(); 710 711 for (JCTree memberDecl : members) { 712 JCTree newDecl = memberDecl; 713 714 if (memberDecl instanceof JCMethodDecl) { 715 JCMethodDecl methodDecl = (JCMethodDecl)memberDecl; 716 JCTree retTypeTree = methodDecl.getReturnType(); 717 718 if (retTypeTree == null) 719 newDecl = make.MethodDef( 720 methodDecl.getModifiers(), 721 name, 722 (JCExpression)methodDecl.getReturnType(), 723 methodDecl.getTypeParameters(), 724 methodDecl.getReceiverParameter(), 725 methodDecl.getParameters(), 726 methodDecl.getThrows(), 727 methodDecl.getBody(), 728 (JCExpression)methodDecl.getDefaultValue()); 729 } 730 731 newMembers.add(newDecl); 732 } 733 734 baseDecl.defs = newMembers.toList(); 735 } 736 737 List<JCVariableDecl> processParams(String paramTypes) { 738 739 if ("none".equals(paramTypes)) 740 return List.<JCVariableDecl>nil(); // empty 741 742 String[] typesArr = paramTypes.split(",(?!(\\w+,)*\\w+>)"); 743 ListBuffer<JCVariableDecl> paramsDecls = new ListBuffer<>(); 744 745 int i = 0; 746 for (String typeName : typesArr) { 747 String paramName = "param" 748 + (typesArr.length == 1 ? "" : String.valueOf(i)); 749 paramsDecls.add( 750 make.VarDef(make.Modifiers(0), 751 names.fromString(paramName), 752 make.Type(getTypeByName(typeName)), 753 null)); 754 i++; 755 } 756 757 return paramsDecls.toList(); 758 } 759 760 // 761 // util methods 762 // 763 764 String getUniqName(String name) { 765 if (!nameIndex.containsKey(name)) 766 nameIndex.put(name, new Integer(0)); 767 Integer index = nameIndex.get(name); 768 String uniqName = name + index; 769 nameIndex.put(name, index + 1); 770 return uniqName; 771 } 772 773 int getUniqIndex(Hashtable<String, Integer> scope, String name) { 774 if (!scope.containsKey(name)) 775 scope.put(name, new Integer(0)); 776 Integer index = scope.get(name); 777 scope.put(name, index + 1); 778 return index; 779 } 780 781 long getFlagByName(String modifierName) { 782 switch (modifierName) { 783 case "public": 784 return Flags.PUBLIC; 785 case "private": 786 return Flags.PRIVATE; 787 case "protected": 788 return Flags.PROTECTED; 789 case "static": 790 return Flags.STATIC; 791 case "final": 792 return Flags.FINAL; 793 case "abstract": 794 return Flags.ABSTRACT; 795 case "strictfp": 796 return Flags.STRICTFP; 797 default: 798 return 0; 799 } 800 } 801 802 Type getTypeByName(String typeName) { 803 //check for primitive types 804 switch (typeName) { 805 case "void": 806 return syms.voidType; 807 case "boolean": 808 return syms.booleanType; 809 case "byte": 810 return syms.byteType; 811 case "char": 812 return syms.charType; 813 case "double": 814 return syms.doubleType; 815 case "float": 816 return syms.floatType; 817 case "int": 818 return syms.intType; 819 case "long": 820 return syms.longType; 821 default: 822 return getTypeByName(typeName, List.<Type>nil()); 823 } 824 } 825 826 Type getTypeByName(String typeName, List<Type> tparams) { 827 return new Type.ClassType( 828 Type.noType, 829 tparams, 830 new Symbol.ClassSymbol(0, names.fromString(typeName), null)); 831 } 832 }