From 8ceea0f93772fdb1bef8a73f560d7b1ceb4a432c Mon Sep 17 00:00:00 2001 From: bradfordcsmith Date: Wed, 18 Apr 2018 10:34:08 -0700 Subject: [PATCH] Refactor CompilerTypeTestCase to fix a problem with TypeCheckTest 1. Disconnect CompilerTypeTestCase from BaseJSTypeTestCase and add methods for getting the correct native types in tests. BaseJSTypeTestCase artificially constructs native types in a way that conflicts with using externs in the normal fashion. This leads to confusing unit test behavior, causing incorrect behavior for one test case in TypeCheckTest and correct behavior for the wrong reason in others. 2. Also create TestExternsBuilder class. This class provides a way to build exactly the externs definitions needed for a test case rather than continually adding definitions to one or more "default" externs variables that grow ever larger creating a performance drain on test cases that don't need most of the definitions they contain. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=193379201 --- .../rhino/testing/BaseJSTypeTestCase.java | 14 - ...ClosureReverseAbstractInterpreterTest.java | 330 ++++---- .../jscomp/CompilerTypeTestCase.java | 242 +++++- .../jscomp/LinkedFlowScopeTest.java | 127 +-- ...emanticReverseAbstractInterpreterTest.java | 425 +++++----- .../javascript/jscomp/TestExternsBuilder.java | 318 ++++++++ .../javascript/jscomp/TypeCheckTest.java | 715 +++++++++-------- .../jscomp/TypeTransformationTest.java | 745 ++++++++++-------- 8 files changed, 1813 insertions(+), 1103 deletions(-) create mode 100644 test/com/google/javascript/jscomp/TestExternsBuilder.java diff --git a/src/com/google/javascript/rhino/testing/BaseJSTypeTestCase.java b/src/com/google/javascript/rhino/testing/BaseJSTypeTestCase.java index 546e98c3b2b..f45777ca085 100644 --- a/src/com/google/javascript/rhino/testing/BaseJSTypeTestCase.java +++ b/src/com/google/javascript/rhino/testing/BaseJSTypeTestCase.java @@ -81,18 +81,15 @@ public abstract class BaseJSTypeTestCase extends TestCase { protected ObjectType FUNCTION_PROTOTYPE; protected JSType GREATEST_FUNCTION_TYPE; protected JSType LEAST_FUNCTION_TYPE; - protected JSType MATH_TYPE; protected JSType NULL_TYPE; protected JSType NUMBER_OBJECT_FUNCTION_TYPE; protected ObjectType NUMBER_OBJECT_TYPE; protected JSType NUMBER_STRING_BOOLEAN; - protected JSType NUMBER_STRING_BOOLEAN_SYMBOL; protected JSType NUMBER_TYPE; protected FunctionType OBJECT_FUNCTION_TYPE; protected JSType NULL_VOID; protected JSType OBJECT_NUMBER_STRING; protected JSType OBJECT_NUMBER_STRING_BOOLEAN; - protected JSType OBJECT_NUMBER_STRING_BOOLEAN_SYMBOL; protected JSType OBJECT_PROTOTYPE; protected ObjectType OBJECT_TYPE; protected JSType RANGE_ERROR_FUNCTION_TYPE; @@ -104,7 +101,6 @@ public abstract class BaseJSTypeTestCase extends TestCase { protected JSType STRING_OBJECT_FUNCTION_TYPE; protected ObjectType STRING_OBJECT_TYPE; protected JSType STRING_TYPE; - protected JSType SYMBOL_OBJECT_FUNCTION_TYPE; protected ObjectType SYMBOL_OBJECT_TYPE; protected JSType SYMBOL_TYPE; protected JSType SYNTAX_ERROR_FUNCTION_TYPE; @@ -179,8 +175,6 @@ protected void initTypes() { registry.getNativeObjectType(JSTypeNative.NUMBER_OBJECT_TYPE); NUMBER_STRING_BOOLEAN = registry.getNativeType(JSTypeNative.NUMBER_STRING_BOOLEAN); - NUMBER_STRING_BOOLEAN_SYMBOL = - registry.getNativeType(JSTypeNative.NUMBER_STRING_BOOLEAN_SYMBOL); NUMBER_TYPE = registry.getNativeType(JSTypeNative.NUMBER_TYPE); OBJECT_FUNCTION_TYPE = @@ -191,8 +185,6 @@ protected void initTypes() { registry.getNativeType(JSTypeNative.OBJECT_NUMBER_STRING); OBJECT_NUMBER_STRING_BOOLEAN = registry.getNativeType(JSTypeNative.OBJECT_NUMBER_STRING_BOOLEAN); - OBJECT_NUMBER_STRING_BOOLEAN_SYMBOL = - registry.getNativeType(JSTypeNative.OBJECT_NUMBER_STRING_BOOLEAN_SYMBOL); OBJECT_PROTOTYPE = registry.getNativeType(JSTypeNative.OBJECT_PROTOTYPE); OBJECT_TYPE = @@ -215,8 +207,6 @@ protected void initTypes() { registry.getNativeObjectType(JSTypeNative.STRING_OBJECT_TYPE); STRING_TYPE = registry.getNativeType(JSTypeNative.STRING_TYPE); - SYMBOL_OBJECT_FUNCTION_TYPE = - registry.getNativeType(JSTypeNative.SYMBOL_OBJECT_FUNCTION_TYPE); SYMBOL_OBJECT_TYPE = registry.getNativeObjectType(JSTypeNative.SYMBOL_OBJECT_TYPE); SYMBOL_TYPE = @@ -622,10 +612,6 @@ protected final void assertTypeNotEquals(JSType a, JSType b) { Asserts.assertTypeNotEquals(a, b); } - protected final void assertTypeNotEquals(String msg, JSType a, JSType b) { - Asserts.assertTypeNotEquals(msg, a, b); - } - protected static String lines(String line) { return line; } diff --git a/test/com/google/javascript/jscomp/ClosureReverseAbstractInterpreterTest.java b/test/com/google/javascript/jscomp/ClosureReverseAbstractInterpreterTest.java index 5eda5cdb3c4..c11bd4d8a7f 100644 --- a/test/com/google/javascript/jscomp/ClosureReverseAbstractInterpreterTest.java +++ b/test/com/google/javascript/jscomp/ClosureReverseAbstractInterpreterTest.java @@ -29,265 +29,293 @@ public final class ClosureReverseAbstractInterpreterTest extends CompilerTypeTestCase { public void testGoogIsDef1() throws Exception { - testClosureFunction("goog.isDef", - createOptionalType(NUMBER_TYPE), - NUMBER_TYPE, - VOID_TYPE); + testClosureFunction( + "goog.isDef", + createOptionalType(getNativeNumberType()), + getNativeNumberType(), + getNativeVoidType()); } public void testGoogIsDef2() throws Exception { - testClosureFunction("goog.isDef", - createNullableType(NUMBER_TYPE), - createNullableType(NUMBER_TYPE), - NO_TYPE); + testClosureFunction( + "goog.isDef", + createNullableType(getNativeNumberType()), + createNullableType(getNativeNumberType()), + getNativeNoType()); } public void testGoogIsDef3() throws Exception { - testClosureFunction("goog.isDef", - ALL_TYPE, - createUnionType(OBJECT_NUMBER_STRING_BOOLEAN_SYMBOL, NULL_TYPE), - VOID_TYPE); + testClosureFunction( + "goog.isDef", + getNativeAllType(), + createUnionType(getNativeObjectNumberStringBooleanSymbolType(), getNativeNullType()), + getNativeVoidType()); } public void testGoogIsDef4() throws Exception { - testClosureFunction("goog.isDef", - UNKNOWN_TYPE, - UNKNOWN_TYPE, // TODO(johnlenz): should be CHECKED_UNKNOWN_TYPE - UNKNOWN_TYPE); + testClosureFunction( + "goog.isDef", + getNativeUnknownType(), + getNativeUnknownType(), // TODO(johnlenz): should be getNativeCheckedUnknownType() + getNativeUnknownType()); } public void testGoogIsNull1() throws Exception { - testClosureFunction("goog.isNull", - createOptionalType(NUMBER_TYPE), - NO_TYPE, - createOptionalType(NUMBER_TYPE)); + testClosureFunction( + "goog.isNull", + createOptionalType(getNativeNumberType()), + getNativeNoType(), + createOptionalType(getNativeNumberType())); } public void testGoogIsNull2() throws Exception { - testClosureFunction("goog.isNull", - createNullableType(NUMBER_TYPE), - NULL_TYPE, - NUMBER_TYPE); + testClosureFunction( + "goog.isNull", + createNullableType(getNativeNumberType()), + getNativeNullType(), + getNativeNumberType()); } public void testGoogIsNull3() throws Exception { - testClosureFunction("goog.isNull", - ALL_TYPE, - NULL_TYPE, - createUnionType(OBJECT_NUMBER_STRING_BOOLEAN_SYMBOL, VOID_TYPE)); + testClosureFunction( + "goog.isNull", + getNativeAllType(), + getNativeNullType(), + createUnionType(getNativeObjectNumberStringBooleanSymbolType(), getNativeVoidType())); } public void testGoogIsNull4() throws Exception { - testClosureFunction("goog.isNull", - UNKNOWN_TYPE, - UNKNOWN_TYPE, - UNKNOWN_TYPE); // TODO(johnlenz): this should be CHECK_UNKNOWN + testClosureFunction( + "goog.isNull", + getNativeUnknownType(), + getNativeUnknownType(), + getNativeUnknownType()); // TODO(johnlenz): this should be CHECK_UNKNOWN } public void testGoogIsDefAndNotNull1() throws Exception { - testClosureFunction("goog.isDefAndNotNull", - createOptionalType(NUMBER_TYPE), - NUMBER_TYPE, - VOID_TYPE); + testClosureFunction( + "goog.isDefAndNotNull", + createOptionalType(getNativeNumberType()), + getNativeNumberType(), + getNativeVoidType()); } public void testGoogIsDefAndNotNull2() throws Exception { - testClosureFunction("goog.isDefAndNotNull", - createNullableType(NUMBER_TYPE), - NUMBER_TYPE, - NULL_TYPE); + testClosureFunction( + "goog.isDefAndNotNull", + createNullableType(getNativeNumberType()), + getNativeNumberType(), + getNativeNullType()); } public void testGoogIsDefAndNotNull3() throws Exception { - testClosureFunction("goog.isDefAndNotNull", - createOptionalType(createNullableType(NUMBER_TYPE)), - NUMBER_TYPE, - NULL_VOID); + testClosureFunction( + "goog.isDefAndNotNull", + createOptionalType(createNullableType(getNativeNumberType())), + getNativeNumberType(), + getNativeNullVoidType()); } public void testGoogIsDefAndNotNull4() throws Exception { - testClosureFunction("goog.isDefAndNotNull", - ALL_TYPE, - OBJECT_NUMBER_STRING_BOOLEAN_SYMBOL, - NULL_VOID); + testClosureFunction( + "goog.isDefAndNotNull", + getNativeAllType(), + getNativeObjectNumberStringBooleanSymbolType(), + getNativeNullVoidType()); } public void testGoogIsDefAndNotNull5() throws Exception { - testClosureFunction("goog.isDefAndNotNull", - UNKNOWN_TYPE, - UNKNOWN_TYPE, // TODO(johnlenz): this should be "CHECKED_UNKNOWN" - UNKNOWN_TYPE); + testClosureFunction( + "goog.isDefAndNotNull", + getNativeUnknownType(), + getNativeUnknownType(), // TODO(johnlenz): this should be "CHECKED_UNKNOWN" + getNativeUnknownType()); } public void testGoogIsString1() throws Exception { - testClosureFunction("goog.isString", - createNullableType(STRING_TYPE), - STRING_TYPE, - NULL_TYPE); + testClosureFunction( + "goog.isString", + createNullableType(getNativeStringType()), + getNativeStringType(), + getNativeNullType()); } public void testGoogIsString2() throws Exception { - testClosureFunction("goog.isString", - createNullableType(NUMBER_TYPE), - createNullableType(NUMBER_TYPE), - createNullableType(NUMBER_TYPE)); + testClosureFunction( + "goog.isString", + createNullableType(getNativeNumberType()), + createNullableType(getNativeNumberType()), + createNullableType(getNativeNumberType())); } public void testGoogIsBoolean1() throws Exception { - testClosureFunction("goog.isBoolean", - createNullableType(BOOLEAN_TYPE), - BOOLEAN_TYPE, - NULL_TYPE); + testClosureFunction( + "goog.isBoolean", + createNullableType(getNativeBooleanType()), + getNativeBooleanType(), + getNativeNullType()); } public void testGoogIsBoolean2() throws Exception { - testClosureFunction("goog.isBoolean", - createUnionType(BOOLEAN_TYPE, STRING_TYPE, NO_OBJECT_TYPE), - BOOLEAN_TYPE, - createUnionType(STRING_TYPE, NO_OBJECT_TYPE)); + testClosureFunction( + "goog.isBoolean", + createUnionType(getNativeBooleanType(), getNativeStringType(), getNativeNoObjectType()), + getNativeBooleanType(), + createUnionType(getNativeStringType(), getNativeNoObjectType())); } public void testGoogIsBoolean3() throws Exception { - testClosureFunction("goog.isBoolean", - ALL_TYPE, - BOOLEAN_TYPE, - ALL_TYPE); // TODO(johnlenz): this should be: - // {Object|number|string|null|void} + testClosureFunction( + "goog.isBoolean", + getNativeAllType(), + getNativeBooleanType(), + // TODO(johnlenz): this should be: {Object|number|string|null|void} + getNativeAllType()); } public void testGoogIsBoolean4() throws Exception { - testClosureFunction("goog.isBoolean", - UNKNOWN_TYPE, - BOOLEAN_TYPE, - CHECKED_UNKNOWN_TYPE); + testClosureFunction( + "goog.isBoolean", + getNativeUnknownType(), + getNativeBooleanType(), + getNativeCheckedUnknownType()); } public void testGoogIsNumber() throws Exception { - testClosureFunction("goog.isNumber", - createNullableType(NUMBER_TYPE), - NUMBER_TYPE, - NULL_TYPE); + testClosureFunction( + "goog.isNumber", + createNullableType(getNativeNumberType()), + getNativeNumberType(), + getNativeNullType()); } public void testGoogIsFunction() throws Exception { - testClosureFunction("goog.isFunction", - createNullableType(OBJECT_FUNCTION_TYPE), - OBJECT_FUNCTION_TYPE, - NULL_TYPE); + testClosureFunction( + "goog.isFunction", + createNullableType(getNativeObjectConstructorType()), + getNativeObjectConstructorType(), + getNativeNullType()); } public void testGoogIsFunction2a() throws Exception { - testClosureFunction("goog.isFunction", - OBJECT_NUMBER_STRING_BOOLEAN, - U2U_CONSTRUCTOR_TYPE, - OBJECT_NUMBER_STRING_BOOLEAN); + testClosureFunction( + "goog.isFunction", + getNativeObjectNumberStringBooleanType(), + getNativeU2UConstructorType(), + getNativeObjectNumberStringBooleanType()); } public void testGoogIsFunction2b() throws Exception { - testClosureFunction("goog.isFunction", - OBJECT_NUMBER_STRING_BOOLEAN_SYMBOL, - U2U_CONSTRUCTOR_TYPE, - OBJECT_NUMBER_STRING_BOOLEAN_SYMBOL); + testClosureFunction( + "goog.isFunction", + getNativeObjectNumberStringBooleanSymbolType(), + getNativeU2UConstructorType(), + getNativeObjectNumberStringBooleanSymbolType()); } public void testGoogIsFunction3() throws Exception { - testClosureFunction("goog.isFunction", - createUnionType(U2U_CONSTRUCTOR_TYPE, NUMBER_STRING_BOOLEAN), - U2U_CONSTRUCTOR_TYPE, - NUMBER_STRING_BOOLEAN); + testClosureFunction( + "goog.isFunction", + createUnionType(getNativeU2UConstructorType(), getNativeNumberStringBooleanType()), + getNativeU2UConstructorType(), + getNativeNumberStringBooleanType()); } public void testGoogIsFunctionOnNull() throws Exception { - testClosureFunction("goog.isFunction", - null, - U2U_CONSTRUCTOR_TYPE, - null); + testClosureFunction("goog.isFunction", null, getNativeU2UConstructorType(), null); } public void testGoogIsArray1() throws Exception { - testClosureFunction("goog.isArray", - OBJECT_TYPE, - ARRAY_TYPE, - OBJECT_TYPE); + testClosureFunction( + "goog.isArray", getNativeObjectType(), getNativeArrayType(), getNativeObjectType()); } public void testGoogIsArray2() throws Exception { - testClosureFunction("goog.isArray", - ALL_TYPE, - ARRAY_TYPE, - ALL_TYPE); + testClosureFunction( + "goog.isArray", getNativeAllType(), getNativeArrayType(), getNativeAllType()); } public void testGoogIsArray3() throws Exception { - testClosureFunction("goog.isArray", - UNKNOWN_TYPE, - CHECKED_UNKNOWN_TYPE, - CHECKED_UNKNOWN_TYPE); + testClosureFunction( + "goog.isArray", + getNativeUnknownType(), + getNativeCheckedUnknownType(), + getNativeCheckedUnknownType()); } public void testGoogIsArray4() throws Exception { - testClosureFunction("goog.isArray", - createUnionType(ARRAY_TYPE, NULL_TYPE), - ARRAY_TYPE, - NULL_TYPE); + testClosureFunction( + "goog.isArray", + createUnionType(getNativeArrayType(), getNativeNullType()), + getNativeArrayType(), + getNativeNullType()); } public void testGoogIsArrayOnNull() throws Exception { - testClosureFunction("goog.isArray", - null, - ARRAY_TYPE, - null); + testClosureFunction("goog.isArray", null, getNativeArrayType(), null); } public void testGoogIsObjectOnNull() throws Exception { - testClosureFunction("goog.isObject", - null, - OBJECT_TYPE, - null); + testClosureFunction("goog.isObject", null, getNativeObjectType(), null); } public void testGoogIsObject1() throws Exception { - testClosureFunction("goog.isObject", - ALL_TYPE, - NO_OBJECT_TYPE, - createUnionType(NUMBER_STRING_BOOLEAN_SYMBOL, NULL_TYPE, VOID_TYPE)); + testClosureFunction( + "goog.isObject", + getNativeAllType(), + getNativeNoObjectType(), + createUnionType( + getNativeNumberStringBooleanSymbolType(), getNativeNullType(), getNativeVoidType())); } public void testGoogIsObject2a() throws Exception { - testClosureFunction("goog.isObject", - createUnionType(OBJECT_TYPE, NUMBER_STRING_BOOLEAN), - OBJECT_TYPE, - NUMBER_STRING_BOOLEAN); + testClosureFunction( + "goog.isObject", + createUnionType(getNativeObjectType(), getNativeNumberStringBooleanType()), + getNativeObjectType(), + getNativeNumberStringBooleanType()); } public void testGoogIsObject2b() throws Exception { - testClosureFunction("goog.isObject", - createUnionType(OBJECT_TYPE, NUMBER_STRING_BOOLEAN_SYMBOL), - OBJECT_TYPE, - NUMBER_STRING_BOOLEAN_SYMBOL); + testClosureFunction( + "goog.isObject", + createUnionType(getNativeObjectType(), getNativeNumberStringBooleanSymbolType()), + getNativeObjectType(), + getNativeNumberStringBooleanSymbolType()); } public void testGoogIsObject3a() 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)); + testClosureFunction( + "goog.isObject", + createUnionType( + getNativeObjectType(), + getNativeNumberStringBooleanType(), + getNativeNullType(), + getNativeVoidType()), + getNativeObjectType(), + createUnionType( + getNativeNumberStringBooleanType(), getNativeNullType(), getNativeVoidType())); } public void testGoogIsObject3b() throws Exception { - testClosureFunction("goog.isObject", - createUnionType( - OBJECT_TYPE, NUMBER_STRING_BOOLEAN_SYMBOL, NULL_TYPE, VOID_TYPE), - OBJECT_TYPE, - createUnionType(NUMBER_STRING_BOOLEAN_SYMBOL, NULL_TYPE, VOID_TYPE)); + testClosureFunction( + "goog.isObject", + createUnionType( + getNativeObjectType(), + getNativeNumberStringBooleanSymbolType(), + getNativeNullType(), + getNativeVoidType()), + getNativeObjectType(), + createUnionType( + getNativeNumberStringBooleanSymbolType(), getNativeNullType(), getNativeVoidType())); } public void testGoogIsObject4() throws Exception { - testClosureFunction("goog.isObject", - UNKNOWN_TYPE, - NO_OBJECT_TYPE, // ? Should this be CHECKED_UNKNOWN? - CHECKED_UNKNOWN_TYPE); + testClosureFunction( + "goog.isObject", + getNativeUnknownType(), + getNativeNoObjectType(), // ? Should this be CHECKED_UNKNOWN? + getNativeCheckedUnknownType()); } private void testClosureFunction(String function, JSType type, diff --git a/test/com/google/javascript/jscomp/CompilerTypeTestCase.java b/test/com/google/javascript/jscomp/CompilerTypeTestCase.java index 0088b0ce1d7..3f3a7b274cc 100644 --- a/test/com/google/javascript/jscomp/CompilerTypeTestCase.java +++ b/test/com/google/javascript/jscomp/CompilerTypeTestCase.java @@ -19,17 +19,30 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; import com.google.javascript.jscomp.CompilerOptions.LanguageMode; import com.google.javascript.jscomp.parsing.parser.FeatureSet.Feature; -import com.google.javascript.rhino.testing.BaseJSTypeTestCase; +import com.google.javascript.rhino.JSTypeExpression; +import com.google.javascript.rhino.Node; +import com.google.javascript.rhino.jstype.FunctionType; +import com.google.javascript.rhino.jstype.JSType; +import com.google.javascript.rhino.jstype.JSTypeNative; +import com.google.javascript.rhino.jstype.JSTypeRegistry; +import com.google.javascript.rhino.jstype.ObjectType; +import com.google.javascript.rhino.jstype.RecordTypeBuilder; +import com.google.javascript.rhino.jstype.TemplatizedType; +import com.google.javascript.rhino.testing.Asserts; +import com.google.javascript.rhino.testing.TestErrorReporter; import java.util.Arrays; +import junit.framework.TestCase; /** - * This class is mostly used by passes testing the old type checker. - * Passes that run after type checking and need type information use - * the class TypeICompilerTestCase. + * This class is mostly used by passes testing the old type checker. Passes that run after type + * checking and need type information use the class TypeICompilerTestCase. */ -abstract class CompilerTypeTestCase extends BaseJSTypeTestCase { +abstract class CompilerTypeTestCase extends TestCase { + protected static final Joiner LINE_JOINER = Joiner.on('\n'); static final String CLOSURE_DEFS = LINE_JOINER.join( "/** @const */ var goog = {};", @@ -60,10 +73,16 @@ abstract class CompilerTypeTestCase extends BaseJSTypeTestCase { "goog.asserts = {};", "/** @return {*} */ goog.asserts.assert = function(x) { return x; };"); - /** A default set of externs for testing. */ + /** + * A default set of externs for testing. + * + * TODO(bradfordcsmith): Replace this with externs built by TestExternsBuilder. + */ static final String DEFAULT_EXTERNS = CompilerTestCase.DEFAULT_EXTERNS; protected Compiler compiler; + protected JSTypeRegistry registry; + protected TestErrorReporter errorReporter; protected CompilerOptions getDefaultOptions() { CompilerOptions options = new CompilerOptions(); @@ -104,6 +123,7 @@ protected void checkReportedWarningsHelper(String[] expected) { @Override protected void setUp() throws Exception { super.setUp(); + errorReporter = new TestErrorReporter(null, null); initializeNewCompiler(getDefaultOptions()); } @@ -120,6 +140,214 @@ protected void initializeNewCompiler(CompilerOptions options) { compiler.initOptions(options); compiler.setFeatureSet(compiler.getFeatureSet().without(Feature.MODULES)); registry = compiler.getTypeRegistry(); - initTypes(); + } + + protected JSType createUnionType(JSType... variants) { + return registry.createUnionType(variants); + } + + protected RecordTypeBuilder createRecordTypeBuilder() { + return new RecordTypeBuilder(registry); + } + + protected JSType createNullableType(JSType type) { + return registry.createNullableType(type); + } + + protected JSType createOptionalType(JSType type) { + return registry.createOptionalType(type); + } + + protected TemplatizedType createTemplatizedType( + ObjectType baseType, ImmutableList templatizedTypes) { + return registry.createTemplatizedType(baseType, templatizedTypes); + } + + protected TemplatizedType createTemplatizedType(ObjectType baseType, JSType... templatizedType) { + return createTemplatizedType(baseType, ImmutableList.copyOf(templatizedType)); + } + + /** Asserts that a Node representing a type expression resolves to the correct {@code JSType}. */ + protected void assertTypeEquals(JSType expected, Node actual) { + assertTypeEquals(expected, new JSTypeExpression(actual, "")); + } + + /** Asserts that a a type expression resolves to the correct {@code JSType}. */ + protected void assertTypeEquals(JSType expected, JSTypeExpression actual) { + assertTypeEquals(expected, resolve(actual)); + } + + protected final void assertTypeEquals(JSType a, JSType b) { + Asserts.assertTypeEquals(a, b); + } + + protected final void assertTypeEquals(String msg, JSType a, JSType b) { + Asserts.assertTypeEquals(msg, a, b); + } + + /** Resolves a type expression, expecting the given warnings. */ + protected JSType resolve(JSTypeExpression n, String... warnings) { + errorReporter.setWarnings(warnings); + return n.evaluate(null, registry); + } + + protected ObjectType getNativeNoObjectType() { + return getNativeObjectType(JSTypeNative.NO_OBJECT_TYPE); + } + + protected ObjectType getNativeArrayType() { + return getNativeObjectType(JSTypeNative.ARRAY_TYPE); + } + + protected ObjectType getNativeStringObjectType() { + return getNativeObjectType(JSTypeNative.STRING_OBJECT_TYPE); + } + + protected ObjectType getNativeNumberObjectType() { + return getNativeObjectType(JSTypeNative.NUMBER_OBJECT_TYPE); + } + + protected ObjectType getNativeBooleanObjectType() { + return getNativeObjectType(JSTypeNative.BOOLEAN_OBJECT_TYPE); + } + + protected ObjectType getNativeNoType() { + return getNativeObjectType(JSTypeNative.NO_TYPE); + } + + protected ObjectType getNativeUnknownType() { + return getNativeObjectType(JSTypeNative.UNKNOWN_TYPE); + } + + protected ObjectType getNativeCheckedUnknownType() { + return getNativeObjectType(JSTypeNative.CHECKED_UNKNOWN_TYPE); + } + + protected ObjectType getNativeErrorType() { + return getNativeObjectType(JSTypeNative.ERROR_TYPE); + } + + protected ObjectType getNativeObjectType() { + return getNativeObjectType(JSTypeNative.OBJECT_TYPE); + } + + ObjectType getNativeObjectType(JSTypeNative jsTypeNative) { + return registry.getNativeObjectType(jsTypeNative); + } + + protected FunctionType getNativeObjectConstructorType() { + return getNativeFunctionType(JSTypeNative.OBJECT_FUNCTION_TYPE); + } + + protected FunctionType getNativeArrayConstructorType() { + return getNativeFunctionType(JSTypeNative.ARRAY_FUNCTION_TYPE); + } + + protected FunctionType getNativeBooleanObjectConstructorType() { + return getNativeFunctionType(JSTypeNative.BOOLEAN_OBJECT_FUNCTION_TYPE); + } + + protected FunctionType getNativeNumberObjectConstructorType() { + return getNativeFunctionType(JSTypeNative.NUMBER_OBJECT_FUNCTION_TYPE); + } + + protected FunctionType getNativeStringObjectConstructorType() { + return getNativeFunctionType(JSTypeNative.STRING_OBJECT_FUNCTION_TYPE); + } + + protected FunctionType getNativeErrorConstructorType() { + return getNativeFunctionType(JSTypeNative.ERROR_FUNCTION_TYPE); + } + + protected FunctionType getNativeEvalErrorConstructorType() { + return getNativeFunctionType(JSTypeNative.EVAL_ERROR_FUNCTION_TYPE); + } + + protected FunctionType getNativeRangeErrorConstructorType() { + return getNativeFunctionType(JSTypeNative.RANGE_ERROR_FUNCTION_TYPE); + } + + protected FunctionType getNativeReferenceErrorConstructorType() { + return getNativeFunctionType(JSTypeNative.REFERENCE_ERROR_FUNCTION_TYPE); + } + + protected FunctionType getNativeSyntaxErrorConstructorType() { + return getNativeFunctionType(JSTypeNative.SYNTAX_ERROR_FUNCTION_TYPE); + } + + protected FunctionType getNativeTypeErrorConstructorType() { + return getNativeFunctionType(JSTypeNative.TYPE_ERROR_FUNCTION_TYPE); + } + + protected FunctionType getNativeUriErrorConstructorType() { + return getNativeFunctionType(JSTypeNative.URI_ERROR_FUNCTION_TYPE); + } + + protected FunctionType getNativeDateConstructorType() { + return getNativeFunctionType(JSTypeNative.DATE_FUNCTION_TYPE); + } + + protected FunctionType getNativeRegexpConstructorType() { + return getNativeFunctionType(JSTypeNative.REGEXP_FUNCTION_TYPE); + } + + protected FunctionType getNativeU2UConstructorType() { + return getNativeFunctionType(JSTypeNative.U2U_CONSTRUCTOR_TYPE); + } + + protected FunctionType getNativeU2UFunctionType() { + return getNativeFunctionType(JSTypeNative.U2U_FUNCTION_TYPE); + } + + FunctionType getNativeFunctionType(JSTypeNative jsTypeNative) { + return registry.getNativeFunctionType(jsTypeNative); + } + + protected JSType getNativeVoidType() { + return getNativeType(JSTypeNative.VOID_TYPE); + } + + protected JSType getNativeNullType() { + return getNativeType(JSTypeNative.NULL_TYPE); + } + + protected JSType getNativeNullVoidType() { + return getNativeType(JSTypeNative.NULL_VOID); + } + + protected JSType getNativeNumberType() { + return getNativeType(JSTypeNative.NUMBER_TYPE); + } + + protected JSType getNativeBooleanType() { + return getNativeType(JSTypeNative.BOOLEAN_TYPE); + } + + protected JSType getNativeStringType() { + return getNativeType(JSTypeNative.STRING_TYPE); + } + + protected JSType getNativeObjectNumberStringBooleanType() { + return getNativeType(JSTypeNative.OBJECT_NUMBER_STRING_BOOLEAN); + } + + protected JSType getNativeNumberStringBooleanType() { + return getNativeType(JSTypeNative.NUMBER_STRING_BOOLEAN); + } + + protected JSType getNativeObjectNumberStringBooleanSymbolType() { + return getNativeType(JSTypeNative.OBJECT_NUMBER_STRING_BOOLEAN_SYMBOL); + } + + protected JSType getNativeNumberStringBooleanSymbolType() { + return getNativeType(JSTypeNative.NUMBER_STRING_BOOLEAN_SYMBOL); + } + + JSType getNativeAllType() { + return getNativeType(JSTypeNative.ALL_TYPE); + } + + JSType getNativeType(JSTypeNative jsTypeNative) { + return registry.getNativeType(jsTypeNative); } } diff --git a/test/com/google/javascript/jscomp/LinkedFlowScopeTest.java b/test/com/google/javascript/jscomp/LinkedFlowScopeTest.java index b88532cbf5a..1e48abd906c 100644 --- a/test/com/google/javascript/jscomp/LinkedFlowScopeTest.java +++ b/test/com/google/javascript/jscomp/LinkedFlowScopeTest.java @@ -61,31 +61,33 @@ public void testOptimize() { FlowScope child = localEntry.createChildFlowScope(); assertEquals(localEntry, child.optimize()); - child.inferSlotType("localB", NUMBER_TYPE); + child.inferSlotType("localB", getNativeNumberType()); assertEquals(child, child.optimize()); } public void testJoin1() { FlowScope childA = localEntry.createChildFlowScope(); - childA.inferSlotType("localB", NUMBER_TYPE); + childA.inferSlotType("localB", getNativeNumberType()); FlowScope childAB = childA.createChildFlowScope(); - childAB.inferSlotType("localB", STRING_TYPE); + childAB.inferSlotType("localB", getNativeStringType()); FlowScope childB = localEntry.createChildFlowScope(); - childB.inferSlotType("localB", BOOLEAN_TYPE); + childB.inferSlotType("localB", getNativeBooleanType()); - assertTypeEquals(STRING_TYPE, childAB.getSlot("localB").getType()); - assertTypeEquals(BOOLEAN_TYPE, childB.getSlot("localB").getType()); + assertTypeEquals(getNativeStringType(), childAB.getSlot("localB").getType()); + assertTypeEquals(getNativeBooleanType(), childB.getSlot("localB").getType()); assertNull(childB.getSlot("localA").getType()); FlowScope joined = join(childB, childAB); - assertTypeEquals(createUnionType(STRING_TYPE, BOOLEAN_TYPE), + assertTypeEquals( + createUnionType(getNativeStringType(), getNativeBooleanType()), joined.getSlot("localB").getType()); assertNull(joined.getSlot("localA").getType()); joined = join(childAB, childB); - assertTypeEquals(createUnionType(STRING_TYPE, BOOLEAN_TYPE), + assertTypeEquals( + createUnionType(getNativeStringType(), getNativeBooleanType()), joined.getSlot("localB").getType()); assertNull(joined.getSlot("localA").getType()); @@ -95,47 +97,51 @@ public void testJoin1() { public void testJoin2() { FlowScope childA = localEntry.createChildFlowScope(); - childA.inferSlotType("localA", STRING_TYPE); + childA.inferSlotType("localA", getNativeStringType()); FlowScope childB = localEntry.createChildFlowScope(); - childB.inferSlotType("globalB", BOOLEAN_TYPE); + childB.inferSlotType("globalB", getNativeBooleanType()); - assertTypeEquals(STRING_TYPE, childA.getSlot("localA").getType()); - assertTypeEquals(BOOLEAN_TYPE, childB.getSlot("globalB").getType()); + assertTypeEquals(getNativeStringType(), childA.getSlot("localA").getType()); + assertTypeEquals(getNativeBooleanType(), childB.getSlot("globalB").getType()); assertNull(childB.getSlot("localB").getType()); FlowScope joined = join(childB, childA); - assertTypeEquals(STRING_TYPE, joined.getSlot("localA").getType()); - assertTypeEquals(BOOLEAN_TYPE, joined.getSlot("globalB").getType()); + assertTypeEquals(getNativeStringType(), joined.getSlot("localA").getType()); + assertTypeEquals(getNativeBooleanType(), joined.getSlot("globalB").getType()); joined = join(childA, childB); - assertTypeEquals(STRING_TYPE, joined.getSlot("localA").getType()); - assertTypeEquals(BOOLEAN_TYPE, joined.getSlot("globalB").getType()); + assertTypeEquals(getNativeStringType(), joined.getSlot("localA").getType()); + assertTypeEquals(getNativeBooleanType(), joined.getSlot("globalB").getType()); assertEquals("Join should be symmetric", join(childB, childA), join(childA, childB)); } public void testJoin3() { - localScope.declare("localC", null, STRING_TYPE, null); - localScope.declare("localD", null, STRING_TYPE, null); + localScope.declare("localC", null, getNativeStringType(), null); + localScope.declare("localD", null, getNativeStringType(), null); FlowScope childA = localEntry.createChildFlowScope(); - childA.inferSlotType("localC", NUMBER_TYPE); + childA.inferSlotType("localC", getNativeNumberType()); FlowScope childB = localEntry.createChildFlowScope(); - childA.inferSlotType("localD", BOOLEAN_TYPE); + childA.inferSlotType("localD", getNativeBooleanType()); FlowScope joined = join(childB, childA); - assertTypeEquals(createUnionType(STRING_TYPE, NUMBER_TYPE), + assertTypeEquals( + createUnionType(getNativeStringType(), getNativeNumberType()), joined.getSlot("localC").getType()); - assertTypeEquals(createUnionType(STRING_TYPE, BOOLEAN_TYPE), + assertTypeEquals( + createUnionType(getNativeStringType(), getNativeBooleanType()), joined.getSlot("localD").getType()); joined = join(childA, childB); - assertTypeEquals(createUnionType(STRING_TYPE, NUMBER_TYPE), + assertTypeEquals( + createUnionType(getNativeStringType(), getNativeNumberType()), joined.getSlot("localC").getType()); - assertTypeEquals(createUnionType(STRING_TYPE, BOOLEAN_TYPE), + assertTypeEquals( + createUnionType(getNativeStringType(), getNativeBooleanType()), joined.getSlot("localD").getType()); assertEquals("Join should be symmetric", @@ -151,10 +157,10 @@ public void testLongChain1() { FlowScope chainB = localEntry.createChildFlowScope(); for (int i = 0; i < LONG_CHAIN_LENGTH; i++) { localScope.declare("local" + i, null, null, null); - chainA.inferSlotType("local" + i, - i % 2 == 0 ? NUMBER_TYPE : BOOLEAN_TYPE); - chainB.inferSlotType("local" + i, - i % 3 == 0 ? STRING_TYPE : BOOLEAN_TYPE); + chainA.inferSlotType( + "local" + i, i % 2 == 0 ? getNativeNumberType() : getNativeBooleanType()); + chainB.inferSlotType( + "local" + i, i % 3 == 0 ? getNativeStringType() : getNativeBooleanType()); chainA = chainA.createChildFlowScope(); chainB = chainB.createChildFlowScope(); @@ -172,10 +178,10 @@ public void testLongChain2() { FlowScope chainB = localEntry.createChildFlowScope(); for (int i = 0; i < LONG_CHAIN_LENGTH * 7; i++) { localScope.declare("local" + i, null, null, null); - chainA.inferSlotType("local" + i, - i % 2 == 0 ? NUMBER_TYPE : BOOLEAN_TYPE); - chainB.inferSlotType("local" + i, - i % 3 == 0 ? STRING_TYPE : BOOLEAN_TYPE); + chainA.inferSlotType( + "local" + i, i % 2 == 0 ? getNativeNumberType() : getNativeBooleanType()); + chainB.inferSlotType( + "local" + i, i % 3 == 0 ? getNativeStringType() : getNativeBooleanType()); if (i % 7 == 0) { chainA = chainA.createChildFlowScope(); @@ -197,10 +203,10 @@ public void testLongChain3() { if (i % 7 == 0) { int j = i / 7; localScope.declare("local" + j, null, null, null); - chainA.inferSlotType("local" + j, - j % 2 == 0 ? NUMBER_TYPE : BOOLEAN_TYPE); - chainB.inferSlotType("local" + j, - j % 3 == 0 ? STRING_TYPE : BOOLEAN_TYPE); + chainA.inferSlotType( + "local" + j, j % 2 == 0 ? getNativeNumberType() : getNativeBooleanType()); + chainB.inferSlotType( + "local" + j, j % 3 == 0 ? getNativeStringType() : getNativeBooleanType()); } chainA = chainA.createChildFlowScope(); @@ -215,23 +221,24 @@ private void verifyLongChains(FlowScope chainA, FlowScope chainB) { FlowScope joined = join(chainA, chainB); for (int i = 0; i < LONG_CHAIN_LENGTH; i++) { assertTypeEquals( - i % 2 == 0 ? NUMBER_TYPE : BOOLEAN_TYPE, + i % 2 == 0 ? getNativeNumberType() : getNativeBooleanType(), chainA.getSlot("local" + i).getType()); assertTypeEquals( - i % 3 == 0 ? STRING_TYPE : BOOLEAN_TYPE, + i % 3 == 0 ? getNativeStringType() : getNativeBooleanType(), chainB.getSlot("local" + i).getType()); JSType joinedSlotType = joined.getSlot("local" + i).getType(); if (i % 6 == 0) { - assertTypeEquals(createUnionType(STRING_TYPE, NUMBER_TYPE), joinedSlotType); + assertTypeEquals( + createUnionType(getNativeStringType(), getNativeNumberType()), joinedSlotType); } else if (i % 2 == 0) { - assertTypeEquals(createUnionType(NUMBER_TYPE, BOOLEAN_TYPE), - joinedSlotType); + assertTypeEquals( + createUnionType(getNativeNumberType(), getNativeBooleanType()), joinedSlotType); } else if (i % 3 == 0) { - assertTypeEquals(createUnionType(STRING_TYPE, BOOLEAN_TYPE), - joinedSlotType); + assertTypeEquals( + createUnionType(getNativeStringType(), getNativeBooleanType()), joinedSlotType); } else { - assertTypeEquals(BOOLEAN_TYPE, joinedSlotType); + assertTypeEquals(getNativeBooleanType(), joinedSlotType); } } @@ -242,44 +249,40 @@ private void verifyLongChains(FlowScope chainA, FlowScope chainB) { public void testFindUniqueSlot() { FlowScope childA = localEntry.createChildFlowScope(); - childA.inferSlotType("localB", NUMBER_TYPE); + childA.inferSlotType("localB", getNativeNumberType()); FlowScope childAB = childA.createChildFlowScope(); - childAB.inferSlotType("localB", STRING_TYPE); + childAB.inferSlotType("localB", getNativeStringType()); FlowScope childABC = childAB.createChildFlowScope(); - childABC.inferSlotType("localA", BOOLEAN_TYPE); + childABC.inferSlotType("localA", getNativeBooleanType()); assertNull(childABC.findUniqueRefinedSlot(childABC)); - assertTypeEquals(BOOLEAN_TYPE, - childABC.findUniqueRefinedSlot(childAB).getType()); + assertTypeEquals(getNativeBooleanType(), childABC.findUniqueRefinedSlot(childAB).getType()); assertNull(childABC.findUniqueRefinedSlot(childA)); assertNull(childABC.findUniqueRefinedSlot(localEntry)); - assertTypeEquals(STRING_TYPE, - childAB.findUniqueRefinedSlot(childA).getType()); - assertTypeEquals(STRING_TYPE, - childAB.findUniqueRefinedSlot(localEntry).getType()); + assertTypeEquals(getNativeStringType(), childAB.findUniqueRefinedSlot(childA).getType()); + assertTypeEquals(getNativeStringType(), childAB.findUniqueRefinedSlot(localEntry).getType()); - assertTypeEquals(NUMBER_TYPE, - childA.findUniqueRefinedSlot(localEntry).getType()); + assertTypeEquals(getNativeNumberType(), childA.findUniqueRefinedSlot(localEntry).getType()); } public void testDiffer1() { FlowScope childA = localEntry.createChildFlowScope(); - childA.inferSlotType("localB", NUMBER_TYPE); + childA.inferSlotType("localB", getNativeNumberType()); FlowScope childAB = childA.createChildFlowScope(); - childAB.inferSlotType("localB", STRING_TYPE); + childAB.inferSlotType("localB", getNativeStringType()); FlowScope childABC = childAB.createChildFlowScope(); - childABC.inferSlotType("localA", BOOLEAN_TYPE); + childABC.inferSlotType("localA", getNativeBooleanType()); FlowScope childB = childAB.createChildFlowScope(); - childB.inferSlotType("localB", STRING_TYPE); + childB.inferSlotType("localB", getNativeStringType()); FlowScope childBC = childB.createChildFlowScope(); - childBC.inferSlotType("localA", NO_TYPE); + childBC.inferSlotType("localA", getNativeNoType()); assertScopesSame(childAB, childB); assertScopesDiffer(childABC, childBC); @@ -295,10 +298,10 @@ public void testDiffer1() { public void testDiffer2() { FlowScope childA = localEntry.createChildFlowScope(); - childA.inferSlotType("localA", NUMBER_TYPE); + childA.inferSlotType("localA", getNativeNumberType()); FlowScope childB = localEntry.createChildFlowScope(); - childB.inferSlotType("localA", NO_TYPE); + childB.inferSlotType("localA", getNativeNoType()); assertScopesDiffer(childA, childB); } diff --git a/test/com/google/javascript/jscomp/SemanticReverseAbstractInterpreterTest.java b/test/com/google/javascript/jscomp/SemanticReverseAbstractInterpreterTest.java index e0e1a3eb186..82edb19bab5 100644 --- a/test/com/google/javascript/jscomp/SemanticReverseAbstractInterpreterTest.java +++ b/test/com/google/javascript/jscomp/SemanticReverseAbstractInterpreterTest.java @@ -23,7 +23,6 @@ import com.google.javascript.rhino.Node; import com.google.javascript.rhino.Token; import com.google.javascript.rhino.jstype.JSType; - import java.util.Arrays; import java.util.Collection; @@ -50,18 +49,17 @@ public FlowScope newScope() { */ public void testNameCondition() throws Exception { FlowScope blind = newScope(); - Node condition = createVar(blind, "a", createNullableType(STRING_TYPE)); + Node condition = createVar(blind, "a", createNullableType(getNativeStringType())); // true outcome. FlowScope informedTrue = interpreter. getPreciserScopeKnowingConditionOutcome(condition, blind, true); - assertTypeEquals(STRING_TYPE, getVarType(informedTrue, "a")); + assertTypeEquals(getNativeStringType(), getVarType(informedTrue, "a")); // false outcome. FlowScope informedFalse = interpreter. getPreciserScopeKnowingConditionOutcome(condition, blind, false); - assertTypeEquals(createNullableType(STRING_TYPE), - getVarType(informedFalse, "a")); + assertTypeEquals(createNullableType(getNativeStringType()), getVarType(informedFalse, "a")); } /** @@ -69,20 +67,19 @@ public void testNameCondition() throws Exception { */ public void testNegatedNameCondition() throws Exception { FlowScope blind = newScope(); - Node a = createVar(blind, "a", createNullableType(STRING_TYPE)); + Node a = createVar(blind, "a", createNullableType(getNativeStringType())); Node condition = new Node(Token.NOT); condition.addChildToBack(a); // true outcome. FlowScope informedTrue = interpreter. getPreciserScopeKnowingConditionOutcome(condition, blind, true); - assertTypeEquals(createNullableType(STRING_TYPE), - getVarType(informedTrue, "a")); + assertTypeEquals(createNullableType(getNativeStringType()), getVarType(informedTrue, "a")); // false outcome. FlowScope informedFalse = interpreter. getPreciserScopeKnowingConditionOutcome(condition, blind, false); - assertTypeEquals(STRING_TYPE, getVarType(informedFalse, "a")); + assertTypeEquals(getNativeStringType(), getVarType(informedFalse, "a")); } /** @@ -91,16 +88,15 @@ public void testNegatedNameCondition() throws Exception { @SuppressWarnings("unchecked") public void testAssignCondition1() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.ASSIGN, - createVar(blind, "a", createNullableType(OBJECT_TYPE)), - createVar(blind, "b", createNullableType(OBJECT_TYPE)), + createVar(blind, "a", createNullableType(getNativeObjectType())), + createVar(blind, "b", createNullableType(getNativeObjectType())), ImmutableSet.of( - new TypedName("a", OBJECT_TYPE), - new TypedName("b", OBJECT_TYPE)), + new TypedName("a", getNativeObjectType()), new TypedName("b", getNativeObjectType())), ImmutableSet.of( - new TypedName("a", NULL_TYPE), - new TypedName("b", NULL_TYPE))); + new TypedName("a", getNativeNullType()), new TypedName("b", getNativeNullType()))); } /** @@ -109,13 +105,14 @@ public void testAssignCondition1() throws Exception { @SuppressWarnings("unchecked") public void testSheqCondition1() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHEQ, - createVar(blind, "a", createUnionType(STRING_TYPE, NUMBER_TYPE)), + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeNumberType())), createNumber(56), - ImmutableSet.of(new TypedName("a", NUMBER_TYPE)), - ImmutableSet.of(new TypedName("a", - createUnionType(STRING_TYPE, NUMBER_TYPE)))); + ImmutableSet.of(new TypedName("a", getNativeNumberType())), + ImmutableSet.of( + new TypedName("a", createUnionType(getNativeStringType(), getNativeNumberType())))); } /** @@ -124,13 +121,14 @@ public void testSheqCondition1() throws Exception { @SuppressWarnings("unchecked") public void testSheqCondition2() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHEQ, createNumber(56), - createVar(blind, "a", createUnionType(STRING_TYPE, NUMBER_TYPE)), - ImmutableSet.of(new TypedName("a", NUMBER_TYPE)), - ImmutableSet.of(new TypedName("a", - createUnionType(STRING_TYPE, NUMBER_TYPE)))); + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeNumberType())), + ImmutableSet.of(new TypedName("a", getNativeNumberType())), + ImmutableSet.of( + new TypedName("a", createUnionType(getNativeStringType(), getNativeNumberType())))); } /** @@ -139,59 +137,59 @@ public void testSheqCondition2() throws Exception { @SuppressWarnings("unchecked") public void testSheqCondition3() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHEQ, - createVar(blind, "b", createUnionType(STRING_TYPE, BOOLEAN_TYPE)), - createVar(blind, "a", createUnionType(STRING_TYPE, NUMBER_TYPE)), - ImmutableSet.of(new TypedName("a", STRING_TYPE), - new TypedName("b", STRING_TYPE)), - ImmutableSet.of(new TypedName("a", - createUnionType(STRING_TYPE, NUMBER_TYPE)), - new TypedName("b", - createUnionType(STRING_TYPE, BOOLEAN_TYPE)))); + createVar(blind, "b", createUnionType(getNativeStringType(), getNativeBooleanType())), + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeNumberType())), + ImmutableSet.of( + new TypedName("a", getNativeStringType()), new TypedName("b", getNativeStringType())), + ImmutableSet.of( + new TypedName("a", createUnionType(getNativeStringType(), getNativeNumberType())), + new TypedName("b", createUnionType(getNativeStringType(), getNativeBooleanType())))); } @SuppressWarnings("unchecked") public void testSheqCondition4() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHEQ, - createVar(blind, "a", createUnionType(STRING_TYPE, VOID_TYPE)), - createVar(blind, "b", createUnionType(VOID_TYPE)), - ImmutableSet.of(new TypedName("a", VOID_TYPE), - new TypedName("b", VOID_TYPE)), - ImmutableSet.of(new TypedName("a", STRING_TYPE), - new TypedName("b", VOID_TYPE))); + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeVoidType())), + createVar(blind, "b", createUnionType(getNativeVoidType())), + ImmutableSet.of( + new TypedName("a", getNativeVoidType()), new TypedName("b", getNativeVoidType())), + ImmutableSet.of( + new TypedName("a", getNativeStringType()), new TypedName("b", getNativeVoidType()))); } @SuppressWarnings("unchecked") public void testSheqCondition5() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHEQ, - createVar(blind, "a", createUnionType(NULL_TYPE, VOID_TYPE)), - createVar(blind, "b", createUnionType(VOID_TYPE)), - ImmutableSet.of(new TypedName("a", VOID_TYPE), - new TypedName("b", VOID_TYPE)), - ImmutableSet.of(new TypedName("a", NULL_TYPE), - new TypedName("b", VOID_TYPE))); + createVar(blind, "a", createUnionType(getNativeNullType(), getNativeVoidType())), + createVar(blind, "b", createUnionType(getNativeVoidType())), + ImmutableSet.of( + new TypedName("a", getNativeVoidType()), new TypedName("b", getNativeVoidType())), + ImmutableSet.of( + new TypedName("a", getNativeNullType()), new TypedName("b", getNativeVoidType()))); } @SuppressWarnings("unchecked") public void testSheqCondition6() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHEQ, - createVar(blind, "a", createUnionType(STRING_TYPE, VOID_TYPE)), - createVar(blind, "b", createUnionType(NUMBER_TYPE, VOID_TYPE)), + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeVoidType())), + createVar(blind, "b", createUnionType(getNativeNumberType(), getNativeVoidType())), ImmutableSet.of( - new TypedName("a", VOID_TYPE), - new TypedName("b", VOID_TYPE)), + new TypedName("a", getNativeVoidType()), new TypedName("b", getNativeVoidType())), ImmutableSet.of( - new TypedName("a", - createUnionType(STRING_TYPE, VOID_TYPE)), - new TypedName("b", - createUnionType(NUMBER_TYPE, VOID_TYPE)))); + new TypedName("a", createUnionType(getNativeStringType(), getNativeVoidType())), + new TypedName("b", createUnionType(getNativeNumberType(), getNativeVoidType())))); } /** @@ -200,13 +198,14 @@ public void testSheqCondition6() throws Exception { @SuppressWarnings("unchecked") public void testShneCondition1() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHNE, - createVar(blind, "a", createUnionType(STRING_TYPE, NUMBER_TYPE)), + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeNumberType())), createNumber(56), - ImmutableSet.of(new TypedName("a", - createUnionType(STRING_TYPE, NUMBER_TYPE))), - ImmutableSet.of(new TypedName("a", NUMBER_TYPE))); + ImmutableSet.of( + new TypedName("a", createUnionType(getNativeStringType(), getNativeNumberType()))), + ImmutableSet.of(new TypedName("a", getNativeNumberType()))); } /** @@ -215,13 +214,14 @@ public void testShneCondition1() throws Exception { @SuppressWarnings("unchecked") public void testShneCondition2() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHNE, createNumber(56), - createVar(blind, "a", createUnionType(STRING_TYPE, NUMBER_TYPE)), - ImmutableSet.of(new TypedName("a", - createUnionType(STRING_TYPE, NUMBER_TYPE))), - ImmutableSet.of(new TypedName("a", NUMBER_TYPE))); + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeNumberType())), + ImmutableSet.of( + new TypedName("a", createUnionType(getNativeStringType(), getNativeNumberType()))), + ImmutableSet.of(new TypedName("a", getNativeNumberType()))); } /** @@ -230,59 +230,59 @@ public void testShneCondition2() throws Exception { @SuppressWarnings("unchecked") public void testShneCondition3() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHNE, - createVar(blind, "b", createUnionType(STRING_TYPE, BOOLEAN_TYPE)), - createVar(blind, "a", createUnionType(STRING_TYPE, NUMBER_TYPE)), - ImmutableSet.of(new TypedName("a", - createUnionType(STRING_TYPE, NUMBER_TYPE)), - new TypedName("b", - createUnionType(STRING_TYPE, BOOLEAN_TYPE))), - ImmutableSet.of(new TypedName("a", STRING_TYPE), - new TypedName("b", STRING_TYPE))); + createVar(blind, "b", createUnionType(getNativeStringType(), getNativeBooleanType())), + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeNumberType())), + ImmutableSet.of( + new TypedName("a", createUnionType(getNativeStringType(), getNativeNumberType())), + new TypedName("b", createUnionType(getNativeStringType(), getNativeBooleanType()))), + ImmutableSet.of( + new TypedName("a", getNativeStringType()), new TypedName("b", getNativeStringType()))); } @SuppressWarnings("unchecked") public void testShneCondition4() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHNE, - createVar(blind, "a", createUnionType(STRING_TYPE, VOID_TYPE)), - createVar(blind, "b", createUnionType(VOID_TYPE)), - ImmutableSet.of(new TypedName("a", STRING_TYPE), - new TypedName("b", VOID_TYPE)), - ImmutableSet.of(new TypedName("a", VOID_TYPE), - new TypedName("b", VOID_TYPE))); + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeVoidType())), + createVar(blind, "b", createUnionType(getNativeVoidType())), + ImmutableSet.of( + new TypedName("a", getNativeStringType()), new TypedName("b", getNativeVoidType())), + ImmutableSet.of( + new TypedName("a", getNativeVoidType()), new TypedName("b", getNativeVoidType()))); } @SuppressWarnings("unchecked") public void testShneCondition5() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHNE, - createVar(blind, "a", createUnionType(NULL_TYPE, VOID_TYPE)), - createVar(blind, "b", createUnionType(NULL_TYPE)), - ImmutableSet.of(new TypedName("a", VOID_TYPE), - new TypedName("b", NULL_TYPE)), - ImmutableSet.of(new TypedName("a", NULL_TYPE), - new TypedName("b", NULL_TYPE))); + createVar(blind, "a", createUnionType(getNativeNullType(), getNativeVoidType())), + createVar(blind, "b", createUnionType(getNativeNullType())), + ImmutableSet.of( + new TypedName("a", getNativeVoidType()), new TypedName("b", getNativeNullType())), + ImmutableSet.of( + new TypedName("a", getNativeNullType()), new TypedName("b", getNativeNullType()))); } @SuppressWarnings("unchecked") public void testShneCondition6() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.SHNE, - createVar(blind, "a", createUnionType(STRING_TYPE, VOID_TYPE)), - createVar(blind, "b", createUnionType(NUMBER_TYPE, VOID_TYPE)), + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeVoidType())), + createVar(blind, "b", createUnionType(getNativeNumberType(), getNativeVoidType())), ImmutableSet.of( - new TypedName("a", - createUnionType(STRING_TYPE, VOID_TYPE)), - new TypedName("b", - createUnionType(NUMBER_TYPE, VOID_TYPE))), + new TypedName("a", createUnionType(getNativeStringType(), getNativeVoidType())), + new TypedName("b", createUnionType(getNativeNumberType(), getNativeVoidType()))), ImmutableSet.of( - new TypedName("a", VOID_TYPE), - new TypedName("b", VOID_TYPE))); + new TypedName("a", getNativeVoidType()), new TypedName("b", getNativeVoidType()))); } /** @@ -291,12 +291,13 @@ public void testShneCondition6() throws Exception { @SuppressWarnings("unchecked") public void testEqCondition1() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.EQ, - createVar(blind, "a", createUnionType(BOOLEAN_TYPE, VOID_TYPE)), + createVar(blind, "a", createUnionType(getNativeBooleanType(), getNativeVoidType())), createNull(), - ImmutableSet.of(new TypedName("a", VOID_TYPE)), - ImmutableSet.of(new TypedName("a", BOOLEAN_TYPE))); + ImmutableSet.of(new TypedName("a", getNativeVoidType())), + ImmutableSet.of(new TypedName("a", getNativeBooleanType()))); } /** @@ -305,12 +306,13 @@ public void testEqCondition1() throws Exception { @SuppressWarnings("unchecked") public void testEqCondition2() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.NE, createNull(), - createVar(blind, "a", createUnionType(BOOLEAN_TYPE, VOID_TYPE)), - ImmutableSet.of(new TypedName("a", BOOLEAN_TYPE)), - ImmutableSet.of(new TypedName("a", VOID_TYPE))); + createVar(blind, "a", createUnionType(getNativeBooleanType(), getNativeVoidType())), + ImmutableSet.of(new TypedName("a", getNativeBooleanType())), + ImmutableSet.of(new TypedName("a", getNativeVoidType()))); } /** @@ -321,16 +323,16 @@ public void testEqCondition3() throws Exception { FlowScope blind = newScope(); // (number,undefined,null) JSType nullableOptionalNumber = - createUnionType(NULL_TYPE, VOID_TYPE, NUMBER_TYPE); + createUnionType(getNativeNullType(), getNativeVoidType(), getNativeNumberType()); // (null,undefined) - JSType nullUndefined = - createUnionType(VOID_TYPE, NULL_TYPE); - testBinop(blind, + JSType nullUndefined = createUnionType(getNativeVoidType(), getNativeNullType()); + testBinop( + blind, Token.EQ, createVar(blind, "a", nullableOptionalNumber), createNull(), ImmutableSet.of(new TypedName("a", nullUndefined)), - ImmutableSet.of(new TypedName("a", NUMBER_TYPE))); + ImmutableSet.of(new TypedName("a", getNativeNumberType()))); } /** @@ -339,16 +341,15 @@ public void testEqCondition3() throws Exception { @SuppressWarnings("unchecked") public void testEqCondition4() throws Exception { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.EQ, - createVar(blind, "a", VOID_TYPE), - createVar(blind, "b", VOID_TYPE), + createVar(blind, "a", getNativeVoidType()), + createVar(blind, "b", getNativeVoidType()), ImmutableSet.of( - new TypedName("a", VOID_TYPE), - new TypedName("b", VOID_TYPE)), + new TypedName("a", getNativeVoidType()), new TypedName("b", getNativeVoidType())), ImmutableSet.of( - new TypedName("a", NO_TYPE), - new TypedName("b", NO_TYPE))); + new TypedName("a", getNativeNoType()), new TypedName("b", getNativeNoType()))); } /** @@ -359,14 +360,14 @@ public void testEqCondition4() throws Exception { public void testInequalitiesCondition1() { for (Token op : Arrays.asList(Token.LT, Token.GT, Token.LE, Token.GE)) { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, op, - createVar(blind, "a", createUnionType(STRING_TYPE, VOID_TYPE)), + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeVoidType())), createNumber(8), + ImmutableSet.of(new TypedName("a", getNativeStringType())), ImmutableSet.of( - new TypedName("a", STRING_TYPE)), - ImmutableSet.of(new TypedName("a", - createUnionType(STRING_TYPE, VOID_TYPE)))); + new TypedName("a", createUnionType(getNativeStringType(), getNativeVoidType())))); } } @@ -378,22 +379,23 @@ public void testInequalitiesCondition1() { public void testInequalitiesCondition2() { for (Token op : Arrays.asList(Token.LT, Token.GT, Token.LE, Token.GE)) { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, op, - createVar(blind, "a", - createUnionType(STRING_TYPE, NUMBER_TYPE, VOID_TYPE)), - createVar(blind, "b", - createUnionType(NUMBER_TYPE, NULL_TYPE)), + createVar( + blind, + "a", + createUnionType(getNativeStringType(), getNativeNumberType(), getNativeVoidType())), + createVar(blind, "b", createUnionType(getNativeNumberType(), getNativeNullType())), ImmutableSet.of( - new TypedName("a", - createUnionType(STRING_TYPE, NUMBER_TYPE)), - new TypedName("b", - createUnionType(NUMBER_TYPE, NULL_TYPE))), + new TypedName("a", createUnionType(getNativeStringType(), getNativeNumberType())), + new TypedName("b", createUnionType(getNativeNumberType(), getNativeNullType()))), ImmutableSet.of( - new TypedName("a", - createUnionType(STRING_TYPE, NUMBER_TYPE, VOID_TYPE)), - new TypedName("b", - createUnionType(NUMBER_TYPE, NULL_TYPE)))); + new TypedName( + "a", + createUnionType( + getNativeStringType(), getNativeNumberType(), getNativeVoidType())), + new TypedName("b", createUnionType(getNativeNumberType(), getNativeNullType())))); } } @@ -405,144 +407,145 @@ public void testInequalitiesCondition2() { public void testInequalitiesCondition3() { for (Token op : Arrays.asList(Token.LT, Token.GT, Token.LE, Token.GE)) { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, op, createUntypedNumber(8), - createVar(blind, "a", createUnionType(STRING_TYPE, VOID_TYPE)), + createVar(blind, "a", createUnionType(getNativeStringType(), getNativeVoidType())), + ImmutableSet.of(new TypedName("a", getNativeStringType())), ImmutableSet.of( - new TypedName("a", STRING_TYPE)), - ImmutableSet.of(new TypedName("a", - createUnionType(STRING_TYPE, VOID_TYPE)))); + new TypedName("a", createUnionType(getNativeStringType(), getNativeVoidType())))); } } @SuppressWarnings("unchecked") public void testAnd() { FlowScope blind = newScope(); - testBinop(blind, - Token.AND, - createVar(blind, "b", createUnionType(STRING_TYPE, NULL_TYPE)), - createVar(blind, "a", createUnionType(NUMBER_TYPE, VOID_TYPE)), - ImmutableSet.of(new TypedName("a", NUMBER_TYPE), - new TypedName("b", STRING_TYPE)), - ImmutableSet.of(new TypedName("a", - createUnionType(NUMBER_TYPE, VOID_TYPE)), - new TypedName("b", - createUnionType(STRING_TYPE, NULL_TYPE)))); + testBinop( + blind, + Token.AND, + createVar(blind, "b", createUnionType(getNativeStringType(), getNativeNullType())), + createVar(blind, "a", createUnionType(getNativeNumberType(), getNativeVoidType())), + ImmutableSet.of( + new TypedName("a", getNativeNumberType()), new TypedName("b", getNativeStringType())), + ImmutableSet.of( + new TypedName("a", createUnionType(getNativeNumberType(), getNativeVoidType())), + new TypedName("b", createUnionType(getNativeStringType(), getNativeNullType())))); } @SuppressWarnings("unchecked") public void testTypeof1() { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.EQ, - new Node(Token.TYPEOF, createVar(blind, "a", OBJECT_TYPE)), + new Node(Token.TYPEOF, createVar(blind, "a", getNativeObjectType())), Node.newString("function"), - ImmutableSet.of( - new TypedName("a", U2U_CONSTRUCTOR_TYPE)), - ImmutableSet.of( - new TypedName("a", OBJECT_TYPE))); + ImmutableSet.of(new TypedName("a", getNativeU2UConstructorType())), + ImmutableSet.of(new TypedName("a", getNativeObjectType()))); } @SuppressWarnings("unchecked") public void testTypeof2() { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.EQ, - new Node(Token.TYPEOF, createVar(blind, "a", ALL_TYPE)), + new Node(Token.TYPEOF, createVar(blind, "a", getNativeAllType())), Node.newString("function"), - ImmutableSet.of( - new TypedName("a", U2U_CONSTRUCTOR_TYPE)), - ImmutableSet.of( - new TypedName("a", ALL_TYPE))); + ImmutableSet.of(new TypedName("a", getNativeU2UConstructorType())), + ImmutableSet.of(new TypedName("a", getNativeAllType()))); } @SuppressWarnings("unchecked") public void testTypeof3() { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.EQ, - new Node(Token.TYPEOF, createVar( - blind, "a", OBJECT_NUMBER_STRING_BOOLEAN)), + new Node(Token.TYPEOF, createVar(blind, "a", getNativeObjectNumberStringBooleanType())), Node.newString("function"), - ImmutableSet.of( - new TypedName("a", U2U_CONSTRUCTOR_TYPE)), - ImmutableSet.of( - new TypedName("a", OBJECT_NUMBER_STRING_BOOLEAN))); + ImmutableSet.of(new TypedName("a", getNativeU2UConstructorType())), + ImmutableSet.of(new TypedName("a", getNativeObjectNumberStringBooleanType()))); } @SuppressWarnings("unchecked") public void testTypeof4() { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.EQ, - new Node(Token.TYPEOF, createVar( - blind, "a", createUnionType( - U2U_CONSTRUCTOR_TYPE, NUMBER_STRING_BOOLEAN))), + new Node( + Token.TYPEOF, + createVar( + blind, + "a", + createUnionType( + getNativeU2UConstructorType(), getNativeNumberStringBooleanType()))), Node.newString("function"), - ImmutableSet.of( - new TypedName("a", U2U_CONSTRUCTOR_TYPE)), - ImmutableSet.of( - new TypedName("a", NUMBER_STRING_BOOLEAN))); + ImmutableSet.of(new TypedName("a", getNativeU2UConstructorType())), + ImmutableSet.of(new TypedName("a", getNativeNumberStringBooleanType()))); } @SuppressWarnings("unchecked") public void testInstanceOf() { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.INSTANCEOF, - createVar(blind, "x", UNKNOWN_TYPE), - createVar(blind, "s", STRING_OBJECT_FUNCTION_TYPE), - ImmutableSet.of( - new TypedName("x", STRING_OBJECT_TYPE), - new TypedName("s", STRING_OBJECT_FUNCTION_TYPE)), + createVar(blind, "x", getNativeUnknownType()), + createVar(blind, "s", getNativeStringObjectConstructorType()), ImmutableSet.of( - new TypedName("s", STRING_OBJECT_FUNCTION_TYPE))); + new TypedName("x", getNativeStringObjectType()), + new TypedName("s", getNativeStringObjectConstructorType())), + ImmutableSet.of(new TypedName("s", getNativeStringObjectConstructorType()))); } @SuppressWarnings("unchecked") public void testInstanceOf2() { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.INSTANCEOF, - createVar(blind, "x", - createUnionType(STRING_OBJECT_TYPE, NUMBER_OBJECT_TYPE)), - createVar(blind, "s", STRING_OBJECT_FUNCTION_TYPE), + createVar( + blind, "x", createUnionType(getNativeStringObjectType(), getNativeNumberObjectType())), + createVar(blind, "s", getNativeStringObjectConstructorType()), ImmutableSet.of( - new TypedName("x", STRING_OBJECT_TYPE), - new TypedName("s", STRING_OBJECT_FUNCTION_TYPE)), + new TypedName("x", getNativeStringObjectType()), + new TypedName("s", getNativeStringObjectConstructorType())), ImmutableSet.of( - new TypedName("x", NUMBER_OBJECT_TYPE), - new TypedName("s", STRING_OBJECT_FUNCTION_TYPE))); + new TypedName("x", getNativeNumberObjectType()), + new TypedName("s", getNativeStringObjectConstructorType()))); } @SuppressWarnings("unchecked") public void testInstanceOf3() { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.INSTANCEOF, - createVar(blind, "x", OBJECT_TYPE), - createVar(blind, "s", STRING_OBJECT_FUNCTION_TYPE), + createVar(blind, "x", getNativeObjectType()), + createVar(blind, "s", getNativeStringObjectConstructorType()), ImmutableSet.of( - new TypedName("x", STRING_OBJECT_TYPE), - new TypedName("s", STRING_OBJECT_FUNCTION_TYPE)), + new TypedName("x", getNativeStringObjectType()), + new TypedName("s", getNativeStringObjectConstructorType())), ImmutableSet.of( - new TypedName("x", OBJECT_TYPE), - new TypedName("s", STRING_OBJECT_FUNCTION_TYPE))); + new TypedName("x", getNativeObjectType()), + new TypedName("s", getNativeStringObjectConstructorType()))); } @SuppressWarnings("unchecked") public void testInstanceOf4() { FlowScope blind = newScope(); - testBinop(blind, + testBinop( + blind, Token.INSTANCEOF, - createVar(blind, "x", ALL_TYPE), - createVar(blind, "s", STRING_OBJECT_FUNCTION_TYPE), - ImmutableSet.of( - new TypedName("x", STRING_OBJECT_TYPE), - new TypedName("s", STRING_OBJECT_FUNCTION_TYPE)), + createVar(blind, "x", getNativeAllType()), + createVar(blind, "s", getNativeStringObjectConstructorType()), ImmutableSet.of( - new TypedName("s", STRING_OBJECT_FUNCTION_TYPE))); + new TypedName("x", getNativeStringObjectType()), + new TypedName("s", getNativeStringObjectConstructorType())), + ImmutableSet.of(new TypedName("s", getNativeStringObjectConstructorType()))); } private void testBinop(FlowScope blind, Token binop, Node left, Node right, @@ -569,13 +572,13 @@ private void testBinop(FlowScope blind, Token binop, Node left, Node right, private Node createNull() { Node n = new Node(Token.NULL); - n.setJSType(NULL_TYPE); + n.setJSType(getNativeNullType()); return n; } private Node createNumber(int n) { Node number = createUntypedNumber(n); - number.setJSType(NUMBER_TYPE); + number.setJSType(getNativeNumberType()); return number; } diff --git a/test/com/google/javascript/jscomp/TestExternsBuilder.java b/test/com/google/javascript/jscomp/TestExternsBuilder.java new file mode 100644 index 00000000000..c81cd1feccc --- /dev/null +++ b/test/com/google/javascript/jscomp/TestExternsBuilder.java @@ -0,0 +1,318 @@ +/* + * Copyright 2018 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.common.base.Joiner; +import java.util.ArrayList; +import java.util.List; + +/** + * Builds a string containing standard externs definitions for use in testing. + * + *

The externs in this file are intentionally far from complete. Please use the actual externs + * definitions (es3.js, etc.) as a model when you need to add something for a test case. + */ +public class TestExternsBuilder { + private static final Joiner LINE_JOINER = Joiner.on('\n'); + + private static final String ITERABLE_EXTERNS = + lines( + // Symbol is needed for Symbol.iterator + "/** ", + " * @constructor", + " * @param {*=} opt_description", + " * @return {symbol}", + " */", + "function Symbol(opt_description) {}", + "", + "/** @const {!symbol} */ Symbol.iterator;", + "", + "/**", + " * @record", + " * @template VALUE", + " */", + "function IIterableResult() {};", + "/** @type {boolean} */", + "IIterableResult.prototype.done;", + "/** @type {VALUE} */", + "IIterableResult.prototype.value;", + "", + "/**", + " * @interface", + " * @template VALUE", + " */", + "function Iterator() {}", + "/**", + " * @param {VALUE=} value", + " * @return {!IIterableResult}", + " */", + "Iterator.prototype.next;", + "", + "/**", + " * @interface", + " * @template VALUE", + " */", + "function Iterable() {}", + "", + "/**", + " * @return {!Iterator}", + " * @suppress {externsValidation}", + " */", + "Iterable.prototype[Symbol.iterator] = function() {};", + "", + "/**", + " * @interface", + " * @extends {Iterator}", + " * @extends {Iterable}", + " * @template VALUE", + " */", + "function IteratorIterable() {}", + ""); + private static final String STRING_EXTERNS = + lines( + "/**", + " * @constructor", + " * @implements {Iterable}", + " * @param {*=} arg", + " * @return {string}", + " */", + "function String(arg) {}", + "/** @type {number} */", + "String.prototype.length;", + "/** @param {number} sliceArg */", + "String.prototype.slice = function(sliceArg) {};", + "/**", + " * @this {?String|string}", + " * @param {?} regex", + " * @param {?} str", + " * @param {string=} opt_flags", + " * @return {string}", + " */", + "String.prototype.replace = function(regex, str, opt_flags) {};", + "/**", + " * @this {String|string}", + " * @param {number} index", + " * @return {string}", + " */", + "String.prototype.charAt = function(index) {};", + "/**", + " * @this {String|string}", + " * @param {*} regexp", + " * @return {Array}", + " */", + "String.prototype.match = function(regexp) {};", + "/**", + " * @this {String|string}", + " * @return {string}", + " */", + "String.prototype.toLowerCase = function() {};", + ""); + private static final String FUNCTION_EXTERNS = + lines( + "/**", + " * @constructor", + " * @param {...*} var_args", + " */", + "function Function(var_args) {}", + "/** @type {!Function} */ Function.prototype.apply;", + "/** @type {!Function} */ Function.prototype.bind;", + "/** @type {!Function} */ Function.prototype.call;", + "/** @type {number} */", + "Function.prototype.length;", + "/** @type {string} */", + "Function.prototype.name;", + ""); + private static final String OBJECT_EXTERNS = + lines( + "/**", + " * @constructor", + " */", + "function ObjectPropertyDescriptor() {}", + "/** @type {*} */", + "ObjectPropertyDescriptor.prototype.value;", + "", + "/**", + " * @constructor", + " * @param {*=} opt_value", + " * @return {!Object}", + " */", + "function Object(opt_value) {}", + "", + "/** @type {?Object} */ Object.prototype.__proto__;", + "/** @return {string} */", + "Object.prototype.toString = function() {};", + "/**", + " * @param {*} propertyName", + " * @return {boolean}", + " */", + "Object.prototype.hasOwnProperty = function(propertyName) {};", + "/** @type {?Function} */ Object.prototype.constructor;", + "/** @return {*} */", + "Object.prototype.valueOf = function() {};", + "/**", + " * @param {!Object} obj", + " * @param {string} prop", + " * @return {!ObjectPropertyDescriptor|undefined}", + " * @nosideeffects", + " */", + "Object.getOwnPropertyDescriptor = function(obj, prop) {};", + "/**", + " * @param {!Object} obj", + " * @param {string} prop", + " * @param {!Object} descriptor", + " * @return {!Object}", + " */", + "Object.defineProperty = function(obj, prop, descriptor) {};", + "/**", + " * @param {?Object} proto", + " * @param {?Object=} opt_properties", + " * @return {!Object}", + " */", + "Object.create = function(proto, opt_properties) {};", + "/**", + " * @param {!Object} obj", + " * @param {?} proto", + " * @return {!Object}", + " */", + "Object.setPrototypeOf = function(obj, proto) {};", + ""); + private static final String ARRAY_EXTERNS = + lines( + "/**", + " * @interface", + " * @template KEY1, VALUE1", + " */", + "function IObject() {};", + "", + "/**", + " * @record", + " * @extends IObject", + " * @template VALUE2", + " */", + "function IArrayLike() {};", + "", + "/**", + " * @template T", + " * @constructor", + " * @implements {IArrayLike} ", + " * @implements {Iterable}", + " * @param {...*} var_args", + " * @return {!Array}", + " */", + "function Array(var_args) {}", + "/** @type {number} */ Array.prototype.length;", + "/**", + " * @param {*} arr", + " * @return {boolean}", + " */", + "Array.isArray = function(arr) {};", + "/**", + " * @param {...T} var_args", + " * @return {number} The new length of the array.", + " * @this {IArrayLike}", + " * @template T", + " * @modifies {this}", + " */", + "Array.prototype.push = function(var_args) {};", + "/**", + " * @this {IArrayLike}", + " * @return {T}", + " * @template T", + " */", + "Array.prototype.shift = function() {};", + "/**", + " * @param {?function(this:S, T, number, !Array): ?} callback", + " * @param {S=} opt_thisobj", + " * @this {?IArrayLike|string}", + " * @template T,S", + " * @return {undefined}", + " */", + "Array.prototype.forEach = function(callback, opt_thisobj) {};", + "/**", + " * @param {?function(this:S, T, number, !Array): ?} callback", + " * @param {S=} opt_thisobj", + " * @return {!Array}", + " * @this {?IArrayLike|string}", + " * @template T,S", + " */", + "Array.prototype.filter = function(callback, opt_thisobj) {};", + "/**", + " * @param {...*} var_args", + " * @return {!Array}", + " * @this {*}", + " */", + "Array.prototype.concat = function(var_args) {};", + ""); + + private boolean includeIterableExterns = false; + private boolean includeStringExterns = false; + private boolean includeFunctionExterns = false; + private boolean includeObjectExterns = false; + private boolean includeArrayExterns = false; + + public TestExternsBuilder addIterable() { + includeIterableExterns = true; + return this; + } + + public TestExternsBuilder addString() { + includeStringExterns = true; + addIterable(); // String implements Iterable + return this; + } + + public TestExternsBuilder addFunction() { + includeFunctionExterns = true; + return this; + } + + public TestExternsBuilder addObject() { + includeObjectExterns = true; + addFunction(); // Object.prototype.constructor has type {?Function} + return this; + } + + public TestExternsBuilder addArray() { + includeArrayExterns = true; + addIterable(); // Array implements Iterable + return this; + } + + public String build() { + List externSections = new ArrayList<>(); + if (includeIterableExterns) { + externSections.add(ITERABLE_EXTERNS); + } + if (includeStringExterns) { + externSections.add(STRING_EXTERNS); + } + if (includeFunctionExterns) { + externSections.add(FUNCTION_EXTERNS); + } + if (includeObjectExterns) { + externSections.add(OBJECT_EXTERNS); + } + if (includeArrayExterns) { + externSections.add(ARRAY_EXTERNS); + } + return LINE_JOINER.join(externSections); + } + + private static String lines(String... lines) { + return LINE_JOINER.join(lines); + } +} diff --git a/test/com/google/javascript/jscomp/TypeCheckTest.java b/test/com/google/javascript/jscomp/TypeCheckTest.java index 0b0789caf02..8acb2628b42 100644 --- a/test/com/google/javascript/jscomp/TypeCheckTest.java +++ b/test/com/google/javascript/jscomp/TypeCheckTest.java @@ -86,29 +86,21 @@ public void testInitialTypingScope() { CodingConventions.getDefault()).createInitialScope( new Node(Token.ROOT)); - assertTypeEquals(ARRAY_FUNCTION_TYPE, s.getVar("Array").getType()); - assertTypeEquals(BOOLEAN_OBJECT_FUNCTION_TYPE, - s.getVar("Boolean").getType()); - assertTypeEquals(DATE_FUNCTION_TYPE, s.getVar("Date").getType()); - assertTypeEquals(ERROR_FUNCTION_TYPE, s.getVar("Error").getType()); - assertTypeEquals(EVAL_ERROR_FUNCTION_TYPE, - s.getVar("EvalError").getType()); - assertTypeEquals(NUMBER_OBJECT_FUNCTION_TYPE, - s.getVar("Number").getType()); - assertTypeEquals(OBJECT_FUNCTION_TYPE, s.getVar("Object").getType()); - assertTypeEquals(RANGE_ERROR_FUNCTION_TYPE, - s.getVar("RangeError").getType()); - assertTypeEquals(REFERENCE_ERROR_FUNCTION_TYPE, - s.getVar("ReferenceError").getType()); - assertTypeEquals(REGEXP_FUNCTION_TYPE, s.getVar("RegExp").getType()); - assertTypeEquals(STRING_OBJECT_FUNCTION_TYPE, - s.getVar("String").getType()); - assertTypeEquals(SYNTAX_ERROR_FUNCTION_TYPE, - s.getVar("SyntaxError").getType()); - assertTypeEquals(TYPE_ERROR_FUNCTION_TYPE, - s.getVar("TypeError").getType()); - assertTypeEquals(URI_ERROR_FUNCTION_TYPE, - s.getVar("URIError").getType()); + assertTypeEquals(getNativeArrayConstructorType(), s.getVar("Array").getType()); + assertTypeEquals(getNativeBooleanObjectConstructorType(), s.getVar("Boolean").getType()); + assertTypeEquals(getNativeDateConstructorType(), s.getVar("Date").getType()); + assertTypeEquals(getNativeErrorConstructorType(), s.getVar("Error").getType()); + assertTypeEquals(getNativeEvalErrorConstructorType(), s.getVar("EvalError").getType()); + assertTypeEquals(getNativeNumberObjectConstructorType(), s.getVar("Number").getType()); + assertTypeEquals(getNativeObjectConstructorType(), s.getVar("Object").getType()); + assertTypeEquals(getNativeRangeErrorConstructorType(), s.getVar("RangeError").getType()); + assertTypeEquals( + getNativeReferenceErrorConstructorType(), s.getVar("ReferenceError").getType()); + assertTypeEquals(getNativeRegexpConstructorType(), s.getVar("RegExp").getType()); + assertTypeEquals(getNativeStringObjectConstructorType(), s.getVar("String").getType()); + assertTypeEquals(getNativeSyntaxErrorConstructorType(), s.getVar("SyntaxError").getType()); + assertTypeEquals(getNativeTypeErrorConstructorType(), s.getVar("TypeError").getType()); + assertTypeEquals(getNativeUriErrorConstructorType(), s.getVar("URIError").getType()); } private void disableStrictMissingPropertyChecks() { @@ -304,11 +296,16 @@ public void testTypeCheckInlineReturns() { } public void testTypeCheckDefaultExterns() { - testTypes("/** @param {string} x */ function f(x) {}" + - "f([].length);" , - "actual parameter 1 of f does not match formal parameter\n" + - "found : number\n" + - "required: string"); + testTypesWithExterns( + new TestExternsBuilder().addArray().build(), + lines( + "/** @param {string} x */", // preserve newlines + "function f(x) {}", + "f([].length);"), + lines( + "actual parameter 1 of f does not match formal parameter", + "found : number", + "required: string")); } public void testTypeCheckCustomExterns() { @@ -854,10 +851,16 @@ public void testTypeOfReduction5() { } public void testTypeOfReduction6() { - testTypes("/** @param {number|string} x\n@return {string} */\n" + - "function f(x) {\n" + - "return typeof x == 'string' && x.length == 3 ? x : 'a';\n" + - "}"); + testTypesWithExterns( + new TestExternsBuilder().addString().build(), + lines( + "/**", + " * @param {number|string} x", + " * @return {string}", + " */", + "function f(x) {", + " return typeof x == 'string' && x.length == 3 ? x : 'a';", + "}")); } public void testTypeOfReduction7() { @@ -1399,7 +1402,8 @@ public void testStrictPropertiesOnFunctions2() { } public void testStrictPropertiesOnEnum1() { - testTypes( + testTypesWithExterns( + new TestExternsBuilder().addString().build(), lines( "/** @enum {string} */ var E = {S:'s'};", "/** @param {E} e\n @return {string} */", @@ -1407,7 +1411,8 @@ public void testStrictPropertiesOnEnum1() { } public void testStrictPropertiesOnEnum2() { - testTypes( + testTypesWithExterns( + new TestExternsBuilder().addString().build(), lines( "/** @enum {?string} */ var E = {S:'s'};", "/** @param {E} e\n @return {string} */", @@ -1415,7 +1420,8 @@ public void testStrictPropertiesOnEnum2() { } public void testStrictPropertiesOnEnum3() { - testTypes( + testTypesWithExterns( + new TestExternsBuilder().addString().build(), lines( "/** @enum {string} */ var E = {S:'s'};", "/** @param {?E} e\n @return {string} */", @@ -1423,7 +1429,8 @@ public void testStrictPropertiesOnEnum3() { } public void testStrictPropertiesOnEnum4() { - testTypes( + testTypesWithExterns( + new TestExternsBuilder().addString().build(), lines( "/** @enum {?string} */ var E = {S:'s'};", "/** @param {?E} e\n @return {string} */", @@ -2000,27 +2007,42 @@ public void testStringComparison6() { } public void testValueOfComparison1() { - testTypes("/** @constructor */function O() {};" + - "/**@override*/O.prototype.valueOf = function() { return 1; };" + - "/**@param {!O} a\n@param {!O} b*/ function f(a,b) { return a < b; }"); + testTypesWithExterns( + new TestExternsBuilder().addObject().build(), + lines( + "/** @constructor */function O() {};", + "/**@override*/O.prototype.valueOf = function() { return 1; };", + "/**@param {!O} a\n@param {!O} b*/ function f(a,b) { return a < b; }")); } public void testValueOfComparison2() { compiler.getOptions().setWarningLevel( DiagnosticGroups.STRICT_PRIMITIVE_OPERATORS, CheckLevel.OFF); - testTypes("/** @constructor */function O() {};" + - "/**@override*/O.prototype.valueOf = function() { return 1; };" + - "/**@param {!O} a\n@param {number} b*/" + - "function f(a,b) { return a < b; }"); + testTypesWithExterns( + new TestExternsBuilder().addObject().build(), + lines( + "/** @constructor */function O() {};", + "/**@override*/O.prototype.valueOf = function() { return 1; };", + "/**", + " * @param {!O} a", + " * @param {number} b", + " */", + "function f(a,b) { return a < b; }")); } public void testValueOfComparison3() { compiler.getOptions().setWarningLevel( DiagnosticGroups.STRICT_PRIMITIVE_OPERATORS, CheckLevel.OFF); - testTypes("/** @constructor */function O() {};" + - "/**@override*/O.prototype.toString = function() { return 'o'; };" + - "/**@param {!O} a\n@param {string} b*/" + - "function f(a,b) { return a < b; }"); + testTypesWithExterns( + new TestExternsBuilder().addObject().build(), + lines( + "/** @constructor */function O() {};", + "/**@override*/O.prototype.toString = function() { return 'o'; };", + "/**", + " * @param {!O} a", + " * @param {string} b", + " */", + "function f(a,b) { return a < b; }")); } public void testGenericRelationalExpression() { @@ -2382,16 +2404,18 @@ public void testFunctionArguments18() { } public void testRestParameters() { - testTypes(lines( - "/**", - " * @template T", - " * @param {...number} x", - " */", - "function f(...x) {", - " var /** string */ s = x[0];", - "}"), + testTypesWithExterns( + new TestExternsBuilder().addArray().build(), lines( - "initializing variable", + "/**", + " * @template T", + " * @param {...number} x", + " */", + "function f(...x) {", + " var /** string */ s = x[0];", + "}"), + lines( + "initializing variable", // preserve newlines "found : number", "required: string")); } @@ -2399,19 +2423,21 @@ public void testRestParameters() { // Test that when transpiling we don't use T in the body of f; it would cause a spurious // unknown-type warning. public void testRestParametersWithGenericsNoWarning() { - testTypes(lines( - "/**", - " * @constructor", - " * @template T", - " */", - "function Foo() {}", - "/**", - " * @template T", - " * @param {...!Foo} x", - " */", - "function f(...x) {", - " return 123;", - "}")); + testTypesWithExterns( + new TestExternsBuilder().addObject().addArray().build(), + lines( + "/**", + " * @constructor", + " * @template T", + " */", + "function Foo() {}", + "/**", + " * @template T", + " * @param {...!Foo} x", + " */", + "function f(...x) {", + " return 123;", + "}")); } public void testPrintFunctionName1() { @@ -3265,34 +3291,37 @@ public void testStubFunctionDeclaration4() { public void testStubFunctionDeclaration5() { testFunctionType( - "/** @constructor */ function f() { " + - " /** @type {Function} */ this.foo;" + - "}", + lines( + "/** @constructor */ function f() { ", // preserve newlines + " /** @type {Function} */ this.foo;", + "}"), "(new f).foo", - createNullableType(U2U_CONSTRUCTOR_TYPE).toString()); + createNullableType(getNativeU2UConstructorType()).toString()); } public void testStubFunctionDeclaration6() { testFunctionType( - "/** @constructor */ function f() {} " + - "/** @type {Function} */ f.prototype.foo;", + lines( + "/** @constructor */ function f() {} ", // preserve newlines + "/** @type {Function} */ f.prototype.foo;"), "(new f).foo", - createNullableType(U2U_CONSTRUCTOR_TYPE).toString()); + createNullableType(getNativeU2UConstructorType()).toString()); } public void testStubFunctionDeclaration7() { testFunctionType( - "/** @constructor */ function f() {} " + - "/** @type {Function} */ f.prototype.foo = function() {};", + lines( + "/** @constructor */ function f() {} ", // preserve newlines + "/** @type {Function} */ f.prototype.foo = function() {};"), "(new f).foo", - createNullableType(U2U_CONSTRUCTOR_TYPE).toString()); + createNullableType(getNativeU2UConstructorType()).toString()); } public void testStubFunctionDeclaration8() { testFunctionType( "/** @type {Function} */ var f = function() {}; ", "f", - createNullableType(U2U_CONSTRUCTOR_TYPE).toString()); + createNullableType(getNativeU2UConstructorType()).toString()); } public void testStubFunctionDeclaration9() { @@ -3543,17 +3572,20 @@ public void testForIn4() { } public void testForIn5() { - testTypes( - "/** @param {boolean} x */ function f(x) {}" + - "/** @constructor */ var E = function(){};" + - "/** @override */ E.prototype.toString = function() { return ''; };" + - "/** @type {Object} */ var obj = {};" + - "for (var k in obj) {" + - " f(k);" + - "}", - "actual parameter 1 of f does not match formal parameter\n" + - "found : string\n" + - "required: boolean"); + testTypesWithExterns( + new TestExternsBuilder().addObject().build(), + lines( + "/** @param {boolean} x */ function f(x) {}", + "/** @constructor */ var E = function(){};", + "/** @override */ E.prototype.toString = function() { return ''; };", + "/** @type {Object} */ var obj = {};", + "for (var k in obj) {", + " f(k);", + "}"), + lines( + "actual parameter 1 of f does not match formal parameter", + "found : string", + "required: boolean")); } public void testForOf1() { @@ -5837,8 +5869,8 @@ public void testVar1() { TypeCheckResult p = parseAndTypeCheckWithScope("/** @type {(string|null)} */var a = null"); - assertTypeEquals(createUnionType(STRING_TYPE, NULL_TYPE), - p.scope.getVar("a").getType()); + assertTypeEquals( + createUnionType(getNativeStringType(), getNativeNullType()), p.scope.getVar("a").getType()); } public void testVar2() { @@ -5848,14 +5880,15 @@ public void testVar2() { public void testVar3() { TypeCheckResult p = parseAndTypeCheckWithScope("var a = 3;"); - assertTypeEquals(NUMBER_TYPE, p.scope.getVar("a").getType()); + assertTypeEquals(getNativeNumberType(), p.scope.getVar("a").getType()); } public void testVar4() { TypeCheckResult p = parseAndTypeCheckWithScope( "var a = 3; a = 'string';"); - assertTypeEquals(createUnionType(STRING_TYPE, NUMBER_TYPE), + assertTypeEquals( + createUnionType(getNativeStringType(), getNativeNumberType()), p.scope.getVar("a").getType()); } @@ -7200,20 +7233,20 @@ public void testThisTypeOfFunction3() { } public void testThisTypeOfFunction4() { - testTypes( - "/** @constructor */ function F() {}" + - "F.prototype.moveTo = function(x, y) {};" + - "F.prototype.lineTo = function(x, y) {};" + - "function demo() {" + - " var path = new F();" + - " var points = [[1,1], [2,2]];" + - " for (var i = 0; i < points.length; i++) {" + - " (i == 0 ? path.moveTo : path.lineTo)(" + - " points[i][0], points[i][1]);" + - " }" + - "}", - "\"function(this:F, ?, ?): undefined\" " + - "must be called with a \"this\" type"); + testTypesWithExterns( + new TestExternsBuilder().addArray().addObject().build(), + lines( + "/** @constructor */ function F() {}", + "F.prototype.moveTo = function(x, y) {};", + "F.prototype.lineTo = function(x, y) {};", + "function demo() {", + " var path = new F();", + " var points = [[1,1], [2,2]];", + " for (var i = 0; i < points.length; i++) {", + " (i == 0 ? path.moveTo : path.lineTo)(points[i][0], points[i][1]);", + " }", + "}"), + "\"function(this:F, ?, ?): undefined\" must be called with a \"this\" type"); } public void testThisTypeOfFunction5() { @@ -7571,25 +7604,25 @@ public void testImplicitCastNotInExterns() { public void testNumberNode() { Node n = typeCheck(Node.newNumber(0)); - assertTypeEquals(NUMBER_TYPE, n.getJSType()); + assertTypeEquals(getNativeNumberType(), n.getJSType()); } public void testStringNode() { Node n = typeCheck(Node.newString("hello")); - assertTypeEquals(STRING_TYPE, n.getJSType()); + assertTypeEquals(getNativeStringType(), n.getJSType()); } public void testBooleanNodeTrue() { Node trueNode = typeCheck(new Node(Token.TRUE)); - assertTypeEquals(BOOLEAN_TYPE, trueNode.getJSType()); + assertTypeEquals(getNativeBooleanType(), trueNode.getJSType()); } public void testBooleanNodeFalse() { Node falseNode = typeCheck(new Node(Token.FALSE)); - assertTypeEquals(BOOLEAN_TYPE, falseNode.getJSType()); + assertTypeEquals(getNativeBooleanType(), falseNode.getJSType()); } public void testUndefinedNode() { @@ -7599,7 +7632,7 @@ public void testUndefinedNode() { p.addChildToBack(Node.newNumber(5)); typeCheck(p); - assertTypeEquals(VOID_TYPE, n.getJSType()); + assertTypeEquals(getNativeVoidType(), n.getJSType()); } public void testNumberAutoboxing() { @@ -7836,10 +7869,12 @@ public void testIssue259() { } public void testIssue301() { - testTypes( - "Array.indexOf = function() {};" + - "var s = 'hello';" + - "alert(s.toLowerCase.indexOf('1'));", + testTypesWithExterns( + new TestExternsBuilder().addString().addArray().build(), + lines( + "Array.indexOf = function() {};", + "var s = 'hello';", + "alert(s.toLowerCase.indexOf('1'));"), "Property indexOf never defined on String.prototype.toLowerCase"); } @@ -7865,28 +7900,33 @@ public void testIssue368() { } public void testIssue380() { - testTypes( - "/** @type { function(string): {innerHTML: string} } */\n" + - "document.getElementById;\n" + - "var list = /** @type {!Array} */ ['hello', 'you'];\n" + - "list.push('?');\n" + - "document.getElementById('node').innerHTML = list.toString();"); + testTypesWithExterns( + new TestExternsBuilder().addArray().addObject().build(), + lines( + "/** @type { function(string): {innerHTML: string} } */", + "document.getElementById;", + "var list = /** @type {!Array} */ ['hello', 'you'];", + "list.push('?');", + "document.getElementById('node').innerHTML = list.toString();")); } public void testIssue483() { - testTypes( - "/** @constructor */ function C() {" + - " /** @type {?Array} */ this.a = [];" + - "}" + - "C.prototype.f = function() {" + - " if (this.a.length > 0) {" + - " g(this.a);" + - " }" + - "};" + - "/** @param {number} a */ function g(a) {}", - "actual parameter 1 of g does not match formal parameter\n" + - "found : Array\n" + - "required: number"); + testTypesWithExterns( + new TestExternsBuilder().addArray().build(), + lines( + "/** @constructor */ function C() {", + " /** @type {?Array} */ this.a = [];", + "}", + "C.prototype.f = function() {", + " if (this.a.length > 0) {", + " g(this.a);", + " }", + "};", + "/** @param {number} a */ function g(a) {}"), + lines( + "actual parameter 1 of g does not match formal parameter", + "found : Array", + "required: number")); } public void testIssue537a() { @@ -8379,8 +8419,11 @@ public void testBug901455b() { * Tests that the match method of strings returns nullable arrays. */ public void testBug908701() { - testTypes("/** @type {String} */var s = new String('foo');" + - "var b = s.match(/a/) != null;"); + testTypesWithExterns( + new TestExternsBuilder().addString().build(), + lines( + "/** @type {String} */ var s = new String('foo');", // preserve newlines + "var b = s.match(/a/) != null;")); } /** @@ -8579,23 +8622,25 @@ public void testStrictInterfaceCheck() { public void testBug7701884() { - testTypes( - "/**\n" + - " * @param {Array} x\n" + - " * @param {function(T)} y\n" + - " * @template T\n" + - " */\n" + - "var forEach = function(x, y) {\n" + - " for (var i = 0; i < x.length; i++) y(x[i]);\n" + - "};" + - "/** @param {number} x */" + - "function f(x) {}" + - "/** @param {?} x */" + - "function h(x) {" + - " var top = null;" + - " forEach(x, function(z) { top = z; });" + - " if (top) f(top);" + - "}"); + testTypesWithExterns( + new TestExternsBuilder().addArray().build(), + lines( + "/**", + " * @param {Array} x", + " * @param {function(T)} y", + " * @template T", + " */", + "var forEach = function(x, y) {", + " for (var i = 0; i < x.length; i++) y(x[i]);", + "};", + "/** @param {number} x */", + "function f(x) {}", + "/** @param {?} x */", + "function h(x) {", + " var top = null;", + " forEach(x, function(z) { top = z; });", + " if (top) f(top);", + "}")); } public void testBug8017789() { @@ -9028,7 +9073,7 @@ public void testNew12() { TypeCheckResult p = parseAndTypeCheckWithScope("var a = new Array();"); TypedVar a = p.scope.getVar("a"); - assertTypeEquals(ARRAY_TYPE, a.getType()); + assertTypeEquals(getNativeArrayType(), a.getType()); } public void testNew13() { @@ -9104,23 +9149,23 @@ public void testNew20() { } public void testName1() { - assertTypeEquals(VOID_TYPE, testNameNode("undefined")); + assertTypeEquals(getNativeVoidType(), testNameNode("undefined")); } public void testName2() { - assertTypeEquals(OBJECT_FUNCTION_TYPE, testNameNode("Object")); + assertTypeEquals(getNativeObjectConstructorType(), testNameNode("Object")); } public void testName3() { - assertTypeEquals(ARRAY_FUNCTION_TYPE, testNameNode("Array")); + assertTypeEquals(getNativeArrayConstructorType(), testNameNode("Array")); } public void testName4() { - assertTypeEquals(DATE_FUNCTION_TYPE, testNameNode("Date")); + assertTypeEquals(getNativeDateConstructorType(), testNameNode("Date")); } public void testName5() { - assertTypeEquals(REGEXP_FUNCTION_TYPE, testNameNode("RegExp")); + assertTypeEquals(getNativeRegexpConstructorType(), testNameNode("RegExp")); } /** @@ -9516,7 +9561,8 @@ public void testNonAbstractMethodCall_Es6Class_prototype() { // GitHub issue #2262: https://github.com/google/closure-compiler/issues/2262 public void testAbstractMethodCall_Es6ClassWithSpread() { - testTypesWithCommonExterns( + testTypesWithExterns( + new TestExternsBuilder().addObject().addArray().build(), lines( "/** @abstract */", "class Base {", @@ -10654,8 +10700,10 @@ public void testComplexNamespace() { googFooGetprop2ObjectType.hasProperty("foo")); assertTrue("bar property not present on goog.foo type", googFooGetprop2ObjectType.hasProperty("bar")); - assertTypeEquals("bar property on goog.foo type incorrectly inferred", - NUMBER_TYPE, googFooGetprop2ObjectType.getPropertyType("bar")); + assertTypeEquals( + "bar property on goog.foo type incorrectly inferred", + getNativeNumberType(), + googFooGetprop2ObjectType.getPropertyType("bar")); } public void testAddingMethodsUsingPrototypeIdiomSimpleNamespace() { @@ -10666,8 +10714,8 @@ public void testAddingMethodsUsingPrototypeIdiomSimpleNamespace() { "A.prototype.m1 = 5"); ObjectType instanceType = getInstanceType(js1Node); - assertEquals(NATIVE_PROPERTIES_COUNT + 2, instanceType.getPropertiesCount()); - checkObjectType(instanceType, "m1", NUMBER_TYPE); + assertHasXMorePropertiesThanNativeObject(instanceType, 1); + checkObjectType(instanceType, "m1", getNativeNumberType()); } public void testAddingMethodsUsingPrototypeIdiomComplexNamespace1() { @@ -10693,14 +10741,14 @@ public void testAddingMethodsUsingPrototypeIdiomComplexNamespace2() { private void testAddingMethodsUsingPrototypeIdiomComplexNamespace( TypeCheckResult p) { ObjectType goog = (ObjectType) p.scope.getVar("goog").getType(); - assertEquals(NATIVE_PROPERTIES_COUNT + 2, goog.getPropertiesCount()); + assertHasXMorePropertiesThanNativeObject(goog, 1); JSType googA = goog.getPropertyType("A"); assertNotNull(googA); assertThat(googA).isInstanceOf(FunctionType.class); FunctionType googAFunction = (FunctionType) googA; ObjectType classA = googAFunction.getInstanceType(); - assertEquals(NATIVE_PROPERTIES_COUNT + 2, classA.getPropertiesCount()); - checkObjectType(classA, "m1", NUMBER_TYPE); + assertHasXMorePropertiesThanNativeObject(classA, 1); + checkObjectType(classA, "m1", getNativeNumberType()); } public void testAddingMethodsPrototypeIdiomAndObjectLiteralSimpleNamespace() { @@ -10710,9 +10758,9 @@ public void testAddingMethodsPrototypeIdiomAndObjectLiteralSimpleNamespace() { "A.prototype = {m1: 5, m2: true}"); ObjectType instanceType = getInstanceType(js1Node); - assertEquals(NATIVE_PROPERTIES_COUNT + 3, instanceType.getPropertiesCount()); - checkObjectType(instanceType, "m1", NUMBER_TYPE); - checkObjectType(instanceType, "m2", BOOLEAN_TYPE); + assertHasXMorePropertiesThanNativeObject(instanceType, 2); + checkObjectType(instanceType, "m1", getNativeNumberType()); + checkObjectType(instanceType, "m2", getNativeBooleanType()); } public void testDontAddMethodsIfNoConstructor() { @@ -10722,10 +10770,8 @@ public void testDontAddMethodsIfNoConstructor() { JSType functionAType = js1Node.getFirstChild().getJSType(); assertEquals("function(): undefined", functionAType.toString()); - assertTypeEquals(UNKNOWN_TYPE, - U2U_FUNCTION_TYPE.getPropertyType("m1")); - assertTypeEquals(UNKNOWN_TYPE, - U2U_FUNCTION_TYPE.getPropertyType("m2")); + assertTypeEquals(getNativeUnknownType(), getNativeU2UFunctionType().getPropertyType("m1")); + assertTypeEquals(getNativeUnknownType(), getNativeU2UFunctionType().getPropertyType("m2")); } public void testFunctionAssignement() { @@ -10748,10 +10794,10 @@ public void testAddMethodsPrototypeTwoWays() { ObjectType instanceType = getInstanceType(js1Node); assertEquals("A", instanceType.toString()); - assertEquals(NATIVE_PROPERTIES_COUNT + 4, instanceType.getPropertiesCount()); - checkObjectType(instanceType, "m1", NUMBER_TYPE); - checkObjectType(instanceType, "m2", BOOLEAN_TYPE); - checkObjectType(instanceType, "m3", STRING_TYPE); + assertHasXMorePropertiesThanNativeObject(instanceType, 3); + checkObjectType(instanceType, "m1", getNativeNumberType()); + checkObjectType(instanceType, "m2", getNativeBooleanType()); + checkObjectType(instanceType, "m3", getNativeStringType()); } public void testPrototypePropertyTypes() { @@ -10767,28 +10813,31 @@ public void testPrototypePropertyTypes() { "/** @type {boolean} */ A.prototype.m6;\n"); ObjectType instanceType = getInstanceType(js1Node); - assertEquals(NATIVE_PROPERTIES_COUNT + 7, instanceType.getPropertiesCount()); - checkObjectType(instanceType, "m1", STRING_TYPE); - checkObjectType(instanceType, "m2", - createUnionType(OBJECT_TYPE, NULL_TYPE)); - checkObjectType(instanceType, "m3", BOOLEAN_TYPE); - checkObjectType(instanceType, "m4", STRING_TYPE); - checkObjectType(instanceType, "m5", NUMBER_TYPE); - checkObjectType(instanceType, "m6", BOOLEAN_TYPE); + assertHasXMorePropertiesThanNativeObject(instanceType, 6); + checkObjectType(instanceType, "m1", getNativeStringType()); + checkObjectType( + instanceType, "m2", createUnionType(getNativeObjectType(), getNativeNullType())); + checkObjectType(instanceType, "m3", getNativeBooleanType()); + checkObjectType(instanceType, "m4", getNativeStringType()); + checkObjectType(instanceType, "m5", getNativeNumberType()); + checkObjectType(instanceType, "m6", getNativeBooleanType()); } public void testValueTypeBuiltInPrototypePropertyType() { - Node node = parseAndTypeCheck("\"x\".charAt(0)"); - assertTypeEquals(STRING_TYPE, node.getFirstFirstChild().getJSType()); + Node node = parseAndTypeCheck(new TestExternsBuilder().addString().build(), "\"x\".charAt(0)"); + assertTypeEquals(getNativeStringType(), node.getFirstFirstChild().getJSType()); } public void testDeclareBuiltInConstructor() { // Built-in prototype properties should be accessible // even if the built-in constructor is declared. - Node node = parseAndTypeCheck( - "/** @constructor */ var String = function(opt_str) {};\n" + - "(new String(\"x\")).charAt(0)"); - assertTypeEquals(STRING_TYPE, node.getLastChild().getFirstChild().getJSType()); + Node node = + parseAndTypeCheck( + new TestExternsBuilder().addString().build(), + lines( + "/** @constructor */ var String = function(opt_str) {};", + "(new String(\"x\")).charAt(0)")); + assertTypeEquals(getNativeStringType(), node.getLastChild().getFirstChild().getJSType()); } public void testExtendBuiltInType1() { @@ -10801,7 +10850,7 @@ public void testExtendBuiltInType1() { "*/\n" + "String.prototype.substr = function(start, opt_length) {};\n"; Node n1 = parseAndTypeCheck(externs + "(new String(\"x\")).substr(0,1);"); - assertTypeEquals(STRING_TYPE, n1.getLastChild().getFirstChild().getJSType()); + assertTypeEquals(getNativeStringType(), n1.getLastChild().getFirstChild().getJSType()); } public void testExtendBuiltInType2() { @@ -10814,7 +10863,7 @@ public void testExtendBuiltInType2() { "*/\n" + "String.prototype.substr = function(start, opt_length) {};\n"; Node n2 = parseAndTypeCheck(externs + "\"x\".substr(0,1);"); - assertTypeEquals(STRING_TYPE, n2.getLastChild().getFirstChild().getJSType()); + assertTypeEquals(getNativeStringType(), n2.getLastChild().getFirstChild().getJSType()); } public void testExtendFunction1() { @@ -10822,7 +10871,7 @@ public void testExtendFunction1() { "function() { return 1; };\n" + "(new Function()).f();"); JSType type = n.getLastChild().getLastChild().getJSType(); - assertTypeEquals(NUMBER_TYPE, type); + assertTypeEquals(getNativeNumberType(), type); } public void testExtendFunction2() { @@ -10830,7 +10879,7 @@ public void testExtendFunction2() { "function() { return 1; };\n" + "(function() {}).f();"); JSType type = n.getLastChild().getLastChild().getJSType(); - assertTypeEquals(NUMBER_TYPE, type); + assertTypeEquals(getNativeNumberType(), type); } public void testInheritanceCheck1() { @@ -11311,8 +11360,8 @@ public void testObjectLiteral() { // value's type ObjectType objectType = (ObjectType) objectNode.getJSType(); - assertTypeEquals(NUMBER_TYPE, objectType.getPropertyType("m1")); - assertTypeEquals(STRING_TYPE, objectType.getPropertyType("m2")); + assertTypeEquals(getNativeNumberType(), objectType.getPropertyType("m1")); + assertTypeEquals(getNativeStringType(), objectType.getPropertyType("m2")); // variable's type assertTypeEquals(objectType, nameNode.getJSType()); @@ -11407,7 +11456,7 @@ public void testCallDateConstructorAsFunction() { // ECMA-262 15.9.2: When Date is called as a function rather than as a // constructor, it returns a string. Node n = parseAndTypeCheck("Date()"); - assertTypeEquals(STRING_TYPE, n.getFirstFirstChild().getJSType()); + assertTypeEquals(getNativeStringType(), n.getFirstFirstChild().getJSType()); } // According to ECMA-262, Error & Array function calls are equivalent to @@ -11415,14 +11464,12 @@ public void testCallDateConstructorAsFunction() { public void testCallErrorConstructorAsFunction() { Node n = parseAndTypeCheck("Error('x')"); - assertTypeEquals(ERROR_TYPE, - n.getFirstFirstChild().getJSType()); + assertTypeEquals(getNativeErrorType(), n.getFirstFirstChild().getJSType()); } public void testCallArrayConstructorAsFunction() { Node n = parseAndTypeCheck("Array()"); - assertTypeEquals(ARRAY_TYPE, - n.getFirstFirstChild().getJSType()); + assertTypeEquals(getNativeArrayType(), n.getFirstFirstChild().getJSType()); } public void testPropertyTypeOfUnionType() { @@ -11970,7 +12017,7 @@ public void testGatherProperyWithoutAnnotation2() { Node n = ns.root; JSType type = n.getLastChild().getLastChild().getJSType(); assertFalse(type.isUnknownType()); - assertTypeEquals(type, OBJECT_TYPE); + assertTypeEquals(type, getNativeObjectType()); assertThat(type).isInstanceOf(ObjectType.class); ObjectType objectType = (ObjectType) type; assertFalse(objectType.hasProperty("x")); @@ -12456,10 +12503,14 @@ public void testGetTypedPercent6() { } private double getTypedPercent(String js) { + return getTypedPercentWithExterns("", js); + } + + private double getTypedPercentWithExterns(String externs, String js) { Node n = compiler.parseTestCode(js); - Node externs = IR.root(); - IR.root(externs, n); + Node externsRoot = compiler.parseTestCode(externs); + IR.root(externsRoot, n); TypeCheck t = makeTypeCheck(); t.processForTesting(null, n); @@ -12497,21 +12548,23 @@ public void testPrototypePropertyReference() { } public void testResolvingNamedTypes() { - String js = "" - + "/** @constructor */\n" - + "var Foo = function() {}\n" - + "/** @param {number} a */\n" - + "Foo.prototype.foo = function(a) {\n" - + " return this.baz().toString();\n" - + "};\n" - + "/** @return {Baz} */\n" - + "Foo.prototype.baz = function() { return new Baz(); };\n" - + "/** @constructor\n" - + " * @extends Foo */\n" - + "var Bar = function() {};" - + "/** @constructor */\n" - + "var Baz = function() {};"; - assertEquals(100.0, getTypedPercent(js), 0.1); + String externs = new TestExternsBuilder().addObject().build(); + String js = + lines( + "/** @constructor */", + "var Foo = function() {}", + "/** @param {number} a */", + "Foo.prototype.foo = function(a) {", + " return this.baz().toString();", + "};", + "/** @return {Baz} */", + "Foo.prototype.baz = function() { return new Baz(); };", + "/** @constructor", + " * @extends Foo */", + "var Bar = function() {};", + "/** @constructor */", + "var Baz = function() {};"); + assertEquals(100.0, getTypedPercentWithExterns(externs, js), 0.1); } public void testMissingProperty1a() { @@ -12972,16 +13025,21 @@ public void testMissingProperty38() { public void testMissingProperty39a() { disableStrictMissingPropertyChecks(); - testTypes( - "/** @return {string|number} */ function f() { return 3; }" + - "f().length;"); + testTypesWithExterns( + new TestExternsBuilder().addString().build(), + lines( + "/** @return {string|number} */ function f() { return 3; }", // preserve newlines + "f().length;")); } public void testMissingProperty39b() { - testTypes( - "/** @return {string|number} */ function f() { return 3; }" + "f().length;" + testTypesWithExterns( + new TestExternsBuilder().addString().build(), + lines( + "/** @return {string|number} */ function f() { return 3; }", // preserve newlines + "f().length;") // TODO(johnlenz): enable this. - //"Property length not defined on all member types of (String|Number)" + // "Property length not defined on all member types of (String|Number)" ); } @@ -13167,14 +13225,14 @@ public void testLends11() { public void testDeclaredNativeTypeEquality() { Node n = parseAndTypeCheck("/** @constructor */ function Object() {};"); - assertTypeEquals(registry.getNativeType(JSTypeNative.OBJECT_FUNCTION_TYPE), - n.getFirstChild().getJSType()); + assertTypeEquals( + registry.getNativeType(JSTypeNative.OBJECT_FUNCTION_TYPE), n.getFirstChild().getJSType()); } public void testUndefinedVar() { Node n = parseAndTypeCheck("var undefined;"); - assertTypeEquals(registry.getNativeType(JSTypeNative.VOID_TYPE), - n.getFirstFirstChild().getJSType()); + assertTypeEquals( + registry.getNativeType(JSTypeNative.VOID_TYPE), n.getFirstFirstChild().getJSType()); } public void testFlowScopeBug1() { @@ -13186,9 +13244,15 @@ public void testFlowScopeBug1() { + "for (; (i + a) < b; ++i) {}}"); // check the type of the add node for i + f - assertTypeEquals(registry.getNativeType(JSTypeNative.NUMBER_TYPE), - n.getFirstChild().getLastChild().getLastChild().getFirstChild() - .getNext().getFirstChild().getJSType()); + assertTypeEquals( + registry.getNativeType(JSTypeNative.NUMBER_TYPE), + n.getFirstChild() + .getLastChild() + .getLastChild() + .getFirstChild() + .getNext() + .getFirstChild() + .getJSType()); } public void testFlowScopeBug2() { @@ -13207,9 +13271,15 @@ public void testFlowScopeBug2() { + "}"); // check the type of afoo when referenced - assertTypeEquals(registry.createNullableType(registry.getGlobalType("Foo")), - n.getLastChild().getLastChild().getLastChild().getLastChild() - .getLastChild().getLastChild().getJSType()); + assertTypeEquals( + registry.createNullableType(registry.getGlobalType("Foo")), + n.getLastChild() + .getLastChild() + .getLastChild() + .getLastChild() + .getLastChild() + .getLastChild() + .getJSType()); } public void testAddSingletonGetter() { @@ -13234,9 +13304,11 @@ public void testTypeCheckStandaloneAST() { IR.root(externs, second); new TypeCheck( - compiler, - new SemanticReverseAbstractInterpreter(registry), - registry, topScope, scopeCreator) + compiler, + new SemanticReverseAbstractInterpreter(registry), + registry, + topScope, + scopeCreator) .process(null, second); assertEquals(1, compiler.getWarningCount()); @@ -13408,13 +13480,16 @@ public void testTemplateType6() { } public void testTemplateType7() { - // TODO(johnlenz): As the @this type for Array.prototype.push includes - // "{length:number}" (and this includes "Array") we don't - // get a type warning here. Consider special-casing array methods. - testTypes( - "/** @type {!Array} */\n" + - "var query = [];\n" + - "query.push(1);\n"); + testTypesWithExterns( + new TestExternsBuilder().addArray().build(), + lines( + "/** @type {!Array} */", // preserve newlines + "var query = [];", + "query.push(1);"), + lines( + "actual parameter 1 of Array.prototype.push does not match formal parameter", + "found : number", + "required: (string|undefined)")); } public void testTemplateType8() { @@ -14161,18 +14236,21 @@ public void testFunctionLiteralDefinedThisArgument() { } public void testFunctionLiteralDefinedThisArgument2() { - testTypes("" - + "/** @param {string} x */ function f(x) {}" - + "/**\n" - + " * @param {?function(this:T, ...)} fn\n" - + " * @param {T=} opt_obj\n" - + " * @template T\n" - + " */\n" - + "function baz(fn, opt_obj) {}\n" - + "function g() { baz(function() { f(this.length); }, []); }", - "actual parameter 1 of f does not match formal parameter\n" - + "found : number\n" - + "required: string"); + testTypesWithExterns( + new TestExternsBuilder().addArray().build(), + lines( + "/** @param {string} x */ function f(x) {}", + "/**", + " * @param {?function(this:T, ...)} fn", + " * @param {T=} opt_obj", + " * @template T", + " */", + "function baz(fn, opt_obj) {}", + "function g() { baz(function() { f(this.length); }, []); }"), + lines( + "actual parameter 1 of f does not match formal parameter", + "found : number", + "required: string")); } public void testFunctionLiteralUnreadNullThisArgument() { @@ -14787,16 +14865,18 @@ public void testBackwardsInferenceGoogArrayFilter3() { public void testBackwardsInferenceGoogArrayFilter4() { testClosureTypes( - CLOSURE_DEFS + - "/** @type {string} */" + - "var out;" + - "/** @type {Array} */ var arr;\n" + - "var out4 = goog.array.filter(" + - " arr," + - " function(item,index,srcArr) {out = srcArr;});", - "assignment\n" + - "found : (null|{length: number})\n" + - "required: string"); + lines( + CLOSURE_DEFS, + "/** @type {string} */", + "var out;", + "/** @type {Array} */ var arr;", + "var out4 = goog.array.filter(", + " arr,", + " function(item,index,srcArr) {out = srcArr;});"), + lines( + "assignment", // keep newlines + "found : (Array|null|{length: number})", + "required: string")); } public void testCatchExpression1() { @@ -15082,12 +15162,9 @@ public void testUnknownTypeDisabledByDefault() { } public void testTemplatizedTypeSubtypes2() { - JSType arrayOfNumber = createTemplatizedType( - ARRAY_TYPE, NUMBER_TYPE); - JSType arrayOfString = createTemplatizedType( - ARRAY_TYPE, STRING_TYPE); - assertFalse(arrayOfString.isSubtypeOf(createUnionType(arrayOfNumber, NULL_VOID))); - + JSType arrayOfNumber = createTemplatizedType(getNativeArrayType(), getNativeNumberType()); + JSType arrayOfString = createTemplatizedType(getNativeArrayType(), getNativeStringType()); + assertFalse(arrayOfString.isSubtypeOf(createUnionType(arrayOfNumber, getNativeNullVoidType()))); } public void testNonexistentPropertyAccessOnStruct() { @@ -15447,42 +15524,43 @@ public void testCheckObjectKeysGoodKey15() { } public void testCheckObjectKeysClassWithToString() { - testTypes( - "/** @constructor */\n" + - "var MyClass = function() {};\n" + - "/** @override*/\n" + - "MyClass.prototype.toString = function() { return ''; };\n" + - - "/** @type {!Object} */\n" + - "var k;"); + testTypesWithExterns( + new TestExternsBuilder().addObject().build(), + lines( + "/** @constructor */", + "var MyClass = function() {};", + "/** @override*/", + "MyClass.prototype.toString = function() { return ''; };", + "/** @type {!Object} */", + "var k;")); } public void testCheckObjectKeysClassInheritsToString() { - testTypes( - "/** @constructor */\n" + - "var Parent = function() {};\n" + - "/** @override */\n" + - "Parent.prototype.toString = function() { return ''; };\n" + - - "/** @constructor @extends {Parent} */\n" + - "var Child = function() {};\n" + - - "/** @type {!Object} */\n" + - "var k;"); + testTypesWithExterns( + new TestExternsBuilder().addObject().build(), + lines( + "/** @constructor */", + "var Parent = function() {};", + "/** @override */", + "Parent.prototype.toString = function() { return ''; };", + "/** @constructor @extends {Parent} */", + "var Child = function() {};", + "/** @type {!Object} */", + "var k;")); } public void testCheckObjectKeysForEnumUsingClassWithToString() { - testTypes( - "/** @constructor */\n" + - "var MyClass = function() {};\n" + - "/** @override*/\n" + - "MyClass.prototype.toString = function() { return ''; };\n" + - - "/** @enum{!MyClass} */\n" + - "var Enum = {};\n" + - - "/** @type {!Object} */\n" + - "var k;"); + testTypesWithExterns( + new TestExternsBuilder().addObject().build(), + lines( + "/** @constructor */", + "var MyClass = function() {};", + "/** @override*/", + "MyClass.prototype.toString = function() { return ''; };", + "/** @enum{!MyClass} */", + "var Enum = {};", + "/** @type {!Object} */", + "var k;")); } public void testBadSuperclassInheritance1() { @@ -19447,7 +19525,8 @@ public void testMixinApplication3() { public void testReassignedSymbolAccessedInClosureIsFlowInsensitive() { // This code is technically correct, but the compiler will probably never be able to prove it. - testTypes( + testTypesWithExterns( + new TestExternsBuilder().addString().build(), lines( "function f(){", " for (var x = {}; ; x = {y: x.y}) {", @@ -19461,7 +19540,7 @@ public void testReassignedSymbolAccessedInClosureIsFlowInsensitive() { " }", "}"), lines( - "sign operator", + "sign operator", // preserve newlines "found : (number|string)", "required: number")); } @@ -19760,6 +19839,10 @@ void testTypesWithExterns(String externs, String js, DiagnosticType diagnosticTy } } + void testTypesWithExterns(String externs, String js, String description) { + testTypesWithExterns(externs, js, description, false); + } + void testTypesWithExterns(String externs, String js) { testTypesWithExterns(externs, js, (String) null, false); } @@ -19773,7 +19856,7 @@ private void testClosureTypesMultipleWarnings( String js, List descriptions) { compiler.initOptions(compiler.getOptions()); Node n = compiler.parseTestCode(js); - Node externs = IR.root(); + Node externs = compiler.parseTestCode(new TestExternsBuilder().addString().build()); IR.root(externs, n); assertEquals("parsing error: " + @@ -19919,4 +20002,14 @@ private TypeCheckResult(Node root, TypedScope scope) { this.scope = scope; } } + + private void assertHasXMorePropertiesThanNativeObject( + ObjectType instanceType, int numExtraProperties) { + assertEquals( + getNativeObjectPropertiesCount() + numExtraProperties, instanceType.getPropertiesCount()); + } + + private int getNativeObjectPropertiesCount() { + return getNativeObjectType().getPropertiesCount(); + } } diff --git a/test/com/google/javascript/jscomp/TypeTransformationTest.java b/test/com/google/javascript/jscomp/TypeTransformationTest.java index 0aa2a5592f7..83abfd22ed4 100644 --- a/test/com/google/javascript/jscomp/TypeTransformationTest.java +++ b/test/com/google/javascript/jscomp/TypeTransformationTest.java @@ -31,40 +31,43 @@ public final class TypeTransformationTest extends CompilerTypeTestCase { private ImmutableMap nameVars; private static JSType recordTypeTest, nestedRecordTypeTest, asynchRecord; - static final String EXTRA_TYPE_DEFS = lines( - "/** @typedef {!Array} */ var ArrayAlias;", - "", - "/** @constructor */", - "function Bar() {}", - "", - "/** @type {number} */", - "var n = 10;"); + static final String EXTRA_TYPE_DEFS = + lines( + "/** @type {number} */ Array.prototype.length;", + "/** @typedef {!Array} */ var ArrayAlias;", + "", + "/** @constructor */", + "function Bar() {}", + "", + "/** @type {number} */", + "var n = 10;"); @Override public void setUp() throws Exception { super.setUp(); errorReporter = new TestErrorReporter(null, null); initRecordTypeTests(); - typeVars = new ImmutableMap.Builder() - .put("S", STRING_TYPE) - .put("N", NUMBER_TYPE) - .put("B", BOOLEAN_TYPE) - .put("BOT", NO_TYPE) - .put("TOP", ALL_TYPE) - .put("UNK", UNKNOWN_TYPE) - .put("CHKUNK", CHECKED_UNKNOWN_TYPE) - .put("SO", STRING_OBJECT_TYPE) - .put("NO", NUMBER_OBJECT_TYPE) - .put("BO", BOOLEAN_OBJECT_TYPE) - .put("NULL", NULL_TYPE) - .put("OBJ", OBJECT_TYPE) - .put("UNDEF", VOID_TYPE) - .put("ARR", ARRAY_TYPE) - .put("ARRNUM", type(ARRAY_TYPE, NUMBER_TYPE)) - .put("REC", recordTypeTest) - .put("NESTEDREC", nestedRecordTypeTest) - .put("ASYNCH", asynchRecord) - .build(); + typeVars = + new ImmutableMap.Builder() + .put("S", getNativeStringType()) + .put("N", getNativeNumberType()) + .put("B", getNativeBooleanType()) + .put("BOT", getNativeNoType()) + .put("TOP", getNativeAllType()) + .put("UNK", getNativeUnknownType()) + .put("CHKUNK", getNativeCheckedUnknownType()) + .put("SO", getNativeStringObjectType()) + .put("NO", getNativeNumberObjectType()) + .put("BO", getNativeBooleanObjectType()) + .put("NULL", getNativeNullType()) + .put("OBJ", getNativeObjectType()) + .put("UNDEF", getNativeVoidType()) + .put("ARR", getNativeArrayType()) + .put("ARRNUM", type(getNativeArrayType(), getNativeNumberType())) + .put("REC", recordTypeTest) + .put("NESTEDREC", nestedRecordTypeTest) + .put("ASYNCH", asynchRecord) + .build(); nameVars = new ImmutableMap.Builder() .put("s", "string") .put("n", "number") @@ -73,333 +76,336 @@ public void setUp() throws Exception { } public void testTransformationWithValidBasicTypePredicate() { - testTTL(NUMBER_TYPE, "'number'"); + testTTL(getNativeNumberType(), "'number'"); } public void testTransformationWithBasicTypePredicateWithInvalidTypename() { - testTTL(UNKNOWN_TYPE, "'foo'", - "Reference to an unknown type name foo"); + testTTL(getNativeUnknownType(), "'foo'", "Reference to an unknown type name foo"); } public void testTransformationWithSingleTypeVar() { - testTTL(STRING_TYPE, "S"); + testTTL(getNativeStringType(), "S"); } public void testTransformationWithMultipleTypeVars() { - testTTL(STRING_TYPE, "S"); - testTTL(NUMBER_TYPE, "N"); + testTTL(getNativeStringType(), "S"); + testTTL(getNativeNumberType(), "N"); } public void testTransformationWithValidUnionTypeOnlyVars() { - testTTL(union(NUMBER_TYPE, STRING_TYPE), "union(N, S)"); + testTTL(union(getNativeNumberType(), getNativeStringType()), "union(N, S)"); } public void testTransformationWithValidUnionTypeOnlyTypePredicates() { - testTTL(union(NUMBER_TYPE, STRING_TYPE), - "union('number', 'string')"); + testTTL(union(getNativeNumberType(), getNativeStringType()), "union('number', 'string')"); } public void testTransformationWithValidUnionTypeMixed() { - testTTL(union(NUMBER_TYPE, STRING_TYPE), "union(S, 'number')"); + testTTL(union(getNativeNumberType(), getNativeStringType()), "union(S, 'number')"); } public void testTransformationWithUnknownParameter() { // Returns ? because foo is not defined - testTTL(UNKNOWN_TYPE, "union(foo, 'number')", + testTTL( + getNativeUnknownType(), + "union(foo, 'number')", "Reference to an unknown type variable foo"); } public void testTransformationWithUnknownParameter2() { // Returns ? because foo is not defined - testTTL(UNKNOWN_TYPE, "union(N, 'foo')", - "Reference to an unknown type name foo"); + testTTL(getNativeUnknownType(), "union(N, 'foo')", "Reference to an unknown type name foo"); } public void testTransformationWithNestedUnionInFirstParameter() { - testTTL(union(NUMBER_TYPE, NULL_TYPE, STRING_TYPE), + testTTL( + union(getNativeNumberType(), getNativeNullType(), getNativeStringType()), "union(union(N, 'null'), S)"); } public void testTransformationWithNestedUnionInSecondParameter() { - testTTL(union(NUMBER_TYPE, NULL_TYPE, STRING_TYPE), + testTTL( + union(getNativeNumberType(), getNativeNullType(), getNativeStringType()), "union(N, union('null', S))"); } public void testTransformationWithRepeatedTypePredicate() { - testTTL(NUMBER_TYPE, "union('number', 'number')"); + testTTL(getNativeNumberType(), "union('number', 'number')"); } public void testTransformationWithUndefinedTypeVar() { - testTTL(UNKNOWN_TYPE, "foo", "Reference to an unknown type variable foo"); + testTTL(getNativeUnknownType(), "foo", "Reference to an unknown type variable foo"); } public void testTransformationWithTrueEqtypeConditional() { - testTTL(STRING_TYPE, "cond(eq(N, N), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(eq(N, N), 'string', 'number')"); } public void testTransformationWithFalseEqtypeConditional() { - testTTL(NUMBER_TYPE, "cond(eq(N, S), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(eq(N, S), 'string', 'number')"); } public void testTransformationWithTrueSubtypeConditional() { - testTTL(STRING_TYPE, - "cond( sub('Number', 'Object'), 'string', 'number')"); + testTTL(getNativeStringType(), "cond( sub('Number', 'Object'), 'string', 'number')"); } public void testTransformationWithFalseSubtypeConditional() { - testTTL(NUMBER_TYPE, - "cond( sub('Number', 'String'), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond( sub('Number', 'String'), 'string', 'number')"); } public void testTransformationWithTrueStreqConditional() { - testTTL(STRING_TYPE, "cond(streq(n, 'number'), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(streq(n, 'number'), 'string', 'number')"); } public void testTransformationWithTrueStreqConditional2() { - testTTL(STRING_TYPE, "cond(streq(n, n), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(streq(n, n), 'string', 'number')"); } public void testTransformationWithTrueStreqConditional3() { - testTTL(STRING_TYPE, "cond(streq('number', 'number'), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(streq('number', 'number'), 'string', 'number')"); } public void testTransformationWithFalseStreqConditional() { - testTTL(NUMBER_TYPE, "cond(streq('number', 'foo'), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(streq('number', 'foo'), 'string', 'number')"); } public void testTransformationWithFalseStreqConditional2() { - testTTL(NUMBER_TYPE, "cond(streq(n, 'foo'), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(streq(n, 'foo'), 'string', 'number')"); } public void testTransformationWithFalseStreqConditional3() { - testTTL(NUMBER_TYPE, "cond(streq(n, s), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(streq(n, s), 'string', 'number')"); } public void testTransformationWithInvalidEqConditional() { // It returns number since a failing boolean expression returns false - testTTL(NUMBER_TYPE, "cond(eq(foo, S), 'string', 'number')", + testTTL( + getNativeNumberType(), + "cond(eq(foo, S), 'string', 'number')", "Reference to an unknown type variable foo"); } public void testTransformationWithInvalidStreqConditional() { // It returns number since a failing boolean expression returns false - testTTL(NUMBER_TYPE, "cond(streq(foo, s), 'string', 'number')", + testTTL( + getNativeNumberType(), + "cond(streq(foo, s), 'string', 'number')", "Reference to an unknown string variable foo"); } public void testTransformationWithNestedExpressionInBooleanFirstParam() { - testTTL(STRING_TYPE, - "cond( eq( cond(eq(N, N), 'string', 'number'), 'string')," - + "'string', " - + "'number')"); + testTTL( + getNativeStringType(), + "cond( eq( cond(eq(N, N), 'string', 'number'), 'string')," + "'string', " + "'number')"); } public void testTransformationWithNestedExpressionInBooleanSecondParam() { - testTTL(STRING_TYPE, - "cond( eq( 'string', cond(eq(N, N), 'string', 'number'))," - + "'string', " - + "'number')"); + testTTL( + getNativeStringType(), + "cond( eq( 'string', cond(eq(N, N), 'string', 'number'))," + "'string', " + "'number')"); } public void testTransformationWithNestedExpressionInIfBranch() { - testTTL(STRING_OBJECT_TYPE, - "cond( eq(N, N)," - + "cond(eq(N, S), 'string', 'String')," - + "'number')"); + testTTL( + getNativeStringObjectType(), + "cond(eq(N, N), cond(eq(N, S), 'string', 'String'), 'number')"); } public void testTransformationWithNestedExpressionInElseBranch() { - testTTL(STRING_OBJECT_TYPE, - "cond( eq(N, S)," - + "'number'," - + "cond(eq(N, S), 'string', 'String'))"); + testTTL( + getNativeStringObjectType(), + "cond(eq(N, S), 'number', cond(eq(N, S), 'string', 'String'))"); } public void testTransformationWithMapunionMappingEverythingToString() { - testTTL(STRING_TYPE, "mapunion(union(S, N), (x) => S)"); + testTTL(getNativeStringType(), "mapunion(union(S, N), (x) => S)"); } public void testTransformationWithMapunionIdentity() { - testTTL(union(NUMBER_TYPE, STRING_TYPE), - "mapunion(union(N, S), (x) => x)"); + testTTL(union(getNativeNumberType(), getNativeStringType()), "mapunion(union(N, S), (x) => x)"); } public void testTransformationWithMapunionWithUnionEvaluatedToANonUnion() { - testTTL(NUMBER_TYPE, - "mapunion(union(N, 'number'), (x) => x)"); + testTTL(getNativeNumberType(), "mapunion(union(N, 'number'), (x) => x)"); } public void testTransformationWithMapunionFilterWithOnlyString() { - testTTL(STRING_TYPE, - "mapunion(union(S, B, N), (x) => cond(eq(x, S), x, BOT))"); + testTTL(getNativeStringType(), "mapunion(union(S, B, N), (x) => cond(eq(x, S), x, BOT))"); } public void testTransformationWithMapunionOnSingletonStringToNumber() { - testTTL(NUMBER_TYPE, "mapunion(S, (x) => cond(eq(x, S), N, BOT))"); + testTTL(getNativeNumberType(), "mapunion(S, (x) => cond(eq(x, S), N, BOT))"); } public void testTransformationWithNestedUnionInMapunionFilterString() { - testTTL(union(NUMBER_TYPE, BOOLEAN_TYPE), - "mapunion(union(union(S, B), union(N, S))," - + "(x) => cond(eq(x, S), BOT, x))"); + testTTL( + union(getNativeNumberType(), getNativeBooleanType()), + "mapunion(union(union(S, B), union(N, S)), (x) => cond(eq(x, S), BOT, x))"); } public void testTransformationWithNestedMapunionInMapFunctionBody() { - testTTL(STRING_TYPE, + testTTL( + getNativeStringType(), "mapunion(union(S, B)," - + "(x) => mapunion(union(S, N), " - + "(y) => cond(eq(x, y), x, BOT)))"); + + "(x) => mapunion(union(S, N), " + + "(y) => cond(eq(x, y), x, BOT)))"); } public void testTransformationWithObjectUseCase() { - testTTL(OBJECT_TYPE, + testTTL( + getNativeObjectType(), "mapunion(" - + "union(S, N, B, NULL, UNDEF, ARR)," - + "(x) => " - + "cond(eq(x, S), SO," - + "cond(eq(x, N), NO," - + "cond(eq(x, B), BO," - + "cond(eq(x, NULL), OBJ," - + "cond(eq(x, UNDEF), OBJ," - + "x ))))))"); + + "union(S, N, B, NULL, UNDEF, ARR)," + + "(x) => " + + "cond(eq(x, S), SO," + + "cond(eq(x, N), NO," + + "cond(eq(x, B), BO," + + "cond(eq(x, NULL), OBJ," + + "cond(eq(x, UNDEF), OBJ," + + "x ))))))"); } // none() is evaluated to bottom in TTL expressions, but if the overall expression evaluates // to bottom, we return unknown to the context. public void testTransformatioWithNoneType() { - testTTL(UNKNOWN_TYPE, "none()"); + testTTL(getNativeUnknownType(), "none()"); } // The conditional is true, so we follow the THEN branch, and the bottom result is returned // to the context as unknown. public void testTransformatioWithNoneTypeInConditional() { - testTTL(UNKNOWN_TYPE, "cond(eq(BOT, none()), none(), N)"); + testTTL(getNativeUnknownType(), "cond(eq(BOT, none()), none(), N)"); } public void testTransformatioWithNoneTypeInMapunionFilterString() { - testTTL(STRING_TYPE, - "mapunion(union(S, B, N), (x) => cond(eq(x, S), x, none()))"); + testTTL(getNativeStringType(), "mapunion(union(S, B, N), (x) => cond(eq(x, S), x, none()))"); } public void testTransformatioWithAllType() { - testTTL(ALL_TYPE, "all()"); + testTTL(getNativeAllType(), "all()"); } public void testTransformatioWithAllTypeInConditional() { - testTTL(ALL_TYPE, "cond(eq(TOP, all()), all(), N)"); + testTTL(getNativeAllType(), "cond(eq(TOP, all()), all(), N)"); } public void testTransformatioWithAllTypeMixUnion() { - testTTL(ALL_TYPE, - "mapunion(union(S, B, N), (x) => cond(eq(x, S), x, all()))"); + testTTL(getNativeAllType(), "mapunion(union(S, B, N), (x) => cond(eq(x, S), x, all()))"); } public void testTransformatioWithUnknownType() { - testTTL(UNKNOWN_TYPE, "unknown()"); + testTTL(getNativeUnknownType(), "unknown()"); } public void testTransformatioWithUnknownTypeInConditional() { - testTTL(NUMBER_TYPE, "cond(eq(UNK, unknown()), N, S)"); + testTTL(getNativeNumberType(), "cond(eq(UNK, unknown()), N, S)"); } public void testTransformatioWithUnknownTypeInMapunionStringToUnknown() { - testTTL(UNKNOWN_TYPE, - "mapunion(union(S, B, N), (x) => cond(eq(x, S), x, unknown()))"); + testTTL( + getNativeUnknownType(), "mapunion(union(S, B, N), (x) => cond(eq(x, S), x, unknown()))"); } public void testTransformationWithTemplatizedType() { - testTTL(type(ARRAY_TYPE, NUMBER_TYPE), "type('Array', 'number')"); + testTTL(type(getNativeArrayType(), getNativeNumberType()), "type('Array', 'number')"); } public void testTransformationWithTemplatizedType2() { - testTTL(type(ARRAY_TYPE, NUMBER_TYPE), "type(ARR, 'number')"); + testTTL(type(getNativeArrayType(), getNativeNumberType()), "type(ARR, 'number')"); } public void testTransformationWithTemplatizedType3() { - testTTL(type(ARRAY_TYPE, NUMBER_TYPE), "type(ARR, N)"); + testTTL(type(getNativeArrayType(), getNativeNumberType()), "type(ARR, N)"); } public void testTransformationWithTemplatizedTypeInvalidBaseType() { - testTTL(UNKNOWN_TYPE, "type('string', 'number')", + testTTL( + getNativeUnknownType(), + "type('string', 'number')", "The type string cannot be templatized"); } public void testTransformationWithTemplatizedTypeInvalidBaseType2() { - testTTL(UNKNOWN_TYPE, "type(S, 'number')", - "The type string cannot be templatized"); + testTTL(getNativeUnknownType(), "type(S, 'number')", "The type string cannot be templatized"); } public void testTransformationWithTemplatizedTypeInvalidBaseType3() { - testTTL(UNKNOWN_TYPE, "type('ArrayAlias', number)", + testTTL( + getNativeUnknownType(), + "type('ArrayAlias', number)", "The type Array cannot be templatized"); } public void testTransformationWithRawTypeOf() { - testTTL(ARRAY_TYPE, "rawTypeOf(type('Array', 'number'))"); + testTTL(getNativeArrayType(), "rawTypeOf(type('Array', 'number'))"); } public void testTransformationWithRawTypeOf2() { - testTTL(ARRAY_TYPE, "rawTypeOf(ARRNUM)"); + testTTL(getNativeArrayType(), "rawTypeOf(ARRNUM)"); } public void testTransformationWithNestedRawTypeOf() { - testTTL(ARRAY_TYPE, "rawTypeOf(type('Array', rawTypeOf(ARRNUM)))"); + testTTL(getNativeArrayType(), "rawTypeOf(type('Array', rawTypeOf(ARRNUM)))"); } public void testTransformationWithInvalidRawTypeOf() { - testTTL(UNKNOWN_TYPE, "rawTypeOf(N)", + testTTL( + getNativeUnknownType(), + "rawTypeOf(N)", "Expected templatized type in rawTypeOf found number"); } public void testTransformationWithTemplateTypeOf() { - testTTL(NUMBER_TYPE, "templateTypeOf(type('Array', 'number'), 0)"); + testTTL(getNativeNumberType(), "templateTypeOf(type('Array', 'number'), 0)"); } public void testTransformationWithTemplateTypeOf2() { - testTTL(NUMBER_TYPE, "templateTypeOf(ARRNUM, 0)"); + testTTL(getNativeNumberType(), "templateTypeOf(ARRNUM, 0)"); } public void testTransformationWithNestedTemplateTypeOf() { - testTTL(NUMBER_TYPE, - "templateTypeOf(" - + "templateTypeOf(type('Array', type('Array', 'number')), 0)," - + "0)"); + testTTL( + getNativeNumberType(), + "templateTypeOf(templateTypeOf(type('Array', type('Array', 'number')), 0), 0)"); } public void testTransformationWithInvalidTypeTemplateTypeOf() { - testTTL(UNKNOWN_TYPE, "templateTypeOf(N, 0)", + testTTL( + getNativeUnknownType(), + "templateTypeOf(N, 0)", "Expected templatized type in templateTypeOf found number"); } public void testTransformationWithInvalidIndexTemplateTypeOf() { - testTTL(UNKNOWN_TYPE, "templateTypeOf(ARRNUM, 2)", + testTTL( + getNativeUnknownType(), + "templateTypeOf(ARRNUM, 2)", "Index out of bounds in templateTypeOf: expected a number less than 1, found 2"); } public void testTransformationWithRecordType() { - testTTL(record("x", NUMBER_TYPE), - "record({x:'number'})"); + testTTL(record("x", getNativeNumberType()), "record({x:'number'})"); } public void testTransformationWithRecordType2() { - testTTL(record("0", NUMBER_TYPE), - "record({0:'number'})"); + testTTL(record("0", getNativeNumberType()), "record({0:'number'})"); } public void testTransformationWithRecordTypeMultipleProperties() { - testTTL(record("x", NUMBER_TYPE, "y", STRING_TYPE), + testTTL( + record("x", getNativeNumberType(), "y", getNativeStringType()), "record({x:'number', y:S})"); } public void testTransformationWithNestedRecordType() { - testTTL(record("x", record("z", BOOLEAN_TYPE), "y", STRING_TYPE), + testTTL( + record("x", record("z", getNativeBooleanType()), "y", getNativeStringType()), "record({x:record({z:B}), y:S})"); } public void testTransformationWithNestedRecordType2() { - testTTL(record("x", NUMBER_TYPE), - "record(record({x:N}))"); + testTTL(record("x", getNativeNumberType()), "record(record({x:N}))"); } public void testTransformationWithEmptyRecordType() { @@ -407,52 +413,58 @@ public void testTransformationWithEmptyRecordType() { } public void testTransformationWithMergeRecord() { - testTTL(record("x", NUMBER_TYPE, "y", STRING_TYPE, "z", BOOLEAN_TYPE), + testTTL( + record("x", getNativeNumberType(), "y", getNativeStringType(), "z", getNativeBooleanType()), "record({x:N}, {y:S}, {z:B})"); } public void testTransformationWithMergeDuplicatedRecords() { - testTTL(record("x", NUMBER_TYPE), - "record({x:N}, {x:N}, {x:N})"); + testTTL(record("x", getNativeNumberType()), "record({x:N}, {x:N}, {x:N})"); } public void testTransformationWithMergeRecordTypeWithEmpty() { - testTTL(record("x", NUMBER_TYPE), - "record({x:N}, {})"); + testTTL(record("x", getNativeNumberType()), "record({x:N}, {})"); } public void testTransformationWithInvalidRecordType() { - testTTL(UNKNOWN_TYPE, "record(N)", - "Expected a record type, found number"); + testTTL(getNativeUnknownType(), "record(N)", "Expected a record type, found number"); } public void testTransformationWithInvalidMergeRecordType() { - testTTL(UNKNOWN_TYPE, "record({x:N}, N)", - "Expected a record type, found number"); + testTTL(getNativeUnknownType(), "record({x:N}, N)", "Expected a record type, found number"); } public void testTransformationWithTTLTypeTransformationInFirstParamMapunion() { - testTTL(union(NUMBER_TYPE, STRING_TYPE), - "mapunion(templateTypeOf(type(ARR, union(N, S)), 0)," - + "(x) => x)"); + testTTL( + union(getNativeNumberType(), getNativeStringType()), + "mapunion(templateTypeOf(type(ARR, union(N, S)), 0), (x) => x)"); } public void testTransformationWithInvalidNestedMapunion() { - testTTL(UNKNOWN_TYPE, + testTTL( + getNativeUnknownType(), "mapunion(union(S, B)," - + "(x) => mapunion(union(S, N), " - + "(x) => cond(eq(x, x), x, BOT)))", + + "(x) => mapunion(union(S, N), " + + "(x) => cond(eq(x, x), x, BOT)))", "The variable x is already defined"); } public void testTransformationWithTTLRecordWithReference() { - testTTL(record("number", NUMBER_TYPE, "string", STRING_TYPE, - "boolean", BOOLEAN_TYPE), + testTTL( + record( + "number", + getNativeNumberType(), + "string", + getNativeStringType(), + "boolean", + getNativeBooleanType()), "record({[n]:N, [s]:S, [b]:B})"); } public void testTransformationWithTTLRecordWithInvalidReference() { - testTTL(UNKNOWN_TYPE, "record({[Foo]:N})", + testTTL( + getNativeUnknownType(), + "record({[Foo]:N})", "Expected a record type, found ?", "Reference to an unknown name variable Foo"); } @@ -461,7 +473,8 @@ public void testTransformationWithMaprecordMappingEverythingToString() { // {n:number, s:string, b:boolean} // is transformed to // {n:string, s:string, b:string} - testTTL(record("n", STRING_TYPE, "s", STRING_TYPE, "b", STRING_TYPE), + testTTL( + record("n", getNativeStringType(), "s", getNativeStringType(), "b", getNativeStringType()), "maprecord(REC, (k, v) => record({[k]:S}))"); } @@ -472,13 +485,14 @@ public void testTransformationWithMaprecordIdentity() { public void testTransformationWithMaprecordDeleteEverything() { // {n:number, s:string, b:boolean} - // is transformed to - // OBJECT_TYPE - testTTL(OBJECT_TYPE, "maprecord(REC, (k, v) => BOT)"); + // is transformed to object type + testTTL(getNativeObjectType(), "maprecord(REC, (k, v) => BOT)"); } public void testTransformationWithInvalidMaprecord() { - testTTL(UNKNOWN_TYPE, "maprecord(REC, (k, v) => 'number')", + testTTL( + getNativeUnknownType(), + "maprecord(REC, (k, v) => 'number')", "The body of a maprecord function must evaluate to a record type " + "or a no type, found number"); } @@ -487,29 +501,34 @@ public void testTransformationWithMaprecordFilterWithOnlyString() { // {n:number, s:string, b:boolean} // is transformed to // {s:string} - testTTL(record("s", STRING_TYPE), + testTTL( + record("s", getNativeStringType()), "maprecord(REC, (k, v) => cond(eq(v, S), record({[k]:v}), BOT))"); } public void testTransformationWithInvalidMaprecordFirstParam() { - testTTL(UNKNOWN_TYPE, "maprecord(N, (k, v) => BOT)", + testTTL( + getNativeUnknownType(), + "maprecord(N, (k, v) => BOT)", "The first parameter of a maprecord must be a record type, found number"); } public void testTransformationWithObjectInMaprecord() { - testTTL(OBJECT_TYPE, "maprecord(OBJ, (k, v) => record({[k]:v}))"); + testTTL(getNativeObjectType(), "maprecord(OBJ, (k, v) => record({[k]:v}))"); } public void testTransformationWithUnionInMaprecord() { - testTTL(UNKNOWN_TYPE, + testTTL( + getNativeUnknownType(), "maprecord(union(record({n:N}), S), (k, v) => record({[k]:v}))", "The first parameter of a maprecord must be a record type, " + "found (string|{n: number})"); } public void testTransformationWithUnionOfRecordsInMaprecord() { - testTTL(UNKNOWN_TYPE, "maprecord(union(record({n:N}), record({s:S})), " - + "(k, v) => record({[k]:v}))", + testTTL( + getNativeUnknownType(), + "maprecord(union(record({n:N}), record({s:S})), (k, v) => record({[k]:v}))", "The first parameter of a maprecord must be a record type, " + "found ({n: number}|{s: string})"); } @@ -518,182 +537,211 @@ public void testTransformationWithNestedRecordInMaprecordFilterOneLevelString() // {s:string, r:{s:string, b:boolean}} // is transformed to // {r:{s:string, b:boolean}} - testTTL(record("r", record("s", STRING_TYPE, "b", BOOLEAN_TYPE)), - "maprecord(NESTEDREC," - + "(k, v) => cond(eq(v, S), BOT, record({[k]:v})))"); + testTTL( + record("r", record("s", getNativeStringType(), "b", getNativeBooleanType())), + "maprecord(NESTEDREC, (k, v) => cond(eq(v, S), BOT, record({[k]:v})))"); } public void testTransformationWithNestedRecordInMaprecordFilterTwoLevelsString() { // {s:string, r:{s:string, b:boolean}} // is transformed to // {r:{b:boolean}} - testTTL(record("r", record("b", BOOLEAN_TYPE)), - "maprecord(NESTEDREC," - + "(k1, v1) => " - + "cond(sub(v1, 'Object'), " - + "maprecord(v1, (k2, v2) => " - + "cond(eq(v2, S), BOT, record({[k1]:record({[k2]:v2})})))," - + "cond(eq(v1, S), BOT, record({[k1]:v1}))))"); + testTTL( + record("r", record("b", getNativeBooleanType())), + lines( + "maprecord(NESTEDREC,", + " (k1, v1) => ", + " cond(sub(v1, 'Object'), ", + " maprecord(v1, (k2, v2) => ", + " cond(eq(v2, S), BOT, record({[k1]:record({[k2]:v2})}))),", + " cond(eq(v1, S), BOT, record({[k1]:v1}))))")); } public void testTransformationWithNestedIdentityOneLevel() { // {r:{n:number, s:string}} - testTTL(record("r", - record("b", BOOLEAN_TYPE, "s", STRING_TYPE)), - "maprecord(record({r:record({b:B, s:S})})," - + "(k1, v1) => " - + "maprecord(v1, " - + "(k2, v2) => " - + "record({[k1]:record({[k2]:v2})})))"); + testTTL( + record("r", record("b", getNativeBooleanType(), "s", getNativeStringType())), + lines( + "maprecord(record({r:record({b:B, s:S})}),", + " (k1, v1) => ", + " maprecord(v1, ", + " (k2, v2) => ", + " record({[k1]:record({[k2]:v2})})))")); } public void testTransformationWithNestedIdentityOneLevel2() { // {r:{n:number, s:string}} - testTTL(record("r", - record("b", BOOLEAN_TYPE, "s", STRING_TYPE)), - "maprecord(record({r:record({b:B, s:S})}),\n" - + "(k1, v1) =>\n" - + "record({[k1]:\n" - + "maprecord(v1, " - + "(k2, v2) => record({[k2]:v2}))}))"); + testTTL( + record("r", record("b", getNativeBooleanType(), "s", getNativeStringType())), + lines( + "maprecord(record({r:record({b:B, s:S})}),", + " (k1, v1) =>", + " record({[k1]:", + " maprecord(v1, ", + " (k2, v2) => record({[k2]:v2}))}))")); } public void testTransformationWithNestedIdentityTwoLevels() { // {r:{r2:{n:number, s:string}}} - testTTL(record("r", record("r2", - record("n", NUMBER_TYPE, "s", STRING_TYPE))), - "maprecord(record({r:record({r2:record({n:N, s:S})})})," - + "(k1, v1) => " - + "maprecord(v1, " - + "(k2, v2) => " - + "maprecord(v2, " - + "(k3, v3) =>" - + "record({[k1]:" - + "record({[k2]:" - + "record({[k3]:v3})})}))))"); + testTTL( + record("r", record("r2", record("n", getNativeNumberType(), "s", getNativeStringType()))), + lines( + "maprecord(record({r:record({r2:record({n:N, s:S})})}),", + " (k1, v1) => ", + " maprecord(v1, ", + " (k2, v2) => ", + " maprecord(v2, ", + " (k3, v3) =>", + " record({[k1]:", + " record({[k2]:", + " record({[k3]:v3})})}))))")); } public void testTransformationWithNestedIdentityTwoLevels2() { // {r:{r2:{n:number, s:string}}} - testTTL(record("r", record("r2", - record("n", NUMBER_TYPE, "s", STRING_TYPE))), - "maprecord(record({r:record({r2:record({n:N, s:S})})})," - + "(k1, v1) => " - + "record({[k1]:" - + "maprecord(v1, " - + "(k2, v2) => " - + "record({[k2]:" - + "maprecord(v2, " - + "(k3, v3) =>" - + "record({[k3]:v3}))}))}))"); + testTTL( + record("r", record("r2", record("n", getNativeNumberType(), "s", getNativeStringType()))), + lines( + "maprecord(record({r:record({r2:record({n:N, s:S})})}),", + " (k1, v1) => ", + " record({[k1]:", + " maprecord(v1, ", + " (k2, v2) => ", + " record({[k2]:", + " maprecord(v2, ", + " (k3, v3) =>", + " record({[k3]:v3}))}))}))")); } public void testTransformationWithNestedIdentityThreeLevels() { // {r:{r2:{r3:{n:number, s:string}}}} - testTTL(record("r", record("r2", record("r3", - record("n", NUMBER_TYPE, "s", STRING_TYPE)))), - "maprecord(record({r:record({r2:record({r3:record({n:N, s:S})})})})," - + "(k1, v1) => " - + "maprecord(v1, " - + "(k2, v2) => " - + "maprecord(v2, " - + "(k3, v3) =>" - + "maprecord(v3," - + "(k4, v4) =>" - + "record({[k1]:" - + "record({[k2]:" - + "record({[k3]:" - + "record({[k4]:v4})})})})))))"); + testTTL( + record( + "r", + record( + "r2", + record("r3", record("n", getNativeNumberType(), "s", getNativeStringType())))), + lines( + "maprecord(record({r:record({r2:record({r3:record({n:N, s:S})})})}),", + " (k1, v1) => ", + " maprecord(v1, ", + " (k2, v2) => ", + " maprecord(v2, ", + " (k3, v3) =>", + " maprecord(v3,", + " (k4, v4) =>", + " record({[k1]:", + " record({[k2]:", + " record({[k3]:", + " record({[k4]:v4})})})})))))")); } public void testTransformationWithNestedIdentityThreeLevels2() { // {r:{r2:{r3:{n:number, s:string}}}} - testTTL(record("r", record("r2", record("r3", - record("n", NUMBER_TYPE, "s", STRING_TYPE)))), - "maprecord(record({r:record({r2:record({r3:record({n:N, s:S})})})})," - + "(k1, v1) => " - + "record({[k1]:" - + "maprecord(v1, " - + "(k2, v2) => " - + "record({[k2]:" - + "maprecord(v2, " - + "(k3, v3) =>" - + "record({[k3]:" - + "maprecord(v3," - + "(k4, v4) =>" - + "record({[k4]:v4}))}))}))}))"); + testTTL( + record( + "r", + record( + "r2", + record("r3", record("n", getNativeNumberType(), "s", getNativeStringType())))), + lines( + "maprecord(record({r:record({r2:record({r3:record({n:N, s:S})})})}),", + " (k1, v1) => ", + " record({[k1]:", + " maprecord(v1, ", + " (k2, v2) => ", + " record({[k2]:", + " maprecord(v2, ", + " (k3, v3) =>", + " record({[k3]:", + " maprecord(v3,", + " (k4, v4) =>", + " record({[k4]:v4}))}))}))}))")); } public void testTransformationWithNestedRecordDeleteLevelTwoAndThree() { // {r:{r2:{r3:{n:number, s:string}}}} // is transformed into // {r:{n:number, s:string}} - testTTL(record("r", record("n", NUMBER_TYPE, "s", STRING_TYPE)), - "maprecord(record({r:record({r2:record({r3:record({n:N, s:S})})})})," - + "(k1, v1) => " - + "maprecord(v1, " - + "(k2, v2) => " - + "maprecord(v2, " - + "(k3, v3) =>" - + "maprecord(v3," - + "(k4, v4) =>" - + "record({[k1]:" - + "record({[k4]:v4})})))))"); + testTTL( + record("r", record("n", getNativeNumberType(), "s", getNativeStringType())), + lines( + "maprecord(record({r:record({r2:record({r3:record({n:N, s:S})})})}),", + " (k1, v1) => ", + " maprecord(v1, ", + " (k2, v2) => ", + " maprecord(v2, ", + " (k3, v3) =>", + " maprecord(v3,", + " (k4, v4) =>", + " record({[k1]:", + " record({[k4]:v4})})))))")); } public void testTransformationWithNestedRecordDeleteLevelTwoAndThree2() { // {r:{r2:{r3:{n:number, s:string}}}} // is transformed into // {r:{n:number, s:string}} - testTTL(record("r", record("n", NUMBER_TYPE, "s", STRING_TYPE)), - "maprecord(record({r:record({r2:record({r3:record({n:N, s:S})})})})," - + "(k1, v1) => " - + "record({[k1]:" - + "maprecord(v1, " - + "(k2, v2) => " - + "maprecord(v2, " - + "(k3, v3) =>" - + "maprecord(v3," - + "(k4, v4) =>" - + "record({[k4]:v4}))))}))"); + testTTL( + record("r", record("n", getNativeNumberType(), "s", getNativeStringType())), + lines( + "maprecord(record({r:record({r2:record({r3:record({n:N, s:S})})})}),", + " (k1, v1) => ", + " record({[k1]:", + " maprecord(v1, ", + " (k2, v2) => ", + " maprecord(v2, ", + " (k3, v3) =>", + " maprecord(v3,", + " (k4, v4) =>", + " record({[k4]:v4}))))}))")); } public void testTransformationWithNestedRecordCollapsePropertiesToRecord() { // {a:Array, b:{n:number}} // is transformed to // {foo:{n:number}} - testTTL(record("foo", record("n", NUMBER_TYPE)), - "maprecord(record({a:ARR, b:record({n:N})})," - + "(k, v) => record({foo:v}))"); + testTTL( + record("foo", record("n", getNativeNumberType())), + "maprecord(record({a:ARR, b:record({n:N})}), (k, v) => record({foo:v}))"); } public void testTransformationWithNestedRecordCollapsePropertiesToType() { // {a:{n:number}, b:Array} // is transformed to // {foo:Array} - testTTL(record("foo", ARRAY_TYPE), - "maprecord(record({a:record({n:N}), b:ARR})," - + "(k, v) => record({foo:v}))"); + testTTL( + record("foo", getNativeArrayType()), + "maprecord(record({a:record({n:N}), b:ARR}), (k, v) => record({foo:v}))"); } public void testTransformationWithNestedRecordCollapsePropertiesJoinRecords() { // {a:{n:number}, b:{s:Array}} // is transformed to // {foo:{n:number, s:Array}} - testTTL(record("foo", record("n", NUMBER_TYPE, "s", ARRAY_TYPE)), - "maprecord(record({a:record({n:N}), b:record({s:ARR})})," - + "(k, v) => record({foo:v}))"); + testTTL( + record("foo", record("n", getNativeNumberType(), "s", getNativeArrayType())), + "maprecord(record({a:record({n:N}), b:record({s:ARR})}), (k, v) => record({foo:v}))"); } public void testTransformationWithNestedRecordCollapsePropertiesJoinRecords2() { // {a:{n:number, {x:number}}, b:{s:Array, {y:number}}} // is transformed to // {foo:{n:number, s:Array, r:{x:number, y:number}}} - testTTL(record("foo", record("n", NUMBER_TYPE, "s", ARRAY_TYPE, - "r", record("x", NUMBER_TYPE, "y", NUMBER_TYPE))), - "maprecord(record({a:record({n:N, r:record({x:N})}), " - + "b:record({s:ARR, r:record({y:N})})})," - + "(k, v) => record({foo:v}))"); + testTTL( + record( + "foo", + record( + "n", + getNativeNumberType(), + "s", + getNativeArrayType(), + "r", + record("x", getNativeNumberType(), "y", getNativeNumberType()))), + lines( + "maprecord(", + " record({a:record({n:N, r:record({x:N})}), b:record({s:ARR, r:record({y:N})})}),", + " (k, v) => record({foo:v}))")); } public void testTransformationWithAsynchUseCase() { @@ -701,170 +749,167 @@ public void testTransformationWithAsynchUseCase() { // {service:Array} // is transformed to // {service:number} - testTTL(record("service", NUMBER_TYPE), - "cond(sub(ASYNCH, 'Object'),\n" - + "maprecord(ASYNCH, \n" - + "(k, v) => cond(eq(rawTypeOf(v), 'Array'),\n" - + "record({[k]:templateTypeOf(v, 0)}),\n" - + "record({[k]:'undefined'})) " - + "),\n" - + "ASYNCH)"); + testTTL( + record("service", getNativeNumberType()), + lines( + "cond(", + " sub(ASYNCH, 'Object'),", + " maprecord(", + " ASYNCH,", + " (k, v) =>", + " cond(", + " eq(rawTypeOf(v), 'Array'),", + " record({[k]:templateTypeOf(v, 0)}),", + " record({[k]:'undefined'}))),", + " ASYNCH)")); } public void testTransformationWithInvalidNestedMaprecord() { - testTTL(UNKNOWN_TYPE, + testTTL( + getNativeUnknownType(), "maprecord(NESTEDREC, (k, v) => maprecord(v, (k, v) => BOT))", "The variable k is already defined"); - } public void testTransformationWithMaprecordAndStringEquivalence() { - testTTL(record("bool", NUMBER_TYPE, "str", STRING_TYPE), + testTTL( + record("bool", getNativeNumberType(), "str", getNativeStringType()), "maprecord(record({bool:B, str:S})," - + "(k, v) => record({[k]:cond(streq(k, 'bool'), N, v)}))"); + + "(k, v) => record({[k]:cond(streq(k, 'bool'), N, v)}))"); } public void testTransformationWithTypeOfVar() { - testTTL(NUMBER_TYPE, "typeOfVar('n')"); + testTTL(getNativeNumberType(), "typeOfVar('n')"); } public void testTransformationWithUnknownTypeOfVar() { - testTTL(UNKNOWN_TYPE, "typeOfVar('foo')", - "Variable foo is undefined in the scope"); + testTTL(getNativeUnknownType(), "typeOfVar('foo')", "Variable foo is undefined in the scope"); } public void testTransformationWithTrueIsConstructorConditional() { - testTTL(STRING_TYPE, "cond(isCtor(typeOfVar('Bar')), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(isCtor(typeOfVar('Bar')), 'string', 'number')"); } public void testTransformationWithFalseIsConstructorConditional() { - testTTL(NUMBER_TYPE, "cond(isCtor(N), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(isCtor(N), 'string', 'number')"); } public void testTransformationWithTrueIsTemplatizedConditional() { - testTTL(STRING_TYPE, "cond(isTemplatized(type(ARR, N)), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(isTemplatized(type(ARR, N)), 'string', 'number')"); } public void testTransformationWithFalseIsTemplatizedConditional() { - testTTL(NUMBER_TYPE, "cond(isTemplatized(ARR), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(isTemplatized(ARR), 'string', 'number')"); } public void testTransformationWithTrueIsRecordConditional() { - testTTL(STRING_TYPE, "cond(isRecord(REC), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(isRecord(REC), 'string', 'number')"); } public void testTransformationWithFalseIsRecordConditional() { - testTTL(NUMBER_TYPE, "cond(isRecord(N), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(isRecord(N), 'string', 'number')"); } public void testTransformationWithTrueIsDefinedConditional() { - testTTL(STRING_TYPE, "cond(isDefined(N), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(isDefined(N), 'string', 'number')"); } public void testTransformationWithFalseIsDefinedConditional() { - testTTL(NUMBER_TYPE, "cond(isDefined(Foo), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(isDefined(Foo), 'string', 'number')"); } public void testTransformationWithTrueIsUnknownConditional() { - testTTL(STRING_TYPE, "cond(isUnknown(UNK), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(isUnknown(UNK), 'string', 'number')"); } public void testTransformationWithTrueIsUnknownConditional2() { - testTTL(STRING_TYPE, "cond(isUnknown(CHKUNK), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(isUnknown(CHKUNK), 'string', 'number')"); } public void testTransformationWithFalseIsUnknownConditional() { - testTTL(NUMBER_TYPE, "cond(isUnknown(N), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(isUnknown(N), 'string', 'number')"); } public void testTransformationWithTrueAndConditional() { - testTTL(STRING_TYPE, - "cond(isDefined(N) && isDefined(N), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(isDefined(N) && isDefined(N), 'string', 'number')"); } public void testTransformationWithFalseAndConditional() { - testTTL(NUMBER_TYPE, - "cond(isDefined(N) && isDefined(Foo), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(isDefined(N) && isDefined(Foo), 'string', 'number')"); } public void testTransformationWithFalseAndConditional2() { - testTTL(NUMBER_TYPE, - "cond(isDefined(Foo) && isDefined(N), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(isDefined(Foo) && isDefined(N), 'string', 'number')"); } public void testTransformationWithFalseAndConditional3() { - testTTL(NUMBER_TYPE, - "cond(isDefined(Foo) && isDefined(Foo), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(isDefined(Foo) && isDefined(Foo), 'string', 'number')"); } public void testTransformationWithTrueOrConditional() { - testTTL(STRING_TYPE, - "cond(isDefined(N) || isDefined(N), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(isDefined(N) || isDefined(N), 'string', 'number')"); } public void testTransformationWithTrueOrConditional2() { - testTTL(STRING_TYPE, - "cond(isDefined(Foo) || isDefined(N), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(isDefined(Foo) || isDefined(N), 'string', 'number')"); } public void testTransformationWithTrueOrConditional3() { - testTTL(STRING_TYPE, - "cond(isDefined(N) || isDefined(Foo), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(isDefined(N) || isDefined(Foo), 'string', 'number')"); } public void testTransformationWithFalseOrConditional() { - testTTL(NUMBER_TYPE, - "cond(isDefined(Foo) || isDefined(Foo), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(isDefined(Foo) || isDefined(Foo), 'string', 'number')"); } public void testTransformationWithTrueNotConditional3() { - testTTL(STRING_TYPE, - "cond(!isDefined(Foo), 'string', 'number')"); + testTTL(getNativeStringType(), "cond(!isDefined(Foo), 'string', 'number')"); } public void testTransformationWithFalseNotConditional() { - testTTL(NUMBER_TYPE, - "cond(!isDefined(N), 'string', 'number')"); + testTTL(getNativeNumberType(), "cond(!isDefined(N), 'string', 'number')"); } public void testTransformationWithInstanceOf() { - testTTL(NUMBER_OBJECT_TYPE, "instanceOf(typeOfVar('Number'))"); + testTTL(getNativeNumberObjectType(), "instanceOf(typeOfVar('Number'))"); } public void testTransformationWithInvalidInstanceOf() { - testTTL(UNKNOWN_TYPE, "instanceOf(N)", - "Expected a constructor type, found number"); + testTTL(getNativeUnknownType(), "instanceOf(N)", "Expected a constructor type, found number"); } public void testTransformationWithInvalidInstanceOf2() { - testTTL(UNKNOWN_TYPE, "instanceOf(foo)", + testTTL( + getNativeUnknownType(), + "instanceOf(foo)", "Expected a constructor type, found Unknown", "Reference to an unknown type variable foo"); } public void testTransformationWithTypeExpr() { - testTTL(NUMBER_TYPE, "typeExpr('number')"); + testTTL(getNativeNumberType(), "typeExpr('number')"); } public void testParserWithTTLNativeTypeExprUnion() { - testTTL(union(NUMBER_TYPE, BOOLEAN_TYPE), "typeExpr('number|boolean')"); + testTTL(union(getNativeNumberType(), getNativeBooleanType()), "typeExpr('number|boolean')"); } public void testParserWithTTLNativeTypeExprRecord() { - testTTL(record("foo", NUMBER_TYPE, "bar", BOOLEAN_TYPE), + testTTL( + record("foo", getNativeNumberType(), "bar", getNativeBooleanType()), "typeExpr('{foo:number, bar:boolean}')"); } public void testParserWithTTLNativeTypeExprNullable() { - testTTL(union(NUMBER_TYPE, NULL_TYPE), "typeExpr('?number')"); + testTTL(union(getNativeNumberType(), getNativeNullType()), "typeExpr('?number')"); } public void testParserWithTTLNativeTypeExprNonNullable() { - testTTL(NUMBER_TYPE, "typeExpr('!number')"); + testTTL(getNativeNumberType(), "typeExpr('!number')"); } public void testTransformationPrintType() { - testTTL(NUMBER_TYPE, "printType('Test message: ', N)"); + testTTL(getNativeNumberType(), "printType('Test message: ', N)"); } public void testTransformationPrintType2() { @@ -872,46 +917,52 @@ public void testTransformationPrintType2() { } public void testTransformationPropType() { - testTTL(NUMBER_TYPE, "propType('a', record({a:N, b:record({x:B})}))"); + testTTL(getNativeNumberType(), "propType('a', record({a:N, b:record({x:B})}))"); } public void testTransformationPropType2() { - testTTL(record("x", BOOLEAN_TYPE), - "propType('b', record({a:N, b:record({x:B})}))"); + testTTL(record("x", getNativeBooleanType()), "propType('b', record({a:N, b:record({x:B})}))"); } public void testTransformationPropTypeNotFound() { - testTTL(UNKNOWN_TYPE, "propType('c', record({a:N, b:record({x:B})}))"); + testTTL(getNativeUnknownType(), "propType('c', record({a:N, b:record({x:B})}))"); } public void testTransformationPropTypeInvalid() { - testTTL(UNKNOWN_TYPE, "propType('c', N)", - "Expected object type, found number"); + testTTL(getNativeUnknownType(), "propType('c', N)", "Expected object type, found number"); } public void testTransformationInstanceObjectToRecord() { - testTTL(OBJECT_TYPE, "record(type(OBJ, N))"); + testTTL(getNativeObjectType(), "record(type(OBJ, N))"); } public void testTransformationInstanceObjectToRecord2() { - testTTL(record("length", NUMBER_TYPE), "record(type(ARR, N))"); + // TODO(bradfordcsmith): Define Array.prototype.length using externs instead. + getNativeArrayType() + .defineDeclaredProperty("length", getNativeNumberType(), /* propertyNode */ null); + testTTL(record("length", getNativeNumberType()), "record(type(ARR, N))"); } public void testTransformationInstanceObjectToRecordInvalid() { - testTTL(UNKNOWN_TYPE, "record(union(OBJ, NULL))", + testTTL( + getNativeUnknownType(), + "record(union(OBJ, NULL))", "Expected a record type, found (Object|null)"); } private void initRecordTypeTests() { // {n:number, s:string, b:boolean} - recordTypeTest = record("n", NUMBER_TYPE, "s", STRING_TYPE, - "b", BOOLEAN_TYPE); + recordTypeTest = + record("n", getNativeNumberType(), "s", getNativeStringType(), "b", getNativeBooleanType()); // {n:number, r:{s:string, b:boolean}} - nestedRecordTypeTest = record("s", STRING_TYPE, - "r", record("s", STRING_TYPE, "b", BOOLEAN_TYPE)); + nestedRecordTypeTest = + record( + "s", + getNativeStringType(), + "r", + record("s", getNativeStringType(), "b", getNativeBooleanType())); // {service:Array} - asynchRecord = record("service", type(ARRAY_TYPE, NUMBER_TYPE)); - + asynchRecord = record("service", type(getNativeArrayType(), getNativeNumberType())); } private JSType union(JSType... variants) {