|  | // 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 = []; | 
|  |  | 
|  | indented(action) {  // TODO: revert to  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(); | 
|  | } |