Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: third_party/closure_linter/closure_linter/scopeutil.py

Issue 2592193002: Remove closure_linter from Chrome (Closed)
Patch Set: Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 #
3 # Copyright 2012 The Closure Linter Authors. All Rights Reserved.
4 # Licensed under the Apache License, Version 2.0 (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
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS-IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 """Tools to match goog.scope alias statements."""
17
18 # Allow non-Google copyright
19 # pylint: disable=g-bad-file-header
20
21 __author__ = ('nnaze@google.com (Nathan Naze)')
22
23 import itertools
24
25 from closure_linter import ecmametadatapass
26 from closure_linter import tokenutil
27 from closure_linter.javascripttokens import JavaScriptTokenType
28
29
30
31 def IsGoogScopeBlock(context):
32 """Whether the given context is a goog.scope block.
33
34 This function only checks that the block is a function block inside
35 a goog.scope() call.
36
37 TODO(nnaze): Implement goog.scope checks that verify the call is
38 in the root context and contains only a single function literal.
39
40 Args:
41 context: An EcmaContext of type block.
42
43 Returns:
44 Whether the context is a goog.scope block.
45 """
46
47 if context.type != ecmametadatapass.EcmaContext.BLOCK:
48 return False
49
50 if not _IsFunctionLiteralBlock(context):
51 return False
52
53 # Check that this function is contained by a group
54 # of form "goog.scope(...)".
55 parent = context.parent
56 if parent and parent.type is ecmametadatapass.EcmaContext.GROUP:
57
58 last_code_token = parent.start_token.metadata.last_code
59
60 if (last_code_token and
61 last_code_token.type is JavaScriptTokenType.IDENTIFIER and
62 last_code_token.string == 'goog.scope'):
63 return True
64
65 return False
66
67
68 def _IsFunctionLiteralBlock(block_context):
69 """Check if a context is a function literal block (without parameters).
70
71 Example function literal block: 'function() {}'
72
73 Args:
74 block_context: An EcmaContext of type block.
75
76 Returns:
77 Whether this context is a function literal block.
78 """
79
80 previous_code_tokens_iter = itertools.ifilter(
81 lambda token: token not in JavaScriptTokenType.NON_CODE_TYPES,
82 reversed(block_context.start_token))
83
84 # Ignore the current token
85 next(previous_code_tokens_iter, None)
86
87 # Grab the previous three tokens and put them in correct order.
88 previous_code_tokens = list(itertools.islice(previous_code_tokens_iter, 3))
89 previous_code_tokens.reverse()
90
91 # There aren't three previous tokens.
92 if len(previous_code_tokens) is not 3:
93 return False
94
95 # Check that the previous three code tokens are "function ()"
96 previous_code_token_types = [token.type for token in previous_code_tokens]
97 if (previous_code_token_types == [
98 JavaScriptTokenType.FUNCTION_DECLARATION,
99 JavaScriptTokenType.START_PARAMETERS,
100 JavaScriptTokenType.END_PARAMETERS]):
101 return True
102
103 return False
104
105
106 def IsInClosurizedNamespace(symbol, closurized_namespaces):
107 """Match a goog.scope alias.
108
109 Args:
110 symbol: An identifier like 'goog.events.Event'.
111 closurized_namespaces: Iterable of valid Closurized namespaces (strings).
112
113 Returns:
114 True if symbol is an identifier in a Closurized namespace, otherwise False.
115 """
116 for ns in closurized_namespaces:
117 if symbol.startswith(ns + '.'):
118 return True
119
120 return False
121
122
123 def _GetVarAssignmentTokens(context):
124 """Returns the tokens from context if it is a var assignment.
125
126 Args:
127 context: An EcmaContext.
128
129 Returns:
130 If a var assignment, the tokens contained within it w/o the trailing
131 semicolon.
132 """
133 if context.type != ecmametadatapass.EcmaContext.VAR:
134 return
135
136 # Get the tokens in this statement.
137 if context.start_token and context.end_token:
138 statement_tokens = tokenutil.GetTokenRange(context.start_token,
139 context.end_token)
140 else:
141 return
142
143 # And now just those tokens that are actually code.
144 is_non_code_type = lambda t: t.type not in JavaScriptTokenType.NON_CODE_TYPES
145 code_tokens = filter(is_non_code_type, statement_tokens)
146
147 # Pop off the semicolon if present.
148 if code_tokens and code_tokens[-1].IsType(JavaScriptTokenType.SEMICOLON):
149 code_tokens.pop()
150
151 if len(code_tokens) < 4:
152 return
153
154 if (code_tokens[0].IsKeyword('var') and
155 code_tokens[1].IsType(JavaScriptTokenType.SIMPLE_LVALUE) and
156 code_tokens[2].IsOperator('=')):
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;
177 alias, symbol = code_tokens[1], code_tokens[3]
178 # Mark both tokens as an alias definition to not count them as usages.
179 alias.metadata.is_alias_definition = True
180 symbol.metadata.is_alias_definition = True
181 return alias.string, tokenutil.GetIdentifierForToken(symbol)
182
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
OLDNEW
« no previous file with comments | « third_party/closure_linter/closure_linter/runner_test.py ('k') | third_party/closure_linter/closure_linter/scopeutil_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698