Skip to content

Commit fbfec8a

Browse files
committed
Simplified cache logic + better error message when JSON not supported
1 parent 25e52a3 commit fbfec8a

1 file changed

Lines changed: 39 additions & 58 deletions

File tree

src/compiler/tsc.ts

Lines changed: 39 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ module ts {
130130
reportStatisticalValue(name, (time / 1000).toFixed(2) + "s");
131131
}
132132

133+
function isJSONSupported() {
134+
return typeof JSON === "object" && typeof JSON.parse === "function";
135+
}
136+
133137
function findConfigFile(): string {
134138
var searchPath = normalizePath(sys.getCurrentDirectory());
135139
var filename = "tsconfig.json";
@@ -151,17 +155,17 @@ module ts {
151155
var commandLine = parseCommandLine(args);
152156
var configFilename: string; // Configuration file name (if any)
153157
var configFileWatcher: FileWatcher; // Configuration file watcher
154-
var cachedSourceFiles: Map<SourceFile>; // Cached SourceFile objects
158+
var cachedProgram: Program; // Program cached from last compilation
155159
var rootFilenames: string[]; // Root filenames for compilation
156160
var compilerOptions: CompilerOptions; // Compiler options for compilation
157161
var compilerHost: CompilerHost; // Compiler host
158162
var hostGetSourceFile: typeof compilerHost.getSourceFile; // getSourceFile method from default host
159163
var timerHandle: number; // Handle for 0.25s wait timer
160164

161165
if (commandLine.options.locale) {
162-
if (typeof JSON === "undefined") {
166+
if (!isJSONSupported()) {
163167
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"));
164-
return sys.exit(1);
168+
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
165169
}
166170
validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors);
167171
}
@@ -185,13 +189,17 @@ module ts {
185189
}
186190

187191
if (commandLine.options.project) {
192+
if (!isJSONSupported()) {
193+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"));
194+
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
195+
}
188196
configFilename = normalizePath(combinePaths(commandLine.options.project, "tsconfig.json"));
189197
if (commandLine.filenames.length !== 0) {
190198
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line));
191199
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
192200
}
193201
}
194-
else if (commandLine.filenames.length === 0) {
202+
else if (commandLine.filenames.length === 0 && isJSONSupported()) {
195203
configFilename = findConfigFile();
196204
}
197205

@@ -216,7 +224,7 @@ module ts {
216224
// Invoked to perform initial compilation or re-compilation in watch mode
217225
function performCompilation() {
218226

219-
if (!cachedSourceFiles) {
227+
if (!cachedProgram) {
220228
if (configFilename) {
221229
var configObject = readConfigFile(configFilename);
222230
if (!configObject) {
@@ -246,80 +254,53 @@ module ts {
246254
return sys.exit(compileResult.exitStatus);
247255
}
248256

249-
updateSourceFileCache(compileResult.program.getSourceFiles());
257+
setCachedProgram(compileResult.program);
250258
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes));
251259
}
252260

253261
function getSourceFile(filename: string, languageVersion: ScriptTarget, onError ?: (message: string) => void) {
254262
// Return existing SourceFile object if one is available
255-
if (cachedSourceFiles) {
256-
var canonicalName = compilerHost.getCanonicalFileName(filename);
257-
if (hasProperty(cachedSourceFiles, canonicalName)) {
258-
return cachedSourceFiles[canonicalName];
263+
if (cachedProgram) {
264+
var sourceFile = cachedProgram.getSourceFile(filename);
265+
// A modified source file has no watcher and should not be reused
266+
if (sourceFile && sourceFile.fileWatcher) {
267+
return sourceFile;
259268
}
260269
}
261270
// Use default host function
262271
var sourceFile = hostGetSourceFile(filename, languageVersion, onError);
263-
// Cache the source file in -watch mode
264272
if (sourceFile && commandLine.options.watch) {
265-
cacheSourceFile(sourceFile);
273+
// Attach a file watcher
274+
sourceFile.fileWatcher = sys.watchFile(sourceFile.filename, () => sourceFileChanged(sourceFile));
266275
}
267276
return sourceFile;
268277
}
269278

270-
// Cache the given source file and watch for changes
271-
function cacheSourceFile(sourceFile: SourceFile) {
272-
cachedSourceFiles = cachedSourceFiles || {};
273-
cachedSourceFiles[compilerHost.getCanonicalFileName(sourceFile.filename)] = sourceFile;
274-
sourceFile.fileWatcher = sys.watchFile(sourceFile.filename, sourceFileChanged);
275-
}
276-
277-
// Remove the given source file from the cache
278-
function forgetSourceFile(sourceFile: SourceFile) {
279-
if (sourceFile.fileWatcher) {
280-
sourceFile.fileWatcher.close();
281-
sourceFile.fileWatcher = undefined;
282-
delete cachedSourceFiles[sourceFile.filename];
283-
}
284-
}
285-
286-
// Update the cache to contain only source files in the given list
287-
function updateSourceFileCache(keepSourceFiles: SourceFile[]) {
288-
for (var filename in cachedSourceFiles) {
289-
var sourceFile = cachedSourceFiles[filename];
290-
if (sourceFile) {
291-
if (!contains(keepSourceFiles, sourceFile)) {
292-
forgetSourceFile(sourceFile);
279+
// Change cached program to the given program
280+
function setCachedProgram(program: Program) {
281+
if (cachedProgram) {
282+
var newSourceFiles = program ? program.getSourceFiles() : undefined;
283+
forEach(cachedProgram.getSourceFiles(), sourceFile => {
284+
if (!(newSourceFiles && contains(newSourceFiles, sourceFile))) {
285+
if (sourceFile.fileWatcher) {
286+
sourceFile.fileWatcher.close();
287+
sourceFile.fileWatcher = undefined;
288+
}
293289
}
294-
}
290+
});
295291
}
292+
cachedProgram = program;
296293
}
297294

298-
// Remove all source files from the cache
299-
function clearSourceFileCache() {
300-
if (cachedSourceFiles) {
301-
for (var filename in cachedSourceFiles) {
302-
var sourceFile = cachedSourceFiles[filename];
303-
if (sourceFile) {
304-
forgetSourceFile(sourceFile);
305-
}
306-
}
307-
}
308-
cachedSourceFiles = undefined;
309-
}
310-
311-
// If a source file changes, remove that file from the cache and start the recompilation timer
312-
function sourceFileChanged(filename: string) {
313-
var sourceFile = cachedSourceFiles[filename];
314-
if (sourceFile) {
315-
forgetSourceFile(sourceFile);
316-
startTimer();
317-
}
295+
// If a source file changes, mark it as unwatched and start the recompilation timer
296+
function sourceFileChanged(sourceFile: SourceFile) {
297+
sourceFile.fileWatcher = undefined;
298+
startTimer();
318299
}
319300

320-
// If the configuration file changes, clear the cache and start the recompilation timer
301+
// If the configuration file changes, forget cached program and start the recompilation timer
321302
function configFileChanged() {
322-
clearSourceFileCache();
303+
setCachedProgram(undefined);
323304
startTimer();
324305
}
325306

0 commit comments

Comments
 (0)