All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.javascript.jscomp.CommandLineRunner Maven / Gradle / Ivy

Go to download

Closure Compiler is a JavaScript optimizing compiler. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what's left. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls. It is used in many of Google's JavaScript apps, including Gmail, Google Web Search, Google Maps, and Google Docs.

There is a newer version: v20240317
Show newest version
/*
 * Copyright 2009 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.javascript.jscomp;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.io.Files;
import com.google.common.io.LimitInputStream;

import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.OptionDef;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.Parameters;
import org.kohsuke.args4j.spi.Setter;
import org.kohsuke.args4j.spi.StringOptionHandler;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * CommandLineRunner translates flags into Java API calls on the Compiler.
 *
 * This class may be extended and used to create other Java classes
 * that behave the same as running the Compiler from the command line. If you
 * want to run the compiler in-process in Java, you should look at this class
 * for hints on what API calls to make, but you should not use this class
 * directly.
 *
 * Example:
 * 
 * class MyCommandLineRunner extends CommandLineRunner {
 *   MyCommandLineRunner(String[] args) {
 *     super(args);
 *   }
 *
 *   {@code @Override} protected CompilerOptions createOptions() {
 *     CompilerOptions options = super.createOptions();
 *     addMyCrazyCompilerPassThatOutputsAnExtraFile(options);
 *     return options;
 *   }
 *
 *   public static void main(String[] args) {
 *     MyCommandLineRunner runner = new MyCommandLineRunner(args);
 *     if (runner.shouldRunCompiler()) {
 *       runner.run();
 *     } else {
 *       System.exit(-1);
 *     }
 *   }
 * }
 * 
* * This class is totally not thread-safe. * * @author [email protected] (Michael Bolin) */ public class CommandLineRunner extends AbstractCommandLineRunner { // I don't really care about unchecked warnings in this class. @SuppressWarnings("unchecked") private static class Flags { private static final WarningGuardSpec warningGuardSpec = new WarningGuardSpec(); @Option(name = "--help", handler = BooleanOptionHandler.class, usage = "Displays this message") private boolean display_help = false; @Option(name = "--print_tree", handler = BooleanOptionHandler.class, usage = "Prints out the parse tree and exits") private boolean print_tree = false; @Option(name = "--print_ast", handler = BooleanOptionHandler.class, usage = "Prints a dot file describing the internal abstract syntax" + " tree and exits") private boolean print_ast = false; @Option(name = "--print_pass_graph", handler = BooleanOptionHandler.class, usage = "Prints a dot file describing the passes that will get run" + " and exits") private boolean print_pass_graph = false; // Turn on (very slow) extra sanity checks for use when modifying the // compiler. @Option(name = "--jscomp_dev_mode", // hidden, no usage aliases = {"--dev_mode"}) private CompilerOptions.DevMode jscomp_dev_mode = CompilerOptions.DevMode.OFF; @Option(name = "--logging_level", usage = "The logging level (standard java.util.logging.Level" + " values) for Compiler progress. Does not control errors or" + " warnings for the JavaScript code under compilation") private String logging_level = Level.WARNING.getName(); @Option(name = "--externs", usage = "The file containing javascript externs. You may specify" + " multiple") private List externs = Lists.newArrayList(); @Option(name = "--js", usage = "The javascript filename. You may specify multiple") private List js = Lists.newArrayList(); @Option(name = "--js_output_file", usage = "Primary output filename. If not specified, output is " + "written to stdout") private String js_output_file = ""; @Option(name = "--module", usage = "A javascript module specification. The format is " + ":[:[,...][:]]]. Module names must be " + "unique. Each dep is the name of a module that this module " + "depends on. Modules must be listed in dependency order, and js " + "source files must be listed in the corresponding order. Where " + "--module flags occur in relation to --js flags is unimportant") private List module = Lists.newArrayList(); @Option(name = "--variable_map_input_file", usage = "File containing the serialized version of the variable " + "renaming map produced by a previous compilation") private String variable_map_input_file = ""; @Option(name = "--property_map_input_file", usage = "File containing the serialized version of the property " + "renaming map produced by a previous compilation") private String property_map_input_file = ""; @Option(name = "--variable_map_output_file", usage = "File where the serialized version of the variable " + "renaming map produced should be saved") private String variable_map_output_file = ""; @Option(name = "--create_name_map_files", handler = BooleanOptionHandler.class, usage = "If true, variable renaming and property renaming map " + "files will be produced as {binary name}_vars_map.out and " + "{binary name}_props_map.out. Note that this flag cannot be used " + "in conjunction with either variable_map_output_file or " + "property_map_output_file") private boolean create_name_map_files = false; @Option(name = "--property_map_output_file", usage = "File where the serialized version of the property " + "renaming map produced should be saved") private String property_map_output_file = ""; @Option(name = "--third_party", handler = BooleanOptionHandler.class, usage = "Check source validity but do not enforce Closure style " + "rules and conventions") private boolean third_party = false; @Option(name = "--summary_detail_level", usage = "Controls how detailed the compilation summary is. Values:" + " 0 (never print summary), 1 (print summary only if there are " + "errors or warnings), 2 (print summary if type checking is on, " + "see --check_types), 3 (always print summary). The default level " + "is 1") private int summary_detail_level = 1; @Option(name = "--output_wrapper", usage = "Interpolate output into this string at the place denoted" + " by the marker token %output%. See --output_wrapper_marker") private String output_wrapper = ""; @Option(name = "--module_wrapper", usage = "An output wrapper for a javascript module (optional). " + "The format is :. The module name must correspond " + "with a module specified using --module. The wrapper must " + "contain %s as the code placeholder. The %basename% placeholder can " + "also be used to substitute the base name of the module output file.") private List module_wrapper = Lists.newArrayList(); @Option(name = "--module_output_path_prefix", usage = "Prefix for filenames of compiled js modules. " + ".js will be appended to this prefix. Directories " + "will be created as needed. Use with --module") private String module_output_path_prefix = "./"; @Option(name = "--create_source_map", usage = "If specified, a source map file mapping the generated " + "source files back to the original source file will be " + "output to the specified path. The %outname% placeholder will " + "expand to the name of the output file that the source map " + "corresponds to.") private String create_source_map = ""; @Option(name = "--source_map_format", usage = "The source map format to produce. " + "Options: V1, V2, V3, DEFAULT. DEFAULT produces V2.") private SourceMap.Format source_map_format = SourceMap.Format.DEFAULT; // Used to define the flag, values are stored by the handler. @SuppressWarnings("unused") @Option(name = "--jscomp_error", handler = WarningGuardErrorOptionHandler.class, usage = "Make the named class of warnings an error. Options:" + DiagnosticGroups.DIAGNOSTIC_GROUP_NAMES) private List jscomp_error = Lists.newArrayList(); // Used to define the flag, values are stored by the handler. @SuppressWarnings("unused") @Option(name = "--jscomp_warning", handler = WarningGuardWarningOptionHandler.class, usage = "Make the named class of warnings a normal warning. " + "Options:" + DiagnosticGroups.DIAGNOSTIC_GROUP_NAMES) private List jscomp_warning = Lists.newArrayList(); // Used to define the flag, values are stored by the handler. @SuppressWarnings("unused") @Option(name = "--jscomp_off", handler = WarningGuardOffOptionHandler.class, usage = "Turn off the named class of warnings. Options:" + DiagnosticGroups.DIAGNOSTIC_GROUP_NAMES) private List jscomp_off = Lists.newArrayList(); @Option(name = "--define", aliases = {"--D", "-D"}, usage = "Override the value of a variable annotated @define. " + "The format is [=], where is the name of a @define " + "variable and is a boolean, number, or a single-quoted string " + "that contains no single quotes. If [=] is omitted, " + "the variable is marked true") private List define = Lists.newArrayList(); @Option(name = "--charset", usage = "Input and output charset for all files. By default, we " + "accept UTF-8 as input and output US_ASCII") private String charset = ""; @Option(name = "--compilation_level", usage = "Specifies the compilation level to use. Options: " + "WHITESPACE_ONLY, SIMPLE_OPTIMIZATIONS, ADVANCED_OPTIMIZATIONS") private CompilationLevel compilation_level = CompilationLevel.SIMPLE_OPTIMIZATIONS; @Option(name = "--warning_level", usage = "Specifies the warning level to use. Options: " + "QUIET, DEFAULT, VERBOSE") private WarningLevel warning_level = WarningLevel.DEFAULT; @Option(name = "--use_only_custom_externs", handler = BooleanOptionHandler.class, usage = "Specifies whether the default externs should be excluded") private boolean use_only_custom_externs = false; @Option(name = "--debug", handler = BooleanOptionHandler.class, usage = "Enable debugging options") private boolean debug = false; @Option(name = "--generate_exports", handler = BooleanOptionHandler.class, usage = "Generates export code for those marked with @export") private boolean generate_exports = false; @Option(name = "--formatting", usage = "Specifies which formatting options, if any, should be " + "applied to the output JS. Options: " + "PRETTY_PRINT, PRINT_INPUT_DELIMITER") private List formatting = Lists.newArrayList(); @Option(name = "--process_common_js_modules", usage = "Process Common JS modules to a concatenable form.") private boolean process_common_js_modules = false; @Option(name = "--common_js_module_path_prefix", usage = "Path prefix to be removed from Common JS module names.") private String common_js_path_prefix = ProcessCommonJSModules.DEFAULT_FILENAME_PREFIX; @Option(name = "--common_js_entry_module", usage = "Root of your common JS dependency hierarchy. "+ "Your main script.") private String common_js_entry_module; @Option(name = "--transform_amd_modules", usage = "Transform AMD to Common JS modules.") private boolean transform_amd_modules = false; @Option(name = "--process_closure_primitives", handler = BooleanOptionHandler.class, usage = "Processes built-ins from the Closure library, such as " + "goog.require(), goog.provide(), and goog.exportSymbol()") private boolean process_closure_primitives = true; @Option(name = "--manage_closure_dependencies", handler = BooleanOptionHandler.class, usage = "Automatically sort dependencies so that a file that " + "goog.provides symbol X will always come before a file that " + "goog.requires symbol X. If an input provides symbols, and " + "those symbols are never required, then that input will not " + "be included in the compilation.") private boolean manage_closure_dependencies = false; @Option(name = "--closure_entry_point", usage = "Entry points to the program. Must be goog.provide'd " + "symbols. Any goog.provide'd symbols that are not a transitive " + "dependency of the entry points will be removed. Files without " + "goog.provides, and their dependencies, will always be left in. " + "If any entry points are specified, then the " + "manage_closure_dependencies option will be set to true and " + "all files will be sorted in dependency order.") private List closure_entry_point = Lists.newArrayList(); @Option(name = "--process_jquery_primitives", handler = BooleanOptionHandler.class, usage = "Processes built-ins from the Jquery library, such as " + "jQuery.fn and jQuery.extend()") private boolean process_jquery_primitives = false; @Option(name = "--output_manifest", usage = "Prints out a list of all the files in the compilation. " + "If --manage_closure_dependencies is on, this will not include " + "files that got dropped because they were not required. " + "The %outname% placeholder expands to the js output file. " + "If you're using modularization, using %outname% will create " + "a manifest for each module.") private String output_manifest = ""; @Option(name = "--accept_const_keyword", usage = "Allows usage of const keyword.") private boolean accept_const_keyword = false; @Option(name = "--language_in", usage = "Sets what language spec that input sources conform. " + "Options: ECMASCRIPT3 (default), ECMASCRIPT5, ECMASCRIPT5_STRICT") private String language_in = "ECMASCRIPT3"; @Option(name = "--version", handler = BooleanOptionHandler.class, usage = "Prints the compiler version to stderr.") private boolean version = false; @Option(name = "--translations_file", usage = "Source of translated messages. Currently only supports XTB.") private String translationsFile = ""; @Option(name = "--translations_project", usage = "Scopes all translations to the specified project." + "When specified, we will use different message ids so that messages " + "in different projects can have different translations.") private String translationsProject = null; @Option(name = "--flagfile", usage = "A file containing additional command-line options.") private String flag_file = ""; @Argument private List arguments = Lists.newArrayList(); /** * Users may specify JS inputs via the legacy {@code --js} option, as well * as via additional arguments to the Closure Compiler. For example, it is * convenient to leverage the additional arguments feature when using the * Closure Compiler in combination with {@code find} and {@code xargs}: *
     * find MY_JS_SRC_DIR -name '*.js' \
     *     | xargs java -jar compiler.jar --manage_closure_dependencies
     * 
* The {@code find} command will produce a list of '*.js' source files in * the {@code MY_JS_SRC_DIR} directory while {@code xargs} will convert them * to a single, space-delimited set of arguments that are appended to the * {@code java} command to run the Compiler. *

* Note that it is important to use the * {@code --manage_closure_dependencies} option in this case because the * order produced by {@code find} is unlikely to be sorted correctly with * respect to {@code goog.provide()} and {@code goog.requires()}. */ List getJsFiles() { List allJsInputs = Lists.newArrayListWithCapacity( js.size() + arguments.size()); allJsInputs.addAll(js); allJsInputs.addAll(arguments); return allJsInputs; } // Our own option parser to be backwards-compatible. // It needs to be public because of the crazy reflection that args4j does. public static class BooleanOptionHandler extends OptionHandler { private static final Set TRUES = Sets.newHashSet("true", "on", "yes", "1"); private static final Set FALSES = Sets.newHashSet("false", "off", "no", "0"); public BooleanOptionHandler( CmdLineParser parser, OptionDef option, Setter setter) { super(parser, option, setter); } @Override public int parseArguments(Parameters params) throws CmdLineException { String param = null; try { param = params.getParameter(0); } catch (CmdLineException e) {} if (param == null) { setter.addValue(true); return 0; } else { String lowerParam = param.toLowerCase(); if (TRUES.contains(lowerParam)) { setter.addValue(true); } else if (FALSES.contains(lowerParam)) { setter.addValue(false); } else { setter.addValue(true); return 0; } return 1; } } @Override public String getDefaultMetaVariable() { return null; } } // Our own parser for warning guards that preserves the original order // of the flags. public static class WarningGuardErrorOptionHandler extends StringOptionHandler { public WarningGuardErrorOptionHandler( CmdLineParser parser, OptionDef option, Setter setter) { super(parser, option, new WarningGuardSetter(setter, CheckLevel.ERROR)); } } public static class WarningGuardWarningOptionHandler extends StringOptionHandler { public WarningGuardWarningOptionHandler( CmdLineParser parser, OptionDef option, Setter setter) { super(parser, option, new WarningGuardSetter(setter, CheckLevel.WARNING)); } } public static class WarningGuardOffOptionHandler extends StringOptionHandler { public WarningGuardOffOptionHandler( CmdLineParser parser, OptionDef option, Setter setter) { super(parser, option, new WarningGuardSetter(setter, CheckLevel.OFF)); } } private static class WarningGuardSetter implements Setter { private final Setter proxy; private final CheckLevel level; private WarningGuardSetter( Setter proxy, CheckLevel level) { this.proxy = proxy; this.level = level; } @Override public boolean isMultiValued() { return proxy.isMultiValued(); } @Override public Class getType() { return (Class) proxy.getType(); } @Override public void addValue(String value) throws CmdLineException { proxy.addValue(value); warningGuardSpec.add(level, value); } } } /** * Set of options that can be used with the --formatting flag. */ private static enum FormattingOption { PRETTY_PRINT, PRINT_INPUT_DELIMITER, ; private void applyToOptions(CompilerOptions options) { switch (this) { case PRETTY_PRINT: options.prettyPrint = true; break; case PRINT_INPUT_DELIMITER: options.printInputDelimiter = true; break; default: throw new RuntimeException("Unknown formatting option: " + this); } } } private final Flags flags = new Flags(); private static final String configResource = "com.google.javascript.jscomp.parsing.ParserConfig"; private boolean isConfigValid = false; /** * Create a new command-line runner. You should only need to call * the constructor if you're extending this class. Otherwise, the main * method should instantiate it. */ protected CommandLineRunner(String[] args) { super(); initConfigFromFlags(args, System.err); } protected CommandLineRunner(String[] args, PrintStream out, PrintStream err) { super(out, err); initConfigFromFlags(args, err); } private List processArgs(String[] args) { // Args4j has a different format that the old command-line parser. // So we use some voodoo to get the args into the format that args4j // expects. Pattern argPattern = Pattern.compile("(--[a-zA-Z_]+)=(.*)"); Pattern quotesPattern = Pattern.compile("^['\"](.*)['\"]$"); List processedArgs = Lists.newArrayList(); for (String arg : args) { Matcher matcher = argPattern.matcher(arg); if (matcher.matches()) { processedArgs.add(matcher.group(1)); String value = matcher.group(2); Matcher quotesMatcher = quotesPattern.matcher(value); if (quotesMatcher.matches()) { processedArgs.add(quotesMatcher.group(1)); } else { processedArgs.add(value); } } else { processedArgs.add(arg); } } return processedArgs; } private void processFlagFile(PrintStream err) throws CmdLineException, IOException { List argsInFile = Lists.newArrayList(); File flagFileInput = new File(flags.flag_file); StringTokenizer tokenizer = new StringTokenizer( Files.toString(flagFileInput, Charset.defaultCharset())); while (tokenizer.hasMoreTokens()) { argsInFile.add(tokenizer.nextToken()); } flags.flag_file = ""; List processedFileArgs = processArgs(argsInFile.toArray(new String[] {})); CmdLineParser parserFileArgs = new CmdLineParser(flags); Flags.warningGuardSpec.clear(); parserFileArgs.parseArgument(processedFileArgs.toArray(new String[] {})); // Currently we are not supporting this (prevent direct/indirect loops) if (!flags.flag_file.equals("")) { err.println("ERROR - Arguments in the file cannot contain " + "--flagfile option."); isConfigValid = false; } } private void initConfigFromFlags(String[] args, PrintStream err) { List processedArgs = processArgs(args); CmdLineParser parser = new CmdLineParser(flags); Flags.warningGuardSpec.clear(); isConfigValid = true; try { parser.parseArgument(processedArgs.toArray(new String[] {})); // For contains --flagfile flag if (!flags.flag_file.equals("")) { processFlagFile(err); } } catch (CmdLineException e) { err.println(e.getMessage()); isConfigValid = false; } catch (IOException ioErr) { err.println("ERROR - " + flags.flag_file + " read error."); isConfigValid = false; } if (flags.version) { ResourceBundle config = ResourceBundle.getBundle(configResource); err.println( "Closure Compiler (http://code.google.com/closure/compiler)\n" + "Version: " + config.getString("compiler.version") + "\n" + "Built on: " + config.getString("compiler.date")); err.flush(); } if (flags.process_common_js_modules) { flags.process_closure_primitives = true; flags.manage_closure_dependencies = true; if (flags.common_js_entry_module == null) { err.println("Please specify --common_js_entry_module."); err.flush(); isConfigValid = false; } flags.closure_entry_point = Lists.newArrayList( ProcessCommonJSModules.toModuleName(flags.common_js_entry_module)); } if (!isConfigValid || flags.display_help) { isConfigValid = false; parser.printUsage(err); } else { getCommandLineConfig() .setPrintTree(flags.print_tree) .setPrintAst(flags.print_ast) .setPrintPassGraph(flags.print_pass_graph) .setJscompDevMode(flags.jscomp_dev_mode) .setLoggingLevel(flags.logging_level) .setExterns(flags.externs) .setJs(flags.getJsFiles()) .setJsOutputFile(flags.js_output_file) .setModule(flags.module) .setVariableMapInputFile(flags.variable_map_input_file) .setPropertyMapInputFile(flags.property_map_input_file) .setVariableMapOutputFile(flags.variable_map_output_file) .setCreateNameMapFiles(flags.create_name_map_files) .setPropertyMapOutputFile(flags.property_map_output_file) .setCodingConvention(flags.third_party ? CodingConventions.getDefault() : new ClosureCodingConvention()) .setSummaryDetailLevel(flags.summary_detail_level) .setOutputWrapper(flags.output_wrapper) .setModuleWrapper(flags.module_wrapper) .setModuleOutputPathPrefix(flags.module_output_path_prefix) .setCreateSourceMap(flags.create_source_map) .setSourceMapFormat(flags.source_map_format) .setWarningGuardSpec(Flags.warningGuardSpec) .setDefine(flags.define) .setCharset(flags.charset) .setManageClosureDependencies(flags.manage_closure_dependencies) .setClosureEntryPoints(flags.closure_entry_point) .setOutputManifest(ImmutableList.of(flags.output_manifest)) .setAcceptConstKeyword(flags.accept_const_keyword) .setLanguageIn(flags.language_in) .setProcessCommonJSModules(flags.process_common_js_modules) .setCommonJSModulePathPrefix(flags.common_js_path_prefix) .setTransformAMDToCJSModules(flags.transform_amd_modules); } } @Override protected CompilerOptions createOptions() { CompilerOptions options = new CompilerOptions(); options.setCodingConvention(new ClosureCodingConvention()); CompilationLevel level = flags.compilation_level; level.setOptionsForCompilationLevel(options); if (flags.debug) { level.setDebugOptionsForCompilationLevel(options); } if (flags.generate_exports) { options.setGenerateExports(flags.generate_exports); } WarningLevel wLevel = flags.warning_level; wLevel.setOptionsForWarningLevel(options); for (FormattingOption formattingOption : flags.formatting) { formattingOption.applyToOptions(options); } options.closurePass = flags.process_closure_primitives; options.jqueryPass = flags.process_jquery_primitives && CompilationLevel.ADVANCED_OPTIMIZATIONS == level; if (flags.process_jquery_primitives) { options.setCodingConvention(new JqueryCodingConvention()); } if (!flags.translationsFile.isEmpty()) { try { options.messageBundle = new XtbMessageBundle( new FileInputStream(flags.translationsFile), flags.translationsProject); } catch (IOException e) { throw new RuntimeException("Reading XTB file", e); } } else if (CompilationLevel.ADVANCED_OPTIMIZATIONS == level) { // In SIMPLE or WHITESPACE mode, if the user hasn't specified a // translations file, they might reasonably try to write their own // implementation of goog.getMsg that makes the substitution at // run-time. // // In ADVANCED mode, goog.getMsg is going to be renamed anyway, // so we might as well inline it. options.messageBundle = new EmptyMessageBundle(); } return options; } @Override protected Compiler createCompiler() { return new Compiler(getErrorPrintStream()); } @Override protected List createExterns() throws FlagUsageException, IOException { List externs = super.createExterns(); if (flags.use_only_custom_externs || isInTestMode()) { return externs; } else { List defaultExterns = getDefaultExterns(); defaultExterns.addAll(externs); return defaultExterns; } } // The externs expected in externs.zip, in sorted order. private static final List DEFAULT_EXTERNS_NAMES = ImmutableList.of( // JS externs "es3.js", "es5.js", // Event APIs "w3c_event.js", "w3c_event3.js", "gecko_event.js", "ie_event.js", "webkit_event.js", // DOM apis "w3c_dom1.js", "w3c_dom2.js", "w3c_dom3.js", "gecko_dom.js", "ie_dom.js", "webkit_dom.js", // CSS apis "w3c_css.js", "gecko_css.js", "ie_css.js", "webkit_css.js", // Top-level namespaces "google.js", "deprecated.js", "fileapi.js", "flash.js", "gears_symbols.js", "gears_types.js", "gecko_xml.js", "html5.js", "ie_vml.js", "iphone.js", "webstorage.js", "w3c_anim_timing.js", "w3c_css3d.js", "w3c_elementtraversal.js", "w3c_geolocation.js", "w3c_indexeddb.js", "w3c_navigation_timing.js", "w3c_range.js", "w3c_selectors.js", "w3c_xml.js", "window.js", "webkit_notifications.js", "webgl.js"); /** * @return a mutable list * @throws IOException */ public static List getDefaultExterns() throws IOException { InputStream input = CommandLineRunner.class.getResourceAsStream( "/externs.zip"); ZipInputStream zip = new ZipInputStream(input); Map externsMap = Maps.newHashMap(); for (ZipEntry entry = null; (entry = zip.getNextEntry()) != null; ) { BufferedInputStream entryStream = new BufferedInputStream( new LimitInputStream(zip, entry.getSize())); externsMap.put(entry.getName(), JSSourceFile.fromInputStream( // Give the files an odd prefix, so that they do not conflict // with the user's files. "externs.zip//" + entry.getName(), entryStream)); } Preconditions.checkState( externsMap.keySet().equals(Sets.newHashSet(DEFAULT_EXTERNS_NAMES)), "Externs zip must match our hard-coded list of externs."); // Order matters, so the resources must be added to the result list // in the expected order. List externs = Lists.newArrayList(); for (String key : DEFAULT_EXTERNS_NAMES) { externs.add(externsMap.get(key)); } return externs; } /** * @return Whether the configuration is valid. */ public boolean shouldRunCompiler() { return this.isConfigValid; } /** * Runs the Compiler. Exits cleanly in the event of an error. */ public static void main(String[] args) { CommandLineRunner runner = new CommandLineRunner(args); if (runner.shouldRunCompiler()) { runner.run(); } else { System.exit(-1); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy