Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Alias colliding names in Closure Library like goog.ui.Component #811

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/com/google/javascript/clutz/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ public interface Constants {
* The alias does not affect the external module declaration, thus the user can still import the
* symbol using unaliased module name (i.e. import bar from 'goog:foo.bar').
*/
static final String COLLDING_PROVIDE_ALIAS_POSTFIX = "__clutz_alias";
static final String COLLIDING_PROVIDE_ALIAS_POSTFIX = "__clutz_alias";
}
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,38 @@ public static void main(String[] args) {

/**
* If one file defines a name and another uses it as a namespace, we have the
* Constants.COLLDING_PROVIDE_ALIAS_POSTFIX workaround. In partial mode, Clutz can't see all
* Constants.COLLIDING_PROVIDE_ALIAS_POSTFIX workaround. In partial mode, Clutz can't see all
* definitions of a name, so the list of names that require aliases must be passed as an input.
* Also Closure Library uses some names as both classes and namespases. For example,
* `goog.ui.Component` is not only a class but also a namespace in `goog.ui.Component.EventType`.
teppeis marked this conversation as resolved.
Show resolved Hide resolved
* See https://github.com/google/closure-library/blob/master/closure/goog/ui/component.js
*/
private Set<String> collidingProvides = new LinkedHashSet<>();
private Set<String> collidingProvides =
Sets.newHashSet(
"goog.ui.AdvancedTooltip",
"goog.ui.AnimatedZippy",
"goog.ui.Checkbox",
"goog.ui.ColorPicker",
"goog.ui.Component",
"goog.ui.Container",
"goog.ui.Control",
"goog.ui.Dialog",
"goog.ui.FilteredMenu",
"goog.ui.HoverCard",
"goog.ui.Menu",
"goog.ui.MenuItem",
"goog.ui.ModalPopup",
"goog.ui.Ratings",
"goog.ui.ScrollFloater",
"goog.ui.SliderBase",
"goog.ui.SplitPane",
"goog.ui.TableSorter",
"goog.ui.Textarea",
"goog.ui.TriStateMenuItem",
"goog.ui.Zippy",
"goog.ui.editor.AbstractDialog",
"goog.ui.editor.LinkDialog",
"goog.ui.tree.BaseNode");

DeclarationGenerator(Options opts) {
this.opts = opts;
Expand Down Expand Up @@ -416,7 +444,7 @@ String generateDeclarations(
legacyNamespaceReexportMap =
new LegacyNamespaceReexportMapBuilder()
.build(compiler.getParsedInputs(), opts.depgraph.getGoogProvides());
collidingProvides = opts.collidingProvides;
collidingProvides.addAll(opts.collidingProvides);
}

unknownType = compiler.getTypeRegistry().getNativeType(JSTypeNative.UNKNOWN_TYPE);
Expand Down Expand Up @@ -512,7 +540,7 @@ String produceDts(Depgraph depgraph) {
rewrittenProvides.add(rewritenProvide);
}
if (needsAlias(shadowedProvides, provide, symbol)) {
emitName += Constants.COLLDING_PROVIDE_ALIAS_POSTFIX;
emitName += Constants.COLLIDING_PROVIDE_ALIAS_POSTFIX;
}
if (symbol == null) {
// Sometimes goog.provide statements are used as pure markers for dependency management, or
Expand Down Expand Up @@ -858,7 +886,7 @@ private void processExternSymbols() {
boolean isDefault = isDefaultExport(symbol);
String emitName = symbol.getName();
if (needsAlias(shadowedSymbols, symbol.getName(), symbol)) {
emitName += Constants.COLLDING_PROVIDE_ALIAS_POSTFIX;
emitName += Constants.COLLIDING_PROVIDE_ALIAS_POSTFIX;
}

// There is nothing to emit for a namespace, because all its symbols will be visited later,
Expand Down Expand Up @@ -1485,6 +1513,9 @@ private TreeWalker(

private String getAbsoluteName(ObjectType objectType) {
String name = objectType.getDisplayName();
if (collidingProvides.contains(name)) {
name += Constants.COLLIDING_PROVIDE_ALIAS_POSTFIX;
}
// Names that do not have a namespace '.' are either platform names in the top level
// namespace like `Object` or `Element`, or they are unqualified `goog.provide`s, e.g.
// `goog.provide('Toplevel')`. In both cases they will be found with the naked name.
Expand Down Expand Up @@ -1513,7 +1544,7 @@ private void walk(TypedVar symbol, String emitName) {
// Since closure inlines all aliases before this step, check against
// the type name.
if (!isAliasedClassOrInterface(symbol, ftype)) {
visitClassOrInterface(getUnqualifiedName(symbol), ftype);
visitClassOrInterface(getUnqualifiedName(emitName), ftype);
} else {
if (KNOWN_CLASS_ALIASES.containsKey(symbol.getName())) {
visitKnownTypeValueAlias(
Expand Down
36 changes: 36 additions & 0 deletions src/test/java/com/google/javascript/clutz/goog_ui_component.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
declare namespace ಠ_ಠ.clutz.goog.ui {
class Component__clutz_alias {
private noStructuralTyping_goog_ui_Component : any;
}
}
declare module 'goog:goog.ui.Component' {
import Component = ಠ_ಠ.clutz.goog.ui.Component__clutz_alias;
export default Component;
}
declare namespace ಠ_ಠ.clutz.goog.ui.Component {
enum EventType {
ACTION = 'action' ,
}
}
declare module 'goog:goog.ui.Component.EventType' {
import EventType = ಠ_ಠ.clutz.goog.ui.Component.EventType;
export default EventType;
}
declare namespace ಠ_ಠ.clutz.goog.ui.tree {
class BaseNode__clutz_alias extends ಠ_ಠ.clutz.goog.ui.Component__clutz_alias {
private noStructuralTyping_goog_ui_tree_BaseNode : any;
}
}
declare module 'goog:goog.ui.tree.BaseNode' {
import BaseNode = ಠ_ಠ.clutz.goog.ui.tree.BaseNode__clutz_alias;
export default BaseNode;
}
declare namespace ಠ_ಠ.clutz.goog.ui.tree.BaseNode {
enum EventType {
BEFORE_COLLAPSE = 'beforecollapse' ,
}
}
declare module 'goog:goog.ui.tree.BaseNode.EventType' {
import EventType = ಠ_ಠ.clutz.goog.ui.tree.BaseNode.EventType;
export default EventType;
}
29 changes: 29 additions & 0 deletions src/test/java/com/google/javascript/clutz/goog_ui_component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
goog.provide('goog.ui.Component');
goog.provide('goog.ui.Component.EventType');
goog.provide('goog.ui.tree.BaseNode');
goog.provide('goog.ui.tree.BaseNode.EventType');

/**
* @constructor
*/
goog.ui.Component = function() {};

/**
* @enum {string}
*/
goog.ui.Component.EventType = {
ACTION: 'action'
};

/**
* @constructor
* @extends {goog.ui.Component}
*/
goog.ui.tree.BaseNode = function() {};

/**
* @enum {string}
*/
goog.ui.tree.BaseNode.EventType = {
BEFORE_COLLAPSE: 'beforecollapse'
};