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

Commit

Permalink
Alias colliding names in Closure Library like goog.ui.Component
Browse files Browse the repository at this point in the history
  • Loading branch information
teppeis committed Mar 14, 2019
1 parent 7acfed8 commit 1bef4d6
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 7 deletions.
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`.
* 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'
};

0 comments on commit 1bef4d6

Please sign in to comment.