OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2012 The Closure Linter Authors. All Rights Reserved. | 3 # Copyright 2012 The Closure Linter Authors. All Rights Reserved. |
4 # Licensed under the Apache License, Version 2.0 (the "License"); | 4 # Licensed under the Apache License, Version 2.0 (the "License"); |
5 # you may not use this file except in compliance with the License. | 5 # you may not use this file except in compliance with the License. |
6 # You may obtain a copy of the License at | 6 # You may obtain a copy of the License at |
7 # | 7 # |
8 # http://www.apache.org/licenses/LICENSE-2.0 | 8 # http://www.apache.org/licenses/LICENSE-2.0 |
9 # | 9 # |
10 # Unless required by applicable law or agreed to in writing, software | 10 # Unless required by applicable law or agreed to in writing, software |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 Returns: | 113 Returns: |
114 True if symbol is an identifier in a Closurized namespace, otherwise False. | 114 True if symbol is an identifier in a Closurized namespace, otherwise False. |
115 """ | 115 """ |
116 for ns in closurized_namespaces: | 116 for ns in closurized_namespaces: |
117 if symbol.startswith(ns + '.'): | 117 if symbol.startswith(ns + '.'): |
118 return True | 118 return True |
119 | 119 |
120 return False | 120 return False |
121 | 121 |
122 | 122 |
123 def MatchAlias(context): | 123 def _GetVarAssignmentTokens(context): |
124 """Match an alias statement (some identifier assigned to a variable). | 124 """Returns the tokens from context if it is a var assignment. |
125 | |
126 Example alias: var MyClass = proj.longNamespace.MyClass. | |
127 | 125 |
128 Args: | 126 Args: |
129 context: An EcmaContext of type EcmaContext.VAR. | 127 context: An EcmaContext. |
130 | 128 |
131 Returns: | 129 Returns: |
132 If a valid alias, returns a tuple of alias and symbol, otherwise None. | 130 If a var assignment, the tokens contained within it w/o the trailing |
| 131 semicolon. |
133 """ | 132 """ |
134 if context.type != ecmametadatapass.EcmaContext.VAR: | 133 if context.type != ecmametadatapass.EcmaContext.VAR: |
135 return | 134 return |
136 | 135 |
137 # The var's parent is a STATEMENT, which should be directly below goog.scope. | |
138 if not IsGoogScopeBlock(context.parent.parent): | |
139 return | |
140 | |
141 # Get the tokens in this statement. | 136 # Get the tokens in this statement. |
142 if context.start_token and context.end_token: | 137 if context.start_token and context.end_token: |
143 statement_tokens = tokenutil.GetTokenRange(context.start_token, | 138 statement_tokens = tokenutil.GetTokenRange(context.start_token, |
144 context.end_token) | 139 context.end_token) |
145 else: | 140 else: |
146 return | 141 return |
147 | 142 |
148 # And now just those tokens that are actually code. | 143 # And now just those tokens that are actually code. |
149 is_non_code_type = lambda t: t.type not in JavaScriptTokenType.NON_CODE_TYPES | 144 is_non_code_type = lambda t: t.type not in JavaScriptTokenType.NON_CODE_TYPES |
150 code_tokens = filter(is_non_code_type, statement_tokens) | 145 code_tokens = filter(is_non_code_type, statement_tokens) |
151 | 146 |
152 # This section identifies statements of the alias form "var alias = symbol". | |
153 | |
154 # Pop off the semicolon if present. | 147 # Pop off the semicolon if present. |
155 if code_tokens and code_tokens[-1].IsType(JavaScriptTokenType.SEMICOLON): | 148 if code_tokens and code_tokens[-1].IsType(JavaScriptTokenType.SEMICOLON): |
156 code_tokens.pop() | 149 code_tokens.pop() |
157 | 150 |
158 if len(code_tokens) < 4: | 151 if len(code_tokens) < 4: |
159 return | 152 return |
160 | 153 |
161 # Verify that this is of the form "var lvalue = identifier;". | |
162 # The identifier may span multiple lines and could be multiple tokens. | |
163 if (code_tokens[0].IsKeyword('var') and | 154 if (code_tokens[0].IsKeyword('var') and |
164 code_tokens[1].IsType(JavaScriptTokenType.SIMPLE_LVALUE) and | 155 code_tokens[1].IsType(JavaScriptTokenType.SIMPLE_LVALUE) and |
165 code_tokens[2].IsOperator('=') and | 156 code_tokens[2].IsOperator('=')): |
166 all(t.IsType(JavaScriptTokenType.IDENTIFIER) for t in code_tokens[3:])): | 157 return code_tokens |
| 158 |
| 159 |
| 160 def MatchAlias(context): |
| 161 """Match an alias statement (some identifier assigned to a variable). |
| 162 |
| 163 Example alias: var MyClass = proj.longNamespace.MyClass. |
| 164 |
| 165 Args: |
| 166 context: An EcmaContext of type EcmaContext.VAR. |
| 167 |
| 168 Returns: |
| 169 If a valid alias, returns a tuple of alias and symbol, otherwise None. |
| 170 """ |
| 171 code_tokens = _GetVarAssignmentTokens(context) |
| 172 if code_tokens is None: |
| 173 return |
| 174 |
| 175 if all(tokenutil.IsIdentifierOrDot(t) for t in code_tokens[3:]): |
| 176 # var Foo = bar.Foo; |
167 alias, symbol = code_tokens[1], code_tokens[3] | 177 alias, symbol = code_tokens[1], code_tokens[3] |
168 # Mark both tokens as an alias definition to avoid counting them as usages. | 178 # Mark both tokens as an alias definition to not count them as usages. |
169 alias.metadata.is_alias_definition = True | 179 alias.metadata.is_alias_definition = True |
170 symbol.metadata.is_alias_definition = True | 180 symbol.metadata.is_alias_definition = True |
| 181 return alias.string, tokenutil.GetIdentifierForToken(symbol) |
171 | 182 |
172 return alias.string, tokenutil.GetIdentifierForToken(symbol) | 183 |
| 184 def MatchModuleAlias(context): |
| 185 """Match an alias statement in a goog.module style import. |
| 186 |
| 187 Example alias: var MyClass = goog.require('proj.longNamespace.MyClass'). |
| 188 |
| 189 Args: |
| 190 context: An EcmaContext. |
| 191 |
| 192 Returns: |
| 193 If a valid alias, returns a tuple of alias and symbol, otherwise None. |
| 194 """ |
| 195 code_tokens = _GetVarAssignmentTokens(context) |
| 196 if code_tokens is None: |
| 197 return |
| 198 |
| 199 if(code_tokens[3].IsType(JavaScriptTokenType.IDENTIFIER) and |
| 200 code_tokens[3].string == 'goog.require'): |
| 201 # var Foo = goog.require('bar.Foo'); |
| 202 alias = code_tokens[1] |
| 203 symbol = tokenutil.GetStringAfterToken(code_tokens[3]) |
| 204 if symbol: |
| 205 alias.metadata.is_alias_definition = True |
| 206 return alias.string, symbol |
OLD | NEW |