Skip to content

Commit

Permalink
[NTI] Introduce a new acceptsArguments method to FunctionTypeI.
Browse files Browse the repository at this point in the history
Also use it in ConformanceRules and prune any dead code that results.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=129480955
  • Loading branch information
aravind-pg authored and blickly committed Aug 5, 2016
1 parent ed3e7ef commit 733261f
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 80 deletions.
72 changes: 10 additions & 62 deletions src/com/google/javascript/jscomp/ConformanceRules.java
Expand Up @@ -586,13 +586,12 @@ static TypeI evaluateTypeString(
* @see TypeCheck#visitParameterList
*/
static boolean validateCall(
AbstractCompiler compiler,
Node callOrNew,
FunctionTypeI functionType,
boolean isCallInvocation) {
Preconditions.checkState(callOrNew.isCall() || callOrNew.isNew());

return validateParameterList(compiler, callOrNew, functionType, isCallInvocation)
return validateParameterList(callOrNew, functionType, isCallInvocation)
&& validateThis(callOrNew, functionType, isCallInvocation);
}

Expand All @@ -619,7 +618,6 @@ private static boolean validateThis(
}

private static boolean validateParameterList(
AbstractCompiler compiler,
Node callOrNew,
FunctionTypeI functionType,
boolean isCallInvocation) {
Expand All @@ -629,61 +627,13 @@ private static boolean validateParameterList(
arguments.next();
}

Iterator<Node> parameters = functionType.getParameters().iterator();
Node parameter = null;
Node argument = null;
while (arguments.hasNext()
&& (parameters.hasNext() || parameter != null && parameter.isVarArgs())) {
// If there are no parameters left in the list, then the while loop
// above implies that this must be a var_args function.
if (parameters.hasNext()) {
parameter = parameters.next();
}
argument = arguments.next();

if (!validateParameter(
getTypeI(compiler, argument), getTypeI(compiler, parameter))) {
return false;
}
}

int numArgs = callOrNew.getChildCount() - 1;
if (isCallInvocation && numArgs > 0) {
numArgs -= 1;
}
int minArgs = functionType.getMinArguments();
int maxArgs = functionType.getMaxArguments();
return minArgs <= numArgs && numArgs <= maxArgs;
}

/**
* Expect that the type of an argument matches the type of the parameter
* that it's fulfilling.
*
* @param argType The type of the argument.
* @param paramType The type of the parameter.
*/
static boolean validateParameter(TypeI argType, TypeI paramType) {
return argType.isSubtypeOf(paramType);
}

/**
* This method gets the TypeI from the Node argument and verifies that it is
* present.
*/
static TypeI getTypeI(AbstractCompiler compiler, Node n) {
TypeI type = n.getTypeI();
if (type == null) {
return getNativeType(compiler, JSTypeNative.UNKNOWN_TYPE);
} else {
return type;
// Get all the annotated types of the argument nodes
ImmutableList.Builder<TypeI> argumentTypes = ImmutableList.builder();
while (arguments.hasNext()) {
argumentTypes.add(arguments.next().getTypeI());
}
return functionType.acceptsArguments(argumentTypes.build());
}

static TypeI getNativeType(AbstractCompiler compiler, JSTypeNative typeId) {
return compiler.getTypeIRegistry().getNativeType(typeId);
}

}

/**
Expand Down Expand Up @@ -736,13 +686,13 @@ protected ConformanceResult checkConformance(NodeTraversal t, Node n) {

if (n.matchesQualifiedName(r.name)) {
if (!ConformanceUtil.validateCall(
compiler, n.getParent(), r.restrictedCallType, false)) {
n.getParent(), r.restrictedCallType, false)) {
return ConformanceResult.VIOLATION;
}
} else if (n.isGetProp() && n.getLastChild().getString().equals("call")
&& n.getFirstChild().matchesQualifiedName(r.name)) {
if (!ConformanceUtil.validateCall(
compiler, n.getParent(), r.restrictedCallType, true)) {
n.getParent(), r.restrictedCallType, true)) {
return ConformanceResult.VIOLATION;
}
}
Expand Down Expand Up @@ -858,14 +808,12 @@ private ConformanceResult checkConformance(
|| targetType.isEquivalentTo(
registry.getNativeType(JSTypeNative.OBJECT_TYPE))) {
if (!ConformanceUtil.validateCall(
compiler, n.getParent(), r.restrictedCallType,
isCallInvocation)) {
n.getParent(), r.restrictedCallType, isCallInvocation)) {
return ConformanceResult.POSSIBLE_VIOLATION_DUE_TO_LOOSE_TYPES;
}
} else if (targetType.isSubtypeOf(methodClassType)) {
if (!ConformanceUtil.validateCall(
compiler, n.getParent(), r.restrictedCallType,
isCallInvocation)) {
n.getParent(), r.restrictedCallType, isCallInvocation)) {
return ConformanceResult.VIOLATION;
}
}
Expand Down
27 changes: 17 additions & 10 deletions src/com/google/javascript/jscomp/newtypes/JSType.java
Expand Up @@ -1674,18 +1674,25 @@ public TypeI getTypeOfThis() {
}

@Override
public int getMinArguments() {
throw new UnsupportedOperationException("getMinArguments not implemented yet");
}
public boolean acceptsArguments(List<? extends TypeI> argumentTypes) {
Preconditions.checkState(this.isFunctionType());

@Override
public int getMaxArguments() {
throw new UnsupportedOperationException("getMaxArguments not implemented yet");
}
int numArgs = argumentTypes.size();
FunctionType fnType = this.getFunTypeIfSingletonObj();

@Override
public Iterable<Node> getParameters() {
throw new UnsupportedOperationException("getParameters not implemented yet");
if (numArgs < fnType.getMinArity() || numArgs > fnType.getMaxArity()) {
return false;
}

for (int i = 0; i < numArgs; i++) {
TypeI ithArgType = argumentTypes.get(i);
JSType ithParamType = fnType.getFormalType(i);
if (!ithArgType.isSubtypeOf(ithParamType)) {
return false;
}
}

return true;
}

@Override
Expand Down
7 changes: 2 additions & 5 deletions src/com/google/javascript/rhino/FunctionTypeI.java
Expand Up @@ -77,9 +77,6 @@ public interface FunctionTypeI extends TypeI {

void setSource(Node n);

int getMinArguments();

int getMaxArguments();

Iterable<Node> getParameters();
/** Checks if a call to this function with the given list of arguments is valid. */
boolean acceptsArguments(List<? extends TypeI> argumentTypes);
}
30 changes: 27 additions & 3 deletions src/com/google/javascript/rhino/jstype/FunctionType.java
Expand Up @@ -53,6 +53,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
Expand Down Expand Up @@ -300,7 +301,6 @@ public boolean hasImplementedInterfaces() {
return false;
}

@Override
public Iterable<Node> getParameters() {
Node n = getParametersNode();
if (n != null) {
Expand All @@ -316,7 +316,6 @@ public Node getParametersNode() {
}

/** Gets the minimum number of arguments that this function requires. */
@Override
public int getMinArguments() {
// NOTE(nicksantos): There are some native functions that have optional
// parameters before required parameters. This algorithm finds the position
Expand All @@ -336,7 +335,6 @@ public int getMinArguments() {
* Gets the maximum number of arguments that this function requires,
* or Integer.MAX_VALUE if this is a variable argument function.
*/
@Override
public int getMaxArguments() {
Node params = getParametersNode();
if (params != null) {
Expand Down Expand Up @@ -1510,4 +1508,30 @@ public List<FunctionType> checkExtendsLoop(HashSet<FunctionType> cache,
}
return null;
}

@Override
public boolean acceptsArguments(List<? extends TypeI> argumentTypes) {
// NOTE(aravindpg): This code is essentially lifted from TypeCheck::visitParameterList,
// but what small differences there are make it very painful to refactor out the shared code.
Iterator<? extends TypeI> arguments = argumentTypes.iterator();
Iterator<Node> parameters = this.getParameters().iterator();
Node parameter = null;
TypeI argument = null;
while (arguments.hasNext()
&& (parameters.hasNext() || parameter != null && parameter.isVarArgs())) {
// If there are no parameters left in the list, then the while loop
// above implies that this must be a var_args function.
if (parameters.hasNext()) {
parameter = parameters.next();
}
argument = arguments.next();

if (!argument.isSubtypeOf(parameter.getTypeI())) {
return false;
}
}

int numArgs = argumentTypes.size();
return this.getMinArguments() <= numArgs && numArgs <= this.getMaxArguments();
}
}

0 comments on commit 733261f

Please sign in to comment.