diff --git a/src/com/google/javascript/jscomp/DiagnosticGroups.java b/src/com/google/javascript/jscomp/DiagnosticGroups.java index b50d150371e..994198951f7 100644 --- a/src/com/google/javascript/jscomp/DiagnosticGroups.java +++ b/src/com/google/javascript/jscomp/DiagnosticGroups.java @@ -355,7 +355,7 @@ public DiagnosticGroup forName(String name) { // NewTypeInference.INEXISTENT_PROPERTY, // NewTypeInference.INVALID_ARGUMENT_TYPE, // NewTypeInference.INVALID_CAST, -// NewTypeInference.INVALID_INDEX_TYPE, + NewTypeInference.INVALID_INDEX_TYPE, NewTypeInference.INVALID_INFERRED_RETURN_TYPE, NewTypeInference.INVALID_OBJLIT_PROPERTY_TYPE, // NewTypeInference.INVALID_OPERAND_TYPE, diff --git a/src/com/google/javascript/jscomp/NewTypeInference.java b/src/com/google/javascript/jscomp/NewTypeInference.java index db788b3451c..83bb1dc7fda 100644 --- a/src/com/google/javascript/jscomp/NewTypeInference.java +++ b/src/com/google/javascript/jscomp/NewTypeInference.java @@ -2978,8 +2978,7 @@ private boolean mayWarnAboutInexistentProp(Node propAccessNode, } if (recvType.isUnknown() || recvType.isTrueOrTruthy() || recvType.isLoose() - || (allowPropertyOnSubtypes - && (recvType.mayContainUnknownObject() || recvType.isIObject()))) { + || allowPropertyOnSubtypes && recvType.mayContainUnknownObject()) { if (symbolTable.isPropertyDefined(pname)) { return false; } diff --git a/src/com/google/javascript/jscomp/newtypes/JSType.java b/src/com/google/javascript/jscomp/newtypes/JSType.java index 6476fac7e10..f3e934f0699 100644 --- a/src/com/google/javascript/jscomp/newtypes/JSType.java +++ b/src/com/google/javascript/jscomp/newtypes/JSType.java @@ -1282,11 +1282,6 @@ public boolean isNonClassyObject() { return nt != null && !nt.isClassy(); } - public boolean isIObject() { - NominalType nt = getNominalTypeIfSingletonObj(); - return nt != null && nt.isIObject(); - } - public boolean isInterfaceDefinition() { FunctionType ft = getFunTypeIfSingletonObj(); return ft != null && ft.isInterfaceDefinition(); diff --git a/src/com/google/javascript/jscomp/newtypes/JSTypeCreatorFromJSDoc.java b/src/com/google/javascript/jscomp/newtypes/JSTypeCreatorFromJSDoc.java index c9fe01a6cf7..c7962428d0a 100644 --- a/src/com/google/javascript/jscomp/newtypes/JSTypeCreatorFromJSDoc.java +++ b/src/com/google/javascript/jscomp/newtypes/JSTypeCreatorFromJSDoc.java @@ -414,22 +414,12 @@ private JSType getNamedTypeHelper( case "Function": checkInvalidGenericsInstantiation(n); return maybeMakeNullable(this.commonTypes.qmarkFunction()); - case "Object": { - JSType result; - if (n.hasChildren()) { - // We consider a parameterized Object<...> as an alias of IObject. - NominalType iobject = this.commonTypes.getIObjectType(); - if (iobject == null) { - // Can happen when using old externs. - return this.commonTypes.UNKNOWN; - } - result = getNominalTypeHelper( - iobject.getRawNominalType(), n, registry, outerTypeParameters); - } else { - result = this.commonTypes.getTopObject(); - } - return maybeMakeNullable(result); - } + case "Object": + // We don't generally handle parameterized Object<...>, but we want to + // at least not warn about inexistent properties on it, so we type it + // as @dict. + return maybeMakeNullable(n.hasChildren() + ? this.commonTypes.getTopDict() : this.commonTypes.getTopObject()); default: return lookupTypeByName(typeName, n, registry, outerTypeParameters); } @@ -544,13 +534,14 @@ private JSType getNominalTypeHelper(RawNominalType rawType, Node n, ImmutableList.Builder typeList = ImmutableList.builder(); if (n.hasChildren()) { // Compute instantiation of polymorphic class/interface. - Preconditions.checkState(n.getFirstChild().isNormalBlock(), n); + Preconditions.checkState(n.getFirstChild().isBlock(), n); for (Node child : n.getFirstChild().children()) { - typeList.add(getTypeFromCommentHelper(child, registry, outerTypeParameters)); + typeList.add( + getTypeFromCommentHelper(child, registry, outerTypeParameters)); } } - List typeArguments = typeList.build(); - List typeParameters = rawType.getTypeParameters(); + ImmutableList typeArguments = typeList.build(); + ImmutableList typeParameters = rawType.getTypeParameters(); int typeArgsSize = typeArguments.size(); int typeParamsSize = typeParameters.size(); if (typeArgsSize != typeParamsSize) { @@ -564,15 +555,16 @@ private JSType getNominalTypeHelper(RawNominalType rawType, Node n, String.valueOf(typeParamsSize), String.valueOf(typeArgsSize))); } - typeArguments = fixLengthOfTypeList(typeParameters.size(), typeArguments); - NominalType instantiated = uninstantiated.instantiateGenerics(typeArguments); - return maybeMakeNullable(JSType.fromObjectType(ObjectType.fromNominalType(instantiated))); + return maybeMakeNullable(JSType.fromObjectType(ObjectType.fromNominalType( + uninstantiated.instantiateGenerics( + fixLengthOfTypeList(typeParameters.size(), typeArguments))))); } return maybeMakeNullable(JSType.fromObjectType(ObjectType.fromNominalType( uninstantiated.instantiateGenerics(typeArguments)))); } - private List fixLengthOfTypeList(int desiredLength, List typeList) { + private List fixLengthOfTypeList( + int desiredLength, List typeList) { int length = typeList.size(); if (length == desiredLength) { return typeList; diff --git a/src/com/google/javascript/jscomp/newtypes/ObjectType.java b/src/com/google/javascript/jscomp/newtypes/ObjectType.java index ec2bcf0070f..c769f93ede5 100644 --- a/src/com/google/javascript/jscomp/newtypes/ObjectType.java +++ b/src/com/google/javascript/jscomp/newtypes/ObjectType.java @@ -682,7 +682,7 @@ private boolean compareRecordTypeToIObject( if (keyType.isNumber() && Ints.tryParse(pname) == null) { return false; } - if (!keyType.isNumber() && !keyType.isString() && !keyType.isUnknown()) { + if (!keyType.isNumber() && !keyType.isString()) { return false; } if (!ptype.isSubtypeOf(valueType, subSuperMap)) { diff --git a/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java b/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java index f2479526a30..7779d1537cf 100644 --- a/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java +++ b/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java @@ -2017,13 +2017,12 @@ private Node parseTopLevelTypeExpression(JsDocToken token) { * TypeExpressionList := TopLevelTypeExpression * | TopLevelTypeExpression ',' TypeExpressionList */ - private Node parseTypeExpressionList(String typeName, JsDocToken token) { + private Node parseTypeExpressionList(JsDocToken token) { Node typeExpr = parseTopLevelTypeExpression(token); if (typeExpr == null) { return null; } Node typeList = IR.block(); - int numTypeExprs = 1; typeList.addChildToBack(typeExpr); while (match(JsDocToken.COMMA)) { next(); @@ -2032,13 +2031,8 @@ private Node parseTypeExpressionList(String typeName, JsDocToken token) { if (typeExpr == null) { return null; } - numTypeExprs++; typeList.addChildToBack(typeExpr); } - if (typeName.equals("Object") && numTypeExprs == 1) { - // Unlike other generic types, Object means Object, not Object. - typeList.addChildToFront(newNode(Token.QMARK)); - } return typeList; } @@ -2167,7 +2161,7 @@ private Node parseTypeName(JsDocToken token) { if (match(JsDocToken.LEFT_ANGLE)) { next(); skipEOLs(); - Node memberType = parseTypeExpressionList(typeName, next()); + Node memberType = parseTypeExpressionList(next()); if (memberType != null) { typeNameNode.addChildToFront(memberType); diff --git a/test/com/google/javascript/jscomp/Es6InlineTypesNotYetParsedTest.java b/test/com/google/javascript/jscomp/Es6InlineTypesNotYetParsedTest.java index 837318976f4..5556356df92 100644 --- a/test/com/google/javascript/jscomp/Es6InlineTypesNotYetParsedTest.java +++ b/test/com/google/javascript/jscomp/Es6InlineTypesNotYetParsedTest.java @@ -115,7 +115,7 @@ public void testParameterizedType() { assertSource("/** @type {Object.} */ var s;") .transpilesTo("var s: Object;"); assertSource("/** @type {Object.} */ var s;") - .transpilesTo("var s: Object;"); + .transpilesTo("var s: Object;"); } public void testParameterizedTypeWithVoid() throws Exception { diff --git a/test/com/google/javascript/jscomp/NewTypeInferenceTest.java b/test/com/google/javascript/jscomp/NewTypeInferenceTest.java index 7c98d929767..8fc7325d468 100644 --- a/test/com/google/javascript/jscomp/NewTypeInferenceTest.java +++ b/test/com/google/javascript/jscomp/NewTypeInferenceTest.java @@ -16350,7 +16350,7 @@ public void testRecursiveStructuralInterfaces() { "}")); } - public void testIObjectBracketAccesses() { + public void testIObjectAccesses() { typeCheck(LINE_JOINER.join( "function f(/** !IObject */ x) {", " return x['asdf'];", @@ -16445,37 +16445,6 @@ public void testIObjectBracketAccesses() { NewTypeInference.MISTYPED_ASSIGN_RHS); } - // A dot access on IObject is not typed as V. - // It is either declared separately with its own type (eg, when Foo implements IObject and - // has some extra properties), or it is a type error. - public void testIObjectDotAccesses() { - typeCheck(LINE_JOINER.join( - "function f(/** !IObject */ x) {", - " return x.hasOwnProperty('test');", - "}")); - - typeCheck(LINE_JOINER.join( - "function g(x) {", - " x.foobar = 123;", - "}", - "function f(/** !IObject */ x) {", - " return x.foobar;", - "}"), - NewTypeInference.INEXISTENT_PROPERTY); - - typeCheck(LINE_JOINER.join( - "/** @constructor */", - "function Foo() {", - " this.foobar = 123;", - "}", - "function f(/** !IObject */ x) {", - " return x.foobar;", - "}"), - NewTypeInference.INEXISTENT_PROPERTY); - - typeCheck("var /** !IObject */ x = { 'abs': '', '%': ''};"); - } - public void testIObjectSubtyping() { typeCheck(LINE_JOINER.join( "function f(/** !IObject */ x) {}", @@ -17961,15 +17930,6 @@ public void testPropertyCheckingCompatibility() { " this.prop = 123;", "}")); - typeCheck(LINE_JOINER.join( - "function f(/** !IObject */ x) {", - " return x.prop + 1;", - "}", - "/** @constructor */", - "function Bar() {", - " this.prop = 123;", - "}")); - typeCheck(LINE_JOINER.join( "/** @constructor */", "function Foo() {}", @@ -18683,63 +18643,4 @@ public void testConstInferenceDependsOnOrderOfScopeTraversing() { " }", "}")); } - - // We currently consider Object to be the same as IObject. - // Since we may change that in the future, they are tested separately. - public void testParameterizedObject() { - typeCheck(LINE_JOINER.join( - "function f(/** !Object */ x) {", - " return x.hasOwnProperty('test');", - "}")); - - typeCheck(LINE_JOINER.join( - "function g(x) {", - " x.foobar = 123;", - "}", - "function f(/** !Object */ x) {", - " return x.foobar;", - "}"), - NewTypeInference.INEXISTENT_PROPERTY); - - typeCheck(LINE_JOINER.join( - "/** @constructor */", - "function Foo() {", - " this.foobar = 123;", - "}", - "function f(/** !Object */ x) {", - " return x.foobar;", - "}"), - NewTypeInference.INEXISTENT_PROPERTY); - - typeCheck("var /** !Object */ x = { 'abs': '', '%': ''};"); - - typeCheck(LINE_JOINER.join( - "function f(/** !Object */ x) {", - " return x['asdf'];", - "}"), - NewTypeInference.INVALID_INDEX_TYPE); - - typeCheck(LINE_JOINER.join( - "function f(/** !Object */ x) {", - " x['asdf'] = 123;", - "}"), - NewTypeInference.INVALID_INDEX_TYPE); - - typeCheck(LINE_JOINER.join( - "function f(/** !Object */ x, /** number */ i) {", - " x[i] - 123;", - "}"), - NewTypeInference.INVALID_OPERAND_TYPE); - - typeCheck(LINE_JOINER.join( - "function f(/** !Object */ x) {", - " var /** string */ s = x['asdf'];", - "}"), - NewTypeInference.MISTYPED_ASSIGN_RHS); - - typeCheck(LINE_JOINER.join( - "function f(/** !Object */ x) {", - " return x[{a: 123}] + x['sadf'];", - "}")); - } }