Skip to content

Commit

Permalink
Roll forward of 20b4233
Browse files Browse the repository at this point in the history
NEW: added two more unit tests. No code changes; the fix was in the originally broken target.

Automated g4 rollback of changelist 184218181.

*** Reason for rollback ***

Fixed jscontainer.

*** Original change description ***

Fix bug in the old type checker where a stub method definition causes loss of type checking.

***

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=184853474
  • Loading branch information
dimvar authored and blickly committed Feb 7, 2018
1 parent f7ef9e8 commit 80e120b
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 3 deletions.
24 changes: 21 additions & 3 deletions src/com/google/javascript/jscomp/TypedScopeCreator.java
Expand Up @@ -1806,6 +1806,22 @@ private ObjectType getObjectSlot(String slotName) {
return null;
}

/**
* When a class has a stub for a property, and the property exists on a super interface,
* use that type.
*/
private JSType getInheritedInterfacePropertyType(ObjectType obj, String propName) {
if (obj != null && obj.isPrototypeObject()) {
FunctionType f = obj.getOwnerFunction();
for (ObjectType i : f.getImplementedInterfaces()) {
if (i.hasProperty(propName)) {
return i.getPropertyType(propName);
}
}
}
return null;
}

/**
* Resolve any stub declarations to unknown types if we could not
* find types for them during traversal.
Expand All @@ -1826,17 +1842,19 @@ void resolveStubDeclarations() {
// If we see a stub property, make sure to register this property
// in the type registry.
ObjectType ownerType = getObjectSlot(ownerName);
defineSlot(n, parent, unknownType, true);
JSType inheritedType = getInheritedInterfacePropertyType(ownerType, propName);
JSType stubType = inheritedType == null ? unknownType : inheritedType;
defineSlot(n, parent, stubType, true);

if (ownerType != null &&
(isExtern || ownerType.isFunctionPrototypeType())) {
// If this is a stub for a prototype, just declare it
// as an unknown type. These are seen often in externs.
ownerType.defineInferredProperty(
propName, unknownType, n);
propName, stubType, n);
} else {
typeRegistry.registerPropertyOnType(
propName, ownerType == null ? unknownType : ownerType);
propName, ownerType == null ? stubType : ownerType);
}
}
}
Expand Down
72 changes: 72 additions & 0 deletions test/com/google/javascript/jscomp/TypeCheckTest.java
Expand Up @@ -2951,6 +2951,78 @@ public void testStubFunctionDeclaration10() {
"function(number): number");
}


public void testStubMethodDeclarationDoesntBlockTypechecking_1() {
testTypes(
lines(
"/** @interface */",
"function Foo() {}",
"/** @return {number} */",
"Foo.prototype.method = function() {};",
"/**",
" * @constructor",
" * @implements {Foo}",
" */",
"function Bar() {}",
"Bar.prototype.method;",
"var /** null */ n = (new Bar).method();"),
lines(
"initializing variable",
"found : number",
"required: null"));
}

public void testStubMethodDeclarationDoesntBlockTypechecking_2() {
testTypes(
lines(
"/** @constructor */",
"function Foo() {}",
"/** @return {number} */",
"Foo.prototype.method = function() {};",
"/**",
" * @constructor",
" * @extends {Foo}",
" */",
"function Bar() {}",
"Bar.prototype.method;",
"var /** null */ n = (new Bar).method();"),
lines(
"initializing variable",
"found : number",
"required: null"));
}

public void testStubMethodDeclarationDoesntBlockTypechecking_3() {
testTypes(
lines(
"/** @interface */",
"var Foo = function() {};",
"/** @type {number} */",
"Foo.prototype.num;",
"/**",
" * @constructor",
" * @implements {Foo}",
" */",
"var Bar = function() {};",
"/** @type {?} */",
"Bar.prototype.num;",
"var /** string */ x = (new Bar).num;"));
}

public void testStubMethodDeclarationDoesntBlockTypechecking_4() {
testTypes(
lines(
"/** @interface */",
"class Foo {}",
"/** @return {number} */",
"Foo.prototype.num;",
"/** @implements {Foo} */",
"class Bar {",
" get num() { return 1; }",
"}",
"var /** string */ x = (new Bar).num;"));
}

public void testNestedFunctionInference1() {
String nestedAssignOfFooAndBar =
"/** @constructor */ function f() {};" +
Expand Down

0 comments on commit 80e120b

Please sign in to comment.