blob: f464eeec52cc3e210193505fe678231da0854b8b [file] [log] [blame]
// 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 'dart:io';
import 'api.dart';
import 'codegen_tools.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<String, String> _variableRenames = const {
'default': 'defaultSdk'
};
/**
* Type references in the spec that are named something else in Java.
*/
static const Map<String, String> _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<String> 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 {
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<String> _valuesSortedByKey(Map<String, String> map) {
List<String> 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<String, String> publicMethods = <String, String>{};
/**
* Temporary storage for private methods.
*/
Map<String, String> privateMethods = <String, String>{};
}
/**
* Use [visitor] to create Java code and output it to [path].
*/
void createJavaCode(String path, CodegenJavaVisitor visitor) {
String code = visitor.collectCode(visitor.visitApi);
File outputFile = new File(path);
outputFile.writeAsStringSync(code);
}