Skip to content

Commit

Permalink
[NTI] Add inferred type to undeclared constructor properties.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=154350174
  • Loading branch information
dimvar authored and Tyler Breisacher committed Apr 28, 2017
1 parent 6a41621 commit bfb95b8
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 16 deletions.
10 changes: 9 additions & 1 deletion src/com/google/javascript/jscomp/GlobalTypeInfo.java
Expand Up @@ -1830,7 +1830,15 @@ private void visitConstructorPropertyDeclaration(Node getProp) {
getProp.putBooleanProp(Node.CONSTANT_PROPERTY_DEF, true); getProp.putBooleanProp(Node.CONSTANT_PROPERTY_DEF, true);
} }
} else { } else {
classType.addUndeclaredCtorProperty(pname, getProp); JSType inferredType = null;
Node initializer = NodeUtil.getRValueOfLValue(getProp);
if (initializer != null) {
inferredType = simpleInferExprType(initializer);
}
if (inferredType == null) {
inferredType = commonTypes.UNKNOWN;
}
classType.addUndeclaredCtorProperty(pname, getProp, inferredType);
} }
} }


Expand Down
3 changes: 1 addition & 2 deletions src/com/google/javascript/jscomp/newtypes/Namespace.java
Expand Up @@ -187,8 +187,7 @@ public final void addProperty(
public final void addUndeclaredProperty( public final void addUndeclaredProperty(
String pname, Node defSite, JSType t, boolean isConstant) { String pname, Node defSite, JSType t, boolean isConstant) {
Preconditions.checkState(this.namespaceType == null); Preconditions.checkState(this.namespaceType == null);
if (otherProps.containsKey(pname) if (otherProps.containsKey(pname) && otherProps.get(pname).isDeclared()) {
&& !otherProps.get(pname).getType().isUnknown()) {
return; return;
} }
otherProps = otherProps.with(pname, isConstant otherProps = otherProps.with(pname, isConstant
Expand Down
28 changes: 16 additions & 12 deletions src/com/google/javascript/jscomp/newtypes/RawNominalType.java
Expand Up @@ -585,16 +585,16 @@ public void addProtoProperty(String pname, Node defSite, JSType type, boolean is
public void addUndeclaredProtoProperty(String pname, Node defSite, JSType inferredType) { public void addUndeclaredProtoProperty(String pname, Node defSite, JSType inferredType) {
Preconditions.checkState(!this.isFrozen); Preconditions.checkState(!this.isFrozen);
Property existingProp = this.protoProps.get(pname); Property existingProp = this.protoProps.get(pname);
if (existingProp == null || !existingProp.isDeclared()) { if (existingProp != null && existingProp.isDeclared()) {
JSType oldType = existingProp == null ? null : existingProp.getType(); return;
if (oldType != null) { }
inferredType = JSType.join(oldType, inferredType); if (existingProp != null) {
} inferredType = JSType.join(existingProp.getType(), inferredType);
this.protoProps = this.protoProps.with(pname, }
Property.makeWithDefsite(defSite, inferredType, null)); this.protoProps =
if (this.randomProps.containsKey(pname)) { this.protoProps.with(pname, Property.makeWithDefsite(defSite, inferredType, null));
this.randomProps = this.randomProps.without(pname); if (this.randomProps.containsKey(pname)) {
} this.randomProps = this.randomProps.without(pname);
} }
} }


Expand All @@ -611,9 +611,13 @@ public void addCtorProperty(String pname, Node defSite, JSType type, boolean isC
} }


/** Add a new undeclared property to this class's constructor */ /** Add a new undeclared property to this class's constructor */
public void addUndeclaredCtorProperty(String pname, Node defSite) { public void addUndeclaredCtorProperty(String pname, Node defSite, JSType inferredType) {
Preconditions.checkState(!this.isFrozen); Preconditions.checkState(!this.isFrozen);
super.addUndeclaredProperty(pname, defSite, this.commonTypes.UNKNOWN, false); Property existingProp = getNsProp(pname);
if (existingProp != null && !existingProp.isDeclared()) {
inferredType = JSType.join(existingProp.getType(), inferredType);
}
super.addUndeclaredProperty(pname, defSite, inferredType, false);
} }


public JSType getCtorPropDeclaredType(String pname) { public JSType getCtorPropDeclaredType(String pname) {
Expand Down
39 changes: 38 additions & 1 deletion test/com/google/javascript/jscomp/NewTypeInferenceTest.java
Expand Up @@ -19926,7 +19926,7 @@ public void testAllowConstructorWithReturnToBeTypedAsFunction() {
"f(Foo);")); "f(Foo);"));
} }


public void testInstantiateTypeVariablesToUnknownWhenUsingCallApply() { public void testHandleClassGenericsWhenUsingCallApply() {
typeCheck(LINE_JOINER.join( typeCheck(LINE_JOINER.join(
"/**", "/**",
" * @constructor", " * @constructor",
Expand Down Expand Up @@ -19992,4 +19992,41 @@ public void testInstantiateTypeVariablesToUnknownWhenUsingCallApply() {
"var /** number */ n = Foo.prototype.f.call(new Foo, 'asdf');"), "var /** number */ n = Foo.prototype.f.call(new Foo, 'asdf');"),
NewTypeInference.MISTYPED_ASSIGN_RHS); NewTypeInference.MISTYPED_ASSIGN_RHS);
} }

public void testInferTypeOfUndeclaredConstructorProperties() {
typeCheck(LINE_JOINER.join(
"/** @constructor */",
"function Foo() {}",
"Foo.prop = 1;",
"function f() {",
" var /** string */ s = Foo.prop;",
"}"),
NewTypeInference.MISTYPED_ASSIGN_RHS);

typeCheck(LINE_JOINER.join(
"/** @constructor */",
"function Foo() {}",
"Foo.prop = 1;",
"Foo.prop = true;"));

// TODO(dimvar): we want to catch the warning here, which requires not tightening the
// property type. Will do in a follow-up CL.
typeCheck(LINE_JOINER.join(
"/** @constructor */",
"function Foo() {}",
"Foo.prop = 'asdf';",
"function f() {",
" var /** string */ s = Foo.prop;",
"}",
"Foo.prop = 1;"));

typeCheck(LINE_JOINER.join(
"/** @constructor */",
"function Foo() {}",
"Foo.prop = 'asdf';",
"function f() {",
" var /** string */ s = Foo.prop;",
"}",
"Foo.prop = globalVar;"));
}
} }

0 comments on commit bfb95b8

Please sign in to comment.