-
Notifications
You must be signed in to change notification settings - Fork 12.8k
"tsc -b" with minimal watch capabilities #24465
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
Conversation
* | ||
* NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. | ||
*/ | ||
public utimesSync(path: string, atime: Date, mtime: Date) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally had this as part of the VFS, the relevant code can be found here: https://gist.github.com/rbuckton/1d064ec108afc0479bc1457d8a46792e#file-filesystem-ts-L596
You should verify the file system isn't read-only before performing updates so that you don't inadvertently modify a copy of the FS shared between multiple tests, i.e.:
if (this.isReadOnly) throw new IOError("EROFS");
throw createIOError("ENOENT"); | ||
} | ||
entry.node.atimeMs = +atime; | ||
entry.node.mtimeMs = +mtime; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should also set entry.node.ctimeMs = this.time()
to set the status change time when you update atimeMs
or mtimeMs
.
lineStart = false; | ||
} | ||
output += s; | ||
updateLineCountAndPosFor(s); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we are walking now every string we write in the emitter to find lineStarts? why is this needed? do you know the perf impact on the emitter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't count the lines and the length of the last one, we don't set the line and column correctly for get line and column, resulting in incorrect sourcemaps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i understand, but how often are these functions called with multi-line text? can we split these to have their own writer function to avoid doing this on every token we write?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably best to discuss this in #24704
src/compiler/tsbuild.ts
Outdated
/** | ||
* Issue a verbose diagnostic message. No-ops when options.verbose is false. | ||
*/ | ||
verbose(diag: DiagnosticMessage, ...args: any[]): void; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in other parts of the system, we have done this through host objects.
src/compiler/tsbuild.ts
Outdated
*/ | ||
function createFileMap<T>(): FileMap<T> { | ||
// tslint:disable-next-line:no-null-keyword | ||
const lookup: { [key: string]: T } = Object.create(/*prototype*/ null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
createMap?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ES Maps has better memory characteristics than objects, since they do not hold on to the property name strings.
src/compiler/tsbuild.ts
Outdated
if (arr.indexOf(element) < 0) { | ||
arr.push(element); | ||
} | ||
if (allKeys.indexOf(key) < 0) allKeys.push(key); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider using a map and returning keys, instead of using indexof
|
||
function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine) { | ||
const relativePath = getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath!), inputFileName, /*ignoreCase*/ true); | ||
const outputPath = resolvePath(configFile.options.declarationDir || configFile.options.outDir || getDirectoryPath(configFile.options.configFilePath!), relativePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like getDeclarationEmitOutputFilePath
, can we consolidate?
src/compiler/tsbuild.ts
Outdated
return changeExtension(outputPath, ".d.ts"); | ||
} | ||
|
||
function getOutputJavaScriptFileName(inputFileName: string, configFile: ParsedCommandLine) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like getOwnEmitOutputFilePath. can we consolidate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Holding off on these because getOwnEmitOutputFilePath
needs a SourceFile
and an EmitHost
and we have neither at this point.
src/compiler/tsbuild.ts
Outdated
} | ||
|
||
function getOutputFileNames(inputFileName: string, configFile: ParsedCommandLine): ReadonlyArray<string> { | ||
if (configFile.options.outFile) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is out
as well.
src/compiler/tsbuild.ts
Outdated
|
||
function getOutFileOutputs(project: ParsedCommandLine): ReadonlyArray<string> { | ||
if (!project.options.outFile) { | ||
throw new Error("Assert - outFile must be set"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug.fail
src/compiler/tsbuild.ts
Outdated
throw new Error("Assert - outFile must be set"); | ||
} | ||
const outputs: string[] = []; | ||
outputs.push(project.options.outFile); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks a lot like getOutputPathsFor. just use that instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same problem here; those functions were written taking much wider inputs than required or present
src/compiler/tsbuild.ts
Outdated
} | ||
|
||
function isDeclarationFile(fileName: string) { | ||
return fileExtensionIs(fileName, ".d.ts"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, use Extension.Dts
instead of ".d.ts"
src/compiler/tsbuild.ts
Outdated
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(f => `\r\n * ${f}`).join(""))); | ||
} | ||
else { | ||
if (!host.deleteFile) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like this should be the first check
src/compiler/tsbuild.ts
Outdated
if (host.fileExists(fullPath)) { | ||
return fullPath as ResolvedConfigFileName; | ||
} | ||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.File_0_not_found, fullPath)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will say something like c:\myconfig.json\tsconfig.json
does not exist
}; | ||
const program = createProgram(programOptions); | ||
|
||
// Don't emit anything in the presence of syntactic errors or options diagnostics |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why? we emit in the presence of errors in tsc.. and why are option errors different from semantic errors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, we are not building for any errors.. nevermind then.
src/compiler/tsbuild.ts
Outdated
rootNames: configFile.fileNames, | ||
options: configFile.options | ||
}; | ||
const program = createProgram(programOptions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should not this just call inot the same routine we have in tsc.ts to perform the compilation, why does it have to be different?
src/compiler/tsbuild.ts
Outdated
} | ||
} | ||
|
||
const semanticDiagnostics = [...program.getSemanticDiagnostics()]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why clone it?
Overall 👍 with some comments:
|
See #22997
Implements
tsbuild
without--watch
. Opening so people have a chance to review non-watch portions sooner. Not planning to merge this unless there is schedule pressure to produce a non-watch build.I also want to rephrase ~all of the error messages and would like suggestions on any of them
@rbuckton there's a vfs fix in here because we were re-using
SourceFile
instances even when the underlying file was changedOpen TODOs I'm aware of:
--verbose
output should be in all situations (seeking feedback)-b
appears out of order in a commandline-b
flags is provided (e.g.--clean --dry --force
, which makes no sense)outFile
compilation to the sample projects folder--build --help
--build
mode (do we need this?)