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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions packages/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
"@typescript/source": "./src/api/fs.ts",
"default": "./dist/api/fs.js"
},
"./unstable/path": {
"@typescript/source": "./src/api/typedPaths.ts",
"default": "./dist/api/typedPaths.js"
},
"./unstable/proto": {
"@typescript/source": "./src/api/proto.ts",
"default": "./dist/api/proto.js"
Expand Down
131 changes: 86 additions & 45 deletions packages/typescript/src/api/async/api.ts

Large diffs are not rendered by default.

87 changes: 70 additions & 17 deletions packages/typescript/src/api/async/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import {
} from "#vscode-jsonrpc/node";
import type { ChildProcess } from "node:child_process";
import type { Socket } from "node:net";
import type {
RootedDirectoryPath,
RootedFilePath,
RootedPath,
} from "../../ast/index.ts";
import type { FileSystemCallbacks } from "../fs.ts";
import {
configureFileSystemCallbacks,
Expand Down Expand Up @@ -142,24 +147,72 @@ export class Client {
): void {
if (!fs) return;
for (const name of configuration.callbackNames) {
if (name === "writeFile") {
const callback = fs.writeFile;
if (typeof callback !== "function") throw new Error("Invalid writeFile callback configuration");

const requestType = new RequestType<{ path: string; data: string; }, unknown, void>(name);
connection.onRequest(requestType, (arg: { path: string; data: string; }) => {
return encodeFileSystemCallbackResult(name, callback(arg.path, arg.data));
});

continue;
switch (name) {
case "readFile": {
const callback = fs.readFile;
if (typeof callback !== "function") throw new Error("Invalid readFile callback configuration");
connection.onRequest(new RequestType<RootedFilePath, unknown, void>(name), fileName => {
return encodeFileSystemCallbackResult(name, callback(fileName));
});
break;
}
case "fileExists": {
const callback = fs.fileExists;
if (typeof callback !== "function") throw new Error("Invalid fileExists callback configuration");
connection.onRequest(new RequestType<RootedFilePath, unknown, void>(name), fileName => {
return encodeFileSystemCallbackResult(name, callback(fileName));
});
break;
}
case "directoryExists": {
const callback = fs.directoryExists;
if (typeof callback !== "function") throw new Error("Invalid directoryExists callback configuration");
connection.onRequest(new RequestType<RootedDirectoryPath, unknown, void>(name), directoryName => {
return encodeFileSystemCallbackResult(name, callback(directoryName));
});
break;
}
case "getAccessibleEntries": {
const callback = fs.getAccessibleEntries;
if (typeof callback !== "function") throw new Error("Invalid getAccessibleEntries callback configuration");
connection.onRequest(new RequestType<RootedDirectoryPath, unknown, void>(name), directoryName => {
return encodeFileSystemCallbackResult(name, callback(directoryName));
});
break;
}
case "realpath": {
const callback = fs.realpath;
if (typeof callback !== "function") throw new Error("Invalid realpath callback configuration");
connection.onRequest(new RequestType<RootedPath, unknown, void>(name), path => {
return encodeFileSystemCallbackResult(name, callback(path));
});
break;
}
case "stat": {
const callback = fs.stat;
if (typeof callback !== "function") throw new Error("Invalid stat callback configuration");
connection.onRequest(new RequestType<RootedPath, unknown, void>(name), path => {
return encodeFileSystemCallbackResult(name, callback(path));
});
break;
}
case "writeFile": {
const callback = fs.writeFile;
if (typeof callback !== "function") throw new Error("Invalid writeFile callback configuration");
connection.onRequest(new RequestType<{ path: RootedFilePath; data: string; }, unknown, void>(name), arg => {
return encodeFileSystemCallbackResult(name, callback(arg.path, arg.data));
});
break;
}
case "removeFile": {
const callback = fs.removeFile;
if (typeof callback !== "function") throw new Error("Invalid removeFile callback configuration");
connection.onRequest(new RequestType<RootedPath, unknown, void>(name), path => {
return encodeFileSystemCallbackResult(name, callback(path));
});
break;
}
}

const callback = fs[name];
if (typeof callback !== "function") throw new Error(`Invalid ${name} callback configuration`);
const requestType = new RequestType<unknown, unknown, void>(name);
connection.onRequest(requestType, (arg: unknown) => {
return encodeFileSystemCallbackResult(name, callback(arg as string));
});
}
}

Expand Down
7 changes: 4 additions & 3 deletions packages/typescript/src/api/async/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
NamedTupleMember,
ParameterDeclaration,
} from "../../ast/ast.ts";
import type { RootedFilePath } from "../../ast/index.ts";
import type {
Diagnostic,
RequestFileSystem,
Expand Down Expand Up @@ -417,21 +418,21 @@ export interface FormatDiagnosticsHost {

export interface EmitOutputFile {
readonly text: string;
readonly sourceFileName?: string | undefined;
readonly sourceFileName?: RootedFilePath | undefined;
}

export interface EmitResult {
readonly emitSkipped: boolean;
readonly diagnostics: readonly Diagnostic[];
readonly emittedFiles: readonly string[];
readonly emittedFiles: readonly RootedFilePath[];
/** Emitted files captured as a filesystem layer suitable for {@link Snapshot.update}. */
readonly fileSystem?: RequestFileSystem | undefined;
}

export interface EmitOutput {
readonly emitSkipped: boolean;
readonly diagnostics: readonly Diagnostic[];
readonly outputFiles: ReadonlyMap<string, EmitOutputFile>;
readonly outputFiles: ReadonlyMap<RootedFilePath, EmitOutputFile>;
}

export interface ImportSymbolAction {
Expand Down
21 changes: 13 additions & 8 deletions packages/typescript/src/api/compilerOptions.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import type { ModuleKind } from "#enums/moduleKind";
import type { ModuleResolutionKind } from "#enums/moduleResolutionKind";
import type { NewLineKind } from "#enums/newLineKind";
import type { ScriptTarget } from "#enums/scriptTarget";
import type {
RootedDirectoryPath,
RootedFilePath,
RootedPath,
} from "../ast/index.ts";

export { JsxEmit } from "#enums/jsxEmit";
export { ModuleDetectionKind } from "#enums/moduleDetectionKind";
Expand All @@ -31,7 +36,7 @@ export interface CompilerOptions {
emitBOM?: boolean | undefined;
emitDecoratorMetadata?: boolean | undefined;
declaration?: boolean | undefined;
declarationDir?: string | undefined;
declarationDir?: RootedDirectoryPath | undefined;
declarationMap?: boolean | undefined;
deduplicatePackages?: boolean | undefined;
disableSizeLimit?: boolean | undefined;
Expand Down Expand Up @@ -81,21 +86,21 @@ export interface CompilerOptions {
noResolve?: boolean | undefined;
noImplicitOverride?: boolean | undefined;
noUncheckedSideEffectImports?: boolean | undefined;
outDir?: string | undefined;
outDir?: RootedDirectoryPath | undefined;
paths?: Record<string, string[]> | undefined;
/** Plugins are parsed only so tools can report that native TypeScript does not support them. */
plugins?: PluginImport[] | undefined;
preserveConstEnums?: boolean | undefined;
preserveSymlinks?: boolean | undefined;
project?: string | undefined;
project?: RootedPath | undefined;
resolveJsonModule?: boolean | undefined;
resolvePackageJsonExports?: boolean | undefined;
resolvePackageJsonImports?: boolean | undefined;
removeComments?: boolean | undefined;
rewriteRelativeImportExtensions?: boolean | undefined;
reactNamespace?: string | undefined;
rootDir?: string | undefined;
rootDirs?: string[] | undefined;
rootDir?: RootedDirectoryPath | undefined;
rootDirs?: RootedDirectoryPath[] | undefined;
skipLibCheck?: boolean | undefined;
stableTypeOrdering?: boolean | undefined;
strict?: boolean | undefined;
Expand All @@ -111,8 +116,8 @@ export interface CompilerOptions {
suppressOutputPathCheck?: boolean | undefined;
target?: ScriptTarget | undefined;
traceResolution?: boolean | undefined;
tsBuildInfoFile?: string | undefined;
typeRoots?: string[] | undefined;
tsBuildInfoFile?: RootedFilePath | undefined;
typeRoots?: RootedDirectoryPath[] | undefined;
types?: string[] | undefined;
useDefineForClassFields?: boolean | undefined;
useUnknownInCatchVariables?: boolean | undefined;
Expand All @@ -121,7 +126,7 @@ export interface CompilerOptions {

// Internal fields

configFilePath?: string | undefined;
configFilePath?: RootedFilePath | undefined;
}

export interface PluginImport {
Expand Down
3 changes: 2 additions & 1 deletion packages/typescript/src/api/diagnosticFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RootedFilePath } from "../ast/index.ts";
import { convertToRelativePath } from "./path.ts";
import type { DiagnosticResponse as Diagnostic } from "./proto.generated.ts";

Expand Down Expand Up @@ -70,7 +71,7 @@ function flattenDiagnosticMessage(diagnostic: Diagnostic, newLine: string, inden
return result;
}

function relativeFileName(fileName: string, host: FormatDiagnosticsHost): string {
function relativeFileName(fileName: RootedFilePath, host: FormatDiagnosticsHost): string {
return convertToRelativePath(
fileName,
host.getCurrentDirectory(),
Expand Down
22 changes: 14 additions & 8 deletions packages/typescript/src/api/fs.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import getExePath from "#getExePath";
import { dirname } from "node:path";
import type {
RootedDirectoryPath,
RootedFilePath,
RootedPath,
} from "../ast/index.ts";
import { normalizePath } from "./path.ts";
import type {
RequestDirectoryEntries,
Expand Down Expand Up @@ -54,15 +59,15 @@ export const serverFS: {

export interface FileSystemCallbacks {
directoryExists:
| ((directoryName: string) => boolean | typeof serverFS.useOS | typeof serverFS.error)
| ((directoryName: RootedDirectoryPath) => boolean | typeof serverFS.useOS | typeof serverFS.error)
| typeof serverFS.useOS
| typeof serverFS.error;
fileExists:
| ((fileName: string) => boolean | typeof serverFS.useOS | typeof serverFS.error)
| ((fileName: RootedFilePath) => boolean | typeof serverFS.useOS | typeof serverFS.error)
| typeof serverFS.useOS
| typeof serverFS.error;
getAccessibleEntries:
| ((directoryName: string) => FileSystemEntries | typeof serverFS.useOS | typeof serverFS.error)
| ((directoryName: RootedDirectoryPath) => FileSystemEntries | typeof serverFS.useOS | typeof serverFS.error)
| typeof serverFS.useOS
| typeof serverFS.error;
/**
Expand All @@ -72,26 +77,27 @@ export interface FileSystemCallbacks {
* - Return {@link serverFS.useOS} to fall back to the server's operating-system filesystem.
*/
readFile:
| ((fileName: string) => string | undefined | typeof serverFS.useOS | typeof serverFS.error)
| ((fileName: RootedFilePath) => string | undefined | typeof serverFS.useOS | typeof serverFS.error)
| typeof serverFS.useOS
| typeof serverFS.error;
/** Relative results are resolved against the queried path's directory by the server. */
realpath:
| ((path: string) => string | typeof serverFS.useOS | typeof serverFS.identity | typeof serverFS.error)
| ((path: RootedPath) => string | typeof serverFS.useOS | typeof serverFS.identity | typeof serverFS.error)
| typeof serverFS.useOS
| typeof serverFS.identity
| typeof serverFS.error;
stat:
| ((path: string) => FileSystemStat | undefined | typeof serverFS.useOS | typeof serverFS.fakeStat | typeof serverFS.error)
| ((path: RootedPath) => FileSystemStat | undefined | typeof serverFS.useOS | typeof serverFS.fakeStat | typeof serverFS.error)
| typeof serverFS.useOS
| typeof serverFS.fakeStat
| typeof serverFS.error;
writeFile:
| ((path: string, content: string) => void | typeof serverFS.useOS | typeof serverFS.noop | typeof serverFS.error)
| ((path: RootedFilePath, content: string) => void | typeof serverFS.useOS | typeof serverFS.noop | typeof serverFS.error)
| typeof serverFS.useOS
| typeof serverFS.noop
| typeof serverFS.error;
removeFile:
| ((path: string) => void | typeof serverFS.useOS | typeof serverFS.noop | typeof serverFS.error)
| ((path: RootedPath) => void | typeof serverFS.useOS | typeof serverFS.noop | typeof serverFS.error)
| typeof serverFS.useOS
| typeof serverFS.noop
| typeof serverFS.error;
Expand Down
1 change: 1 addition & 0 deletions packages/typescript/src/api/node/node.infrastructure.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
type FileReference,
type Node,
type PathKey,
SyntaxKind,
} from "../../ast/index.ts";
export { modifierToFlag } from "../../ast/modifiers.ts";
Expand Down
Loading
Loading