// 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(); }