/usr/share/pyshared/closure_linter/javascriptstatetracker.py is in closure-linter 2.3.13-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | #!/usr/bin/env python
# Copyright 2008 The Closure Linter Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Parser for JavaScript files."""
from closure_linter import javascripttokens
from closure_linter import statetracker
from closure_linter import tokenutil
# Shorthand
Type = javascripttokens.JavaScriptTokenType
class JsDocFlag(statetracker.DocFlag):
"""Javascript doc flag object.
Attribute:
flag_type: param, return, define, type, etc.
flag_token: The flag token.
type_start_token: The first token specifying the flag JS type,
including braces.
type_end_token: The last token specifying the flag JS type,
including braces.
type: The JavaScript type spec.
name_token: The token specifying the flag name.
name: The flag name
description_start_token: The first token in the description.
description_end_token: The end token in the description.
description: The description.
"""
# Please keep these lists alphabetized.
# Some projects use the following extensions to JsDoc.
# TODO(robbyw): determine which of these, if any, should be illegal.
EXTENDED_DOC = frozenset([
'class', 'code', 'desc', 'final', 'hidden', 'inheritDoc', 'link',
'meaning', 'provideGoog', 'throws'])
LEGAL_DOC = EXTENDED_DOC | statetracker.DocFlag.LEGAL_DOC
def __init__(self, flag_token):
"""Creates the JsDocFlag object and attaches it to the given start token.
Args:
flag_token: The starting token of the flag.
"""
statetracker.DocFlag.__init__(self, flag_token)
class JavaScriptStateTracker(statetracker.StateTracker):
"""JavaScript state tracker.
Inherits from the core EcmaScript StateTracker adding extra state tracking
functionality needed for JavaScript.
"""
def __init__(self):
"""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.
This function call is language specific. In some languages like
JavaScript, a function is top level if it is not inside any parenthesis.
In languages such as ActionScript, a function is top level if it is directly
within a class.
Returns:
Whether we are at the top level in the class.
"""
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.
Code blocks come after parameters, keywords like else, and closing parens.
Args:
token: The current token. Can be assumed to be type START_BLOCK
Returns:
Code block type for current token.
"""
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: 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)
|