Skip to content

Commit

Permalink
Split off the GWT-specific parts of JsfileParser into a separate file.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=260049168
  • Loading branch information
tjgq authored and rishipal committed Jul 26, 2019
1 parent 2c94c36 commit f712aff
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 137 deletions.
Expand Up @@ -23,7 +23,7 @@
*/ */
final class CompilerMain implements EntryPoint { final class CompilerMain implements EntryPoint {
private static final GwtRunner gwtRunner = new GwtRunner(); private static final GwtRunner gwtRunner = new GwtRunner();
private static final JsfileParser jsFileParser = new JsfileParser(); private static final JsfileParserGwt jsFileParser = new JsfileParserGwt();


@Override @Override
public void onModuleLoad() { public void onModuleLoad() {
Expand Down
142 changes: 7 additions & 135 deletions src/com/google/javascript/jscomp/gwt/client/JsfileParser.java
Expand Up @@ -32,8 +32,6 @@
import com.google.javascript.jscomp.JSError; import com.google.javascript.jscomp.JSError;
import com.google.javascript.jscomp.SourceFile; import com.google.javascript.jscomp.SourceFile;
import com.google.javascript.jscomp.deps.ModuleLoader.ResolutionMode; 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.modules.ModuleMetadataMap.ModuleMetadata;
import com.google.javascript.jscomp.parsing.Config; import com.google.javascript.jscomp.parsing.Config;
import com.google.javascript.jscomp.parsing.ParserRunner; import com.google.javascript.jscomp.parsing.ParserRunner;
Expand All @@ -47,47 +45,17 @@
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import jsinterop.annotations.JsFunction;
import jsinterop.annotations.JsMethod;


/** /**
* GWT module to parse files for dependency and * A parser that extracts dependency information from a .js file, including goog.require,
* {@literal @}{@code fileoverview} annotation * goog.provide, goog.module, import/export statements, and JSDoc annotations related to dependency
* information. * management.
*/ */
public class JsfileParser { public class JsfileParser {

/**
* All the information parsed out of a single file.
* Exported as a JSON object:
* <pre> {@code {
* "custom_annotations": {?Array<[string, string]>}, @.*
* "goog": {?bool}, whether 'goog' is implicitly required
* "has_soy_delcalls": {?Array<string>}, @fileoverview @hassoydelcall {.*}
* "has_soy_deltemplates": {?Array<string>}, @fileoverview @hassoydeltemplate {.*}
* "imported_modules": {?Array<string>}, import ... from .*
* "is_config": {?bool}, @fileoverview @config
* "is_externs": {?bool}, @fileoverview @externs
* "load_flags": {?Array<[string, string]>},
* "mod_name": {?Array<string>}, @fileoverview @modName .*, @modName {.*}
* "mods": {?Array<string>}, @fileoverview @mods {.*}
* "provide_goog": {?bool}, @fileoverview @provideGoog
* "provides": {?Array<string>},
* "requires": {?Array<string>}, note: look for goog.* for 'goog'
* "requires_css": {?Array<string>}, @fileoverview @requirecss {.*}
* "testonly": {?bool}, goog.setTestOnly
* "type_requires": {?Array<string>},
* "visibility: {?Array<string>}, @fileoverview @visibility {.*}
* }}</pre>
* Any trivial values are omitted.
*/
static final class FileInfo { static final class FileInfo {
final ErrorReporter reporter;

boolean goog = false; boolean goog = false;
boolean isConfig = false; boolean isConfig = false;
boolean isExterns = false; boolean isExterns = false;
Expand All @@ -111,56 +79,8 @@ static final class FileInfo {


final Multimap<String, String> customAnnotations = TreeMultimap.create(); final Multimap<String, String> customAnnotations = TreeMultimap.create();
final Multimap<String, String> loadFlags = TreeMultimap.create(); final Multimap<String, String> 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<Object> 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.
*
* <p>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. */ /** Represents a single JSDoc annotation, with an optional argument. */
private static class CommentAnnotation { private static class CommentAnnotation {


Expand Down Expand Up @@ -204,14 +124,8 @@ static List<CommentAnnotation> parse(String comment) {
private static final int ANNOTATION_VALUE_GROUP = 2; private static final int ANNOTATION_VALUE_GROUP = 2;
} }


/** Method exported to JS to parse a file for dependencies and annotations. */ /** Parses a JavaScript file for dependencies and annotations. */
@JsMethod(namespace = "jscomp") public static FileInfo parse(String code, String filename, @Nullable Reporter reporter) {
public static JsObject<Object> 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) {
ErrorReporter errorReporter = new DelegatingReporter(reporter); ErrorReporter errorReporter = new DelegatingReporter(reporter);
Compiler compiler = Compiler compiler =
new Compiler( new Compiler(
Expand Down Expand Up @@ -251,7 +165,7 @@ protected void printSummary() {}
/* extraAnnotationNames */ ImmutableSet.<String>of(), /* extraAnnotationNames */ ImmutableSet.<String>of(),
/* parseInlineSourceMaps */ true, /* parseInlineSourceMaps */ true,
Config.StrictMode.SLOPPY); Config.StrictMode.SLOPPY);
FileInfo info = new FileInfo(errorReporter); FileInfo info = new FileInfo();
ParserRunner.ParseResult parsed = ParserRunner.parse(source, code, config, errorReporter); ParserRunner.ParseResult parsed = ParserRunner.parse(source, code, config, errorReporter);
parsed.ast.setInputId(new InputId(filename)); parsed.ast.setInputId(new InputId(filename));
String version = parsed.features.version(); String version = parsed.features.version();
Expand Down Expand Up @@ -358,8 +272,7 @@ private static void parseComment(Comment comment, FileInfo info) {
} }
} }


/** JS function interface for reporting errors. */ /** Interface for reporting errors. */
@JsFunction
public interface Reporter { public interface Reporter {
void report(boolean fatal, String message, String sourceName, int line, int lineOffset); void report(boolean fatal, String message, String sourceName, int line, int lineOffset);
} }
Expand Down Expand Up @@ -387,45 +300,4 @@ public void error(String message, String sourceName, int line, int lineOffset) {
public void report( public void report(
boolean fatal, String message, String sourceName, int line, int lineOffset) {} 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> object = new JsObject<>();

SparseObject set(String key, Iterable<String> iterable) {
JsArray<String> array = JsArray.copyOf(iterable);
if (array.getLength() > 0) {
object.set(key, array);
}
return this;
}

SparseObject set(String key, Multimap<String, String> map) {
JsArray<JsArray<String>> array = new JsArray<>();
for (Map.Entry<String, String> entry : map.entries()) {
JsArray<String> 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;
}
}
} }
155 changes: 155 additions & 0 deletions 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.
*
* <p>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.
*
* <p>The result is a JSON object:
*
* <pre> {@code {
* "custom_annotations": {?Array<[string, string]>}, @.*
* "goog": {?bool}, whether 'goog' is implicitly required
* "has_soy_delcalls": {?Array<string>}, @fileoverview @hassoydelcall {.*}
* "has_soy_deltemplates": {?Array<string>}, @fileoverview @hassoydeltemplate {.*}
* "imported_modules": {?Array<string>}, import ... from .*
* "is_config": {?bool}, @fileoverview @config
* "is_externs": {?bool}, @fileoverview @externs
* "load_flags": {?Array<[string, string]>},
* "mod_name": {?Array<string>}, @fileoverview @modName .*, @modName {.*}
* "mods": {?Array<string>}, @fileoverview @mods {.*}
* "provide_goog": {?bool}, @fileoverview @provideGoog
* "provides": {?Array<string>},
* "requires": {?Array<string>}, note: look for goog.* for 'goog'
* "requires_css": {?Array<string>}, @fileoverview @requirecss {.*}
* "testonly": {?bool}, goog.setTestOnly
* "type_requires": {?Array<string>},
* "visibility: {?Array<string>}, @fileoverview @visibility {.*}
* }}</pre>
*
* <p>Any trivial values are omitted.
*/
@JsMethod(namespace = "jscomp")
public static JsObject<Object> 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> object = new JsObject<>();

SparseObject set(String key, Iterable<String> iterable) {
JsArray<String> array = JsArray.copyOf(iterable);
if (array.getLength() > 0) {
object.set(key, array);
}
return this;
}

SparseObject set(String key, Multimap<String, String> map) {
JsArray<JsArray<String>> array = new JsArray<>();
for (Map.Entry<String, String> entry : map.entries()) {
JsArray<String> 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;
}
}
}
Expand Up @@ -21,7 +21,7 @@
* Entry point that exports just the JsfileParser. * Entry point that exports just the JsfileParser.
*/ */
final class JsfileParserMain implements EntryPoint { final class JsfileParserMain implements EntryPoint {
private static final JsfileParser jsFileParser = new JsfileParser(); private static final JsfileParserGwt jsFileParser = new JsfileParserGwt();


@Override @Override
public void onModuleLoad() { public void onModuleLoad() {
Expand Down

0 comments on commit f712aff

Please sign in to comment.