blob: 75a77a0222848cc186b2ee126b730eced516d591 [file] [log] [blame]
// Copyright (c) 2011, 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.
List sorted(Iterable input, [compare, key]) {
comparator(compare, key) {
if (compare == null && key == null) return (a, b) => a.compareTo(b);
if (compare == null) return (a, b) => key(a).compareTo(key(b));
if (key == null) return compare;
return (a, b) => compare(key(a), key(b));
}
List copy = new List.from(input);
copy.sort(comparator(compare, key));
return copy;
}
render(idl_node, [indent_str = ' ']) {
var output = [''];
var indent_stack = [];
// TODO: revert to indented(action()) {
indented(action) {
indent_stack.add(indent_str);
action();
indent_stack.removeLast();
}
sort(nodes) => sorted(nodes, key: (a) => a.id);
var w; // For some reason mutually recursive local functions don't work.
wln([node]) {
w(node);
output.add('\n');
}
w = (node, [list_separator]) {
/*
Writes the given node.
Args:
node -- a string, IDLNode instance or a list of such.
list_separator -- if provided, and node is a list,
list_separator will be written between the list items.
*/
if (node == null) {
return;
} else if (node is String) {
if (output.last.endsWith('\n')) output.addAll(indent_stack);
output.add(node);
} else if (node is List) {
var separator = null;
for (var element in node) {
w(separator);
separator = list_separator;
w(element);
}
} else if (node is IDLFile) {
w(node.modules);
w(node.interfaces);
} else if (node is IDLModule) {
w(node.annotations);
w(node.extAttrs);
wln('module ${node.id} {');
indented(() {
w(node.interfaces);
w(node.typedefs);
});
wln('};');
} else if (node is IDLInterface) {
w(node.annotations);
w(node.extAttrs);
w('interface ${node.id}');
indented(() {
if (!node.parents.isEmpty) {
wln(' :');
w(node.parents, ',\n');
}
wln(' {');
section(list, comment) {
if (list != null && !list.isEmpty) {
wln();
wln(comment);
w(sort(list));
}
}
section(node.constants, '/* Constants */');
section(node.attributes, '/* Attributes */');
section(node.operations, '/* Operations */');
section(node.snippets, '/* Snippets */');
});
wln('};');
} else if (node is IDLParentInterface) {
w(node.annotations);
w(node.type.id);
} else if (node is IDLAnnotations) {
for (var name in sorted(node.map.keys)) {
IDLAnnotation annotation = node.map[name];
var args = annotation.map;
if (args.isEmpty) {
w('@$name');
} else {
var formattedArgs = [];
for (var argName in sorted(args.keys)) {
var argValue = args[argName];
if (argValue == null)
formattedArgs.add(argName);
else
formattedArgs.add('$argName=$argValue');
}
w('@$name(${formattedArgs.join(',')})');
}
w(' ');
}
} else if (node is IDLExtAttrs) {
if (!node.map.isEmpty) {
w('[');
var sep = null;
for (var name in sorted(node.map.keys)) {
w(sep);
sep = ', ';
w(name);
var value = node.map[name];
if (value != null) {
w('=');
w(value);
}
}
w('] ');
}
} else if (node is IDLAttribute) {
w(node.annotations);
w(node.extAttrs);
//if (node.isFcGetter)
// w('getter ');
//if (node.isFcSetter)
// w('setter ');
wln('attribute ${node.type.id} ${node.id};');
} else if (node is IDLConstant) {
w(node.annotations);
w(node.extAttrs);
wln('const ${node.type.id} ${node.id} = ${node.value};');
} else if (node is IDLSnippet) {
w(node.annotations);
wln('snippet {${node.text}};');
} else if (node is IDLOperation) {
w(node.annotations);
w(node.extAttrs);
if (node.specials != null && !node.specials.isEmpty) {
w(node.specials, ' ');
w(' ');
}
w('${node.type.id} ${node.id}');
w('(');
w(node.arguments, ', ');
wln(');');
} else if (node is IDLArgument) {
w(node.extAttrs);
w('in ');
if (node.isOptional) w('optional ');
w('${node.type.id} ${node.id}');
} else if (node is IDLExtAttrFunctionValue) {
w(node.name);
w('(');
w(node.arguments, ', ');
w(')');
} else if (node is IDLTypeDef) {
wln('typedef ${node.type.id} ${node.id};');
} else {
w('// $node\n');
}
};
w(idl_node);
return output.join();
}