// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. /** * Tools for Java code generation. */ library CodegenJava; import 'api.dart'; import 'codegen_tools.dart'; import 'from_html.dart'; import 'to_html.dart'; /** * Common code for all Java code generation. */ class CodegenJavaVisitor extends HierarchicalApiVisitor with CodeGenerator { _CodegenJavaState _state; /** * Variable names which must be changed in order to avoid conflict with * reserved words in Java. */ static const Map _variableRenames = const { 'default': 'defaultSdk' }; /** * Type references in the spec that are named something else in Java. */ static const Map _typeRenames = const { 'bool': 'boolean', 'FilePath': 'String', 'DebugContextId': 'String', 'object': 'Object', }; /** * Visitor used to produce doc comments. */ final ToHtmlVisitor toHtmlVisitor; CodegenJavaVisitor(Api api) : super(api), toHtmlVisitor = new ToHtmlVisitor(api); /** * Create a private method, using [callback] to create its contents. */ void privateMethod(String methodName, void callback()) { _state.privateMethods[methodName] = collectCode(callback); } /** * Create a public method, using [callback] to create its contents. */ void publicMethod(String methodName, void callback()) { _state.publicMethods[methodName] = collectCode(callback); } /** * Execute [callback], collecting any methods that are output using * [privateMethod] or [publicMethod], and insert the class (with methods * sorted). [header] is the part of the class declaration before the * opening brace. */ void makeClass(String header, void callback()) { _CodegenJavaState oldState = _state; try { _state = new _CodegenJavaState(); callback(); writeln('$header {'); indent(() { List allMethods = _valuesSortedByKey(_state.publicMethods).toList(); allMethods.addAll(_valuesSortedByKey(_state.privateMethods)); for (String method in allMethods) { writeln(); write(method); } }); writeln('}'); } finally { _state = oldState; } } /** * Convert the given [TypeDecl] to a Java type. */ String javaType(TypeDecl type) { if (type is TypeReference) { TypeReference resolvedType = resolveTypeReferenceChain(type); String typeName = resolvedType.typeName; if (_typeRenames.containsKey(typeName)) { return _typeRenames[typeName]; } else { return typeName; } } else if (type is TypeList) { return 'List<${javaType(type.itemType)}>'; } else if (type is TypeMap) { return 'Map<${javaType(type.keyType)}, ${javaType(type.valueType)}>'; } else if (type is TypeUnion) { return 'Object'; } else { throw new Exception("Can't make type buildable"); } } /** * Return a suitable representation of [name] as the name of a Java variable. */ String javaName(String name) { if (_variableRenames.containsKey(name)) { return _variableRenames[name]; } return name; } @override TypeReference resolveTypeReferenceChain(TypeReference type) { TypeDecl typeDecl = super.resolveTypeReferenceChain(type); if (typeDecl is TypeEnum) { return new TypeReference('String', null); } return type; } } /** * Iterate through the values in [map] in the order of increasing keys. */ Iterable _valuesSortedByKey(Map map) { List keys = map.keys.toList(); keys.sort(); return keys.map((String key) => map[key]); } /** * State used by [CodegenJavaVisitor]. */ class _CodegenJavaState { /** * Temporary storage for public methods. */ Map publicMethods = {}; /** * Temporary storage for private methods. */ Map privateMethods = {}; } /** * Create a [GeneratedFile] that creates Java code and outputs it to [path]. * [path] uses Posix-style path separators regardless of the OS. */ GeneratedFile javaGeneratedFile(String path, CodegenJavaVisitor createVisitor(Api api)) { return new GeneratedFile(path, () { CodegenJavaVisitor visitor = createVisitor(readApi()); return visitor.collectCode(visitor.visitApi); }); }