1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#!/usr/bin/env python 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)# Copyright 2014 The Chromium Authors. All rights reserved. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)# found in the LICENSE file. 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)'''Uses the closure compiler to check the ChromeVox javascript files. 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)With no arguments, checks all ChromeVox scripts. If any arguments are 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)specified, only scripts that include any of the specified files will be 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)compiled. A useful argument list is the output of the command 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)'git diff --name-only --relative'. 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)''' 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import optparse 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import os 176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)import re 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import sys 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)from multiprocessing import pool 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)from jsbundler import Bundle, CalcDeps, ReadSources 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)from jscompilerwrapper import RunCompiler 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)_CHROME_SOURCE_DIR = os.path.normpath( 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) os.path.join(_SCRIPT_DIR, *[os.path.pardir] * 6)) 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def CVoxPath(path='.'): 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) '''Converts a path relative to the top-level chromevox directory to a 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) path relative to the current directory. 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ''' 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return os.path.relpath(os.path.join(_SCRIPT_DIR, '..', path)) 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)# Externs common to many ChromeVox scripts. 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)_COMMON_EXTERNS = [ 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CVoxPath('common/externs.js'), 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CVoxPath('common/chrome_extension_externs.js'), 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CVoxPath('chromevox/background/externs.js'), 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CVoxPath('chromevox/injected/externs.js'), 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CVoxPath('liblouis_nacl/externs.js'), 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CVoxPath('host/chrome/externs.js')] 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)# List of top-level scripts and externs that we can check. 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)_TOP_LEVEL_SCRIPTS = [ 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) [[CVoxPath('chromevox/background/kbexplorer_loader.js')], 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) [CVoxPath('common/chrome_extension_externs.js')]], 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) [[CVoxPath('chromevox/background/loader.js')], _COMMON_EXTERNS], 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) [[CVoxPath('chromevox/background/options_loader.js')], _COMMON_EXTERNS], 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) [[CVoxPath('chromevox/injected/loader.js')], _COMMON_EXTERNS], 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ] 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def _Compile(js_files, externs): 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) try: 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RunCompiler(js_files, externs) 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) except KeyboardInterrupt: 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return (False, 'KeyboardInterrupt') 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def CheckChromeVox(changed_files=None): 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if changed_files is not None: 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) changed_files_set = frozenset( 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (os.path.relpath(path) for path in changed_files)) 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if len(changed_files_set) == 0: 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return (True, '') 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) else: 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) changed_files_set = None 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ret_success = True 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ret_output = '' 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) roots = [CVoxPath(), 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) os.path.relpath( 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) os.path.join( 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) _CHROME_SOURCE_DIR, 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'chrome/third_party/chromevox/third_party/closure-library/' 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'closure/goog'))] 796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) sources = ReadSources(roots, need_source_text=True, 806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) exclude=[re.compile('testing')]) 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) work_pool = pool.Pool(len(_TOP_LEVEL_SCRIPTS)) 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) try: 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) results = [] 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for top_level in _TOP_LEVEL_SCRIPTS: 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) tl_files, externs = top_level 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bundle = Bundle() 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CalcDeps(bundle, sources, tl_files) 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bundle.Add((sources[name] for name in tl_files)) 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ordered_paths = list(bundle.GetInPaths()) 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (changed_files_set is not None and 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) changed_files_set.isdisjoint(ordered_paths + externs)): 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) print 'Compiling %s' % ','.join(tl_files) 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) results.append([tl_files, 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) work_pool.apply_async( 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) _Compile, 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) args=[ordered_paths, externs])]) 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for result in results: 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) tl_files = result[0] 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) success, output = result[1].get() 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if not success: 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ret_output += '\nFrom compiling %s:\n%s\n' % (','.join(tl_files), 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) output) 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ret_success = False 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) work_pool.close() 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) except: 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) work_pool.terminate() 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) raise 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) finally: 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) work_pool.join() 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return (ret_success, ret_output) 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def main(): 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) parser = optparse.OptionParser(description=__doc__) 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) parser.usage = '%prog [<changed_file>...]' 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) _, args = parser.parse_args() 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) changed_paths = None 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if len(args) > 0: 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) changed_paths = (os.path.relpath(p) for p in args) 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) success, output = CheckChromeVox(changed_paths) 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if len(output) > 0: 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) print output 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return int(not success) 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)if __name__ == '__main__': 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) sys.exit(main()) 130