| OLD | NEW |
| 1 #! /usr/bin/env python | 1 #! /usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 import itertools | 6 import itertools |
| 7 import json | 7 import json |
| 8 import os.path | 8 import os.path |
| 9 import pprint | 9 import pprint |
| 10 import re | 10 import re |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 to other arguments. | 43 to other arguments. |
| 44 |arg2_name|: Description of arg2... | 44 |arg2_name|: Description of arg2... |
| 45 | 45 |
| 46 Newlines are removed, and leading and trailing whitespace is stripped. | 46 Newlines are removed, and leading and trailing whitespace is stripped. |
| 47 | 47 |
| 48 Args: | 48 Args: |
| 49 comment: The string from a Comment node. | 49 comment: The string from a Comment node. |
| 50 | 50 |
| 51 Returns: A tuple that looks like: | 51 Returns: A tuple that looks like: |
| 52 ( | 52 ( |
| 53 "The processed comment, minus all |parameter| mentions.", | 53 "The processed comment, minus all |parameter| mentions and jsexterns.", |
| 54 "Any block wrapped in <jsexterns></jsexterns>.", |
| 54 { | 55 { |
| 55 'parameter_name_1': "The comment that followed |parameter_name_1|:", | 56 'parameter_name_1': "The comment that followed |parameter_name_1|:", |
| 56 ... | 57 ... |
| 57 } | 58 } |
| 58 ) | 59 ) |
| 59 ''' | 60 ''' |
| 61 jsexterns = None |
| 62 match = re.search('<jsexterns>(.*)</jsexterns>', comment, re.DOTALL) |
| 63 if match: |
| 64 jsexterns = match.group(1).strip() |
| 65 comment = comment[:match.start()] + comment[match.end():] |
| 66 |
| 60 def add_paragraphs(content): | 67 def add_paragraphs(content): |
| 61 paragraphs = content.split('\n\n') | 68 paragraphs = content.split('\n\n') |
| 62 if len(paragraphs) < 2: | 69 if len(paragraphs) < 2: |
| 63 return content | 70 return content |
| 64 return '<p>' + '</p><p>'.join(p.strip() for p in paragraphs) + '</p>' | 71 return '<p>' + '</p><p>'.join(p.strip() for p in paragraphs) + '</p>' |
| 65 | 72 |
| 66 # Find all the parameter comments of the form '|name|: comment'. | 73 # Find all the parameter comments of the form '|name|: comment'. |
| 67 parameter_starts = list(re.finditer(r' *\|([^|]*)\| *: *', comment)) | 74 parameter_starts = list(re.finditer(r' *\|([^|]*)\| *: *', comment)) |
| 68 | 75 |
| 69 # Get the parent comment (everything before the first parameter comment. | 76 # Get the parent comment (everything before the first parameter comment. |
| 70 first_parameter_location = (parameter_starts[0].start() | 77 first_parameter_location = (parameter_starts[0].start() |
| 71 if parameter_starts else len(comment)) | 78 if parameter_starts else len(comment)) |
| 72 parent_comment = (add_paragraphs(comment[:first_parameter_location].strip()) | 79 parent_comment = (add_paragraphs(comment[:first_parameter_location].strip()) |
| 73 .replace('\n', '')) | 80 .replace('\n', '')) |
| 74 | 81 |
| 75 params = OrderedDict() | 82 params = OrderedDict() |
| 76 for (cur_param, next_param) in itertools.izip_longest(parameter_starts, | 83 for (cur_param, next_param) in itertools.izip_longest(parameter_starts, |
| 77 parameter_starts[1:]): | 84 parameter_starts[1:]): |
| 78 param_name = cur_param.group(1) | 85 param_name = cur_param.group(1) |
| 79 | 86 |
| 80 # A parameter's comment goes from the end of its introduction to the | 87 # A parameter's comment goes from the end of its introduction to the |
| 81 # beginning of the next parameter's introduction. | 88 # beginning of the next parameter's introduction. |
| 82 param_comment_start = cur_param.end() | 89 param_comment_start = cur_param.end() |
| 83 param_comment_end = next_param.start() if next_param else len(comment) | 90 param_comment_end = next_param.start() if next_param else len(comment) |
| 84 params[param_name] = ( | 91 params[param_name] = ( |
| 85 add_paragraphs(comment[param_comment_start:param_comment_end].strip()) | 92 add_paragraphs(comment[param_comment_start:param_comment_end].strip()) |
| 86 .replace('\n', '')) | 93 .replace('\n', '')) |
| 87 | 94 |
| 88 return (parent_comment, params) | 95 return (parent_comment, jsexterns, params) |
| 89 | 96 |
| 90 | 97 |
| 91 class Callspec(object): | 98 class Callspec(object): |
| 92 ''' | 99 ''' |
| 93 Given a Callspec node representing an IDL function declaration, converts into | 100 Given a Callspec node representing an IDL function declaration, converts into |
| 94 a tuple: | 101 a tuple: |
| 95 (name, list of function parameters, return type) | 102 (name, list of function parameters, return type) |
| 96 ''' | 103 ''' |
| 97 def __init__(self, callspec_node, comment): | 104 def __init__(self, callspec_node, comment): |
| 98 self.node = callspec_node | 105 self.node = callspec_node |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 ('supportsRules', lambda s: s == 'true')]: | 195 ('supportsRules', lambda s: s == 'true')]: |
| 189 if self.node.GetProperty(option_name): | 196 if self.node.GetProperty(option_name): |
| 190 if 'options' not in properties: | 197 if 'options' not in properties: |
| 191 properties['options'] = {} | 198 properties['options'] = {} |
| 192 properties['options'][option_name] = sanitizer(self.node.GetProperty( | 199 properties['options'][option_name] = sanitizer(self.node.GetProperty( |
| 193 option_name)) | 200 option_name)) |
| 194 type_override = None | 201 type_override = None |
| 195 parameter_comments = OrderedDict() | 202 parameter_comments = OrderedDict() |
| 196 for node in self.node.GetChildren(): | 203 for node in self.node.GetChildren(): |
| 197 if node.cls == 'Comment': | 204 if node.cls == 'Comment': |
| 198 (parent_comment, parameter_comments) = ProcessComment(node.GetName()) | 205 (parent_comment, jsexterns, parameter_comments) = ProcessComment( |
| 206 node.GetName()) |
| 199 properties['description'] = parent_comment | 207 properties['description'] = parent_comment |
| 208 properties['jsexterns'] = jsexterns |
| 200 elif node.cls == 'Callspec': | 209 elif node.cls == 'Callspec': |
| 201 name, parameters, return_type = (Callspec(node, parameter_comments) | 210 name, parameters, return_type = (Callspec(node, parameter_comments) |
| 202 .process(callbacks)) | 211 .process(callbacks)) |
| 203 if functions_are_properties: | 212 if functions_are_properties: |
| 204 # If functions are treated as properties (which will happen if the | 213 # If functions are treated as properties (which will happen if the |
| 205 # interface is named Properties) then this isn't a function, it's a | 214 # interface is named Properties) then this isn't a function, it's a |
| 206 # property which is encoded as a function with no arguments. The | 215 # property which is encoded as a function with no arguments. The |
| 207 # property type is the return type. This is an egregious hack in lieu | 216 # property type is the return type. This is an egregious hack in lieu |
| 208 # of the IDL parser supporting 'const'. | 217 # of the IDL parser supporting 'const'. |
| 209 assert parameters == [], ( | 218 assert parameters == [], ( |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 print json.dumps(schema, indent=2) | 560 print json.dumps(schema, indent=2) |
| 552 else: | 561 else: |
| 553 contents = sys.stdin.read() | 562 contents = sys.stdin.read() |
| 554 idl = idl_parser.IDLParser().ParseData(contents, '<stdin>') | 563 idl = idl_parser.IDLParser().ParseData(contents, '<stdin>') |
| 555 schema = IDLSchema(idl).process() | 564 schema = IDLSchema(idl).process() |
| 556 print json.dumps(schema, indent=2) | 565 print json.dumps(schema, indent=2) |
| 557 | 566 |
| 558 | 567 |
| 559 if __name__ == '__main__': | 568 if __name__ == '__main__': |
| 560 Main() | 569 Main() |
| OLD | NEW |