Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion _packages/native-preview/src/api/async/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@ import type {
AssertsThisTypePredicate,
ConditionalType,
Diagnostic,
FreshableType,
IdentifierTypePredicate,
IndexedAccessType,
IndexInfo,
IndexType,
InterfaceType,
IntersectionType,
IntrinsicType,
LiteralType,
ObjectType,
StringMappingType,
Expand All @@ -91,7 +93,7 @@ import type {

export { DiagnosticCategory, ElementFlags, ModifierFlags, NodeBuilderFlags, ObjectFlags, SignatureFlags, SignatureKind, SymbolFlags, TypeFlags, TypePredicateKind };
export type { APIOptions, ClientSocketOptions, ClientSpawnOptions, DocumentIdentifier, DocumentPosition, LSPConnectionOptions };
export type { AssertsIdentifierTypePredicate, AssertsThisTypePredicate, ConditionalType, Diagnostic, IdentifierTypePredicate, IndexedAccessType, IndexInfo, IndexType, InterfaceType, IntersectionType, LiteralType, ObjectType, StringMappingType, SubstitutionType, TemplateLiteralType, ThisTypePredicate, TupleType, Type, TypeParameter, TypePredicate, TypePredicateBase, TypeReference, UnionOrIntersectionType, UnionType };
export type { AssertsIdentifierTypePredicate, AssertsThisTypePredicate, ConditionalType, Diagnostic, FreshableType, IdentifierTypePredicate, IndexedAccessType, IndexInfo, IndexType, InterfaceType, IntersectionType, IntrinsicType, LiteralType, ObjectType, StringMappingType, SubstitutionType, TemplateLiteralType, ThisTypePredicate, TupleType, Type, TypeParameter, TypePredicate, TypePredicateBase, TypeReference, UnionOrIntersectionType, UnionType };
export { documentURIToFileName, fileNameToDocumentURI } from "../path.ts";

/** Type alias for the snapshot-scoped object registry */
Expand Down Expand Up @@ -689,6 +691,15 @@ export class Checker {
});
}

async isTypeAssignableTo(source: Type, target: Type): Promise<boolean> {
return this.client.apiRequest<boolean>("isTypeAssignableTo", {
snapshot: this.snapshotId,
project: this.projectId,
source: source.id,
target: target.id,
});
}

async getShorthandAssignmentValueSymbol(node: Node): Promise<Symbol | undefined> {
const data = await this.client.apiRequest<SymbolResponse | null>("getShorthandAssignmentValueSymbol", {
snapshot: this.snapshotId,
Expand Down Expand Up @@ -980,10 +991,16 @@ class TypeObject implements Type {
readonly flags: TypeFlags;
readonly objectFlags!: ObjectFlags;
readonly value!: string | number | boolean;
readonly intrinsicName!: string;
readonly isThisType!: boolean;
readonly freshType!: number;
readonly regularType!: number;
readonly target!: number;
readonly typeParameters!: readonly number[];
readonly outerTypeParameters!: readonly number[];
readonly localTypeParameters!: readonly number[];
readonly aliasTypeArguments!: readonly number[];
readonly aliasSymbol!: number;
readonly elementFlags!: readonly ElementFlags[];
readonly fixedLength!: number;
readonly readonly!: boolean;
Expand All @@ -1004,10 +1021,16 @@ class TypeObject implements Type {
this.flags = data.flags;
if (data.objectFlags !== undefined) this.objectFlags = data.objectFlags;
if (data.value !== undefined) this.value = data.value;
if (data.intrinsicName !== undefined) this.intrinsicName = data.intrinsicName;
if (data.isThisType !== undefined) this.isThisType = data.isThisType;
if (data.freshType !== undefined) this.freshType = data.freshType;
if (data.regularType !== undefined) this.regularType = data.regularType;
if (data.target !== undefined) this.target = data.target;
if (data.typeParameters !== undefined) this.typeParameters = data.typeParameters;
if (data.outerTypeParameters !== undefined) this.outerTypeParameters = data.outerTypeParameters;
if (data.localTypeParameters !== undefined) this.localTypeParameters = data.localTypeParameters;
if (data.aliasTypeArguments !== undefined) this.aliasTypeArguments = data.aliasTypeArguments;
if (data.aliasSymbol !== undefined) this.aliasSymbol = data.aliasSymbol;
if (data.elementFlags !== undefined) this.elementFlags = data.elementFlags;
if (data.fixedLength !== undefined) this.fixedLength = data.fixedLength;
if (data.readonly !== undefined) this.readonly = data.readonly;
Expand All @@ -1025,6 +1048,14 @@ class TypeObject implements Type {
return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
}

async getAliasSymbol(): Promise<Symbol | undefined> {
if (!this.aliasSymbol) return undefined;
const cached = this.objectRegistry.getSymbol(this.aliasSymbol);
if (cached) return cached;
const data = await this.client.apiRequest<SymbolResponse | null>("getAliasSymbolOfType", { snapshot: this.snapshotId, type: this.id });
return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
}

private async fetchType(handle: number | undefined, method: string): Promise<Type> {
const cached = handle !== undefined ? this.objectRegistry.getType(handle) : undefined;
if (cached) return cached as Type;
Expand All @@ -1042,6 +1073,22 @@ class TypeObject implements Type {
return this.fetchType(this.target, "getTargetOfType");
}

async getFreshType(): Promise<FreshableType | undefined> {
if (!this.freshType) return undefined;
const cached = this.objectRegistry.getType(this.freshType);
if (cached) return cached as FreshableType;
const data = await this.client.apiRequest<TypeResponse | null>("getFreshTypeOfType", { snapshot: this.snapshotId, type: this.id });
return data ? this.objectRegistry.getOrCreateType(data) as FreshableType : undefined;
}

async getRegularType(): Promise<FreshableType | undefined> {
if (!this.regularType) return undefined;
const cached = this.objectRegistry.getType(this.regularType);
if (cached) return cached as FreshableType;
const data = await this.client.apiRequest<TypeResponse | null>("getRegularTypeOfType", { snapshot: this.snapshotId, type: this.id });
return data ? this.objectRegistry.getOrCreateType(data) as FreshableType : undefined;
}

async getTypes(): Promise<readonly Type[]> {
return this.fetchTypes("getTypesOfType");
}
Expand All @@ -1058,6 +1105,10 @@ class TypeObject implements Type {
return this.fetchTypes("getLocalTypeParametersOfType");
}

async getAliasTypeArguments(): Promise<readonly Type[]> {
return this.fetchTypes("getAliasTypeArgumentsOfType");
}

async getObjectType(): Promise<Type> {
return this.fetchType(this.objectType, "getObjectTypeOfType");
}
Expand Down
26 changes: 25 additions & 1 deletion _packages/native-preview/src/api/async/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,26 @@ export interface Type {

/** Get the symbol associated with this type, if any */
getSymbol(): Promise<Symbol | undefined>;

/** Get the type arguments of the type alias this type was instantiated from, if any */
getAliasTypeArguments(): Promise<readonly Type[]>;

/** Get the symbol of the type alias this type was instantiated from, if any */
getAliasSymbol(): Promise<Symbol | undefined>;
}

/**
* Freshable types (TypeFlags.Freshable) - literal types (TypeFlags.Literal) and computed enum types (TypeFlags.Enum).
*/
export interface FreshableType extends Type {
/** Get the fresh version of this type, if any */
getFreshType(): Promise<FreshableType | undefined>;
/** Get the regular (non-fresh) version of this type, if any */
getRegularType(): Promise<FreshableType | undefined>;
}

/** Literal types: StringLiteral, NumberLiteral, BigIntLiteral, BooleanLiteral */
export interface LiteralType extends Type {
export interface LiteralType extends FreshableType {
/** The literal value */
readonly value: string | number | boolean;
}
Expand Down Expand Up @@ -81,6 +97,8 @@ export interface IntersectionType extends UnionOrIntersectionType {

/** Type parameters (TypeFlags.TypeParameter) */
export interface TypeParameter extends Type {
/** True if this is the synthetic `this` type of an interface, class, or tuple */
readonly isThisType?: boolean;
}

/** Index types — keyof T (TypeFlags.Index) */
Expand Down Expand Up @@ -125,6 +143,12 @@ export interface StringMappingType extends Type {
getTarget(): Promise<Type>;
}

/** Intrinsic types — any, unknown, string, number, bigint, symbol, void, undefined, null, never, object (TypeFlags.Intrinsic) */
export interface IntrinsicType extends Type {
/** The intrinsic type name (e.g. "any", "string", "never") */
readonly intrinsicName: string;
}

/** Base for all type predicates */
export interface TypePredicateBase {
readonly kind: TypePredicateKind;
Expand Down
4 changes: 4 additions & 0 deletions _packages/native-preview/src/api/objectRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export class ObjectRegistry<
return this.types.get(id);
}

getSymbol(id: number): TSymbol | undefined {
return this.symbols.get(id);
}

getOrCreateSignature(data: SignatureResponse): TSignature {
let signature = this.signatures.get(data.id);
if (signature) {
Expand Down
6 changes: 6 additions & 0 deletions _packages/native-preview/src/api/proto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ export interface TypeResponse {
flags: number;
objectFlags?: number;
value?: string | number | boolean;
freshType?: number;
regularType?: number;
target?: number;
typeParameters?: number[];
outerTypeParameters?: number[];
Expand All @@ -154,6 +156,10 @@ export interface TypeResponse {
baseType?: number;
substConstraint?: number;
texts?: string[];
intrinsicName?: string;
isThisType?: boolean;
aliasTypeArguments?: number[];
aliasSymbol?: number;
symbol?: number;
}

Expand Down
53 changes: 52 additions & 1 deletion _packages/native-preview/src/api/sync/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,14 @@ import type {
AssertsThisTypePredicate,
ConditionalType,
Diagnostic,
FreshableType,
IdentifierTypePredicate,
IndexedAccessType,
IndexInfo,
IndexType,
InterfaceType,
IntersectionType,
IntrinsicType,
LiteralType,
ObjectType,
StringMappingType,
Expand All @@ -99,7 +101,7 @@ import type {

export { DiagnosticCategory, ElementFlags, ModifierFlags, NodeBuilderFlags, ObjectFlags, SignatureFlags, SignatureKind, SymbolFlags, TypeFlags, TypePredicateKind };
export type { APIOptions, ClientSocketOptions, ClientSpawnOptions, DocumentIdentifier, DocumentPosition, LSPConnectionOptions };
export type { AssertsIdentifierTypePredicate, AssertsThisTypePredicate, ConditionalType, Diagnostic, IdentifierTypePredicate, IndexedAccessType, IndexInfo, IndexType, InterfaceType, IntersectionType, LiteralType, ObjectType, StringMappingType, SubstitutionType, TemplateLiteralType, ThisTypePredicate, TupleType, Type, TypeParameter, TypePredicate, TypePredicateBase, TypeReference, UnionOrIntersectionType, UnionType };
export type { AssertsIdentifierTypePredicate, AssertsThisTypePredicate, ConditionalType, Diagnostic, FreshableType, IdentifierTypePredicate, IndexedAccessType, IndexInfo, IndexType, InterfaceType, IntersectionType, IntrinsicType, LiteralType, ObjectType, StringMappingType, SubstitutionType, TemplateLiteralType, ThisTypePredicate, TupleType, Type, TypeParameter, TypePredicate, TypePredicateBase, TypeReference, UnionOrIntersectionType, UnionType };
export { documentURIToFileName, fileNameToDocumentURI } from "../path.ts";

/** Type alias for the snapshot-scoped object registry */
Expand Down Expand Up @@ -697,6 +699,15 @@ export class Checker {
});
}

isTypeAssignableTo(source: Type, target: Type): boolean {
return this.client.apiRequest<boolean>("isTypeAssignableTo", {
snapshot: this.snapshotId,
project: this.projectId,
source: source.id,
target: target.id,
});
}

getShorthandAssignmentValueSymbol(node: Node): Symbol | undefined {
const data = this.client.apiRequest<SymbolResponse | null>("getShorthandAssignmentValueSymbol", {
snapshot: this.snapshotId,
Expand Down Expand Up @@ -988,10 +999,16 @@ class TypeObject implements Type {
readonly flags: TypeFlags;
readonly objectFlags!: ObjectFlags;
readonly value!: string | number | boolean;
readonly intrinsicName!: string;
readonly isThisType!: boolean;
readonly freshType!: number;
readonly regularType!: number;
readonly target!: number;
readonly typeParameters!: readonly number[];
readonly outerTypeParameters!: readonly number[];
readonly localTypeParameters!: readonly number[];
readonly aliasTypeArguments!: readonly number[];
readonly aliasSymbol!: number;
readonly elementFlags!: readonly ElementFlags[];
readonly fixedLength!: number;
readonly readonly!: boolean;
Expand All @@ -1012,10 +1029,16 @@ class TypeObject implements Type {
this.flags = data.flags;
if (data.objectFlags !== undefined) this.objectFlags = data.objectFlags;
if (data.value !== undefined) this.value = data.value;
if (data.intrinsicName !== undefined) this.intrinsicName = data.intrinsicName;
if (data.isThisType !== undefined) this.isThisType = data.isThisType;
if (data.freshType !== undefined) this.freshType = data.freshType;
if (data.regularType !== undefined) this.regularType = data.regularType;
if (data.target !== undefined) this.target = data.target;
if (data.typeParameters !== undefined) this.typeParameters = data.typeParameters;
if (data.outerTypeParameters !== undefined) this.outerTypeParameters = data.outerTypeParameters;
if (data.localTypeParameters !== undefined) this.localTypeParameters = data.localTypeParameters;
if (data.aliasTypeArguments !== undefined) this.aliasTypeArguments = data.aliasTypeArguments;
if (data.aliasSymbol !== undefined) this.aliasSymbol = data.aliasSymbol;
if (data.elementFlags !== undefined) this.elementFlags = data.elementFlags;
if (data.fixedLength !== undefined) this.fixedLength = data.fixedLength;
if (data.readonly !== undefined) this.readonly = data.readonly;
Expand All @@ -1033,6 +1056,14 @@ class TypeObject implements Type {
return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
}

getAliasSymbol(): Symbol | undefined {
if (!this.aliasSymbol) return undefined;
const cached = this.objectRegistry.getSymbol(this.aliasSymbol);
if (cached) return cached;
const data = this.client.apiRequest<SymbolResponse | null>("getAliasSymbolOfType", { snapshot: this.snapshotId, type: this.id });
return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
}
Comment thread
piotrtomiak marked this conversation as resolved.

private fetchType(handle: number | undefined, method: string): Type {
const cached = handle !== undefined ? this.objectRegistry.getType(handle) : undefined;
if (cached) return cached as Type;
Expand All @@ -1050,6 +1081,22 @@ class TypeObject implements Type {
return this.fetchType(this.target, "getTargetOfType");
}

getFreshType(): FreshableType | undefined {
if (!this.freshType) return undefined;
const cached = this.objectRegistry.getType(this.freshType);
if (cached) return cached as FreshableType;
const data = this.client.apiRequest<TypeResponse | null>("getFreshTypeOfType", { snapshot: this.snapshotId, type: this.id });
return data ? this.objectRegistry.getOrCreateType(data) as FreshableType : undefined;
}

getRegularType(): FreshableType | undefined {
if (!this.regularType) return undefined;
const cached = this.objectRegistry.getType(this.regularType);
if (cached) return cached as FreshableType;
const data = this.client.apiRequest<TypeResponse | null>("getRegularTypeOfType", { snapshot: this.snapshotId, type: this.id });
return data ? this.objectRegistry.getOrCreateType(data) as FreshableType : undefined;
}

getTypes(): readonly Type[] {
return this.fetchTypes("getTypesOfType");
}
Expand All @@ -1066,6 +1113,10 @@ class TypeObject implements Type {
return this.fetchTypes("getLocalTypeParametersOfType");
}

getAliasTypeArguments(): readonly Type[] {
return this.fetchTypes("getAliasTypeArgumentsOfType");
}

getObjectType(): Type {
return this.fetchType(this.objectType, "getObjectTypeOfType");
}
Expand Down
26 changes: 25 additions & 1 deletion _packages/native-preview/src/api/sync/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,26 @@ export interface Type {

/** Get the symbol associated with this type, if any */
getSymbol(): Symbol | undefined;

/** Get the type arguments of the type alias this type was instantiated from, if any */
getAliasTypeArguments(): readonly Type[];

/** Get the symbol of the type alias this type was instantiated from, if any */
getAliasSymbol(): Symbol | undefined;
}

/**
* Freshable types (TypeFlags.Freshable) - literal types (TypeFlags.Literal) and computed enum types (TypeFlags.Enum).
*/
export interface FreshableType extends Type {
/** Get the fresh version of this type, if any */
getFreshType(): FreshableType | undefined;
/** Get the regular (non-fresh) version of this type, if any */
getRegularType(): FreshableType | undefined;
}

/** Literal types: StringLiteral, NumberLiteral, BigIntLiteral, BooleanLiteral */
export interface LiteralType extends Type {
export interface LiteralType extends FreshableType {
/** The literal value */
readonly value: string | number | boolean;
}
Expand Down Expand Up @@ -89,6 +105,8 @@ export interface IntersectionType extends UnionOrIntersectionType {

/** Type parameters (TypeFlags.TypeParameter) */
export interface TypeParameter extends Type {
/** True if this is the synthetic `this` type of an interface, class, or tuple */
readonly isThisType?: boolean;
}

/** Index types — keyof T (TypeFlags.Index) */
Expand Down Expand Up @@ -133,6 +151,12 @@ export interface StringMappingType extends Type {
getTarget(): Type;
}

/** Intrinsic types — any, unknown, string, number, bigint, symbol, void, undefined, null, never, object (TypeFlags.Intrinsic) */
export interface IntrinsicType extends Type {
/** The intrinsic type name (e.g. "any", "string", "never") */
readonly intrinsicName: string;
}

/** Base for all type predicates */
export interface TypePredicateBase {
readonly kind: TypePredicateKind;
Expand Down
Loading
Loading