300 lines
8.8 KiB
Java
300 lines
8.8 KiB
Java
|
/*
|
||
|
* Copyright 2007 The Closure Compiler Authors.
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package com.google.javascript.jscomp;
|
||
|
|
||
|
import com.google.javascript.jscomp.type.ClosureReverseAbstractInterpreter;
|
||
|
import com.google.javascript.jscomp.type.FlowScope;
|
||
|
import com.google.javascript.rhino.Node;
|
||
|
import com.google.javascript.rhino.Token;
|
||
|
import com.google.javascript.rhino.jstype.JSType;
|
||
|
import com.google.javascript.rhino.testing.Asserts;
|
||
|
|
||
|
public class ClosureReverseAbstractInterpreterTest extends
|
||
|
CompilerTypeTestCase {
|
||
|
|
||
|
public void testGoogIsDef1() throws Exception {
|
||
|
testClosureFunction("goog.isDef",
|
||
|
createOptionalType(NUMBER_TYPE),
|
||
|
NUMBER_TYPE,
|
||
|
VOID_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsDef2() throws Exception {
|
||
|
testClosureFunction("goog.isDef",
|
||
|
createNullableType(NUMBER_TYPE),
|
||
|
createNullableType(NUMBER_TYPE),
|
||
|
NO_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsDef3() throws Exception {
|
||
|
testClosureFunction("goog.isDef",
|
||
|
ALL_TYPE,
|
||
|
createUnionType(OBJECT_NUMBER_STRING_BOOLEAN,NULL_TYPE),
|
||
|
VOID_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsDef4() throws Exception {
|
||
|
testClosureFunction("goog.isDef",
|
||
|
UNKNOWN_TYPE,
|
||
|
UNKNOWN_TYPE, // TODO(johnlenz): should be CHECKED_UNKNOWN_TYPE
|
||
|
UNKNOWN_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsNull1() throws Exception {
|
||
|
testClosureFunction("goog.isNull",
|
||
|
createOptionalType(NUMBER_TYPE),
|
||
|
NO_TYPE,
|
||
|
createOptionalType(NUMBER_TYPE));
|
||
|
}
|
||
|
|
||
|
public void testGoogIsNull2() throws Exception {
|
||
|
testClosureFunction("goog.isNull",
|
||
|
createNullableType(NUMBER_TYPE),
|
||
|
NULL_TYPE,
|
||
|
NUMBER_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsNull3() throws Exception {
|
||
|
testClosureFunction("goog.isNull",
|
||
|
ALL_TYPE,
|
||
|
NULL_TYPE,
|
||
|
createUnionType(OBJECT_NUMBER_STRING_BOOLEAN, VOID_TYPE));
|
||
|
}
|
||
|
|
||
|
public void testGoogIsNull4() throws Exception {
|
||
|
testClosureFunction("goog.isNull",
|
||
|
UNKNOWN_TYPE,
|
||
|
UNKNOWN_TYPE,
|
||
|
UNKNOWN_TYPE); // TODO(johnlenz): this should be CHECK_UNKNOWN
|
||
|
}
|
||
|
|
||
|
public void testGoogIsDefAndNotNull1() throws Exception {
|
||
|
testClosureFunction("goog.isDefAndNotNull",
|
||
|
createOptionalType(NUMBER_TYPE),
|
||
|
NUMBER_TYPE,
|
||
|
VOID_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsDefAndNotNull2() throws Exception {
|
||
|
testClosureFunction("goog.isDefAndNotNull",
|
||
|
createNullableType(NUMBER_TYPE),
|
||
|
NUMBER_TYPE,
|
||
|
NULL_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsDefAndNotNull3() throws Exception {
|
||
|
testClosureFunction("goog.isDefAndNotNull",
|
||
|
createOptionalType(createNullableType(NUMBER_TYPE)),
|
||
|
NUMBER_TYPE,
|
||
|
NULL_VOID);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsDefAndNotNull4() throws Exception {
|
||
|
testClosureFunction("goog.isDefAndNotNull",
|
||
|
ALL_TYPE,
|
||
|
OBJECT_NUMBER_STRING_BOOLEAN,
|
||
|
NULL_VOID);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsDefAndNotNull5() throws Exception {
|
||
|
testClosureFunction("goog.isDefAndNotNull",
|
||
|
UNKNOWN_TYPE,
|
||
|
UNKNOWN_TYPE, // TODO(johnlenz): this should be "CHECKED_UNKNOWN"
|
||
|
UNKNOWN_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsString1() throws Exception {
|
||
|
testClosureFunction("goog.isString",
|
||
|
createNullableType(STRING_TYPE),
|
||
|
STRING_TYPE,
|
||
|
NULL_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsString2() throws Exception {
|
||
|
testClosureFunction("goog.isString",
|
||
|
createNullableType(NUMBER_TYPE),
|
||
|
createNullableType(NUMBER_TYPE),
|
||
|
createNullableType(NUMBER_TYPE));
|
||
|
}
|
||
|
|
||
|
public void testGoogIsBoolean1() throws Exception {
|
||
|
testClosureFunction("goog.isBoolean",
|
||
|
createNullableType(BOOLEAN_TYPE),
|
||
|
BOOLEAN_TYPE,
|
||
|
NULL_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsBoolean2() throws Exception {
|
||
|
testClosureFunction("goog.isBoolean",
|
||
|
createUnionType(BOOLEAN_TYPE, STRING_TYPE, NO_OBJECT_TYPE),
|
||
|
BOOLEAN_TYPE,
|
||
|
createUnionType(STRING_TYPE, NO_OBJECT_TYPE));
|
||
|
}
|
||
|
|
||
|
public void testGoogIsBoolean3() throws Exception {
|
||
|
testClosureFunction("goog.isBoolean",
|
||
|
ALL_TYPE,
|
||
|
BOOLEAN_TYPE,
|
||
|
ALL_TYPE); // TODO(johnlenz): this should be:
|
||
|
// {Object|number|string|null|void}
|
||
|
}
|
||
|
|
||
|
public void testGoogIsBoolean4() throws Exception {
|
||
|
testClosureFunction("goog.isBoolean",
|
||
|
UNKNOWN_TYPE,
|
||
|
BOOLEAN_TYPE,
|
||
|
CHECKED_UNKNOWN_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsNumber() throws Exception {
|
||
|
testClosureFunction("goog.isNumber",
|
||
|
createNullableType(NUMBER_TYPE),
|
||
|
NUMBER_TYPE,
|
||
|
NULL_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsFunction() throws Exception {
|
||
|
testClosureFunction("goog.isFunction",
|
||
|
createNullableType(OBJECT_FUNCTION_TYPE),
|
||
|
OBJECT_FUNCTION_TYPE,
|
||
|
NULL_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsFunction2() throws Exception {
|
||
|
testClosureFunction("goog.isFunction",
|
||
|
OBJECT_NUMBER_STRING_BOOLEAN,
|
||
|
U2U_CONSTRUCTOR_TYPE,
|
||
|
OBJECT_NUMBER_STRING_BOOLEAN);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsFunction3() throws Exception {
|
||
|
testClosureFunction("goog.isFunction",
|
||
|
createUnionType(U2U_CONSTRUCTOR_TYPE, NUMBER_STRING_BOOLEAN),
|
||
|
U2U_CONSTRUCTOR_TYPE,
|
||
|
NUMBER_STRING_BOOLEAN);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsFunctionOnNull() throws Exception {
|
||
|
testClosureFunction("goog.isFunction",
|
||
|
null,
|
||
|
U2U_CONSTRUCTOR_TYPE,
|
||
|
null);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsArray1() throws Exception {
|
||
|
testClosureFunction("goog.isArray",
|
||
|
OBJECT_TYPE,
|
||
|
ARRAY_TYPE,
|
||
|
OBJECT_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsArray2() throws Exception {
|
||
|
testClosureFunction("goog.isArray",
|
||
|
ALL_TYPE,
|
||
|
ALL_TYPE, // TODO(johnlenz): should be ARRAY_TYPE?
|
||
|
ALL_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsArray3() throws Exception {
|
||
|
testClosureFunction("goog.isArray",
|
||
|
UNKNOWN_TYPE,
|
||
|
CHECKED_UNKNOWN_TYPE,
|
||
|
CHECKED_UNKNOWN_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsArray4() throws Exception {
|
||
|
testClosureFunction("goog.isArray",
|
||
|
createUnionType(ARRAY_TYPE, NULL_TYPE),
|
||
|
ARRAY_TYPE,
|
||
|
NULL_TYPE);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsArrayOnNull() throws Exception {
|
||
|
testClosureFunction("goog.isArray",
|
||
|
null,
|
||
|
ARRAY_TYPE,
|
||
|
null);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsObjectOnNull() throws Exception {
|
||
|
testClosureFunction("goog.isObject",
|
||
|
null,
|
||
|
OBJECT_TYPE,
|
||
|
null);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsObject1() throws Exception {
|
||
|
testClosureFunction("goog.isObject",
|
||
|
ALL_TYPE,
|
||
|
NO_OBJECT_TYPE,
|
||
|
createUnionType(NUMBER_STRING_BOOLEAN, NULL_TYPE, VOID_TYPE));
|
||
|
}
|
||
|
|
||
|
public void testGoogIsObject2() throws Exception {
|
||
|
testClosureFunction("goog.isObject",
|
||
|
createUnionType(OBJECT_TYPE, NUMBER_STRING_BOOLEAN),
|
||
|
OBJECT_TYPE,
|
||
|
NUMBER_STRING_BOOLEAN);
|
||
|
}
|
||
|
|
||
|
public void testGoogIsObject3() throws Exception {
|
||
|
testClosureFunction("goog.isObject",
|
||
|
createUnionType(
|
||
|
OBJECT_TYPE, NUMBER_STRING_BOOLEAN, NULL_TYPE, VOID_TYPE),
|
||
|
OBJECT_TYPE,
|
||
|
createUnionType(NUMBER_STRING_BOOLEAN, NULL_TYPE, VOID_TYPE));
|
||
|
}
|
||
|
|
||
|
public void testGoogIsObject4() throws Exception {
|
||
|
testClosureFunction("goog.isObject",
|
||
|
UNKNOWN_TYPE,
|
||
|
NO_OBJECT_TYPE, // ? Should this be CHECKED_UNKNOWN?
|
||
|
CHECKED_UNKNOWN_TYPE);
|
||
|
}
|
||
|
|
||
|
private void testClosureFunction(String function, JSType type,
|
||
|
JSType trueType, JSType falseType) {
|
||
|
// function(a) where a : type
|
||
|
Node n = compiler.parseTestCode("var a; " + function + "(a)");
|
||
|
Node call = n.getLastChild().getLastChild();
|
||
|
Node name = call.getLastChild();
|
||
|
|
||
|
Scope scope = new SyntacticScopeCreator(compiler).createScope(n, null);
|
||
|
FlowScope flowScope = LinkedFlowScope.createEntryLattice(scope);
|
||
|
|
||
|
assertEquals(Token.CALL, call.getType());
|
||
|
assertEquals(Token.NAME, name.getType());
|
||
|
|
||
|
GoogleCodingConvention convention = new GoogleCodingConvention();
|
||
|
flowScope.inferSlotType("a", type);
|
||
|
ClosureReverseAbstractInterpreter rai =
|
||
|
new ClosureReverseAbstractInterpreter(convention, registry);
|
||
|
|
||
|
// trueScope
|
||
|
Asserts.assertTypeEquals(
|
||
|
trueType,
|
||
|
rai.getPreciserScopeKnowingConditionOutcome(call, flowScope, true)
|
||
|
.getSlot("a").getType());
|
||
|
|
||
|
// falseScope
|
||
|
Asserts.assertTypeEquals(
|
||
|
falseType,
|
||
|
rai.getPreciserScopeKnowingConditionOutcome(call, flowScope, false)
|
||
|
.getSlot("a").getType());
|
||
|
}
|
||
|
}
|