jscompilerwrapper.py revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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 syntax and semantics of a js module
8with dependencies.'''
9
10import os
11import re
12import subprocess
13import sys
14
15_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
16_CHROME_SOURCE_DIR = os.path.normpath(
17    os.path.join(
18        _SCRIPT_DIR, *[os.path.pardir] * 6))
19
20# Compiler path.
21_CLOSURE_COMPILER_JAR = os.path.join(
22    _CHROME_SOURCE_DIR, 'third_party', 'WebKit', 'Source', 'devtools',
23    'scripts', 'closure', 'compiler.jar')
24
25# List of compilation errors to enable with the --jscomp_errors flag.
26_JSCOMP_ERRORS = [ 'accessControls', 'checkTypes', 'checkVars', 'invalidCasts',
27                   'missingProperties', 'undefinedNames', 'undefinedVars',
28                   'visibility' ]
29
30_java_executable = 'java'
31
32
33def _Error(msg):
34  print >>sys.stderr, msg
35  sys.exit(1)
36
37
38def _ExecuteCommand(args, ignore_exit_status=False):
39  try:
40    return subprocess.check_output(args, stderr=subprocess.STDOUT)
41  except subprocess.CalledProcessError as e:
42    if ignore_exit_status and e.returncode > 0:
43      return e.output
44    _Error('%s\nCommand \'%s\' returned non-zero exit status %d' %
45           (e.output, ' '.join(e.cmd), e.returncode))
46  except (OSError, IOError) as e:
47    _Error('Error executing %s: %s' % (_java_executable, str(e)))
48
49
50def _CheckJava():
51  global _java_executable
52  java_home = os.environ.get('JAVAHOME')
53  if java_home is not None:
54    _java_executable = os.path.join(java_home, 'bin', 'java')
55  output = _ExecuteCommand([_java_executable, '-version'])
56  match = re.search(r'version "(?:\d+)\.(\d+)', output)
57  if match is None or int(match.group(1)) < 7:
58    _Error('Java 7 or later is required: \n%s' % output)
59
60_CheckJava()
61
62
63def RunCompiler(js_files, externs=[]):
64  args = [_java_executable, '-jar', _CLOSURE_COMPILER_JAR]
65  args.extend(['--compilation_level', 'SIMPLE_OPTIMIZATIONS'])
66  args.extend(['--jscomp_error=%s' % error for error in _JSCOMP_ERRORS])
67  args.extend(['--externs=%s' % extern for extern in externs])
68  args.extend(['--js=%s' % js for js in js_files])
69  args.extend(['--js_output_file', '/dev/null'])
70  output = _ExecuteCommand(args, ignore_exit_status=True)
71  success = len(output) == 0
72  return success, output
73