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