OLD | NEW |
1 # Copyright 2017 The Chromium Authors. All rights reserved. | 1 # Copyright 2017 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 """Logic for parsing a C/C++ function signature.""" | 5 """Logic for parsing a C/C++ function signature.""" |
6 | 6 |
7 | 7 |
8 def _FindParameterListParen(name): | 8 def _FindParameterListParen(name): |
9 """Finds index of the "(" that denotes the start of a paremeter list.""" | 9 """Finds index of the "(" that denotes the start of a paremeter list.""" |
10 # This loops from left-to-right, but the only reason (I think) that this | 10 # This loops from left-to-right, but the only reason (I think) that this |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 space_idx = _FindLastCharOutsideOfBrackets(name, ' ', space_idx) | 79 space_idx = _FindLastCharOutsideOfBrackets(name, ' ', space_idx) |
80 # Special case: "operator new", and "operator<< <template>". | 80 # Special case: "operator new", and "operator<< <template>". |
81 if -1 == space_idx or ( | 81 if -1 == space_idx or ( |
82 -1 == name.find('operator', space_idx - 8, space_idx) and | 82 -1 == name.find('operator', space_idx - 8, space_idx) and |
83 -1 == name.find('operator<<', space_idx - 10, space_idx)): | 83 -1 == name.find('operator<<', space_idx - 10, space_idx)): |
84 break | 84 break |
85 space_idx -= 8 | 85 space_idx -= 8 |
86 return space_idx | 86 return space_idx |
87 | 87 |
88 | 88 |
| 89 def _StripTemplateArgs(name): |
| 90 last_right_idx = None |
| 91 while True: |
| 92 last_right_idx = name.rfind('>', 0, last_right_idx) |
| 93 if last_right_idx == -1: |
| 94 return name |
| 95 left_idx = _FindLastCharOutsideOfBrackets(name, '<', last_right_idx + 1) |
| 96 if left_idx == -1: |
| 97 return name |
| 98 # Special case: std::operator<< < |
| 99 if left_idx > 0 and name[left_idx - 1] == ' ': |
| 100 left_idx -= 1 |
| 101 name = name[:left_idx] + name[last_right_idx + 1:] |
| 102 last_right_idx = left_idx |
| 103 |
| 104 |
89 def _NormalizeTopLevelLambda(name, space_idx, left_paren_idx): | 105 def _NormalizeTopLevelLambda(name, space_idx, left_paren_idx): |
90 # cc::{lambda(PaintOp*)#63}::_FUN() -> cc:{lambda#63}() | 106 # cc::{lambda(PaintOp*)#63}::_FUN() -> cc:{lambda#63}() |
91 paren_idx = name.index('(', space_idx + 1) | 107 paren_idx = name.index('(', space_idx + 1) |
92 hash_idx = name.rindex('#', paren_idx) | 108 hash_idx = name.rindex('#', paren_idx) |
93 return (name[:paren_idx] + name[hash_idx:left_paren_idx - 6] + | 109 return (name[:paren_idx] + name[hash_idx:left_paren_idx - 6] + |
94 name[left_paren_idx:]) | 110 name[left_paren_idx:]) |
95 | 111 |
96 | 112 |
97 def Parse(name): | 113 def Parse(name): |
98 """Extracts a function name from a function signature. | 114 """Strips return type and breaks function signature into parts. |
99 | 115 |
100 See unit tests for example signatures. | 116 See unit tests for example signatures. |
101 | 117 |
102 Returns: | 118 Returns: |
103 A tuple of (name_without_return_type, name_without_return_type_and_params). | 119 A tuple of: |
| 120 * name without return type (symbol.full_name), |
| 121 * full_name without params (symbol.template_name), |
| 122 * full_name without params and template args (symbol.name) |
104 """ | 123 """ |
105 left_paren_idx = _FindParameterListParen(name) | 124 left_paren_idx = _FindParameterListParen(name) |
106 | 125 |
107 full_name = name | 126 full_name = name |
108 if left_paren_idx > 0: | 127 if left_paren_idx > 0: |
109 right_paren_idx = name.rindex(')') | 128 right_paren_idx = name.rindex(')') |
110 assert right_paren_idx > left_paren_idx | 129 assert right_paren_idx > left_paren_idx |
111 space_idx = _FindReturnValueSpace(name, left_paren_idx) | 130 space_idx = _FindReturnValueSpace(name, left_paren_idx) |
112 name_without_attrib = name[space_idx + 1:left_paren_idx] | 131 name_no_params = name[space_idx + 1:left_paren_idx] |
113 # Special case for top-level lamdas. | 132 # Special case for top-level lamdas. |
114 if name_without_attrib.endswith('}::_FUN'): | 133 if name_no_params.endswith('}::_FUN'): |
115 # Don't use name_without_attrib in here since prior _idx will be off if | 134 # Don't use name_no_params in here since prior _idx will be off if |
116 # there was a return value. | 135 # there was a return value. |
117 name = _NormalizeTopLevelLambda(name, space_idx, left_paren_idx) | 136 name = _NormalizeTopLevelLambda(name, space_idx, left_paren_idx) |
118 return Parse(name) | 137 return Parse(name) |
119 | 138 |
120 full_name = name[space_idx + 1:] | 139 full_name = name[space_idx + 1:] |
121 name = name_without_attrib + name[right_paren_idx + 1:] | 140 name = name_no_params + name[right_paren_idx + 1:] |
122 | 141 |
123 return full_name, name | 142 template_name = name |
| 143 name = _StripTemplateArgs(name) |
| 144 return full_name, template_name, name |
| 145 |
| 146 |
| 147 # An odd place for this, but pylint doesn't want it as a static in models |
| 148 # (circular dependency), nor as an method on BaseSymbol |
| 149 # (attribute-defined-outside-init). |
| 150 def InternSameNames(symbol): |
| 151 """Allow using "is" to compare names (and should help with RAM).""" |
| 152 if symbol.template_name == symbol.full_name: |
| 153 symbol.template_name = symbol.full_name |
| 154 if symbol.name == symbol.template_name: |
| 155 symbol.name = symbol.template_name |
OLD | NEW |