diff --git a/src/com/google/javascript/jscomp/CheckRequiresForConstructors.java b/src/com/google/javascript/jscomp/CheckRequiresForConstructors.java index 9dcebb7c9c5..b254f9c1cb1 100644 --- a/src/com/google/javascript/jscomp/CheckRequiresForConstructors.java +++ b/src/com/google/javascript/jscomp/CheckRequiresForConstructors.java @@ -149,8 +149,13 @@ public void visit(NodeTraversal t, Node n, Node parent) { maybeAddConstructor(n); } break; + case Token.NAME: + if (!NodeUtil.isLValue(n)) { + visitQualifiedName(n); + } + break; case Token.GETPROP: - visitGetProp(n); + visitQualifiedName(n); break; case Token.CALL: visitCallNode(n, parent); @@ -293,7 +298,7 @@ private void visitCallNode(Node call, Node parent) { } } - private void visitGetProp(Node getprop) { + private void visitQualifiedName(Node getprop) { // For "foo.bar.baz.qux" add weak usages for "foo.bar.baz.qux", foo.bar.baz", // "foo.bar", and "foo" because those might all be goog.provide'd in different files, // so it doesn't make sense to require the user to goog.require all of them. @@ -507,7 +512,7 @@ public void visit(Node typeNode) { // var MyHandler = function() {}; Node getprop = NodeUtil.newQName(compiler, typeString); getprop.useSourceInfoIfMissingFromForTree(typeNode); - visitGetProp(getprop); + visitQualifiedName(getprop); } else { // Even if the root namespace is in externs, add a weak usage because the full // namespace may still be goog.provided. diff --git a/src/com/google/javascript/jscomp/NodeUtil.java b/src/com/google/javascript/jscomp/NodeUtil.java index 01cd2664caa..3af3b6fd233 100644 --- a/src/com/google/javascript/jscomp/NodeUtil.java +++ b/src/com/google/javascript/jscomp/NodeUtil.java @@ -2681,9 +2681,16 @@ public static boolean isLValue(Node n) { || parent.isInc() || parent.isParamList() || parent.isCatch() + || isImportedName(n) || isLhsByDestructuring(n); } + public static boolean isImportedName(Node n) { + Node parent = n.getParent(); + return parent.isImport() + || parent.isImportSpec() && parent.getLastChild() == n; + } + public static boolean isLhsByDestructuring(Node n) { Node parent = n.getParent(); diff --git a/src/com/google/javascript/rhino/Node.java b/src/com/google/javascript/rhino/Node.java index 738ec26b4bd..5af1c1f463a 100644 --- a/src/com/google/javascript/rhino/Node.java +++ b/src/com/google/javascript/rhino/Node.java @@ -2679,6 +2679,10 @@ public boolean isImport() { return this.getType() == Token.IMPORT; } + public boolean isImportSpec() { + return this.getType() == Token.IMPORT_SPEC; + } + public boolean isIn() { return this.getType() == Token.IN; } diff --git a/test/com/google/javascript/jscomp/SingleFileCheckRequiresTest.java b/test/com/google/javascript/jscomp/SingleFileCheckRequiresTest.java index c720be025d3..2f835832505 100644 --- a/test/com/google/javascript/jscomp/SingleFileCheckRequiresTest.java +++ b/test/com/google/javascript/jscomp/SingleFileCheckRequiresTest.java @@ -63,6 +63,34 @@ public void testReferenceToQualifiedName() { MISSING_REQUIRE_WARNING); } + public void testReferenceToUnqualifiedName() { + testSameEs6( + LINE_JOINER.join( + "goog.module('a.b.c');", + "var z = goog.require('x.y.z');", + "", + "exports = { foobar : z };")); + + testSameEs6( + LINE_JOINER.join( + "goog.module('a.b.c');", + "var {z} = goog.require('x.y');", + "", + "exports = { foobar : z };")); + + testSameEs6( + LINE_JOINER.join( + "import {z} from 'x.y'", + "", + "export var foobar = z;")); + + testSameEs6( + LINE_JOINER.join( + "import z from 'x.y.z'", + "", + "export var foobar = z;")); + } + public void testExtraRequire() { testErrorEs6("goog.require('foo.Bar');", EXTRA_REQUIRE_WARNING); }