Skip to content

Commit

Permalink
[NTI] Convert RemoveUnusedPolyfills to TypeI.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=138649498
  • Loading branch information
dimvar authored and blickly committed Nov 9, 2016
1 parent 2a512ea commit 1f859c5
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 10 deletions.
20 changes: 13 additions & 7 deletions src/com/google/javascript/jscomp/RemoveUnusedPolyfills.java
Expand Up @@ -23,8 +23,8 @@
import com.google.common.collect.SetMultimap; import com.google.common.collect.SetMultimap;
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback; import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
import com.google.javascript.rhino.Node; import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.TypeI;
import com.google.javascript.rhino.TypeIRegistry; import com.google.javascript.rhino.TypeIRegistry;
import com.google.javascript.rhino.jstype.JSType;
import com.google.javascript.rhino.jstype.JSTypeNative; import com.google.javascript.rhino.jstype.JSTypeNative;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
Expand Down Expand Up @@ -132,7 +132,13 @@ void visitPossiblePolyfillUse(Node n) {
if (methods.isEmpty()) { if (methods.isEmpty()) {
return; return;
} }
JSType receiverType = n.getFirstChild().getJSType(); TypeI receiverType = n.getFirstChild().getTypeI();
if (NodeUtil.isPrototypeProperty(n)) {
TypeI maybeCtor = n.getFirstFirstChild().getTypeI();
if (maybeCtor != null && maybeCtor.isConstructor()) {
receiverType = maybeCtor.toMaybeFunctionType().getInstanceType();
}
}
if (receiverType == null) { if (receiverType == null) {
// TODO(sdh): When does this happen? If it means incomplete type information, then // TODO(sdh): When does this happen? If it means incomplete type information, then
// we need to remove all the potential methods. If not, we can just return. // we need to remove all the potential methods. If not, we can just return.
Expand All @@ -142,8 +148,8 @@ void visitPossiblePolyfillUse(Node n) {
receiverType = receiverType.restrictByNotNullOrUndefined(); receiverType = receiverType.restrictByNotNullOrUndefined();
TypeIRegistry registry = compiler.getTypeIRegistry(); TypeIRegistry registry = compiler.getTypeIRegistry();
if (receiverType.isUnknownType() if (receiverType.isUnknownType()
|| receiverType.isEmptyType() || receiverType.isBottom()
|| receiverType.isAllType() || receiverType.isTop()
|| receiverType.isEquivalentTo( || receiverType.isEquivalentTo(
registry.getNativeType(JSTypeNative.OBJECT_TYPE))) { registry.getNativeType(JSTypeNative.OBJECT_TYPE))) {
unusedMethodPolyfills.keySet().removeAll(methods); unusedMethodPolyfills.keySet().removeAll(methods);
Expand All @@ -158,12 +164,12 @@ void visitPossiblePolyfillUse(Node n) {
} }


private void checkType( private void checkType(
JSType targetType, TypeIRegistry registry, PrototypeMethod method, String typeName) { TypeI receiverType, TypeIRegistry registry, PrototypeMethod method, String typeName) {
JSType type = registry.getType(typeName); TypeI type = registry.getType(typeName);
if (type == null) { if (type == null) {
throw new RuntimeException("Missing built-in type: " + typeName); throw new RuntimeException("Missing built-in type: " + typeName);
} }
if (!targetType.getGreatestSubtype(type).isBottom()) { if (!receiverType.meetWith(type).isBottom()) {
unusedMethodPolyfills.remove(method); unusedMethodPolyfills.remove(method);
} }
} }
Expand Down
5 changes: 5 additions & 0 deletions src/com/google/javascript/jscomp/newtypes/JSType.java
Expand Up @@ -1625,6 +1625,11 @@ public ObjectTypeI autoboxAndGetObject() {
return this.autobox().restrictByNotNullOrUndefined().toMaybeObjectType(); return this.autobox().restrictByNotNullOrUndefined().toMaybeObjectType();
} }


@Override
public TypeI meetWith(TypeI other) {
return meet(this, (JSType) other);
}

@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == null) { if (o == null) {
Expand Down
2 changes: 2 additions & 0 deletions src/com/google/javascript/rhino/TypeI.java
Expand Up @@ -118,5 +118,7 @@ public interface TypeI {
*/ */
Iterable<? extends TypeI> getUnionMembers(); Iterable<? extends TypeI> getUnionMembers();


TypeI meetWith(TypeI other);

String getDisplayName(); String getDisplayName();
} }
5 changes: 5 additions & 0 deletions src/com/google/javascript/rhino/jstype/JSType.java
Expand Up @@ -1047,6 +1047,11 @@ public JSType getGreatestSubtype(JSType that) {
return getGreatestSubtype(this, that); return getGreatestSubtype(this, that);
} }


@Override
public TypeI meetWith(TypeI that) {
return getGreatestSubtype(this, (JSType) that);
}

/** /**
* A generic implementation meant to be used as a helper for common * A generic implementation meant to be used as a helper for common
* getGreatestSubtype implementations. * getGreatestSubtype implementations.
Expand Down
15 changes: 12 additions & 3 deletions test/com/google/javascript/jscomp/RemoveUnusedPolyfillsTest.java
Expand Up @@ -17,14 +17,14 @@
package com.google.javascript.jscomp; package com.google.javascript.jscomp;


/** Unit tests for the RemoveUnusedPolyfills compiler pass. */ /** Unit tests for the RemoveUnusedPolyfills compiler pass. */
public final class RemoveUnusedPolyfillsTest extends CompilerTestCase { public final class RemoveUnusedPolyfillsTest extends TypeICompilerTestCase {


private static final String EXTERNS = LINE_JOINER.join( private static final String EXTERNS = LINE_JOINER.join(
DEFAULT_EXTERNS,
// Polyfill // Polyfill
"var $jscomp = {};", "var $jscomp = {};",
"$jscomp.polyfill = function(name, func, from, to) {};", "$jscomp.polyfill = function(name, func, from, to) {};",
// Methods // Methods
"Function.prototype.call = function(ctx) {};",
"Array.prototype.includes = function() {};", "Array.prototype.includes = function() {};",
"String.prototype.includes = function() {};", "String.prototype.includes = function() {};",
"/** @constructor */ function Foo() {}", "/** @constructor */ function Foo() {}",
Expand Down Expand Up @@ -62,14 +62,21 @@ public final class RemoveUnusedPolyfillsTest extends CompilerTestCase {


public RemoveUnusedPolyfillsTest() { public RemoveUnusedPolyfillsTest() {
super(EXTERNS); super(EXTERNS);
enableTypeCheck();
} }


@Override @Override
protected CompilerPass getProcessor(final Compiler compiler) { protected CompilerPass getProcessor(final Compiler compiler) {
return new RemoveUnusedPolyfills(compiler); return new RemoveUnusedPolyfills(compiler);
} }


@Override
protected CompilerOptions getOptions() {
CompilerOptions options = super.getOptions();
// NTI warns about property accesses on *
options.setWarningLevel(DiagnosticGroups.NEW_CHECK_TYPES_EXTRA_CHECKS, CheckLevel.OFF);
return options;
}

public void testRemovesPolyfillInstanceMethods() { public void testRemovesPolyfillInstanceMethods() {
test(STRING_INCLUDES, ""); test(STRING_INCLUDES, "");
test(STRING_INCLUDES + ARRAY_INCLUDES, ""); test(STRING_INCLUDES + ARRAY_INCLUDES, "");
Expand Down Expand Up @@ -104,6 +111,8 @@ public void testDoesNotRemoveMethodsCalledOnAllType() {
public void testDoesNotRemoveMethodsCalledOnObject() { public void testDoesNotRemoveMethodsCalledOnObject() {
testSame(STRING_INCLUDES + "obj.includes();"); testSame(STRING_INCLUDES + "obj.includes();");
testSame(BOTH_INCLUDES + "obj.includes();"); testSame(BOTH_INCLUDES + "obj.includes();");
testSame(ARRAY_INCLUDES
+ "function f(/** !Object */ x) { x.includes = function() {}; x.includes(); }");
} }


public void testDoesNotRemoveMethodsCalledOnCorrectTypes() { public void testDoesNotRemoveMethodsCalledOnCorrectTypes() {
Expand Down

0 comments on commit 1f859c5

Please sign in to comment.