Skip to content

Commit

Permalink
[NTI] Some bugfixes around @struct and @dict.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=138241228
  • Loading branch information
dimvar authored and blickly committed Nov 7, 2016
1 parent 69245fc commit 3971bdb
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 51 deletions.
3 changes: 2 additions & 1 deletion src/com/google/javascript/jscomp/DiagnosticGroups.java
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ public DiagnosticGroup forName(String name) {
GlobalTypeInfo.CONST_WITHOUT_INITIALIZER,
// GlobalTypeInfo.COULD_NOT_INFER_CONST_TYPE,
GlobalTypeInfo.CTOR_IN_DIFFERENT_SCOPE,
GlobalTypeInfo.DICT_WITHOUT_CTOR,
GlobalTypeInfo.DUPLICATE_JSDOC,
GlobalTypeInfo.DUPLICATE_PROP_IN_ENUM,
GlobalTypeInfo.EXPECTED_CONSTRUCTOR,
Expand All @@ -331,7 +332,7 @@ public DiagnosticGroup forName(String name) {
GlobalTypeInfo.MISPLACED_CONST_ANNOTATION,
GlobalTypeInfo.ONE_TYPE_FOR_MANY_VARS,
// GlobalTypeInfo.REDECLARED_PROPERTY,
GlobalTypeInfo.STRUCTDICT_WITHOUT_CTOR,
GlobalTypeInfo.STRUCT_WITHOUT_CTOR_OR_INTERF,
GlobalTypeInfo.SUPER_INTERFACES_HAVE_INCOMPATIBLE_PROPERTIES,
GlobalTypeInfo.UNKNOWN_OVERRIDE,
GlobalTypeInfo.UNRECOGNIZED_TYPE_NAME,
Expand Down
44 changes: 24 additions & 20 deletions src/com/google/javascript/jscomp/GlobalTypeInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.google.javascript.jscomp.newtypes.JSTypes;
import com.google.javascript.jscomp.newtypes.Namespace;
import com.google.javascript.jscomp.newtypes.NominalType;
import com.google.javascript.jscomp.newtypes.ObjectKind;
import com.google.javascript.jscomp.newtypes.QualifiedName;
import com.google.javascript.jscomp.newtypes.RawNominalType;
import com.google.javascript.jscomp.newtypes.Typedef;
Expand Down Expand Up @@ -96,9 +97,13 @@ class GlobalTypeInfo implements CompilerPass, TypeIRegistry {
"JSC_NTI_UNRECOGNIZED_TYPE_NAME",
"Type annotation references non-existent type {0}.");

static final DiagnosticType STRUCTDICT_WITHOUT_CTOR = DiagnosticType.warning(
"JSC_NTI_STRUCTDICT_WITHOUT_CTOR",
"{0} used without @constructor.");
static final DiagnosticType STRUCT_WITHOUT_CTOR_OR_INTERF = DiagnosticType.warning(
"JSC_NTI_STRUCT_WITHOUT_CTOR_OR_INTERF",
"@struct used without @constructor, @interface, or @record.");

static final DiagnosticType DICT_WITHOUT_CTOR = DiagnosticType.warning(
"JSC_NTI_DICT_WITHOUT_CTOR",
"@dict used without @constructor.");

static final DiagnosticType EXPECTED_CONSTRUCTOR = DiagnosticType.warning(
"JSC_NTI_EXPECTED_CONSTRUCTOR",
Expand Down Expand Up @@ -221,6 +226,7 @@ class GlobalTypeInfo implements CompilerPass, TypeIRegistry {

static final DiagnosticGroup COMPATIBLE_DIAGNOSTICS = new DiagnosticGroup(
CANNOT_OVERRIDE_FINAL_METHOD,
DICT_WITHOUT_CTOR,
DUPLICATE_PROP_IN_ENUM,
EXPECTED_CONSTRUCTOR,
EXPECTED_INTERFACE,
Expand All @@ -233,7 +239,7 @@ class GlobalTypeInfo implements CompilerPass, TypeIRegistry {
LENDS_ON_BAD_TYPE,
ONE_TYPE_FOR_MANY_VARS,
REDECLARED_PROPERTY,
STRUCTDICT_WITHOUT_CTOR,
STRUCT_WITHOUT_CTOR_OR_INTERF,
SUPER_INTERFACES_HAVE_INCOMPATIBLE_PROPERTIES,
UNKNOWN_OVERRIDE,
UNRECOGNIZED_TYPE_NAME,
Expand Down Expand Up @@ -1115,21 +1121,18 @@ private void maybeRecordNominalType(
}
ImmutableList<String> typeParameters = builder.build();
RawNominalType rawType;
if (fnDoc.usesImplicitMatch()) {
ObjectKind objKind = fnDoc.makesStructs()
? ObjectKind.STRUCT : (fnDoc.makesDicts() ? ObjectKind.DICT : ObjectKind.UNRESTRICTED);
if (fnDoc.isConstructor()) {
rawType = RawNominalType.makeClass(
commonTypes, defSite, qname, typeParameters, objKind);
} else if (fnDoc.usesImplicitMatch()) {
rawType = RawNominalType.makeStructuralInterface(
commonTypes, defSite, qname, typeParameters);
} else if (fnDoc.isInterface()) {
rawType = RawNominalType.makeNominalInterface(
commonTypes, defSite, qname, typeParameters);
} else if (fnDoc.makesStructs()) {
rawType = RawNominalType.makeStructClass(
commonTypes, defSite, qname, typeParameters);
} else if (fnDoc.makesDicts()) {
rawType = RawNominalType.makeDictClass(
commonTypes, defSite, qname, typeParameters);
commonTypes, defSite, qname, typeParameters, objKind);
} else {
rawType = RawNominalType.makeUnrestrictedClass(
commonTypes, defSite, qname, typeParameters);
Preconditions.checkState(fnDoc.isInterface());
rawType = RawNominalType.makeNominalInterface(
commonTypes, defSite, qname, typeParameters, objKind);
}
nominaltypesByNode.put(defSite, rawType);
if (isRedeclaration) {
Expand All @@ -1148,9 +1151,10 @@ private void maybeRecordNominalType(
currentScope.addNamespace(nameNode, rawType);
}
} else if (fnDoc.makesStructs()) {
warnings.add(JSError.make(defSite, STRUCTDICT_WITHOUT_CTOR, "@struct"));
} else if (fnDoc.makesDicts()) {
warnings.add(JSError.make(defSite, STRUCTDICT_WITHOUT_CTOR, "@dict"));
warnings.add(JSError.make(defSite, STRUCT_WITHOUT_CTOR_OR_INTERF));
}
if (fnDoc.makesDicts() && !fnDoc.isConstructor()) {
warnings.add(JSError.make(defSite, DICT_WITHOUT_CTOR));
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/com/google/javascript/jscomp/newtypes/ObjectKind.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* @author blickly@google.com (Ben Lickly)
* @author dimvar@google.com (Dimitris Vardoulakis)
*/
class ObjectKind {
public class ObjectKind {
private static final int UNRESTRICTED_MASK = 0;
private static final int STRUCT_MASK = 1;
private static final int DICT_MASK = 2;
Expand All @@ -30,9 +30,9 @@ class ObjectKind {

private int mask;

static final ObjectKind UNRESTRICTED = new ObjectKind(UNRESTRICTED_MASK);
static final ObjectKind STRUCT = new ObjectKind(STRUCT_MASK);
static final ObjectKind DICT = new ObjectKind(DICT_MASK);
public static final ObjectKind UNRESTRICTED = new ObjectKind(UNRESTRICTED_MASK);
public static final ObjectKind STRUCT = new ObjectKind(STRUCT_MASK);
public static final ObjectKind DICT = new ObjectKind(DICT_MASK);
private static final ObjectKind BOTH = new ObjectKind(BOTH_MASK);

private static final ObjectKind[] vals = {
Expand Down
40 changes: 16 additions & 24 deletions src/com/google/javascript/jscomp/newtypes/RawNominalType.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,36 +132,28 @@ private static boolean isValidDefsite(Node defSite) {
return false;
}

public static RawNominalType makeUnrestrictedClass(JSTypes commonTypes,
Node defSite, String name, ImmutableList<String> typeParameters) {
return new RawNominalType(commonTypes, defSite,
name, typeParameters, Kind.CLASS, ObjectKind.UNRESTRICTED);
}

public static RawNominalType makeStructClass(JSTypes commonTypes,
Node defSite, String name, ImmutableList<String> typeParameters) {
return new RawNominalType(commonTypes, defSite,
name, typeParameters, Kind.CLASS, ObjectKind.STRUCT);
}

public static RawNominalType makeDictClass(JSTypes commonTypes,
Node defSite, String name, ImmutableList<String> typeParameters) {
return new RawNominalType(commonTypes, defSite,
name, typeParameters, Kind.CLASS, ObjectKind.DICT);
public static RawNominalType makeClass(JSTypes commonTypes,
Node defSite, String name, ImmutableList<String> typeParameters, ObjectKind objKind) {
return new RawNominalType(
commonTypes, defSite, name, typeParameters, Kind.CLASS, objKind);
}

public static RawNominalType makeNominalInterface(JSTypes commonTypes,
Node defSite, String name, ImmutableList<String> typeParameters) {
// interfaces are struct by default
return new RawNominalType(commonTypes, defSite,
name, typeParameters, Kind.INTERFACE, ObjectKind.UNRESTRICTED);
Node defSite, String name, ImmutableList<String> typeParameters, ObjectKind objKind) {
if (objKind == ObjectKind.DICT) {
objKind = ObjectKind.UNRESTRICTED;
}
return new RawNominalType(
commonTypes, defSite, name, typeParameters, Kind.INTERFACE, objKind);
}

public static RawNominalType makeStructuralInterface(JSTypes commonTypes,
Node defSite, String name, ImmutableList<String> typeParameters) {
// interfaces are struct by default
return new RawNominalType(commonTypes, defSite,
name, typeParameters, Kind.RECORD, ObjectKind.UNRESTRICTED);
Node defSite, String name, ImmutableList<String> typeParameters, ObjectKind objKind) {
if (objKind == ObjectKind.DICT) {
objKind = ObjectKind.UNRESTRICTED;
}
return new RawNominalType(
commonTypes, defSite, name, typeParameters, Kind.RECORD, objKind);
}

JSTypes getCommonTypes() {
Expand Down
18 changes: 16 additions & 2 deletions test/com/google/javascript/jscomp/NewTypeInferenceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9429,6 +9429,17 @@ public void testStructPropAccess() {
"}",
"(new Foo).prop = 'asdf';"),
NewTypeInference.MISTYPED_ASSIGN_RHS);

typeCheck(LINE_JOINER.join(
"/**",
" * @record",
" * @struct",
" */",
"function Foo() {}",
"/** @type {string} */",
"Foo.prototype.prop;",
"function f(/** !Foo */ x) { return x['prop']; }"),
NewTypeInference.ILLEGAL_PROPERTY_ACCESS);
}

public void testDictPropAccess() {
Expand Down Expand Up @@ -9741,10 +9752,13 @@ public void testStructPropCreation() {
public void testMisplacedStructDictAnnotation() {
typeCheck(
"/** @struct */ function Struct1() {}",
GlobalTypeInfo.STRUCTDICT_WITHOUT_CTOR);
GlobalTypeInfo.STRUCT_WITHOUT_CTOR_OR_INTERF);
typeCheck(
"/** @dict */ function Dict() {}",
GlobalTypeInfo.STRUCTDICT_WITHOUT_CTOR);
GlobalTypeInfo.DICT_WITHOUT_CTOR);
typeCheck(
"/** @dict @interface */ function Foo() {}",
GlobalTypeInfo.DICT_WITHOUT_CTOR);
}

public void testFunctionUnions() {
Expand Down

0 comments on commit 3971bdb

Please sign in to comment.