| // 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. |
| |
| /** |
| * Code generation for the file "AnalysisServer.java". |
| */ |
| import 'package:analyzer/src/codegen/tools.dart'; |
| import 'package:front_end/src/codegen/tools.dart'; |
| import 'package:html/dom.dart' as dom; |
| |
| import 'api.dart'; |
| import 'codegen_java.dart'; |
| import 'from_html.dart'; |
| import 'implied_types.dart'; |
| |
| /** |
| * A map between the field names and values for the Element object such as: |
| * |
| * private static final int ABSTRACT = 0x01; |
| */ |
| const Map<String, String> _extraFieldsOnElement = const { |
| 'ABSTRACT': '0x01', |
| 'CONST': '0x02', |
| 'FINAL': '0x04', |
| 'TOP_LEVEL_STATIC': '0x08', |
| 'PRIVATE': '0x10', |
| 'DEPRECATED': '0x20', |
| }; |
| |
| /** |
| * A map between the method names and field names to generate additional methods on the Element object: |
| * |
| * public boolean isFinal() { |
| * return (flags & FINAL) != 0; |
| * } |
| */ |
| const Map<String, String> _extraMethodsOnElement = const { |
| 'isAbstract': 'ABSTRACT', |
| 'isConst': 'CONST', |
| 'isDeprecated': 'DEPRECATED', |
| 'isFinal': 'FINAL', |
| 'isPrivate': 'PRIVATE', |
| 'isTopLevelOrStatic': 'TOP_LEVEL_STATIC', |
| }; |
| |
| /** |
| * Type references in the spec that are named something else in Java. |
| */ |
| const Map<String, String> _typeRenames = const { |
| 'Override': 'OverrideMember', |
| }; |
| |
| final String pathToGenTypes = 'tool/spec/generated/java/types'; |
| |
| final GeneratedDirectory targetDir = |
| new GeneratedDirectory(pathToGenTypes, (String pkgPath) { |
| Api api = readApi(pkgPath); |
| Map<String, ImpliedType> impliedTypes = computeImpliedTypes(api); |
| Map<String, FileContentsComputer> map = |
| new Map<String, FileContentsComputer>(); |
| for (ImpliedType impliedType in impliedTypes.values) { |
| String typeNameInSpec = capitalize(impliedType.camelName); |
| bool isRefactoringFeedback = impliedType.kind == 'refactoringFeedback'; |
| bool isRefactoringOption = impliedType.kind == 'refactoringOptions'; |
| if (impliedType.kind == 'typeDefinition' || |
| isRefactoringFeedback || |
| isRefactoringOption) { |
| TypeDecl type = impliedType.type; |
| if (type is TypeObject || type is TypeEnum) { |
| // This is for situations such as 'Override' where the name in the spec |
| // doesn't match the java object that we generate: |
| String typeNameInJava = typeNameInSpec; |
| if (_typeRenames.containsKey(typeNameInSpec)) { |
| typeNameInJava = _typeRenames[typeNameInSpec]; |
| } |
| map['$typeNameInJava.java'] = (String pkgPath) async { |
| String superclassName = null; |
| if (isRefactoringFeedback) { |
| superclassName = 'RefactoringFeedback'; |
| } |
| if (isRefactoringOption) { |
| superclassName = 'RefactoringOptions'; |
| } |
| // configure accessors |
| bool generateGetters = true; |
| bool generateSetters = false; |
| if (isRefactoringOption || |
| typeNameInSpec == 'Outline' || |
| typeNameInSpec == 'RefactoringMethodParameter') { |
| generateSetters = true; |
| } |
| // create the visitor |
| CodegenJavaType visitor = new CodegenJavaType(api, typeNameInJava, |
| superclassName, generateGetters, generateSetters); |
| return visitor.collectCode(() { |
| dom.Element doc = type.html; |
| if (impliedType.apiNode is TypeDefinition) { |
| doc = (impliedType.apiNode as TypeDefinition).html; |
| } |
| visitor.emitType(type, doc); |
| }); |
| }; |
| } |
| } |
| } |
| return map; |
| }); |
| |
| class CodegenJavaType extends CodegenJavaVisitor { |
| final String className; |
| final String superclassName; |
| final bool generateGetters; |
| final bool generateSetters; |
| |
| CodegenJavaType(Api api, this.className, this.superclassName, |
| this.generateGetters, this.generateSetters) |
| : super(api); |
| |
| /** |
| * Get the name of the consumer class for responses to this request. |
| */ |
| String consumerName(Request request) { |
| return camelJoin([request.method, 'consumer'], doCapitalize: true); |
| } |
| |
| void emitType(TypeDecl type, dom.Element html) { |
| outputHeader(javaStyle: true); |
| writeln('package org.dartlang.analysis.server.protocol;'); |
| writeln(); |
| if (type is TypeObject) { |
| _writeTypeObject(type, html); |
| } else if (type is TypeEnum) { |
| _writeTypeEnum(type, html); |
| } |
| } |
| |
| String _getAsTypeMethodName(TypeDecl typeDecl) { |
| String name = javaType(typeDecl, true); |
| if (name == 'String') { |
| return 'getAsString'; |
| } else if (name == 'boolean' || name == 'Boolean') { |
| return 'getAsBoolean'; |
| } else if (name == 'int' || name == 'Integer') { |
| return 'getAsInt'; |
| } else if (name == 'long' || name == 'Long') { |
| return 'getAsLong'; |
| } else if (name.startsWith('List')) { |
| return 'getAsJsonArray'; |
| } else { |
| // TODO (jwren) cleanup |
| return 'getAsJsonArray'; |
| } |
| } |
| |
| String _getEqualsLogicForField(TypeObjectField field, String other) { |
| String name = javaName(field.name); |
| if (isPrimitive(field.type) && !field.optional) { |
| return '$other.$name == $name'; |
| } else if (isArray(field.type)) { |
| return 'Arrays.equals(other.$name, $name)'; |
| } else { |
| return 'ObjectUtilities.equals($other.$name, $name)'; |
| } |
| } |
| |
| /** |
| * For some [TypeObjectField] return the [String] source for the field value |
| * for the toString generation. |
| */ |
| String _getToStringForField(TypeObjectField field) { |
| String name = javaName(field.name); |
| if (isArray(field.type) || isList(field.type)) { |
| return 'StringUtils.join($name, ", ")'; |
| } else { |
| return name; |
| } |
| } |
| |
| bool _isTypeFieldInUpdateContentUnionType( |
| String className, String fieldName) { |
| if ((className == 'AddContentOverlay' || |
| className == 'ChangeContentOverlay' || |
| className == 'RemoveContentOverlay') && |
| fieldName == 'type') { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| /** |
| * This method writes extra fields and methods to the Element type. |
| */ |
| void _writeExtraContentInElementType() { |
| // |
| // Extra fields on the Element type such as: |
| // private static final int ABSTRACT = 0x01; |
| // |
| _extraFieldsOnElement.forEach((String name, String value) { |
| publicField(javaName(name), () { |
| writeln('private static final int $name = $value;'); |
| }); |
| }); |
| |
| // |
| // Extra methods for the Element type such as: |
| // public boolean isFinal() { |
| // return (flags & FINAL) != 0; |
| // } |
| // |
| _extraMethodsOnElement.forEach((String methodName, String fieldName) { |
| publicMethod(methodName, () { |
| writeln('public boolean $methodName() {'); |
| writeln(' return (flags & $fieldName) != 0;'); |
| writeln('}'); |
| }); |
| }); |
| } |
| |
| /** |
| * For some [TypeObjectField] write out the source that adds the field |
| * information to the 'jsonObject'. |
| */ |
| void _writeOutJsonObjectAddStatement(TypeObjectField field) { |
| String name = javaName(field.name); |
| if (isDeclaredInSpec(field.type)) { |
| writeln('jsonObject.add("$name", $name.toJson());'); |
| } else if (field.type is TypeList) { |
| TypeDecl listItemType = (field.type as TypeList).itemType; |
| String jsonArrayName = 'jsonArray${capitalize(name)}'; |
| writeln('JsonArray $jsonArrayName = new JsonArray();'); |
| writeln('for (${javaType(listItemType)} elt : $name) {'); |
| indent(() { |
| if (isDeclaredInSpec(listItemType)) { |
| writeln('$jsonArrayName.add(elt.toJson());'); |
| } else { |
| writeln('$jsonArrayName.add(new JsonPrimitive(elt));'); |
| } |
| }); |
| writeln('}'); |
| writeln('jsonObject.add("$name", $jsonArrayName);'); |
| } else { |
| writeln('jsonObject.addProperty("$name", $name);'); |
| } |
| } |
| |
| void _writeTypeEnum(TypeDecl type, dom.Element html) { |
| javadocComment(toHtmlVisitor.collectHtml(() { |
| toHtmlVisitor.translateHtml(html); |
| toHtmlVisitor.br(); |
| toHtmlVisitor.write('@coverage dart.server.generated.types'); |
| })); |
| makeClass('public class $className', () { |
| TypeEnum typeEnum = type as TypeEnum; |
| List<TypeEnumValue> values = typeEnum.values; |
| // |
| // enum fields |
| // |
| for (TypeEnumValue value in values) { |
| privateField(javaName(value.value), () { |
| javadocComment(toHtmlVisitor.collectHtml(() { |
| toHtmlVisitor.translateHtml(value.html); |
| })); |
| writeln( |
| 'public static final String ${value.value} = \"${value.value}\";'); |
| }); |
| } |
| }); |
| } |
| |
| void _writeTypeObject(TypeDecl type, dom.Element html) { |
| writeln('import java.util.Arrays;'); |
| writeln('import java.util.List;'); |
| writeln('import java.util.Map;'); |
| writeln('import com.google.common.collect.Lists;'); |
| writeln('import com.google.dart.server.utilities.general.JsonUtilities;'); |
| writeln('import com.google.dart.server.utilities.general.ObjectUtilities;'); |
| writeln('import com.google.gson.JsonArray;'); |
| writeln('import com.google.gson.JsonElement;'); |
| writeln('import com.google.gson.JsonObject;'); |
| writeln('import com.google.gson.JsonPrimitive;'); |
| writeln('import org.apache.commons.lang3.builder.HashCodeBuilder;'); |
| writeln('import java.util.ArrayList;'); |
| writeln('import java.util.Iterator;'); |
| writeln('import org.apache.commons.lang3.StringUtils;'); |
| writeln(); |
| javadocComment(toHtmlVisitor.collectHtml(() { |
| toHtmlVisitor.translateHtml(html); |
| toHtmlVisitor.br(); |
| toHtmlVisitor.write('@coverage dart.server.generated.types'); |
| })); |
| writeln('@SuppressWarnings("unused")'); |
| String header = 'public class $className'; |
| if (superclassName != null) { |
| header += ' extends $superclassName'; |
| } |
| makeClass(header, () { |
| // |
| // fields |
| // |
| // |
| // public static final "EMPTY_ARRAY" field |
| // |
| publicField(javaName("EMPTY_ARRAY"), () { |
| writeln( |
| 'public static final $className[] EMPTY_ARRAY = new $className[0];'); |
| }); |
| |
| // |
| // public static final "EMPTY_LIST" field |
| // |
| publicField(javaName("EMPTY_LIST"), () { |
| writeln( |
| 'public static final List<$className> EMPTY_LIST = Lists.newArrayList();'); |
| }); |
| |
| // |
| // "private static String name;" fields: |
| // |
| TypeObject typeObject = type as TypeObject; |
| List<TypeObjectField> fields = typeObject.fields; |
| for (TypeObjectField field in fields) { |
| String type = javaFieldType(field); |
| String name = javaName(field.name); |
| if (!(className == 'Outline' && name == 'children')) { |
| privateField(name, () { |
| javadocComment(toHtmlVisitor.collectHtml(() { |
| toHtmlVisitor.translateHtml(field.html); |
| })); |
| if (generateSetters) { |
| writeln('private $type $name;'); |
| } else { |
| writeln('private final $type $name;'); |
| } |
| }); |
| } |
| } |
| if (className == 'Outline') { |
| privateField(javaName('parent'), () { |
| writeln('private final Outline parent;'); |
| }); |
| privateField(javaName('children'), () { |
| writeln('private List<Outline> children;'); |
| }); |
| } |
| if (className == 'NavigationRegion') { |
| privateField(javaName('targetObjects'), () { |
| writeln( |
| 'private final List<NavigationTarget> targetObjects = Lists.newArrayList();'); |
| }); |
| } |
| if (className == 'NavigationTarget') { |
| privateField(javaName('file'), () { |
| writeln('private String file;'); |
| }); |
| } |
| |
| // |
| // constructor |
| // |
| constructor(className, () { |
| javadocComment(toHtmlVisitor.collectHtml(() { |
| toHtmlVisitor.write('Constructor for {@link $className}.'); |
| })); |
| write('public $className('); |
| // write out parameters to constructor |
| List<String> parameters = new List(); |
| if (className == 'Outline') { |
| parameters.add('Outline parent'); |
| } |
| for (TypeObjectField field in fields) { |
| String type = javaFieldType(field); |
| String name = javaName(field.name); |
| if (!_isTypeFieldInUpdateContentUnionType(className, field.name) && |
| !(className == 'Outline' && name == 'children')) { |
| parameters.add('$type $name'); |
| } |
| } |
| write(parameters.join(', ')); |
| writeln(') {'); |
| // write out the assignments in the body of the constructor |
| indent(() { |
| if (className == 'Outline') { |
| writeln('this.parent = parent;'); |
| } |
| for (TypeObjectField field in fields) { |
| String name = javaName(field.name); |
| if (!_isTypeFieldInUpdateContentUnionType(className, field.name) && |
| !(className == 'Outline' && name == 'children')) { |
| writeln('this.$name = $name;'); |
| } else if (className == 'AddContentOverlay') { |
| writeln('this.type = "add";'); |
| } else if (className == 'ChangeContentOverlay') { |
| writeln('this.type = "change";'); |
| } else if (className == 'RemoveContentOverlay') { |
| writeln('this.type = "remove";'); |
| } |
| } |
| }); |
| writeln('}'); |
| }); |
| |
| // |
| // getter methods |
| // |
| if (generateGetters) { |
| for (TypeObjectField field in fields) { |
| String type = javaFieldType(field); |
| String name = javaName(field.name); |
| publicMethod('get$name', () { |
| javadocComment(toHtmlVisitor.collectHtml(() { |
| toHtmlVisitor.translateHtml(field.html); |
| })); |
| if (type == 'boolean') { |
| writeln('public $type $name() {'); |
| } else { |
| writeln('public $type get${capitalize(name)}() {'); |
| } |
| writeln(' return $name;'); |
| writeln('}'); |
| }); |
| } |
| } |
| |
| // |
| // setter methods |
| // |
| if (generateSetters) { |
| for (TypeObjectField field in fields) { |
| String type = javaFieldType(field); |
| String name = javaName(field.name); |
| publicMethod('set$name', () { |
| javadocComment(toHtmlVisitor.collectHtml(() { |
| toHtmlVisitor.translateHtml(field.html); |
| })); |
| String setterName = 'set' + capitalize(name); |
| writeln('public void $setterName($type $name) {'); |
| writeln(' this.$name = $name;'); |
| writeln('}'); |
| }); |
| } |
| } |
| |
| if (className == 'NavigationRegion') { |
| publicMethod('lookupTargets', () { |
| writeln( |
| 'public void lookupTargets(List<NavigationTarget> allTargets) {'); |
| writeln(' for (int i = 0; i < targets.length; i++) {'); |
| writeln(' int targetIndex = targets[i];'); |
| writeln(' NavigationTarget target = allTargets.get(targetIndex);'); |
| writeln(' targetObjects.add(target);'); |
| writeln(' }'); |
| writeln('}'); |
| }); |
| publicMethod('getTargetObjects', () { |
| writeln('public List<NavigationTarget> getTargetObjects() {'); |
| writeln(' return targetObjects;'); |
| writeln('}'); |
| }); |
| } |
| if (className == 'NavigationTarget') { |
| publicMethod('lookupFile', () { |
| writeln('public void lookupFile(String[] allTargetFiles) {'); |
| writeln(' file = allTargetFiles[fileIndex];'); |
| writeln('}'); |
| }); |
| publicMethod('getFile', () { |
| writeln('public String getFile() {'); |
| writeln(' return file;'); |
| writeln('}'); |
| }); |
| } |
| |
| // |
| // fromJson(JsonObject) factory constructor, example: |
| // public JsonObject toJson(JsonObject jsonObject) { |
| // String x = jsonObject.get("x").getAsString(); |
| // return new Y(x); |
| // } |
| if (className != 'Outline') { |
| publicMethod('fromJson', () { |
| writeln('public static $className fromJson(JsonObject jsonObject) {'); |
| indent(() { |
| for (TypeObjectField field in fields) { |
| write('${javaFieldType(field)} ${javaName(field.name)} = '); |
| if (field.optional) { |
| write( |
| 'jsonObject.get("${javaName(field.name)}") == null ? null : '); |
| } |
| if (isDeclaredInSpec(field.type)) { |
| write('${javaFieldType(field)}.fromJson('); |
| write( |
| 'jsonObject.get("${javaName(field.name)}").getAsJsonObject())'); |
| } else { |
| if (isList(field.type)) { |
| if (javaFieldType(field).endsWith('<String>')) { |
| write( |
| 'JsonUtilities.decodeStringList(jsonObject.get("${javaName(field.name)}").${_getAsTypeMethodName(field.type)}())'); |
| } else { |
| write( |
| '${javaType((field.type as TypeList).itemType)}.fromJsonArray(jsonObject.get("${javaName(field.name)}").${_getAsTypeMethodName(field.type)}())'); |
| } |
| } else if (isArray(field.type)) { |
| if (javaFieldType(field).startsWith('int')) { |
| write( |
| 'JsonUtilities.decodeIntArray(jsonObject.get("${javaName(field.name)}").${_getAsTypeMethodName(field.type)}())'); |
| } |
| } else { |
| write( |
| 'jsonObject.get("${javaName(field.name)}").${_getAsTypeMethodName(field.type)}()'); |
| } |
| } |
| writeln(';'); |
| } |
| write('return new $className('); |
| List<String> parameters = new List(); |
| for (TypeObjectField field in fields) { |
| if (!_isTypeFieldInUpdateContentUnionType( |
| className, field.name)) { |
| parameters.add('${javaName(field.name)}'); |
| } |
| } |
| write(parameters.join(', ')); |
| writeln(');'); |
| }); |
| writeln('}'); |
| }); |
| } else { |
| publicMethod('fromJson', () { |
| writeln( |
| '''public static Outline fromJson(Outline parent, JsonObject outlineObject) { |
| JsonObject elementObject = outlineObject.get("element").getAsJsonObject(); |
| Element element = Element.fromJson(elementObject); |
| int offset = outlineObject.get("offset").getAsInt(); |
| int length = outlineObject.get("length").getAsInt(); |
| |
| // create outline object |
| Outline outline = new Outline(parent, element, offset, length); |
| |
| // compute children recursively |
| List<Outline> childrenList = Lists.newArrayList(); |
| JsonElement childrenJsonArray = outlineObject.get("children"); |
| if (childrenJsonArray instanceof JsonArray) { |
| Iterator<JsonElement> childrenElementIterator = ((JsonArray) childrenJsonArray).iterator(); |
| while (childrenElementIterator.hasNext()) { |
| JsonObject childObject = childrenElementIterator.next().getAsJsonObject(); |
| childrenList.add(fromJson(outline, childObject)); |
| } |
| } |
| outline.setChildren(childrenList); |
| return outline; |
| }'''); |
| }); |
| publicMethod('getParent', () { |
| writeln('''public Outline getParent() { |
| return parent; |
| }'''); |
| }); |
| } |
| |
| // |
| // fromJson(JsonArray) factory constructor |
| // |
| if (className != 'Outline' && |
| className != 'RefactoringFeedback' && |
| className != 'RefactoringOptions') { |
| publicMethod('fromJsonArray', () { |
| writeln( |
| 'public static List<$className> fromJsonArray(JsonArray jsonArray) {'); |
| indent(() { |
| writeln('if (jsonArray == null) {'); |
| writeln(' return EMPTY_LIST;'); |
| writeln('}'); |
| writeln( |
| 'ArrayList<$className> list = new ArrayList<$className>(jsonArray.size());'); |
| writeln('Iterator<JsonElement> iterator = jsonArray.iterator();'); |
| writeln('while (iterator.hasNext()) {'); |
| writeln(' list.add(fromJson(iterator.next().getAsJsonObject()));'); |
| writeln('}'); |
| writeln('return list;'); |
| }); |
| writeln('}'); |
| }); |
| } |
| |
| // |
| // toJson() method, example: |
| // public JsonObject toJson() { |
| // JsonObject jsonObject = new JsonObject(); |
| // jsonObject.addProperty("x", x); |
| // jsonObject.addProperty("y", y); |
| // return jsonObject; |
| // } |
| if (className != 'Outline') { |
| publicMethod('toJson', () { |
| writeln('public JsonObject toJson() {'); |
| indent(() { |
| writeln('JsonObject jsonObject = new JsonObject();'); |
| for (TypeObjectField field in fields) { |
| if (!isObject(field.type)) { |
| if (field.optional) { |
| writeln('if (${javaName(field.name)} != null) {'); |
| indent(() { |
| _writeOutJsonObjectAddStatement(field); |
| }); |
| writeln('}'); |
| } else { |
| _writeOutJsonObjectAddStatement(field); |
| } |
| } |
| } |
| writeln('return jsonObject;'); |
| }); |
| writeln('}'); |
| }); |
| } |
| |
| // |
| // equals() method |
| // |
| publicMethod('equals', () { |
| writeln('@Override'); |
| writeln('public boolean equals(Object obj) {'); |
| indent(() { |
| writeln('if (obj instanceof $className) {'); |
| indent(() { |
| writeln('$className other = ($className) obj;'); |
| writeln('return'); |
| indent(() { |
| List<String> equalsForField = new List<String>(); |
| for (TypeObjectField field in fields) { |
| equalsForField.add(_getEqualsLogicForField(field, 'other')); |
| } |
| if (equalsForField.isNotEmpty) { |
| write(equalsForField.join(' && \n')); |
| } else { |
| write('true'); |
| } |
| }); |
| writeln(';'); |
| }); |
| writeln('}'); |
| writeln('return false;'); |
| }); |
| writeln('}'); |
| }); |
| |
| // |
| // containsInclusive(int x) |
| // |
| if (className == 'HighlightRegion' || |
| className == 'NavigationRegion' || |
| className == 'Outline') { |
| publicMethod('containsInclusive', () { |
| writeln('public boolean containsInclusive(int x) {'); |
| indent(() { |
| writeln('return offset <= x && x <= offset + length;'); |
| }); |
| writeln('}'); |
| }); |
| } |
| |
| // |
| // contains(int x) |
| // |
| if (className == 'Occurrences') { |
| publicMethod('containsInclusive', () { |
| writeln('public boolean containsInclusive(int x) {'); |
| indent(() { |
| writeln('for (int offset : offsets) {'); |
| writeln(' if (offset <= x && x <= offset + length) {'); |
| writeln(' return true;'); |
| writeln(' }'); |
| writeln('}'); |
| writeln('return false;'); |
| }); |
| writeln('}'); |
| }); |
| } |
| |
| // |
| // hashCode |
| // |
| publicMethod('hashCode', () { |
| writeln('@Override'); |
| writeln('public int hashCode() {'); |
| indent(() { |
| writeln('HashCodeBuilder builder = new HashCodeBuilder();'); |
| for (int i = 0; i < fields.length; i++) { |
| writeln("builder.append(${javaName(fields[i].name)});"); |
| } |
| writeln('return builder.toHashCode();'); |
| }); |
| writeln('}'); |
| }); |
| |
| // |
| // toString |
| // |
| publicMethod('toString', () { |
| writeln('@Override'); |
| writeln('public String toString() {'); |
| indent(() { |
| writeln('StringBuilder builder = new StringBuilder();'); |
| writeln('builder.append(\"[\");'); |
| for (int i = 0; i < fields.length; i++) { |
| writeln("builder.append(\"${javaName(fields[i].name)}=\");"); |
| write("builder.append(${_getToStringForField(fields[i])}"); |
| if (i + 1 != fields.length) { |
| // this is not the last field |
| write(' + \", \"'); |
| } |
| writeln(');'); |
| } |
| writeln('builder.append(\"]\");'); |
| writeln('return builder.toString();'); |
| }); |
| writeln('}'); |
| }); |
| |
| if (className == 'Element') { |
| _writeExtraContentInElementType(); |
| } |
| |
| // |
| // getBestName() |
| // |
| if (className == 'TypeHierarchyItem') { |
| publicMethod('getBestName', () { |
| writeln('public String getBestName() {'); |
| indent(() { |
| writeln('if (displayName == null) {'); |
| writeln(' return classElement.getName();'); |
| writeln('} else {'); |
| writeln(' return displayName;'); |
| writeln('}'); |
| }); |
| writeln('}'); |
| }); |
| } |
| }); |
| } |
| } |