1#!/usr/bin/env python 2# 3# Copyright 2008 The Closure Linter Authors. All Rights Reserved. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS-IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""Parser for JavaScript files.""" 18 19 20 21from closure_linter import javascripttokens 22from closure_linter import statetracker 23from closure_linter import tokenutil 24 25# Shorthand 26Type = javascripttokens.JavaScriptTokenType 27 28 29class JsDocFlag(statetracker.DocFlag): 30 """Javascript doc flag object. 31 32 Attribute: 33 flag_type: param, return, define, type, etc. 34 flag_token: The flag token. 35 type_start_token: The first token specifying the flag JS type, 36 including braces. 37 type_end_token: The last token specifying the flag JS type, 38 including braces. 39 type: The JavaScript type spec. 40 name_token: The token specifying the flag name. 41 name: The flag name 42 description_start_token: The first token in the description. 43 description_end_token: The end token in the description. 44 description: The description. 45 """ 46 47 # Please keep these lists alphabetized. 48 49 # Some projects use the following extensions to JsDoc. 50 # TODO(robbyw): determine which of these, if any, should be illegal. 51 EXTENDED_DOC = frozenset([ 52 'class', 'code', 'desc', 'final', 'hidden', 'inheritDoc', 'link', 53 'meaning', 'protected', 'notypecheck', 'throws']) 54 55 LEGAL_DOC = EXTENDED_DOC | statetracker.DocFlag.LEGAL_DOC 56 57 def __init__(self, flag_token): 58 """Creates the JsDocFlag object and attaches it to the given start token. 59 60 Args: 61 flag_token: The starting token of the flag. 62 """ 63 statetracker.DocFlag.__init__(self, flag_token) 64 65 66class JavaScriptStateTracker(statetracker.StateTracker): 67 """JavaScript state tracker. 68 69 Inherits from the core EcmaScript StateTracker adding extra state tracking 70 functionality needed for JavaScript. 71 """ 72 73 def __init__(self): 74 """Initializes a JavaScript token stream state tracker.""" 75 statetracker.StateTracker.__init__(self, JsDocFlag) 76 77 def InTopLevel(self): 78 """Compute whether we are at the top level in the class. 79 80 This function call is language specific. In some languages like 81 JavaScript, a function is top level if it is not inside any parenthesis. 82 In languages such as ActionScript, a function is top level if it is directly 83 within a class. 84 85 Returns: 86 Whether we are at the top level in the class. 87 """ 88 return not self.InParentheses() 89 90 def GetBlockType(self, token): 91 """Determine the block type given a START_BLOCK token. 92 93 Code blocks come after parameters, keywords like else, and closing parens. 94 95 Args: 96 token: The current token. Can be assumed to be type START_BLOCK 97 Returns: 98 Code block type for current token. 99 """ 100 last_code = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES, None, 101 True) 102 if last_code.type in (Type.END_PARAMETERS, Type.END_PAREN, 103 Type.KEYWORD) and not last_code.IsKeyword('return'): 104 return self.CODE 105 else: 106 return self.OBJECT_LITERAL 107 108 def HandleToken(self, token, last_non_space_token): 109 """Handles the given token and updates state. 110 111 Args: 112 token: The token to handle. 113 last_non_space_token: 114 """ 115 super(JavaScriptStateTracker, self).HandleToken(token, 116 last_non_space_token) 117