From f712affc5846b8d832d842c63b1b2ef20c43053c Mon Sep 17 00:00:00 2001 From: tjgq Date: Thu, 25 Jul 2019 16:56:57 -0700 Subject: [PATCH] Split off the GWT-specific parts of JsfileParser into a separate file. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=260049168 --- .../jscomp/gwt/client/CompilerMain.java | 2 +- .../jscomp/gwt/client/JsfileParser.java | 142 +--------------- .../jscomp/gwt/client/JsfileParserGwt.java | 155 ++++++++++++++++++ .../jscomp/gwt/client/JsfileParserMain.java | 2 +- 4 files changed, 164 insertions(+), 137 deletions(-) create mode 100644 src/com/google/javascript/jscomp/gwt/client/JsfileParserGwt.java diff --git a/src/com/google/javascript/jscomp/gwt/client/CompilerMain.java b/src/com/google/javascript/jscomp/gwt/client/CompilerMain.java index d5a57229409..5a9ea782d46 100644 --- a/src/com/google/javascript/jscomp/gwt/client/CompilerMain.java +++ b/src/com/google/javascript/jscomp/gwt/client/CompilerMain.java @@ -23,7 +23,7 @@ */ final class CompilerMain implements EntryPoint { private static final GwtRunner gwtRunner = new GwtRunner(); - private static final JsfileParser jsFileParser = new JsfileParser(); + private static final JsfileParserGwt jsFileParser = new JsfileParserGwt(); @Override public void onModuleLoad() { diff --git a/src/com/google/javascript/jscomp/gwt/client/JsfileParser.java b/src/com/google/javascript/jscomp/gwt/client/JsfileParser.java index 6574ead9833..6305e2e931b 100644 --- a/src/com/google/javascript/jscomp/gwt/client/JsfileParser.java +++ b/src/com/google/javascript/jscomp/gwt/client/JsfileParser.java @@ -32,8 +32,6 @@ import com.google.javascript.jscomp.JSError; import com.google.javascript.jscomp.SourceFile; import com.google.javascript.jscomp.deps.ModuleLoader.ResolutionMode; -import com.google.javascript.jscomp.gwt.client.Util.JsArray; -import com.google.javascript.jscomp.gwt.client.Util.JsObject; import com.google.javascript.jscomp.modules.ModuleMetadataMap.ModuleMetadata; import com.google.javascript.jscomp.parsing.Config; import com.google.javascript.jscomp.parsing.ParserRunner; @@ -47,47 +45,17 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.TreeSet; import javax.annotation.Nullable; -import jsinterop.annotations.JsFunction; -import jsinterop.annotations.JsMethod; /** - * GWT module to parse files for dependency and - * {@literal @}{@code fileoverview} annotation - * information. + * A parser that extracts dependency information from a .js file, including goog.require, + * goog.provide, goog.module, import/export statements, and JSDoc annotations related to dependency + * management. */ public class JsfileParser { - - /** - * All the information parsed out of a single file. - * Exported as a JSON object: - *
 {@code {
-   *   "custom_annotations": {?Array<[string, string]>},  @.*
-   *   "goog": {?bool},  whether 'goog' is implicitly required
-   *   "has_soy_delcalls": {?Array},  @fileoverview @hassoydelcall {.*}
-   *   "has_soy_deltemplates": {?Array},  @fileoverview @hassoydeltemplate {.*}
-   *   "imported_modules": {?Array},  import ... from .*
-   *   "is_config": {?bool},  @fileoverview @config
-   *   "is_externs": {?bool},  @fileoverview @externs
-   *   "load_flags": {?Array<[string, string]>},
-   *   "mod_name": {?Array},  @fileoverview @modName .*, @modName {.*}
-   *   "mods": {?Array},  @fileoverview @mods {.*}
-   *   "provide_goog": {?bool},  @fileoverview @provideGoog
-   *   "provides": {?Array},
-   *   "requires": {?Array},  note: look for goog.* for 'goog'
-   *   "requires_css": {?Array},  @fileoverview @requirecss {.*}
-   *   "testonly": {?bool},  goog.setTestOnly
-   *   "type_requires": {?Array},
-   *   "visibility: {?Array},  @fileoverview @visibility {.*}
-   * }}
- * Any trivial values are omitted. - */ static final class FileInfo { - final ErrorReporter reporter; - boolean goog = false; boolean isConfig = false; boolean isExterns = false; @@ -111,56 +79,8 @@ static final class FileInfo { final Multimap customAnnotations = TreeMultimap.create(); final Multimap loadFlags = TreeMultimap.create(); - - FileInfo(ErrorReporter reporter) { - this.reporter = reporter; - } - - private void handleGoog() { - if (provideGoog) { - provides.add("goog"); - } else if (goog) { - requires.add("goog"); - } - } - - /** Exports the file info as a JSON object. */ - JsObject full() { - handleGoog(); - return new SparseObject() - .set("custom_annotations", customAnnotations) - .set("goog", goog) - .set("has_soy_delcalls", hasSoyDelcalls) - .set("has_soy_deltemplates", hasSoyDeltemplates) - .set("imported_modules", importedModules) - .set("is_config", isConfig) - .set("is_externs", isExterns) - .set("load_flags", loadFlags) - .set("modName", modName) - .set("mods", mods) - .set("provide_goog", provideGoog) - .set("provides", provides) - .set("requires", requires) - .set("requiresCss", requiresCss) - .set("testonly", testonly) - .set("type_requires", typeRequires) - .set("visibility", visibility) - .object; - } } - /** - * Exports the {@link #compile} method via JSNI. - * - *

This will be placed on {@code module.exports.gjd} or the global {@code jscomp.gjd}. - */ - public native void exportGjd() /*-{ - var fn = $entry(@com.google.javascript.jscomp.gwt.client.JsfileParser::gjd(*)); - if (typeof module !== 'undefined' && module.exports) { - module.exports.gjd = fn; - } - }-*/; - /** Represents a single JSDoc annotation, with an optional argument. */ private static class CommentAnnotation { @@ -204,14 +124,8 @@ static List parse(String comment) { private static final int ANNOTATION_VALUE_GROUP = 2; } - /** Method exported to JS to parse a file for dependencies and annotations. */ - @JsMethod(namespace = "jscomp") - public static JsObject gjd(String code, String filename, @Nullable Reporter reporter) { - return parse(code, filename, reporter).full(); - } - - /** Internal implementation to produce the {@link FileInfo} object. */ - private static FileInfo parse(String code, String filename, @Nullable Reporter reporter) { + /** Parses a JavaScript file for dependencies and annotations. */ + public static FileInfo parse(String code, String filename, @Nullable Reporter reporter) { ErrorReporter errorReporter = new DelegatingReporter(reporter); Compiler compiler = new Compiler( @@ -251,7 +165,7 @@ protected void printSummary() {} /* extraAnnotationNames */ ImmutableSet.of(), /* parseInlineSourceMaps */ true, Config.StrictMode.SLOPPY); - FileInfo info = new FileInfo(errorReporter); + FileInfo info = new FileInfo(); ParserRunner.ParseResult parsed = ParserRunner.parse(source, code, config, errorReporter); parsed.ast.setInputId(new InputId(filename)); String version = parsed.features.version(); @@ -358,8 +272,7 @@ private static void parseComment(Comment comment, FileInfo info) { } } - /** JS function interface for reporting errors. */ - @JsFunction + /** Interface for reporting errors. */ public interface Reporter { void report(boolean fatal, String message, String sourceName, int line, int lineOffset); } @@ -387,45 +300,4 @@ public void error(String message, String sourceName, int line, int lineOffset) { public void report( boolean fatal, String message, String sourceName, int line, int lineOffset) {} }; - - /** Sparse object helper class: only adds non-trivial values. */ - private static class SparseObject { - final JsObject object = new JsObject<>(); - - SparseObject set(String key, Iterable iterable) { - JsArray array = JsArray.copyOf(iterable); - if (array.getLength() > 0) { - object.set(key, array); - } - return this; - } - - SparseObject set(String key, Multimap map) { - JsArray> array = new JsArray<>(); - for (Map.Entry entry : map.entries()) { - JsArray pair = new JsArray<>(); - pair.push(entry.getKey()); - pair.push(entry.getValue()); - array.push(pair); - } - if (array.getLength() > 0) { - object.set(key, array); - } - return this; - } - - SparseObject set(String key, String value) { - if (value != null && !value.isEmpty()) { - object.set(key, value); - } - return this; - } - - SparseObject set(String key, boolean value) { - if (value) { - object.set(key, value); - } - return this; - } - } } diff --git a/src/com/google/javascript/jscomp/gwt/client/JsfileParserGwt.java b/src/com/google/javascript/jscomp/gwt/client/JsfileParserGwt.java new file mode 100644 index 00000000000..122aa1352d4 --- /dev/null +++ b/src/com/google/javascript/jscomp/gwt/client/JsfileParserGwt.java @@ -0,0 +1,155 @@ +/* + * Copyright 2015 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.gwt.client; + +import com.google.common.collect.Multimap; +import com.google.javascript.jscomp.gwt.client.Util.JsArray; +import com.google.javascript.jscomp.gwt.client.Util.JsObject; +import java.util.Map; +import javax.annotation.Nullable; +import jsinterop.annotations.JsFunction; +import jsinterop.annotations.JsMethod; + +/** + * GWT module to parse files for dependency and {@literal @}{@code fileoverview} annotation + * information. + */ +public class JsfileParserGwt { + /** + * Exports the {@link #gjd} method via JSNI. + * + *

This will be placed on {@code module.exports.gjd} or the global {@code jscomp.gjd}. + */ + public native void exportGjd() /*-{ + var fn = $entry(@com.google.javascript.jscomp.gwt.client.JsfileParserGwt::gjd(*)); + if (typeof module !== 'undefined' && module.exports) { + module.exports.gjd = fn; + } + }-*/; + + /** + * Method exported to JS to parse a file for dependencies and annotations. + * + *

The result is a JSON object: + * + *

 {@code {
+   *   "custom_annotations": {?Array<[string, string]>},  @.*
+   *   "goog": {?bool},  whether 'goog' is implicitly required
+   *   "has_soy_delcalls": {?Array},  @fileoverview @hassoydelcall {.*}
+   *   "has_soy_deltemplates": {?Array},  @fileoverview @hassoydeltemplate {.*}
+   *   "imported_modules": {?Array},  import ... from .*
+   *   "is_config": {?bool},  @fileoverview @config
+   *   "is_externs": {?bool},  @fileoverview @externs
+   *   "load_flags": {?Array<[string, string]>},
+   *   "mod_name": {?Array},  @fileoverview @modName .*, @modName {.*}
+   *   "mods": {?Array},  @fileoverview @mods {.*}
+   *   "provide_goog": {?bool},  @fileoverview @provideGoog
+   *   "provides": {?Array},
+   *   "requires": {?Array},  note: look for goog.* for 'goog'
+   *   "requires_css": {?Array},  @fileoverview @requirecss {.*}
+   *   "testonly": {?bool},  goog.setTestOnly
+   *   "type_requires": {?Array},
+   *   "visibility: {?Array},  @fileoverview @visibility {.*}
+   * }}
+ * + *

Any trivial values are omitted. + */ + @JsMethod(namespace = "jscomp") + public static JsObject gjd(String code, String filename, @Nullable Reporter reporter) { + JsfileParser.FileInfo info = JsfileParser.parse(code, filename, adaptReporter(reporter)); + if (info.provideGoog) { + info.provides.add("goog"); + } else if (info.goog) { + info.requires.add("goog"); + } + return new SparseObject() + .set("custom_annotations", info.customAnnotations) + .set("goog", info.goog) + .set("has_soy_delcalls", info.hasSoyDelcalls) + .set("has_soy_deltemplates", info.hasSoyDeltemplates) + .set("imported_modules", info.importedModules) + .set("is_config", info.isConfig) + .set("is_externs", info.isExterns) + .set("load_flags", info.loadFlags) + .set("modName", info.modName) + .set("mods", info.mods) + .set("provide_goog", info.provideGoog) + .set("provides", info.provides) + .set("requires", info.requires) + .set("requiresCss", info.requiresCss) + .set("testonly", info.testonly) + .set("type_requires", info.typeRequires) + .set("visibility", info.visibility) + .object; + } + + /** JS function interface for reporting errors. */ + @JsFunction + public interface Reporter { + void report(boolean fatal, String message, String sourceName, int line, int lineOffset); + } + + private static JsfileParser.Reporter adaptReporter(@Nullable Reporter r) { + if (r == null) { + return null; + } + return (fatal, message, sourceName, line, lineOffset) -> { + r.report(fatal, message, sourceName, line, lineOffset); + }; + } + + /** Sparse object helper class: only adds non-trivial values. */ + private static class SparseObject { + final JsObject object = new JsObject<>(); + + SparseObject set(String key, Iterable iterable) { + JsArray array = JsArray.copyOf(iterable); + if (array.getLength() > 0) { + object.set(key, array); + } + return this; + } + + SparseObject set(String key, Multimap map) { + JsArray> array = new JsArray<>(); + for (Map.Entry entry : map.entries()) { + JsArray pair = new JsArray<>(); + pair.push(entry.getKey()); + pair.push(entry.getValue()); + array.push(pair); + } + if (array.getLength() > 0) { + object.set(key, array); + } + return this; + } + + SparseObject set(String key, String value) { + if (value != null && !value.isEmpty()) { + object.set(key, value); + } + return this; + } + + SparseObject set(String key, boolean value) { + if (value) { + object.set(key, value); + } + return this; + } + } +} diff --git a/src/com/google/javascript/jscomp/gwt/client/JsfileParserMain.java b/src/com/google/javascript/jscomp/gwt/client/JsfileParserMain.java index 3c67635e22c..39510664727 100644 --- a/src/com/google/javascript/jscomp/gwt/client/JsfileParserMain.java +++ b/src/com/google/javascript/jscomp/gwt/client/JsfileParserMain.java @@ -21,7 +21,7 @@ * Entry point that exports just the JsfileParser. */ final class JsfileParserMain implements EntryPoint { - private static final JsfileParser jsFileParser = new JsfileParser(); + private static final JsfileParserGwt jsFileParser = new JsfileParserGwt(); @Override public void onModuleLoad() {