| OLD | NEW | 
|---|
| 1 // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file | 
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a | 
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 /** | 5 /** | 
| 6  * Tools for Java code generation. | 6  * Tools for Java code generation. | 
| 7  */ | 7  */ | 
| 8 library CodegenJava; | 8 library CodegenJava; | 
| 9 | 9 | 
| 10 import 'package:html5lib/dom.dart' as dom; | 10 import 'package:html5lib/dom.dart' as dom; | 
|  | 11 | 
| 11 import 'api.dart'; | 12 import 'api.dart'; | 
| 12 import 'codegen_tools.dart'; | 13 import 'codegen_tools.dart'; | 
| 13 import 'from_html.dart'; | 14 import 'from_html.dart'; | 
| 14 import 'to_html.dart'; | 15 import 'to_html.dart'; | 
| 15 | 16 | 
| 16 /** | 17 /** | 
|  | 18  * Create a [GeneratedFile] that creates Java code and outputs it to [path]. | 
|  | 19  * [path] uses Posix-style path separators regardless of the OS. | 
|  | 20  */ | 
|  | 21 GeneratedFile javaGeneratedFile(String path, CodegenJavaVisitor | 
|  | 22     createVisitor(Api api)) { | 
|  | 23   return new GeneratedFile(path, () { | 
|  | 24     CodegenJavaVisitor visitor = createVisitor(readApi()); | 
|  | 25     return visitor.collectCode(visitor.visitApi); | 
|  | 26   }); | 
|  | 27 } | 
|  | 28 | 
|  | 29 /** | 
|  | 30  * Iterate through the values in [map] in the order of increasing keys. | 
|  | 31  */ | 
|  | 32 Iterable<String> _valuesSortedByKey(Map<String, String> map) { | 
|  | 33   List<String> keys = map.keys.toList(); | 
|  | 34   keys.sort(); | 
|  | 35   return keys.map((String key) => map[key]); | 
|  | 36 } | 
|  | 37 | 
|  | 38 /** | 
| 17  * Common code for all Java code generation. | 39  * Common code for all Java code generation. | 
| 18  */ | 40  */ | 
| 19 class CodegenJavaVisitor extends HierarchicalApiVisitor with CodeGenerator { | 41 class CodegenJavaVisitor extends HierarchicalApiVisitor with CodeGenerator { | 
| 20   _CodegenJavaState _state; |  | 
| 21 |  | 
| 22   /** | 42   /** | 
| 23    * Variable names which must be changed in order to avoid conflict with | 43    * Variable names which must be changed in order to avoid conflict with | 
| 24    * reserved words in Java. | 44    * reserved words in Java. | 
| 25    */ | 45    */ | 
| 26   static const Map<String, String> _variableRenames = const { | 46   static const Map<String, String> _variableRenames = const { | 
| 27     'default': 'defaultSdk' | 47     'default': 'defaultSdk' | 
| 28   }; | 48   }; | 
| 29 | 49 | 
| 30   /** | 50   /** | 
| 31    * Type references in the spec that are named something else in Java. | 51    * Type references in the spec that are named something else in Java. | 
| 32    */ | 52    */ | 
| 33   static const Map<String, String> _typeRenames = const { | 53   static const Map<String, String> _typeRenames = const { | 
| 34     'bool': 'boolean', | 54     'bool': 'boolean', | 
| 35     'int': 'int', | 55     'int': 'int', | 
| 36     'ExecutionContextId': 'String', | 56     'ExecutionContextId': 'String', | 
| 37     'FilePath': 'String', | 57     'FilePath': 'String', | 
| 38     'DebugContextId': 'String', | 58     'DebugContextId': 'String', | 
| 39     'object': 'Object', | 59     'object': 'Object', | 
| 40     'Override': 'OverrideMember', | 60     'Override': 'OverrideMember', | 
| 41   }; | 61   }; | 
| 42 | 62 | 
|  | 63   _CodegenJavaState _state; | 
|  | 64 | 
| 43   /** | 65   /** | 
| 44    * Visitor used to produce doc comments. | 66    * Visitor used to produce doc comments. | 
| 45    */ | 67    */ | 
| 46   final ToHtmlVisitor toHtmlVisitor; | 68   final ToHtmlVisitor toHtmlVisitor; | 
| 47 | 69 | 
| 48   CodegenJavaVisitor(Api api) | 70   CodegenJavaVisitor(Api api) | 
| 49       : super(api), | 71       : super(api), | 
| 50         toHtmlVisitor = new ToHtmlVisitor(api); | 72         toHtmlVisitor = new ToHtmlVisitor(api); | 
| 51 | 73 | 
| 52   /** | 74   /** | 
|  | 75    * Create a constructor, using [callback] to create its contents. | 
|  | 76    */ | 
|  | 77   void constructor(String name, void callback()) { | 
|  | 78     _state.constructors[name] = collectCode(callback); | 
|  | 79   } | 
|  | 80 | 
|  | 81   /** | 
|  | 82    * Return true iff the passed [TypeDecl] will represent an array in Java. | 
|  | 83    */ | 
|  | 84   bool isArray(TypeDecl type) { | 
|  | 85     return type is TypeList && isPrimitive(type.itemType); | 
|  | 86   } | 
|  | 87 | 
|  | 88   /** | 
|  | 89    * Return true iff the passed [TypeDecl] is a type declared in the spec_input. | 
|  | 90    */ | 
|  | 91   bool isDeclaredInSpec(TypeDecl type) { | 
|  | 92 //    TypeReference resolvedType = super.resolveTypeReferenceChain(type); | 
|  | 93 //    if(resolvedType is TypeObject) { | 
|  | 94 //      return truye; | 
|  | 95 //    } | 
|  | 96     if (type is TypeReference) { | 
|  | 97       return api.types.containsKey(type.typeName) && javaType(type) != 'String'; | 
|  | 98     } | 
|  | 99     return false; | 
|  | 100   } | 
|  | 101 | 
|  | 102   /** | 
|  | 103    * Return true iff the passed [TypeDecl] will represent an array in Java. | 
|  | 104    */ | 
|  | 105   bool isList(TypeDecl type) { | 
|  | 106     return type is TypeList && !isPrimitive(type.itemType); | 
|  | 107   } | 
|  | 108 | 
|  | 109   /** | 
|  | 110    * Return true iff the passed [TypeDecl] will represent a Map in type. | 
|  | 111    */ | 
|  | 112   bool isMap(TypeDecl type) { | 
|  | 113     return type is TypeMap; | 
|  | 114   } | 
|  | 115 | 
|  | 116   /** | 
|  | 117    * Return true iff the passed [TypeDecl] will be represented as Object in Java
     . | 
|  | 118    */ | 
|  | 119   bool isObject(TypeDecl type) { | 
|  | 120     String typeStr = javaType(type); | 
|  | 121     return typeStr == 'Object'; | 
|  | 122   } | 
|  | 123 | 
|  | 124   /** | 
|  | 125    * Return true iff the passed [TypeDecl] will represent a primitive Java type. | 
|  | 126    */ | 
|  | 127   bool isPrimitive(TypeDecl type) { | 
|  | 128     if (type is TypeReference) { | 
|  | 129       String typeStr = javaType(type); | 
|  | 130       return typeStr == 'boolean' || typeStr == 'int' || typeStr == 'long'; | 
|  | 131     } | 
|  | 132     return false; | 
|  | 133   } | 
|  | 134 | 
|  | 135   /** | 
| 53    * Convenience method for subclasses for calling docComment. | 136    * Convenience method for subclasses for calling docComment. | 
| 54    */ | 137    */ | 
| 55   void javadocComment(List<dom.Node> docs) { | 138   void javadocComment(List<dom.Node> docs) { | 
| 56     docComment(docs, width: 99, javadocStyle: true); | 139     docComment(docs, width: 99, javadocStyle: true); | 
| 57   } | 140   } | 
| 58 | 141 | 
| 59   /** | 142   /** | 
| 60    * Create a public field, using [callback] to create its contents. |  | 
| 61    */ |  | 
| 62   void publicField(String fieldName, void callback()) { |  | 
| 63     _state.publicFields[fieldName] = collectCode(callback); |  | 
| 64   } |  | 
| 65 |  | 
| 66   /** |  | 
| 67    * Create a private field, using [callback] to create its contents. |  | 
| 68    */ |  | 
| 69   void privateField(String fieldName, void callback()) { |  | 
| 70     _state.privateFields[fieldName] = collectCode(callback); |  | 
| 71   } |  | 
| 72 |  | 
| 73   /** |  | 
| 74    * Create a constructor, using [callback] to create its contents. |  | 
| 75    */ |  | 
| 76   void constructor(String name, void callback()) { |  | 
| 77     _state.constructors[name] = collectCode(callback); |  | 
| 78   } |  | 
| 79 |  | 
| 80   /** |  | 
| 81    * Create a private method, using [callback] to create its contents. |  | 
| 82    */ |  | 
| 83   void privateMethod(String methodName, void callback()) { |  | 
| 84     _state.privateMethods[methodName] = collectCode(callback); |  | 
| 85   } |  | 
| 86 |  | 
| 87   /** |  | 
| 88    * Create a public method, using [callback] to create its contents. |  | 
| 89    */ |  | 
| 90   void publicMethod(String methodName, void callback()) { |  | 
| 91     _state.publicMethods[methodName] = collectCode(callback); |  | 
| 92   } |  | 
| 93 |  | 
| 94   /** |  | 
| 95    * Execute [callback], collecting any methods that are output using |  | 
| 96    * [privateMethod] or [publicMethod], and insert the class (with methods |  | 
| 97    * sorted).  [header] is the part of the class declaration before the |  | 
| 98    * opening brace. |  | 
| 99    */ |  | 
| 100   void makeClass(String header, void callback()) { |  | 
| 101     _CodegenJavaState oldState = _state; |  | 
| 102     try { |  | 
| 103       _state = new _CodegenJavaState(); |  | 
| 104       callback(); |  | 
| 105       writeln('$header {'); |  | 
| 106       indent(() { |  | 
| 107         // fields |  | 
| 108         List<String> allFields = _state.publicFields.values.toList(); |  | 
| 109         allFields.addAll(_state.privateFields.values.toList()); |  | 
| 110         for (String field in allFields) { |  | 
| 111           writeln(); |  | 
| 112           write(field); |  | 
| 113         } |  | 
| 114 |  | 
| 115         // constructors |  | 
| 116         List<String> allConstructors = _state.constructors.values.toList(); |  | 
| 117         for (String constructor in allConstructors) { |  | 
| 118           writeln(); |  | 
| 119           write(constructor); |  | 
| 120         } |  | 
| 121 |  | 
| 122         // methods (ordered by method name) |  | 
| 123         List<String> allMethods = |  | 
| 124             _valuesSortedByKey(_state.publicMethods).toList(); |  | 
| 125         allMethods.addAll(_valuesSortedByKey(_state.privateMethods)); |  | 
| 126         for (String method in allMethods) { |  | 
| 127           writeln(); |  | 
| 128           write(method); |  | 
| 129         } |  | 
| 130         writeln(); |  | 
| 131       }); |  | 
| 132       writeln('}'); |  | 
| 133     } finally { |  | 
| 134       _state = oldState; |  | 
| 135     } |  | 
| 136   } |  | 
| 137 |  | 
| 138   /** |  | 
| 139    * Return a Java type for the given [TypeObjectField]. | 143    * Return a Java type for the given [TypeObjectField]. | 
| 140    */ | 144    */ | 
| 141   String javaFieldType(TypeObjectField field) { | 145   String javaFieldType(TypeObjectField field) { | 
| 142     return javaType(field.type, field.optional); | 146     return javaType(field.type, field.optional); | 
| 143   } | 147   } | 
| 144 | 148 | 
| 145   /** | 149   /** | 
|  | 150    * Return a suitable representation of [name] as the name of a Java variable. | 
|  | 151    */ | 
|  | 152   String javaName(String name) { | 
|  | 153     if (_variableRenames.containsKey(name)) { | 
|  | 154       return _variableRenames[name]; | 
|  | 155     } | 
|  | 156     return name; | 
|  | 157   } | 
|  | 158 | 
|  | 159   /** | 
| 146    * Convert the given [TypeDecl] to a Java type. | 160    * Convert the given [TypeDecl] to a Java type. | 
| 147    */ | 161    */ | 
| 148   String javaType(TypeDecl type, [bool optional = false]) { | 162   String javaType(TypeDecl type, [bool optional = false]) { | 
| 149     if (type is TypeReference) { | 163     if (type is TypeReference) { | 
| 150       TypeReference resolvedType = resolveTypeReferenceChain(type); | 164       TypeReference resolvedType = resolveTypeReferenceChain(type); | 
| 151       String typeName = resolvedType.typeName; | 165       String typeName = resolvedType.typeName; | 
| 152       if (_typeRenames.containsKey(typeName)) { | 166       if (_typeRenames.containsKey(typeName)) { | 
| 153         typeName = _typeRenames[typeName]; | 167         typeName = _typeRenames[typeName]; | 
| 154         if (optional) { | 168         if (optional) { | 
| 155           if (typeName == 'boolean') { | 169           if (typeName == 'boolean') { | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 169     } else if (type is TypeMap) { | 183     } else if (type is TypeMap) { | 
| 170       return 'Map<${javaType(type.keyType)}, ${javaType(type.valueType)}>'; | 184       return 'Map<${javaType(type.keyType)}, ${javaType(type.valueType)}>'; | 
| 171     } else if (type is TypeUnion) { | 185     } else if (type is TypeUnion) { | 
| 172       return 'Object'; | 186       return 'Object'; | 
| 173     } else { | 187     } else { | 
| 174       throw new Exception("Can't make type buildable"); | 188       throw new Exception("Can't make type buildable"); | 
| 175     } | 189     } | 
| 176   } | 190   } | 
| 177 | 191 | 
| 178   /** | 192   /** | 
| 179    * Return true iff the passed [TypeDecl] will represent a primitive Java type. | 193    * Execute [callback], collecting any methods that are output using | 
|  | 194    * [privateMethod] or [publicMethod], and insert the class (with methods | 
|  | 195    * sorted).  [header] is the part of the class declaration before the | 
|  | 196    * opening brace. | 
| 180    */ | 197    */ | 
| 181   bool isPrimitive(TypeDecl type) { | 198   void makeClass(String header, void callback()) { | 
| 182     if (type is TypeReference) { | 199     _CodegenJavaState oldState = _state; | 
| 183       String typeStr = javaType(type); | 200     try { | 
| 184       return typeStr == 'boolean' || typeStr == 'int' || typeStr == 'long'; | 201       _state = new _CodegenJavaState(); | 
|  | 202       callback(); | 
|  | 203       writeln('$header {'); | 
|  | 204       indent(() { | 
|  | 205         // fields | 
|  | 206         List<String> allFields = _state.publicFields.values.toList(); | 
|  | 207         allFields.addAll(_state.privateFields.values.toList()); | 
|  | 208         for (String field in allFields) { | 
|  | 209           writeln(); | 
|  | 210           write(field); | 
|  | 211         } | 
|  | 212 | 
|  | 213         // constructors | 
|  | 214         List<String> allConstructors = _state.constructors.values.toList(); | 
|  | 215         for (String constructor in allConstructors) { | 
|  | 216           writeln(); | 
|  | 217           write(constructor); | 
|  | 218         } | 
|  | 219 | 
|  | 220         // methods (ordered by method name) | 
|  | 221         List<String> allMethods = | 
|  | 222             _valuesSortedByKey(_state.publicMethods).toList(); | 
|  | 223         allMethods.addAll(_valuesSortedByKey(_state.privateMethods)); | 
|  | 224         for (String method in allMethods) { | 
|  | 225           writeln(); | 
|  | 226           write(method); | 
|  | 227         } | 
|  | 228         writeln(); | 
|  | 229       }); | 
|  | 230       writeln('}'); | 
|  | 231     } finally { | 
|  | 232       _state = oldState; | 
| 185     } | 233     } | 
| 186     return false; |  | 
| 187   } | 234   } | 
| 188 | 235 | 
| 189   /** | 236   /** | 
| 190    * Return true iff the passed [TypeDecl] is a type declared in the spec_input. | 237    * Create a private field, using [callback] to create its contents. | 
| 191    */ | 238    */ | 
| 192   bool isDeclaredInSpec(TypeDecl type) { | 239   void privateField(String fieldName, void callback()) { | 
| 193 //    TypeReference resolvedType = super.resolveTypeReferenceChain(type); | 240     _state.privateFields[fieldName] = collectCode(callback); | 
| 194 //    if(resolvedType is TypeObject) { |  | 
| 195 //      return truye; |  | 
| 196 //    } |  | 
| 197     if (type is TypeReference) { |  | 
| 198       return api.types.containsKey(type.typeName) && javaType(type) != 'String'; |  | 
| 199     } |  | 
| 200     return false; |  | 
| 201   } | 241   } | 
| 202 | 242 | 
| 203   /** | 243   /** | 
| 204    * Return true iff the passed [TypeDecl] will be represented as Object in Java
     . | 244    * Create a private method, using [callback] to create its contents. | 
| 205    */ | 245    */ | 
| 206   bool isObject(TypeDecl type) { | 246   void privateMethod(String methodName, void callback()) { | 
| 207     String typeStr = javaType(type); | 247     _state.privateMethods[methodName] = collectCode(callback); | 
| 208     return typeStr == 'Object'; |  | 
| 209   } | 248   } | 
| 210 | 249 | 
| 211   /** | 250   /** | 
| 212    * Return true iff the passed [TypeDecl] will represent an array in Java. | 251    * Create a public field, using [callback] to create its contents. | 
| 213    */ | 252    */ | 
| 214   bool isList(TypeDecl type) { | 253   void publicField(String fieldName, void callback()) { | 
| 215     return type is TypeList && !isPrimitive(type.itemType); | 254     _state.publicFields[fieldName] = collectCode(callback); | 
| 216   } | 255   } | 
| 217 | 256 | 
| 218   /** | 257   /** | 
| 219    * Return true iff the passed [TypeDecl] will represent an array in Java. | 258    * Create a public method, using [callback] to create its contents. | 
| 220    */ | 259    */ | 
| 221   bool isArray(TypeDecl type) { | 260   void publicMethod(String methodName, void callback()) { | 
| 222     return type is TypeList && isPrimitive(type.itemType); | 261     _state.publicMethods[methodName] = collectCode(callback); | 
| 223   } |  | 
| 224 |  | 
| 225   /** |  | 
| 226    * Return true iff the passed [TypeDecl] will represent a Map in type. |  | 
| 227    */ |  | 
| 228   bool isMap(TypeDecl type) { |  | 
| 229     return type is TypeMap; |  | 
| 230   } |  | 
| 231 |  | 
| 232   /** |  | 
| 233    * Return a suitable representation of [name] as the name of a Java variable. |  | 
| 234    */ |  | 
| 235   String javaName(String name) { |  | 
| 236     if (_variableRenames.containsKey(name)) { |  | 
| 237       return _variableRenames[name]; |  | 
| 238     } |  | 
| 239     return name; |  | 
| 240   } | 262   } | 
| 241 | 263 | 
| 242   @override | 264   @override | 
| 243   TypeReference resolveTypeReferenceChain(TypeReference type) { | 265   TypeReference resolveTypeReferenceChain(TypeReference type) { | 
| 244     TypeDecl typeDecl = super.resolveTypeReferenceChain(type); | 266     TypeDecl typeDecl = super.resolveTypeReferenceChain(type); | 
| 245     if (typeDecl is TypeEnum) { | 267     if (typeDecl is TypeEnum) { | 
| 246       return new TypeReference('String', null); | 268       return new TypeReference('String', null); | 
| 247     } | 269     } | 
| 248     return type; | 270     return type; | 
| 249   } | 271   } | 
| 250 } | 272 } | 
| 251 | 273 | 
| 252 /** | 274 /** | 
| 253  * Iterate through the values in [map] in the order of increasing keys. |  | 
| 254  */ |  | 
| 255 Iterable<String> _valuesSortedByKey(Map<String, String> map) { |  | 
| 256   List<String> keys = map.keys.toList(); |  | 
| 257   keys.sort(); |  | 
| 258   return keys.map((String key) => map[key]); |  | 
| 259 } |  | 
| 260 |  | 
| 261 /** |  | 
| 262  * State used by [CodegenJavaVisitor]. | 275  * State used by [CodegenJavaVisitor]. | 
| 263  */ | 276  */ | 
| 264 class _CodegenJavaState { | 277 class _CodegenJavaState { | 
| 265   /** | 278   /** | 
| 266    * Temporary storage for public methods. | 279    * Temporary storage for public methods. | 
| 267    */ | 280    */ | 
| 268   Map<String, String> publicMethods = <String, String>{}; | 281   Map<String, String> publicMethods = <String, String>{}; | 
| 269 | 282 | 
| 270   /** | 283   /** | 
| 271    * Temporary storage for private methods. | 284    * Temporary storage for private methods. | 
| 272    */ | 285    */ | 
| 273   Map<String, String> privateMethods = <String, String>{}; | 286   Map<String, String> privateMethods = <String, String>{}; | 
| 274 | 287 | 
| 275   /** | 288   /** | 
| 276    * Temporary storage for public fields. | 289    * Temporary storage for public fields. | 
| 277    */ | 290    */ | 
| 278   Map<String, String> publicFields = <String, String>{}; | 291   Map<String, String> publicFields = <String, String>{}; | 
| 279 | 292 | 
| 280   /** | 293   /** | 
| 281    * Temporary storage for private fields. | 294    * Temporary storage for private fields. | 
| 282    */ | 295    */ | 
| 283   Map<String, String> privateFields = <String, String>{}; | 296   Map<String, String> privateFields = <String, String>{}; | 
| 284 | 297 | 
| 285   /** | 298   /** | 
| 286    * Temporary storage for constructors. | 299    * Temporary storage for constructors. | 
| 287    */ | 300    */ | 
| 288   Map<String, String> constructors = <String, String>{}; | 301   Map<String, String> constructors = <String, String>{}; | 
| 289 } | 302 } | 
| 290 |  | 
| 291 /** |  | 
| 292  * Create a [GeneratedFile] that creates Java code and outputs it to [path]. |  | 
| 293  * [path] uses Posix-style path separators regardless of the OS. |  | 
| 294  */ |  | 
| 295 GeneratedFile javaGeneratedFile(String path, CodegenJavaVisitor |  | 
| 296     createVisitor(Api api)) { |  | 
| 297   return new GeneratedFile(path, () { |  | 
| 298     CodegenJavaVisitor visitor = createVisitor(readApi()); |  | 
| 299     return visitor.collectCode(visitor.visitApi); |  | 
| 300   }); |  | 
| 301 } |  | 
| OLD | NEW | 
|---|