Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simply create a new file when calling updateFile #3154

Open
wants to merge 2 commits into
base: v2
Choose a base branch
from
Open
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
60 changes: 26 additions & 34 deletions packages/typescript-vfs/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
type System = import("typescript").System
type CompilerOptions = import("typescript").CompilerOptions
type CustomTransformers = import("typescript").CustomTransformers
type LanguageServiceHost = import("typescript").LanguageServiceHost
type CompilerHost = import("typescript").CompilerHost
type SourceFile = import("typescript").SourceFile
type TS = typeof import("typescript")
import type {
System,
CompilerOptions,
CustomTransformers,
SourceFile,
CompilerHost,
LanguageServiceHost,
} from "typescript"
import type TS from "typescript"

type FetchLike = (url: string) => Promise<{ json(): Promise<any>; text(): Promise<string> }>

Expand All @@ -14,13 +16,13 @@ interface LocalStorageLike {
removeItem(key: string): void
}

declare var localStorage: LocalStorageLike | undefined;
declare var fetch: FetchLike | undefined;
declare var localStorage: LocalStorageLike | undefined
declare var fetch: FetchLike | undefined

let hasLocalStorage = false
try {
hasLocalStorage = typeof localStorage !== `undefined`
} catch (error) { }
} catch (error) {}

const hasProcess = typeof process !== `undefined`
const shouldDebug = (hasLocalStorage && localStorage!.getItem("DEBUG")) || (hasProcess && process.env.DEBUG)
Expand All @@ -31,7 +33,7 @@ export interface VirtualTypeScriptEnvironment {
languageService: import("typescript").LanguageService
getSourceFile: (fileName: string) => import("typescript").SourceFile | undefined
createFile: (fileName: string, content: string) => void
updateFile: (fileName: string, content: string, replaceTextSpan?: import("typescript").TextSpan) => void
updateFile: (fileName: string, content: string) => void
}

/**
Expand All @@ -48,7 +50,7 @@ export interface VirtualTypeScriptEnvironment {
export function createVirtualTypeScriptEnvironment(
sys: System,
rootFiles: string[],
ts: TS,
ts: typeof TS,
compilerOptions: CompilerOptions = {},
customTransformers?: CustomTransformers
): VirtualTypeScriptEnvironment {
Expand Down Expand Up @@ -77,25 +79,15 @@ export function createVirtualTypeScriptEnvironment(
getSourceFile: fileName => languageService.getProgram()?.getSourceFile(fileName),

createFile: (fileName, content) => {
updateFile(ts.createSourceFile(fileName, content, mergedCompilerOpts.target!, false))
updateFile(ts.createSourceFile(fileName, content, mergedCompilerOpts.target!))
},
updateFile: (fileName, content, optPrevTextSpan) => {
updateFile: (fileName, content) => {
const prevSourceFile = languageService.getProgram()!.getSourceFile(fileName)
if (!prevSourceFile) {
throw new Error("Did not find a source file for " + fileName)
}
const prevFullContents = prevSourceFile.text

// TODO: Validate if the default text span has a fencepost error?
const prevTextSpan = optPrevTextSpan ?? ts.createTextSpan(0, prevFullContents.length)
const newText =
prevFullContents.slice(0, prevTextSpan.start) +
content +
prevFullContents.slice(prevTextSpan.start + prevTextSpan.length)
const newSourceFile = ts.updateSourceFile(prevSourceFile, newText, {
span: prevTextSpan,
newLength: content.length,
})

const newSourceFile = ts.createSourceFile(fileName, content, mergedCompilerOpts.target!)

updateFile(newSourceFile)
},
Expand All @@ -113,7 +105,7 @@ export function createVirtualTypeScriptEnvironment(
* @param target The compiler settings target baseline
* @param ts A copy of the TypeScript module
*/
export const knownLibFilesForCompilerOptions = (compilerOptions: CompilerOptions, ts: TS) => {
export const knownLibFilesForCompilerOptions = (compilerOptions: CompilerOptions, ts: typeof TS) => {
const target = compilerOptions.target || ts.ScriptTarget.ES5
const lib = compilerOptions.lib || []

Expand Down Expand Up @@ -207,7 +199,7 @@ export const knownLibFilesForCompilerOptions = (compilerOptions: CompilerOptions
"lib.esnext.promise.d.ts",
"lib.esnext.string.d.ts",
"lib.esnext.symbol.d.ts",
"lib.esnext.weakref.d.ts"
"lib.esnext.weakref.d.ts",
]

const targetToCut = ts.ScriptTarget[target]
Expand Down Expand Up @@ -326,7 +318,7 @@ export const createDefaultMapFromCDN = (
options: CompilerOptions,
version: string,
cache: boolean,
ts: TS,
ts: typeof TS,
lzstring?: LZString,
fetcher?: FetchLike,
storer?: LocalStorageLike
Expand All @@ -352,7 +344,7 @@ export const createDefaultMapFromCDN = (
contents.forEach((text, index) => fsMap.set("/" + files[index], text))
})
// Return a NOOP for .d.ts files which aren't in the current build of TypeScript
.catch(() => { })
.catch(() => {})
)
}

Expand Down Expand Up @@ -383,7 +375,7 @@ export const createDefaultMapFromCDN = (
return t
})
// Return a NOOP for .d.ts files which aren't in the current build of TypeScript
.catch(() => { })
.catch(() => {})
)
} else {
return Promise.resolve(unzip(content))
Expand Down Expand Up @@ -477,7 +469,7 @@ export function createSystem(files: Map<string, string>): System {
export function createFSBackedSystem(
files: Map<string, string>,
_projectRoot: string,
ts: TS,
ts: typeof TS,
tsLibDirectory?: string
): System {
// We need to make an isolated folder for the tsconfig, but also need to be able to resolve the
Expand Down Expand Up @@ -554,7 +546,7 @@ export function createFSBackedSystem(
* which works with TypeScript objects - returns both a compiler host, and a way to add new SourceFile
* instances to the in-memory file system.
*/
export function createVirtualCompilerHost(sys: System, compilerOptions: CompilerOptions, ts: TS) {
export function createVirtualCompilerHost(sys: System, compilerOptions: CompilerOptions, ts: typeof TS) {
const sourceFiles = new Map<string, SourceFile>()
const save = (sourceFile: SourceFile) => {
sourceFiles.set(sourceFile.fileName, sourceFile)
Expand Down Expand Up @@ -606,7 +598,7 @@ export function createVirtualLanguageServiceHost(
sys: System,
rootFiles: string[],
compilerOptions: CompilerOptions,
ts: TS,
ts: typeof TS,
customTransformers?: CustomTransformers
) {
const fileNames = [...rootFiles]
Expand Down
Loading