15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#!/usr/bin/env python 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Copyright 2012 The Closure Linter Authors. All Rights Reserved. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Licensed under the Apache License, Version 2.0 (the "License"); 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# you may not use this file except in compliance with the License. 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# You may obtain a copy of the License at 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# http://www.apache.org/licenses/LICENSE-2.0 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Unless required by applicable law or agreed to in writing, software 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# distributed under the License is distributed on an "AS-IS" BASIS, 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# See the License for the specific language governing permissions and 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# limitations under the License. 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)"""Pass that scans for goog.scope aliases and lint/usage errors.""" 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Allow non-Google copyright 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# pylint: disable=g-bad-file-header 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)__author__ = ('nnaze@google.com (Nathan Naze)') 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import itertools 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from closure_linter import ecmametadatapass 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from closure_linter import errors 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from closure_linter import javascripttokens 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from closure_linter import scopeutil 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from closure_linter import tokenutil 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from closure_linter.common import error 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# TODO(nnaze): Create a Pass interface and move this class, EcmaMetaDataPass, 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# and related classes onto it. 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def _GetAliasForIdentifier(identifier, alias_map): 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Returns the aliased_symbol name for an identifier. 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Example usage: 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> alias_map = {'MyClass': 'goog.foo.MyClass'} 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> _GetAliasForIdentifier('MyClass.prototype.action', alias_map) 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'goog.foo.MyClass.prototype.action' 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> _GetAliasForIdentifier('MyClass.prototype.action', {}) 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) None 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Args: 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) identifier: The identifier. 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) alias_map: A dictionary mapping a symbol to an alias. 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Returns: 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) The aliased symbol name or None if not found. 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns = identifier.split('.', 1)[0] 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) aliased_symbol = alias_map.get(ns) 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if aliased_symbol: 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return aliased_symbol + identifier[len(ns):] 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class AliasPass(object): 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Pass to identify goog.scope() usages. 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Identifies goog.scope() usages and finds lint/usage errors. Notes any 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) aliases of symbols in Closurized namespaces (that is, reassignments 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) such as "var MyClass = goog.foo.MyClass;") and annotates identifiers 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) when they're using an alias (so they may be expanded to the full symbol 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) later -- that "MyClass.prototype.action" refers to 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "goog.foo.MyClass.prototype.action" when expanded.). 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, closurized_namespaces=None, error_handler=None): 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Creates a new pass. 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Args: 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) closurized_namespaces: A set of Closurized namespaces (e.g. 'goog'). 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error_handler: An error handler to report lint errors to. 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_handler = error_handler 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # If we have namespaces, freeze the set. 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if closurized_namespaces: 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) closurized_namespaces = frozenset(closurized_namespaces) 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._closurized_namespaces = closurized_namespaces 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def Process(self, start_token): 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Runs the pass on a token stream. 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Args: 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start_token: The first token in the stream. 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if start_token is None: 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # TODO(nnaze): Add more goog.scope usage checks. 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._CheckGoogScopeCalls(start_token) 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # If we have closurized namespaces, identify aliased identifiers. 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self._closurized_namespaces: 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) context = start_token.metadata.context 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) root_context = context.GetRoot() 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._ProcessRootContext(root_context) 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _CheckGoogScopeCalls(self, start_token): 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Check goog.scope calls for lint/usage errors.""" 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def IsScopeToken(token): 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (token.type is javascripttokens.JavaScriptTokenType.IDENTIFIER and 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) token.string == 'goog.scope') 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Find all the goog.scope tokens in the file 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scope_tokens = [t for t in start_token if IsScopeToken(t)] 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for token in scope_tokens: 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scope_context = token.metadata.context 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not (scope_context.type == ecmametadatapass.EcmaContext.STATEMENT and 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scope_context.parent.type == ecmametadatapass.EcmaContext.ROOT): 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._MaybeReportError( 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error.Error(errors.INVALID_USE_OF_GOOG_SCOPE, 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'goog.scope call not in global scope', token)) 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # There should be only one goog.scope reference. Register errors for 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # every instance after the first. 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for token in scope_tokens[1:]: 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._MaybeReportError( 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error.Error(errors.EXTRA_GOOG_SCOPE_USAGE, 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'More than one goog.scope call in file.', token)) 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _MaybeReportError(self, err): 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Report an error to the handler (if registered).""" 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self._error_handler: 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_handler.HandleError(err) 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) @classmethod 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _YieldAllContexts(cls, context): 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Yields all contexts that are contained by the given context.""" 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield context 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for child_context in context.children: 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for descendent_child in cls._YieldAllContexts(child_context): 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield descendent_child 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) @staticmethod 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _IsTokenInParentBlock(token, parent_block): 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Determines whether the given token is contained by the given block. 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Args: 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) token: A token 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parent_block: An EcmaContext. 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Returns: 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Whether the token is in a context that is or is a child of the given 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parent_block context. 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) context = token.metadata.context 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while context: 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if context is parent_block: 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return True 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) context = context.parent 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _ProcessRootContext(self, root_context): 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Processes all goog.scope blocks under the root context.""" 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert root_context.type is ecmametadatapass.EcmaContext.ROOT 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Identify all goog.scope blocks. 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) goog_scope_blocks = itertools.ifilter( 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scopeutil.IsGoogScopeBlock, 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._YieldAllContexts(root_context)) 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Process each block to find aliases. 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for scope_block in goog_scope_blocks: 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._ProcessGoogScopeBlock(scope_block) 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _ProcessGoogScopeBlock(self, scope_block): 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Scans a goog.scope block to find aliases and mark alias tokens.""" 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) alias_map = dict() 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Iterate over every token in the scope_block. Each token points to one 1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # context, but multiple tokens may point to the same context. We only want 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # to check each context once, so keep track of those we've seen. 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) seen_contexts = set() 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) token = scope_block.start_token 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while token and self._IsTokenInParentBlock(token, scope_block): 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) token_context = token.metadata.context 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Check to see if this token is an alias. 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if token_context not in seen_contexts: 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) seen_contexts.add(token_context) 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # If this is a alias statement in the goog.scope block. 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (token_context.type == ecmametadatapass.EcmaContext.VAR and 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) token_context.parent.parent is scope_block): 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) match = scopeutil.MatchAlias(token_context) 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # If this is an alias, remember it in the map. 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if match: 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) alias, symbol = match 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) symbol = _GetAliasForIdentifier(symbol, alias_map) or symbol 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if scopeutil.IsInClosurizedNamespace(symbol, 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._closurized_namespaces): 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) alias_map[alias] = symbol 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # If this token is an identifier that matches an alias, 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # mark the token as an alias to the original symbol. 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (token.type is javascripttokens.JavaScriptTokenType.SIMPLE_LVALUE or 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) token.type is javascripttokens.JavaScriptTokenType.IDENTIFIER): 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) identifier = tokenutil.GetIdentifierForToken(token) 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if identifier: 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) aliased_symbol = _GetAliasForIdentifier(identifier, alias_map) 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if aliased_symbol: 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) token.metadata.aliased_symbol = aliased_symbol 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) token = token.next # Get next token 223