| OLD | NEW | 
|    1 # Copyright 2014 The Chromium Authors. All rights reserved. |    1 # Copyright 2014 The Chromium Authors. All rights reserved. | 
|    2 # Use of this source code is governed by a BSD-style license that can be |    2 # Use of this source code is governed by a BSD-style license that can be | 
|    3 # found in the LICENSE file. |    3 # found in the LICENSE file. | 
|    4  |    4  | 
|    5 """Utility functions (file reading, simple IDL parsing by regexes) for IDL build
     . |    5 """Utility functions (file reading, simple IDL parsing by regexes) for IDL build
     . | 
|    6  |    6  | 
|    7 Design doc: http://www.chromium.org/developers/design-documents/idl-build |    7 Design doc: http://www.chromium.org/developers/design-documents/idl-build | 
|    8 """ |    8 """ | 
|    9  |    9  | 
|   10 import os |   10 import os | 
|   11 import cPickle as pickle |   11 import cPickle as pickle | 
|   12 import re |   12 import re | 
|   13 import string |   13 import string | 
|   14 import subprocess |   14 import subprocess | 
|   15  |   15  | 
|   16  |   16  | 
|   17 KNOWN_COMPONENTS = frozenset(['core', 'modules']) |   17 KNOWN_COMPONENTS = frozenset(['core', 'modules']) | 
|   18  |   18  | 
|   19  |   19  | 
|   20 class IdlBadFilenameError(Exception): |  | 
|   21     """Raised if an IDL filename disagrees with the interface name in the file."
     "" |  | 
|   22     pass |  | 
|   23  |  | 
|   24  |  | 
|   25 def idl_filename_to_interface_name(idl_filename): |   20 def idl_filename_to_interface_name(idl_filename): | 
|   26     # interface name is the root of the basename: InterfaceName.idl |   21     # interface name is the root of the basename: InterfaceName.idl | 
|   27     return os.path.splitext(os.path.basename(idl_filename))[0] |   22     return os.path.splitext(os.path.basename(idl_filename))[0] | 
|   28  |   23  | 
|   29  |   24  | 
|   30 def idl_filename_to_component(idl_filename): |   25 def idl_filename_to_component(idl_filename): | 
|   31     path = os.path.dirname(os.path.realpath(idl_filename)) |   26     path = os.path.dirname(os.path.realpath(idl_filename)) | 
|   32     while path: |   27     while path: | 
|   33         dirname, basename = os.path.split(path) |   28         dirname, basename = os.path.split(path) | 
|   34         if not basename: |   29         if not basename: | 
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  129  |  124  | 
|  130  |  125  | 
|  131 ################################################################################ |  126 ################################################################################ | 
|  132 # IDL parsing |  127 # IDL parsing | 
|  133 # |  128 # | 
|  134 # We use regular expressions for parsing; this is incorrect (Web IDL is not a |  129 # We use regular expressions for parsing; this is incorrect (Web IDL is not a | 
|  135 # regular language), but simple and sufficient in practice. |  130 # regular language), but simple and sufficient in practice. | 
|  136 # Leading and trailing context (e.g. following '{') used to avoid false matches. |  131 # Leading and trailing context (e.g. following '{') used to avoid false matches. | 
|  137 ################################################################################ |  132 ################################################################################ | 
|  138  |  133  | 
|  139 def get_partial_interface_name_from_idl(file_contents): |  | 
|  140     match = re.search(r'partial\s+interface\s+(\w+)\s*{', file_contents) |  | 
|  141     return match and match.group(1) |  | 
|  142  |  | 
|  143  |  | 
|  144 def get_implements_from_idl(file_contents, interface_name): |  | 
|  145     """Returns lists of implementing and implemented interfaces. |  | 
|  146  |  | 
|  147     Rule is: identifier-A implements identifier-B; |  | 
|  148     i.e., implement*ing* implements implement*ed*; |  | 
|  149     http://www.w3.org/TR/WebIDL/#idl-implements-statements |  | 
|  150  |  | 
|  151     Returns two lists of interfaces: identifier-As and identifier-Bs. |  | 
|  152     An 'implements' statements can be present in the IDL file for either the |  | 
|  153     implementing or the implemented interface, but not other files. |  | 
|  154     """ |  | 
|  155     implements_re = (r'^\s*' |  | 
|  156                      r'(\w+)\s+' |  | 
|  157                      r'implements\s+' |  | 
|  158                      r'(\w+)\s*' |  | 
|  159                      r';') |  | 
|  160     implements_matches = re.finditer(implements_re, file_contents, re.MULTILINE) |  | 
|  161     implements_pairs = [match.groups() for match in implements_matches] |  | 
|  162  |  | 
|  163     foreign_implements = [pair for pair in implements_pairs |  | 
|  164                           if interface_name not in pair] |  | 
|  165     if foreign_implements: |  | 
|  166         left, right = foreign_implements.pop() |  | 
|  167         raise IdlBadFilenameError( |  | 
|  168                 'implements statement found in unrelated IDL file.\n' |  | 
|  169                 'Statement is:\n' |  | 
|  170                 '    %s implements %s;\n' |  | 
|  171                 'but filename is unrelated "%s.idl"' % |  | 
|  172                 (left, right, interface_name)) |  | 
|  173  |  | 
|  174     return ( |  | 
|  175         [left for left, right in implements_pairs if right == interface_name], |  | 
|  176         [right for left, right in implements_pairs if left == interface_name]) |  | 
|  177  |  | 
|  178  |  | 
|  179 def is_callback_interface_from_idl(file_contents): |  134 def is_callback_interface_from_idl(file_contents): | 
|  180     match = re.search(r'callback\s+interface\s+\w+\s*{', file_contents) |  135     match = re.search(r'callback\s+interface\s+\w+\s*{', file_contents) | 
|  181     return bool(match) |  136     return bool(match) | 
|  182  |  137  | 
|  183  |  138  | 
|  184 def is_dictionary_from_idl(file_contents): |  | 
|  185     match = re.search(r'dictionary\s+\w+\s*{', file_contents) |  | 
|  186     return bool(match) |  | 
|  187  |  | 
|  188  |  | 
|  189 def get_parent_interface(file_contents): |  | 
|  190     match = re.search(r'interface\s+' |  | 
|  191                       r'\w+\s*' |  | 
|  192                       r':\s*(\w+)\s*' |  | 
|  193                       r'{', |  | 
|  194                       file_contents) |  | 
|  195     return match and match.group(1) |  | 
|  196  |  | 
|  197  |  | 
|  198 def get_interface_extended_attributes_from_idl(file_contents): |  139 def get_interface_extended_attributes_from_idl(file_contents): | 
|  199     # Strip comments |  140     # Strip comments | 
|  200     # re.compile needed b/c Python 2.6 doesn't support flags in re.sub |  141     # re.compile needed b/c Python 2.6 doesn't support flags in re.sub | 
|  201     single_line_comment_re = re.compile(r'//.*$', flags=re.MULTILINE) |  142     single_line_comment_re = re.compile(r'//.*$', flags=re.MULTILINE) | 
|  202     block_comment_re = re.compile(r'/\*.*?\*/', flags=re.MULTILINE | re.DOTALL) |  143     block_comment_re = re.compile(r'/\*.*?\*/', flags=re.MULTILINE | re.DOTALL) | 
|  203     file_contents = re.sub(single_line_comment_re, '', file_contents) |  144     file_contents = re.sub(single_line_comment_re, '', file_contents) | 
|  204     file_contents = re.sub(block_comment_re, '', file_contents) |  145     file_contents = re.sub(block_comment_re, '', file_contents) | 
|  205  |  146  | 
|  206     match = re.search(r'\[(.*)\]\s*' |  147     match = re.search(r'\[(.*)\]\s*' | 
|  207                       r'((callback|partial)\s+)?' |  148                       r'((callback|partial)\s+)?' | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  218     # FIXME: this splitting is WRONG: it fails on extended attributes where list
     s of |  159     # FIXME: this splitting is WRONG: it fails on extended attributes where list
     s of | 
|  219     # multiple values are used, which are seperated by a comma and a space. |  160     # multiple values are used, which are seperated by a comma and a space. | 
|  220     parts = [extended_attribute.strip() |  161     parts = [extended_attribute.strip() | 
|  221              for extended_attribute in re.split(',\s+', extended_attributes_stri
     ng) |  162              for extended_attribute in re.split(',\s+', extended_attributes_stri
     ng) | 
|  222              # Discard empty parts, which may exist due to trailing comma |  163              # Discard empty parts, which may exist due to trailing comma | 
|  223              if extended_attribute.strip()] |  164              if extended_attribute.strip()] | 
|  224     for part in parts: |  165     for part in parts: | 
|  225         name, _, value = map(string.strip, part.partition('=')) |  166         name, _, value = map(string.strip, part.partition('=')) | 
|  226         extended_attributes[name] = value |  167         extended_attributes[name] = value | 
|  227     return extended_attributes |  168     return extended_attributes | 
|  228  |  | 
|  229  |  | 
|  230 def get_put_forward_interfaces_from_idl(file_contents): |  | 
|  231     put_forwards_pattern = (r'\[[^\]]*PutForwards=[^\]]*\]\s+' |  | 
|  232                             r'readonly\s+' |  | 
|  233                             r'attribute\s+' |  | 
|  234                             r'(\w+)') |  | 
|  235     return sorted(set(match.group(1) |  | 
|  236                       for match in re.finditer(put_forwards_pattern, |  | 
|  237                                                file_contents, |  | 
|  238                                                flags=re.DOTALL))) |  | 
| OLD | NEW |