use of com.google.javascript.rhino.QualifiedName in project closure-compiler by google.
the class CheckMissingRequires method visitNode.
private void visitNode(NodeTraversal t, Node n, ModuleMetadata currentModule) {
JSDocInfo info = n.getJSDocInfo();
if (info != null) {
visitJsDocInfo(t, currentModule, info);
}
if (n.isQualifiedName() && !n.getParent().isGetProp()) {
QualifiedName qualifiedName = n.getQualifiedNameObject();
String root = qualifiedName.getRoot();
if (root.equals("this") || root.equals("super")) {
return;
}
visitQualifiedName(t, n, currentModule, n.getQualifiedNameObject(), /* isStrongReference= */
true);
}
}
use of com.google.javascript.rhino.QualifiedName in project closure-compiler by google.
the class CheckMissingRequires method hasAcceptableRequire.
/**
* Does `rdep` contain an acceptable require for `namespace` from `dep`?
*
* <p>Any require for a parent of `namespace` from `rdep` onto `dep`, which declares that parent,
* is sufficient. This constraint still ensures correct dependency ordering.
*
* <p>We loosen the check in this way because we want to make it easy to migrate multi-provide
* files into modules. That includes deleting obsolete provides and splitting provides into
* different files.
*/
private static boolean hasAcceptableRequire(ModuleMetadata rdep, QualifiedName namespace, ModuleMetadata dep, boolean isStrongReference) {
Set<String> acceptableRequires = rdep.stronglyRequiredGoogNamespaces().elementSet();
if (!isStrongReference) {
acceptableRequires = Sets.union(acceptableRequires, rdep.weaklyRequiredGoogNamespaces().elementSet());
}
acceptableRequires = Sets.intersection(acceptableRequires, dep.googNamespaces().elementSet());
for (QualifiedName parent = namespace; parent != null; parent = parent.getOwner()) {
if (acceptableRequires.contains(parent.join())) {
return true;
}
}
return false;
}
use of com.google.javascript.rhino.QualifiedName in project closure-compiler by google.
the class ModuleRenaming method getGlobalNameForJsDoc.
/**
* Returns the globalized name of a reference to a binding in JS Doc.
*
* <p>For example:
*
* <pre>
* // bar
* export class Bar {}
* </pre>
*
* <pre>
* // foo
* import * as bar from 'bar';
* export {bar};
* </pre>
*
* <pre>
* import * as foo from 'foo';
* let /** !foo.bar.Bar *\/ b;
* </pre>
*
* <p>Should call this method with the binding for {@code foo} and a list ("bar", "Bar"). In this
* example any of these properties could also be modules. This method will replace as much as the
* GETPROP as it can with module exported variables. Meaning in the above example this would
* return something like "baz$$module$bar", whereas if this method were called for just "foo.bar"
* it would return "module$bar", as it refers to a module object itself.
*/
static String getGlobalNameForJsDoc(ModuleMap moduleMap, Binding binding, List<String> propertyChain) {
int prop = 0;
while (binding.isModuleNamespace() && binding.metadata().isEs6Module() && prop < propertyChain.size()) {
String propertyName = propertyChain.get(prop);
Module m = moduleMap.getModule(binding.metadata().path());
if (m.namespace().containsKey(propertyName)) {
binding = m.namespace().get(propertyName);
} else {
// error, but we're working on type checking modules soon.
break;
}
prop++;
}
QualifiedName globalName = getGlobalName(binding);
while (prop < propertyChain.size()) {
globalName = globalName.getprop(propertyChain.get(prop++));
}
return globalName.join();
}
use of com.google.javascript.rhino.QualifiedName in project closure-compiler by google.
the class CheckMissingRequires method visitQualifiedName.
private void visitQualifiedName(NodeTraversal t, Node n, ModuleMetadata currentFile, QualifiedName qualifiedName, boolean isStrongReference) {
if (qualifiedName.isSimple() && templateParamNames.contains(qualifiedName.getRoot())) {
// precede the reference within the same source file (e.g. an ES5 ctor in a different file).
return;
}
if (qualifiedName.isSimple() && qualifiedName.getRoot().equals("xid")) {
// TODO(b/160167649): Decide if we should report `xid` which initially was too common to fix.
return;
}
Var var = t.getScope().getVar(qualifiedName.getRoot());
if (var != null && var.getScope().isLocal()) {
// by the aliasing and destructuring forms of `goog.require` and `goog.requireType`.
return;
}
// Look for the longest prefix match against a provided namespace.
for (QualifiedName subName = qualifiedName; subName != null; subName = subName.getOwner()) {
String namespace = subName.join();
if (namespace.equals("goog.module")) {
// name, but it's (confusingly) unrelated to the `goog.module` primitive.
return;
}
// TODO(tjgq): Also check for these references.
if (currentFile.googNamespaces().contains(namespace)) {
return;
}
ModuleMetadata requiredFile = moduleByNamespace.get(namespace);
if (requiredFile == null) {
continue;
}
final DiagnosticType toReport;
if (currentFile.isModule()) {
/**
* In files that represent modules, report a require without an alias the same as a totally
* missing require.
*/
toReport = isStrongReference ? MISSING_REQUIRE : MISSING_REQUIRE_TYPE;
} else if (!hasAcceptableRequire(currentFile, subName, requiredFile, isStrongReference)) {
/**
* In files that aren't modules, report a qualified name reference only if there's no
* require to satisfy it.
*/
toReport = isStrongReference ? MISSING_REQUIRE_IN_PROVIDES_FILE : MISSING_REQUIRE_TYPE_IN_PROVIDES_FILE;
} else {
return;
}
t.report(n, toReport, namespace);
return;
}
}
use of com.google.javascript.rhino.QualifiedName in project closure-compiler by google.
the class Es6RewriteModules method visitScript.
private void visitScript(NodeTraversal t, Node script) {
final Node moduleBody = script.getFirstChild();
// TypedScopeCreator sets the module object type on the MODULE_BODY during type checking.
final AstFactory.Type moduleObjectType = type(moduleBody);
inlineModuleToGlobalScope(moduleBody);
ClosureRewriteModule.checkAndSetStrictModeDirective(t, script);
Module thisModule = moduleMap.getModule(t.getInput().getPath());
QualifiedName qualifiedName = ModuleRenaming.getGlobalName(thisModule.metadata(), /* googNamespace= */
null);
checkState(qualifiedName.isSimple(), "Unexpected qualified name %s", qualifiedName);
String moduleName = qualifiedName.getRoot();
Node moduleVar = createExportsObject(moduleName, t, script, moduleObjectType);
// Rename vars to not conflict in global scope.
NodeTraversal.traverse(compiler, script, new RenameGlobalVars(thisModule));
// Rename the exports object to something we can reference later.
moduleVar.getFirstChild().setString(moduleName);
moduleVar.makeNonIndexableRecursive();
declareGlobalVariable(moduleVar.getFirstChild(), t);
// rewriteRequires is here (rather than being part of the main visit() method, because we only
// want to rewrite the requires if this is an ES6 module. Note that we also want to do this
// AFTER renaming all module scoped vars in the event that something that is goog.require'd is
// a global, unqualified name (e.g. if "goog.provide('foo')" exists, we don't want to rewrite
// "const foo = goog.require('foo')" to "const foo = foo". If we rewrite our module scoped names
// first then we'll rewrite to "const foo$module$fudge = goog.require('foo')", then to
// "const foo$module$fudge = foo".
rewriteRequires(script);
t.reportCodeChange();
}
Aggregations