Index: third_party/closure_linter/closure_linter/javascriptstatetracker.py |
diff --git a/third_party/closure_linter/closure_linter/javascriptstatetracker.py b/third_party/closure_linter/closure_linter/javascriptstatetracker.py |
index 2ce5c02c6c4af432b049adf0faaf46893c33e80e..1b051d3bf6bd2de91ee6fd318a14e16ea2469819 100755 |
--- a/third_party/closure_linter/closure_linter/javascriptstatetracker.py |
+++ b/third_party/closure_linter/closure_linter/javascriptstatetracker.py |
@@ -1,5 +1,4 @@ |
#!/usr/bin/env python |
-# |
# Copyright 2008 The Closure Linter Authors. All Rights Reserved. |
# |
# Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -50,7 +49,7 @@ class JsDocFlag(statetracker.DocFlag): |
# TODO(robbyw): determine which of these, if any, should be illegal. |
EXTENDED_DOC = frozenset([ |
'class', 'code', 'desc', 'final', 'hidden', 'inheritDoc', 'link', |
- 'meaning', 'protected', 'notypecheck', 'throws']) |
+ 'meaning', 'provideGoog', 'throws']) |
LEGAL_DOC = EXTENDED_DOC | statetracker.DocFlag.LEGAL_DOC |
@@ -74,6 +73,11 @@ class JavaScriptStateTracker(statetracker.StateTracker): |
"""Initializes a JavaScript token stream state tracker.""" |
statetracker.StateTracker.__init__(self, JsDocFlag) |
+ def Reset(self): |
+ self._scope_depth = 0 |
+ self._block_stack = [] |
+ super(JavaScriptStateTracker, self).Reset() |
+ |
def InTopLevel(self): |
"""Compute whether we are at the top level in the class. |
@@ -85,7 +89,26 @@ class JavaScriptStateTracker(statetracker.StateTracker): |
Returns: |
Whether we are at the top level in the class. |
""" |
- return not self.InParentheses() |
+ return self._scope_depth == self.ParenthesesDepth() |
+ |
+ def InFunction(self): |
+ """Returns true if the current token is within a function. |
+ |
+ This js-specific override ignores goog.scope functions. |
+ |
+ Returns: |
+ True if the current token is within a function. |
+ """ |
+ return self._scope_depth != self.FunctionDepth() |
+ |
+ def InNonScopeBlock(self): |
+ """Compute whether we are nested within a non-goog.scope block. |
+ |
+ Returns: |
+ True if the token is not enclosed in a block that does not originate from |
+ a goog.scope statement. False otherwise. |
+ """ |
+ return self._scope_depth != self.BlockDepth() |
def GetBlockType(self, token): |
"""Determine the block type given a START_BLOCK token. |
@@ -97,20 +120,38 @@ class JavaScriptStateTracker(statetracker.StateTracker): |
Returns: |
Code block type for current token. |
""" |
- last_code = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES, None, |
- True) |
+ last_code = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES, reverse=True) |
if last_code.type in (Type.END_PARAMETERS, Type.END_PAREN, |
Type.KEYWORD) and not last_code.IsKeyword('return'): |
return self.CODE |
else: |
return self.OBJECT_LITERAL |
+ def GetCurrentBlockStart(self): |
+ """Gets the start token of current block. |
+ |
+ Returns: |
+ Starting token of current block. None if not in block. |
+ """ |
+ if self._block_stack: |
+ return self._block_stack[-1] |
+ else: |
+ return None |
+ |
def HandleToken(self, token, last_non_space_token): |
"""Handles the given token and updates state. |
Args: |
token: The token to handle. |
- last_non_space_token: |
+ last_non_space_token: The last non space token encountered |
""" |
+ if token.type == Type.START_BLOCK: |
+ self._block_stack.append(token) |
+ if token.type == Type.IDENTIFIER and token.string == 'goog.scope': |
+ self._scope_depth += 1 |
+ if token.type == Type.END_BLOCK: |
+ start_token = self._block_stack.pop() |
+ if tokenutil.GoogScopeOrNoneFromStartBlock(start_token): |
+ self._scope_depth -= 1 |
super(JavaScriptStateTracker, self).HandleToken(token, |
last_non_space_token) |