Skip to content
Open
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
110 changes: 110 additions & 0 deletions packages/typescript/src/api/async/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2296,6 +2296,59 @@ function toEmitOutput(response: ProtocolEmitOutputResponse): EmitOutput {
};
}

/** The documentation comment and JSDoc tags of one symbol. */
export interface SymbolDocumentation {
/** Tag name/text pairs. Empty when the symbol has no tags. */
readonly tags: readonly JSDocTagInfo[];
/** The rendered documentation comment, or an empty string. */
readonly comment: string;
}

/** Member kinds accepted by {@link Checker.getMembersOfType}. */
export type MemberKind = "property" | "accessor" | "method" | "parameterProperty";

/** Visibilities accepted by {@link Checker.getMembersOfType}. ECMAScript private names count as private. */
export type MemberVisibility = "public" | "protected" | "private";

/**
* Which declaring types contribute members beyond the queried type's own members.
* Omit it, or pass neither `all` nor `types`, for own members only.
*/
export interface MembersInheritedFrom {
/** Include every member {@link Checker.getPropertiesOfType} would return. */
readonly all?: boolean | undefined;
/** Declaring types whose members are included along with the queried type's own members. */
readonly types?: readonly Type[] | undefined;
}

/**
* Filters applied before a member's type is computed. Every field is optional.
* `visibility` and `kinds` are allow-lists; an empty list does not filter.
* `excludeNamePattern` is a RE2 regular expression matched against the source name.
*/
export interface GetMembersOfTypeOptions {
readonly visibility?: readonly MemberVisibility[] | undefined;
readonly kinds?: readonly MemberKind[] | undefined;
readonly excludeJsDocTags?: readonly string[] | undefined;
/** Drop members whose source name matches. ECMAScript private names are matched as written (`#name`). */
readonly excludeNamePattern?: string | undefined;
readonly includeInheritedFrom?: MembersInheritedFrom | undefined;
/** Attach each member's declared type, the same type {@link Checker.getTypeOfSymbol} returns. */
readonly includeDeclaredType?: boolean | undefined;
}

/** One member returned by {@link Checker.getMembersOfType}. */
export interface TypeMember {
readonly symbol: Symbol;
/** The symbol of the class or interface that declares this member. */
readonly declaringSymbol?: Symbol | undefined;
readonly kind: MemberKind;
readonly tags: readonly JSDocTagInfo[];
readonly comment: string;
/** Present when {@link GetMembersOfTypeOptions.includeDeclaredType} is set. */
readonly declaredType?: Type | undefined;
}

export class Checker {
private snapshotId: number;
private project: Project;
Expand Down Expand Up @@ -3145,6 +3198,63 @@ export class Checker {
});
}

/**
* Returns the documentation comment and JSDoc tags of many symbols in one request.
* Each entry matches {@link getJsDocTagsOfSymbol} and {@link getDocumentationCommentOfSymbol}.
*/
async getSymbolDocumentations(symbols: readonly Symbol[]): Promise<SymbolDocumentation[]> {
if (symbols.length === 0) {
return [];
}
const data = await this.client.apiRequest("getSymbolDocumentations", {
snapshot: this.snapshotId,
project: this.project.handle,
symbols: symbols.map(symbol => symbol.reference),
});
return data.map(entry => ({
tags: entry.tags ?? [],
comment: entry.comment,
}));
}

/**
* Returns the members of a type that pass `options`, in one request.
* Member symbols are the same objects {@link getPropertiesOfType} returns, and
* `declaredType` is the same type {@link getTypeOfSymbol} returns.
* Without `includeInheritedFrom`, only members declared on the type itself are returned.
*/
async getMembersOfType(type: Type, options?: GetMembersOfTypeOptions): Promise<TypeMember[]> {
const data = await this.client.apiRequest("getMembersOfType", {
snapshot: this.snapshotId,
project: this.project.handle,
type: type.id,
filter: options && {
visibility: options.visibility && [...options.visibility],
kinds: options.kinds && [...options.kinds],
excludeJsDocTags: options.excludeJsDocTags && [...options.excludeJsDocTags],
excludeNamePattern: options.excludeNamePattern,
includeDeclaredType: options.includeDeclaredType,
includeInheritedFrom: options.includeInheritedFrom && {
all: options.includeInheritedFrom.all,
types: options.includeInheritedFrom.types?.map(inherited => inherited.id),
},
},
});
return data.map(entry => {
if (!entry.symbol) {
throw new Error("getMembersOfType returned a member without a symbol");
}
return {
symbol: this.objectRegistry.getOrCreateSymbol(entry.symbol),
declaringSymbol: entry.declaringSymbol ? this.objectRegistry.getOrCreateSymbol(entry.declaringSymbol) : undefined,
kind: entry.kind as MemberKind,
tags: entry.tags ?? [],
comment: entry.comment,
declaredType: entry.declaredType ? this.objectRegistry.getOrCreateType(entry.declaredType) : undefined,
};
});
}

/**
* Get the type arguments of a type reference (e.g. the `string` in `Array<string>`).
*/
Expand Down
69 changes: 69 additions & 0 deletions packages/typescript/src/api/proto.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ export interface APIMethodInfo {
getMemberInModuleExports: APIMethod<GetMemberInModuleExportsParams, SymbolResponse | null>;
getJsDocTags: APIMethod<CheckerSymbolParams, JSDocTagInfo[] | null>;
getDocumentationComment: APIMethod<CheckerSymbolParams, string>;
getSymbolDocumentations: APIMethod<GetSymbolDocumentationsParams, SymbolDocumentationResponse[]>;
getMembersOfType: APIMethod<GetMembersOfTypeParams, MemberOfTypeResponse[]>;
isArrayType: APIMethod<CheckerTypeParams, boolean>;
isReadonlySymbol: APIMethod<CheckerSymbolParams, boolean>;
getReferencesToSymbolInFile: APIMethod<GetReferencesToSymbolInFileParams, string[]>;
Expand Down Expand Up @@ -950,6 +952,44 @@ export interface JSDocTagInfo {
text?: string | undefined;
}

/** GetSymbolDocumentationsParams requests the documentation of many symbols at once. */
export interface GetSymbolDocumentationsParams {
snapshot: number;
project: number;
symbols: readonly SymbolReference[] | null;
}

/**
* SymbolDocumentationResponse is the JSDoc getJsDocTags and getDocumentationComment
* return for one symbol. Tags is null when the symbol has no tags, matching getJsDocTags.
*/
export interface SymbolDocumentationResponse {
tags: JSDocTagInfo[] | null;
comment: string;
}

/** GetMembersOfTypeParams requests the members of one type. */
export interface GetMembersOfTypeParams {
snapshot: number;
project: number;
type: number;
filter?: MembersOfTypeFilter | undefined;
}

/**
* MemberOfTypeResponse is one member of a type. Symbol and DeclaringSymbol use
* the same handles as getPropertiesOfType and getParentOfSymbol. DeclaredType,
* when requested, is the same type getTypeOfSymbol returns.
*/
export interface MemberOfTypeResponse {
symbol: SymbolResponse | null;
declaringSymbol?: SymbolResponse | undefined;
kind: string;
tags: JSDocTagInfo[] | null;
comment: string;
declaredType?: TypeResponse | undefined;
}

/** GetReferencesToSymbolInFileParams are the parameters for the getReferencesToSymbolInFile method. */
export interface GetReferencesToSymbolInFileParams {
snapshot: number;
Expand Down Expand Up @@ -1220,6 +1260,7 @@ export interface BatchRequest {
| "getLocalTypeParametersOfType"
| "getMemberInModuleExports"
| "getMembersOfSymbol"
| "getMembersOfType"
| "getMergedSymbol"
| "getModeForResolutionAtIndex"
| "getModeForUsageLocation"
Expand Down Expand Up @@ -1262,6 +1303,7 @@ export interface BatchRequest {
| "getSuggestionDiagnostics"
| "getSymbolAtLocation"
| "getSymbolAtPosition"
| "getSymbolDocumentations"
| "getSymbolOfDeclaration"
| "getSymbolOfDeclarationForChecker"
| "getSymbolOfNode"
Expand Down Expand Up @@ -1402,6 +1444,7 @@ export interface BatchResponse {
| "getLocalTypeParametersOfType"
| "getMemberInModuleExports"
| "getMembersOfSymbol"
| "getMembersOfType"
| "getMergedSymbol"
| "getModeForResolutionAtIndex"
| "getModeForUsageLocation"
Expand Down Expand Up @@ -1444,6 +1487,7 @@ export interface BatchResponse {
| "getSuggestionDiagnostics"
| "getSymbolAtLocation"
| "getSymbolAtPosition"
| "getSymbolDocumentations"
| "getSymbolOfDeclaration"
| "getSymbolOfDeclarationForChecker"
| "getSymbolOfNode"
Expand Down Expand Up @@ -1682,6 +1726,20 @@ export interface ImportAdderAction {
isValidTypeOnlyUseSite?: boolean | undefined;
}

/**
* MembersOfTypeFilter drops members before their types are materialized.
* Every condition is optional. Visibility and Kinds are independent allow-lists;
* an empty list does not filter. ExcludeNamePattern is a RE2 regular expression.
*/
export interface MembersOfTypeFilter {
visibility?: string[] | undefined;
kinds?: string[] | undefined;
excludeJsDocTags?: string[] | undefined;
excludeNamePattern?: string | undefined;
includeInheritedFrom?: MembersInheritedFrom | undefined;
includeDeclaredType?: boolean | undefined;
}

/** CompletionEntryResponse represents a single completion item. */
export interface CompletionEntryResponse {
name: string;
Expand Down Expand Up @@ -1772,6 +1830,17 @@ export interface ModuleResolutionEntry {
result: StaticModuleResolution;
}

/**
* MembersInheritedFrom selects declaring types whose members are included in
* addition to the queried type's own members. All includes every member
* getPropertiesOfType would return. An absent filter, or one with neither All
* nor Types, returns own members only.
*/
export interface MembersInheritedFrom {
all?: boolean | undefined;
types?: number[] | undefined;
}

/** CompletionEntryLabelDetailsResponse holds additional label display text for a completion entry. */
export interface CompletionEntryLabelDetailsResponse {
detail?: string | undefined;
Expand Down
Loading