| 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 """Node objects for the AST for a Mojo IDL file.""" | 5 """Node classes for the AST for a Mojo IDL file.""" |
| 6 | 6 |
| 7 # Note: For convenience of testing, you probably want to define __eq__() methods | 7 # Note: For convenience of testing, you probably want to define __eq__() methods |
| 8 # for all node types; it's okay to be slightly lax (e.g., not compare filename | 8 # for all node types; it's okay to be slightly lax (e.g., not compare filename |
| 9 # and lineno). | 9 # and lineno). You may also define __repr__() to help with analyzing test |
| 10 # failures, especially for more complex types. |
| 10 | 11 |
| 11 | 12 |
| 12 class NodeBase(object): | 13 class NodeBase(object): |
| 13 """Base class for nodes in the AST.""" | 14 """Base class for nodes in the AST.""" |
| 14 | 15 |
| 15 def __init__(self, filename=None, lineno=None): | 16 def __init__(self, filename=None, lineno=None): |
| 16 self.filename = filename | 17 self.filename = filename |
| 17 self.lineno = lineno | 18 self.lineno = lineno |
| 18 | 19 |
| 19 | 20 |
| 21 # TODO(vtl): Some of this is complicated enough that it should be tested. |
| 20 class NodeListBase(NodeBase): | 22 class NodeListBase(NodeBase): |
| 21 """Represents a list of other nodes, all having the same type. (This is meant | 23 """Represents a list of other nodes, all having the same type. (This is meant |
| 22 to be subclassed, with subclasses defining _list_item_type to be the class of | 24 to be subclassed, with subclasses defining _list_item_type to be the class of |
| 23 the members of the list; _list_item_type should also be a NodeBase.)""" | 25 the members of the list; _list_item_type should also be a NodeBase.)""" |
| 24 | 26 |
| 25 def __init__(self, item_or_items=None, **kwargs): | 27 def __init__(self, item_or_items=None, **kwargs): |
| 26 assert issubclass(self._list_item_type, NodeBase) | 28 assert issubclass(self._list_item_type, NodeBase) |
| 27 NodeBase.__init__(self, **kwargs) | 29 NodeBase.__init__(self, **kwargs) |
| 28 if item_or_items is None: | 30 if item_or_items is None: |
| 29 self.elements = [] | 31 self.elements = [] |
| 30 elif isinstance(item_or_items, list): | 32 elif isinstance(item_or_items, list): |
| 31 # TODO(vtl): Possibly we should assert that each element of the list is a | 33 # TODO(vtl): Possibly we should assert that each element of the list is a |
| 32 # |_list_item_type|. | 34 # |_list_item_type|. |
| 33 self.elements = list(item_or_items) | 35 self.elements = list(item_or_items) |
| 34 else: | 36 else: |
| 35 assert isinstance(item_or_items, self._list_item_type) | 37 assert isinstance(item_or_items, self._list_item_type) |
| 36 self.elements = [item_or_items] | 38 self.elements = [item_or_items] |
| 37 self._UpdateFilenameAndLineno() | 39 self._UpdateFilenameAndLineno() |
| 38 | 40 |
| 39 # Support iteration. For everything else, users should just access |elements| | 41 # Support iteration. For everything else, users should just access |elements| |
| 40 # directly. (We intentionally do NOT supply |__len__()| or |__nonzero__()|, so | 42 # directly. (We intentionally do NOT supply |__len__()| or |__nonzero__()|, so |
| 41 # |bool(NodeListBase())| is true.) | 43 # |bool(NodeListBase())| is true.) |
| 42 def __iter__(self): | 44 def __iter__(self): |
| 43 return self.elements.__iter__() | 45 return self.elements.__iter__() |
| 44 | 46 |
| 45 def __eq__(self, other): | 47 def __eq__(self, other): |
| 46 if type(self) != type(other): | 48 return type(self) == type(other) and \ |
| 47 return False | 49 len(self.elements) == len(other.elements) and \ |
| 48 for element in self.elements: | 50 all(self.elements[i] == other.elements[i] \ |
| 49 if self.elements != other.elements: | 51 for i in xrange(len(self.elements))) |
| 50 return False | 52 |
| 51 return True | 53 # Implement this so that on failure, we get slightly more sensible output. |
| 54 def __repr__(self): |
| 55 return self.__class__.__name__ + "([" + \ |
| 56 ", ".join([repr(elem) for elem in self.elements]) + "])" |
| 52 | 57 |
| 53 def Append(self, item): | 58 def Append(self, item): |
| 54 assert isinstance(item, self._list_item_type) | 59 assert isinstance(item, self._list_item_type) |
| 55 self.elements.append(item) | 60 self.elements.append(item) |
| 56 self._UpdateFilenameAndLineno() | 61 self._UpdateFilenameAndLineno() |
| 57 | 62 |
| 58 def _UpdateFilenameAndLineno(self): | 63 def _UpdateFilenameAndLineno(self): |
| 59 if self.elements: | 64 if self.elements: |
| 60 self.filename = self.elements[0].filename | 65 self.filename = self.elements[0].filename |
| 61 self.lineno = self.elements[0].lineno | 66 self.lineno = self.elements[0].lineno |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 def __eq__(self, other): | 113 def __eq__(self, other): |
| 109 return self.typename == other.typename and \ | 114 return self.typename == other.typename and \ |
| 110 self.name == other.name and \ | 115 self.name == other.name and \ |
| 111 self.ordinal == other.ordinal | 116 self.ordinal == other.ordinal |
| 112 | 117 |
| 113 | 118 |
| 114 class ParameterList(NodeListBase): | 119 class ParameterList(NodeListBase): |
| 115 """Represents a list of (method request or response) parameters.""" | 120 """Represents a list of (method request or response) parameters.""" |
| 116 | 121 |
| 117 _list_item_type = Parameter | 122 _list_item_type = Parameter |
| OLD | NEW |