[Tern] fix inheritance of infer objects and added missing stuff. (#35518)

* [Tern] fix inheritance of infer objects and added missing stuff.

The inheritance of abstract values and types was wrong.
Primitives were not yet implemented and some methods were on the wrong
level of inheritance, leading to unfounded complaints from the compiler

workstream:

* follow-up fix: proto Obj has a name (if it exists)

workstream:

* fix tests

workstream:

* redo changes that were accidentally deleted

workstream:

* infer.Arr has always the name "Array".

workstream:

* fix tests

workstream:

* removed unknown since dependants are on TS v2.8

workstream:
This commit is contained in:
Nikolaj Kappler
2019-05-16 09:45:03 -07:00
committed by Nathan Shively-Sanders
parent df31e13c58
commit 17a590cc85
2 changed files with 93 additions and 30 deletions
-7
View File
@@ -4,12 +4,5 @@
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.8
// IMPORTANT Note: These type definitions adhere strictly to the official documentation,
// which does not seem to match the implementation exactly in some places.
// As a result, these type definitions may lack some parts of the API that are actually exposed.
// The type definitions are at a point where they are usable and match the documentation,
// thus if you want to use undocumented APIs, you should extends these definitions with
// ambient declaration merging: https://www.typescriptlang.org/docs/handbook/declaration-merging.html
export * from "./lib/infer";
export * from "./lib/tern";
+93 -23
View File
@@ -11,11 +11,11 @@ export interface Context {
parent?: Server;
topScope: Scope;
/** The primitive number type. */
num: Type;
num: Prim & { name: "number" };
/** The primitive string type. */
str: Type;
str: Prim & { name: "string" };
/** The primitive boolean type. */
bool: Type;
bool: Prim & { name: "bool" };
}
/** Returns the current context object. */
export function cx(): Context;
@@ -52,9 +52,11 @@ interface ObjConstructor {
}
/** Constructor for the type that represents JavaScript objects. `proto` may be another object, or `true` as a short-hand for `Object.prototype`, or `null` for prototype-less objects. */
export const Obj: ObjConstructor;
export interface Obj extends Type {
export interface Obj extends IType {
/** The name of the type, if any. */
name: string | undefined;
/** The prototype of the object, or null. */
proto: any;
proto: (Obj & { name: string }) | null;
/** An object mapping the object’s known properties to AVals. Don’t manipulate this directly (ever), only use it if you have to iterate over the properties. */
props: Readonly<{
[key: string]: AVal;
@@ -63,7 +65,17 @@ export interface Obj extends Type {
hasProp(prop: string): AVal | null;
/** Looks up the given property, or defines it if it did not yet exist (in which case it will be associated with the given AST node). */
defProp(prop: string, originNode?: ESTree.Node): AVal;
/**
* Asks the AVal if it contains an Object type. Useful when
* you aren’t interested in other kinds of types.
*/
getObjType(): Obj;
getType(): Obj;
/** Get an `AVal` that represents the named property of this type. */
getProp(prop: string): AVal;
/** Call the given function for all properties of the object, including properties that are added in the future. */
forAllProps(f: (prop: string, val: AVal, local: boolean) => void): void;
gatherProperties(f: (...args: any[]) => void, depth: number): void;
}
interface FnConstructor {
@@ -76,22 +88,47 @@ export interface Fn extends Obj {
readonly argNames?: string[];
self?: Type;
readonly retval: AVal;
/**
* Asks the AVal if it contains a function type. Useful when
* you aren’t interested in other kinds of types.
*/
getFunctionType(): Fn;
isArrowFn(): boolean;
getType(): Fn;
}
interface PrimConstructor {
new(proto: object | null, name?: string): Prim;
}
export const Prim: PrimConstructor;
export interface Prim extends IType {
/** The name of the type, if any. */
name: "string" | "bool" | "number";
/** The prototype of the object, or null. */
proto: Obj & { name: string };
/** Get an `AVal` that represents the named property of this type. */
getProp(prop: string): AVal;
getType(): Prim;
gatherProperties(f: (...args: any[]) => void, depth: number): void;
}
interface ArrConstructor {
/** Constructor that creates an array type with the given content type. */
new(contentType?: AVal): Arr;
}
export const Arr: ArrConstructor;
export interface Arr extends Obj {
name: "Array";
getType(): Arr;
}
interface TypeConstructor {
new(): Type;
}
export const Type: TypeConstructor;
export type Type = Obj | Prim;
export interface Type extends AVal {
/** The name of the type, if any. */
name: string | undefined;
// tslint:disable-next-line: interface-name
export interface IType extends ANull {
/** The origin file of the type. */
origin: string;
/**
@@ -102,8 +139,8 @@ export interface Type extends AVal {
originNode?: ESTree.Node;
/** Return a string that describes the type. maxDepth indicates the depth to which inner types should be shown. */
toString(maxDepth: number): string;
/** Call the given function for all properties of the object, including properties that are added in the future. */
forAllProps(f: (prop: string, val: AVal, local: boolean) => void): void;
/** Queries whether the AVal _currently_ holds the given type. */
hasType(type: Type): boolean;
getType(): Type;
}
@@ -113,7 +150,21 @@ interface AValConstructor {
new(): AVal;
}
export const AVal: AValConstructor;
export interface AVal {
/**
* Abstract values are objects used to represent sets of types. Each variable
* and property has an abstract value associated with it, but they are also
* used for other purposes, such as tracking the return type of a function,
* or building up the type for some kinds of expressions.
*
* In a cleanly typed program where each thing has only a single type,
* abstract values will all have one type associated with them. When,
* for example, a variable can hold two different types of values,
* the associated abstract value will hold both these types. In some cases,
* no type can be assigned to something at all,
* in which case the abstract value remains empty.
*/
export interface AVal extends ANull {
/**
* Add a type to this abstract value. If the type is already in there,
* this is a no-op. weight can be given to give this type a non-default
@@ -147,6 +198,8 @@ export interface AVal {
getFunctionType(): Fn | undefined;
/** Get an `AVal` that represents the named property of this type. */
getProp(prop: string): AVal;
/** Call the given function for all properties of the object, including properties that are added in the future. */
forAllProps(f: (prop: string, val: AVal, local: boolean) => void): void;
/**
* Asks the AVal if it contains an Object type. Useful when
* you aren’t interested in other kinds of types.
@@ -157,21 +210,38 @@ export interface AVal {
* or properties will have, when possible, an `originNode`
* property pointing to an AST node.
*/
gatherProperties(f: (...args: any[]) => void, depth: number): void;
originNode?: ESTree.Node;
/** An object mapping the object’s known properties to AVals. Don’t manipulate this directly (ever), only use it if you have to iterate over the properties. */
props: Partial<Readonly<{
[key: string]: AVal;
}>>;
readonly types: Type[];
readonly propertyOf?: Obj;
}
/**
* A variant of AVal used for unknown, dead-end values. Also serves
* a prototype for AVals, Types, and Constraints because it
* implements 'empty' versions of all the methods that the code expects.
*/
export const ANull: ANull;
export interface ANull extends AVal {
addType(): void;
propagate(target: never): void;
hasType(): false;
isEmpty(): true;
getFunctionType(): undefined;
getType(): null;
originNode: undefined;
export interface ANull {
addType(...args: any[]): void;
propagate(...args: any[]): void;
getProp(...args: any[]): ANull;
forAllProps(...args: any[]): void;
hasType(...args: any[]): boolean;
isEmpty(...args: any[]): boolean;
getFunctionType(...args: any[]): ANull | undefined;
getObjType(...args: any[]): ANull | undefined | null;
getSymbolType(...args: any[]): ANull | undefined;
getType(...args: any[]): ANull | undefined | null;
gatherProperties(...args: any[]): void;
propagatesTo(): any;
typeHint(...args: any[]): ANull | undefined | null;
propHint(...args: any[]): string | undefined;
toString(...args: any[]): string;
}
// #### Constraints ####
@@ -184,11 +254,11 @@ interface ConstraintConstructor {
* which will run its construct method on its arguments when instantiated.
*/
export const constraint: ConstraintConstructor;
export interface Constraint extends AVal {
export interface Constraint extends ANull {
/** May return a type that `getType` can use to “guess” its type based on the fact that it propagates to this constraint. */
typeHint?(): Type | undefined;
typeHint(): Type | undefined;
/** May return a string when this constraint is indicative of the presence of a specific property in the source AVal. */
propHint?(): string | undefined;
propHint(): string | undefined;
}
// #### Scopes ####