Skip to content

Commit efe498b

Browse files
committed
Merge branch 'master' into watchOptions
2 parents c5b21d4 + ed941c2 commit efe498b

File tree

110 files changed

+2949
-1056
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+2949
-1056
lines changed

src/compiler/checker.ts

+320-225
Large diffs are not rendered by default.

src/compiler/commandLineParser.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ namespace ts {
187187
description: Diagnostics.Generates_corresponding_d_ts_file,
188188
},
189189
{
190-
name: "emitDeclarationsOnly",
190+
name: "emitDeclarationOnly",
191191
type: "boolean",
192192
category: Diagnostics.Advanced_Options,
193193
description: Diagnostics.Only_emit_d_ts_declaration_files,

src/compiler/core.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2989,7 +2989,7 @@ namespace ts {
29892989
*/
29902990
export function matchedText(pattern: Pattern, candidate: string): string {
29912991
Debug.assert(isPatternMatch(pattern, candidate));
2992-
return candidate.substr(pattern.prefix.length, candidate.length - pattern.suffix.length);
2992+
return candidate.substring(pattern.prefix.length, candidate.length - pattern.suffix.length);
29932993
}
29942994

29952995
/** Return the object corresponding to the best pattern to match `candidate`. */

src/compiler/emitter.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ namespace ts {
135135

136136
function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) {
137137
// Make sure not to write js file and source map file if any of them cannot be written
138-
if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit && !compilerOptions.emitDeclarationsOnly) {
138+
if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit && !compilerOptions.emitDeclarationOnly) {
139139
if (!emitOnlyDtsFiles) {
140140
printSourceFileOrBundle(jsFilePath, sourceMapFilePath, sourceFileOrBundle);
141141
}

src/compiler/parser.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2986,7 +2986,7 @@ namespace ts {
29862986
return parseFunctionOrConstructorType(SyntaxKind.ConstructorType);
29872987
}
29882988
const type = parseUnionTypeOrHigher();
2989-
if (!noConditionalTypes && parseOptional(SyntaxKind.ExtendsKeyword)) {
2989+
if (!noConditionalTypes && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) {
29902990
const node = <ConditionalTypeNode>createNode(SyntaxKind.ConditionalType, type.pos);
29912991
node.checkType = type;
29922992
// The type following 'extends' is not permitted to be another conditional type

src/compiler/program.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -2201,13 +2201,13 @@ namespace ts {
22012201
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "checkJs", "allowJs"));
22022202
}
22032203

2204-
if (options.emitDeclarationsOnly) {
2204+
if (options.emitDeclarationOnly) {
22052205
if (!options.declaration) {
2206-
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDeclarationsOnly", "declarations");
2206+
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDeclarationOnly", "declarations");
22072207
}
22082208

22092209
if (options.noEmit) {
2210-
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationsOnly", "noEmit");
2210+
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationOnly", "noEmit");
22112211
}
22122212
}
22132213

@@ -2233,7 +2233,7 @@ namespace ts {
22332233
const emitHost = getEmitHost();
22342234
const emitFilesSeen = createMap<true>();
22352235
forEachEmittedFile(emitHost, (emitFileNames) => {
2236-
if (!options.emitDeclarationsOnly) {
2236+
if (!options.emitDeclarationOnly) {
22372237
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
22382238
}
22392239
verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen);

src/compiler/types.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1638,7 +1638,7 @@ namespace ts {
16381638
multiLine?: boolean;
16391639
}
16401640

1641-
export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression | ParenthesizedExpression;
1641+
export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression;
16421642
export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression;
16431643

16441644
export interface PropertyAccessExpression extends MemberExpression, NamedDeclaration {
@@ -2027,6 +2027,7 @@ namespace ts {
20272027

20282028
export interface ClassDeclaration extends ClassLikeDeclarationBase, DeclarationStatement {
20292029
kind: SyntaxKind.ClassDeclaration;
2030+
/** May be undefined in `export default class { ... }`. */
20302031
name?: Identifier;
20312032
}
20322033

@@ -3310,6 +3311,7 @@ namespace ts {
33103311
immediateTarget?: Symbol; // Immediate target of an alias. May be another alias. Do not access directly, use `checker.getImmediateAliasedSymbol` instead.
33113312
target?: Symbol; // Resolved (non-alias) target of an alias
33123313
type?: Type; // Type of value symbol
3314+
uniqueESSymbolType?: Type; // UniqueESSymbol type for a symbol
33133315
declaredType?: Type; // Type of class, interface, enum, type alias, or type parameter
33143316
typeParameters?: TypeParameter[]; // Type parameters of type alias (undefined if non-generic)
33153317
outerTypeParameters?: TypeParameter[]; // Outer type parameters of anonymous object type
@@ -3903,6 +3905,7 @@ namespace ts {
39033905
}
39043906

39053907
export const enum InferenceFlags {
3908+
None = 0, // No special inference behaviors
39063909
InferUnionTypes = 1 << 0, // Infer union types for disjoint candidates (otherwise unknownType)
39073910
NoDefault = 1 << 1, // Infer unknownType for no inferences (otherwise anyType or emptyObjectType)
39083911
AnyDefault = 1 << 2, // Infer anyType for no inferences (otherwise emptyObjectType)
@@ -4024,7 +4027,7 @@ namespace ts {
40244027
/** configFile is set as non enumerable property so as to avoid checking of json source files */
40254028
/* @internal */ readonly configFile?: JsonSourceFile;
40264029
declaration?: boolean;
4027-
emitDeclarationsOnly?: boolean;
4030+
emitDeclarationOnly?: boolean;
40284031
declarationDir?: string;
40294032
/* @internal */ diagnostics?: boolean;
40304033
/* @internal */ extendedDiagnostics?: boolean;

src/compiler/utilities.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3286,7 +3286,7 @@ namespace ts {
32863286
&& isClassLike(node.parent.parent);
32873287
}
32883288

3289-
export function isEntityNameExpression(node: Expression): node is EntityNameExpression {
3289+
export function isEntityNameExpression(node: Node): node is EntityNameExpression {
32903290
return node.kind === SyntaxKind.Identifier ||
32913291
node.kind === SyntaxKind.PropertyAccessExpression && isEntityNameExpression((<PropertyAccessExpression>node).expression);
32923292
}

src/compiler/watch.ts

+56-56
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@ namespace ts {
420420
}
421421
}
422422

423+
const initialVersion = 1;
424+
423425
/**
424426
* Creates the watch from the host for root files and compiler options
425427
*/
@@ -429,19 +431,25 @@ namespace ts {
429431
*/
430432
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfConfigFile<T>): WatchOfConfigFile<T>;
431433
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfFilesAndCompilerOptions<T> & WatchCompilerHostOfConfigFile<T>): WatchOfFilesAndCompilerOptions<T> | WatchOfConfigFile<T> {
432-
interface HostFileInfo {
434+
interface FilePresentOnHost {
433435
version: number;
434436
sourceFile: SourceFile;
435437
fileWatcher: FileWatcher;
436438
}
439+
type FileMissingOnHost = number;
440+
interface FilePresenceUnknownOnHost {
441+
version: number;
442+
}
443+
type FileMayBePresentOnHost = FilePresentOnHost | FilePresenceUnknownOnHost;
444+
type HostFileInfo = FilePresentOnHost | FileMissingOnHost | FilePresenceUnknownOnHost;
437445

438446
let builderProgram: T;
439447
let reloadLevel: ConfigFileProgramReloadLevel; // level to indicate if the program needs to be reloaded from config file/just filenames etc
440448
let missingFilesMap: Map<FileWatcher>; // Map of file watchers for the missing files
441449
let watchedWildcardDirectories: Map<WildcardDirectoryWatcher>; // map of watchers for the wild card directories in the config file
442450
let timerToUpdateProgram: any; // timer callback to recompile the program
443451

444-
const sourceFilesCache = createMap<HostFileInfo | string>(); // Cache that stores the source file and version info
452+
const sourceFilesCache = createMap<HostFileInfo>(); // Cache that stores the source file and version info
445453
let missingFilePathsRequestedForRelease: Path[]; // These paths are held temparirly so that we can remove the entry from source file cache if the file is not tracked by missing files
446454
let hasChangedCompilerOptions = false; // True if the compiler options have changed between compilations
447455
let hasChangedAutomaticTypeDirectiveNames = false; // True if the automatic type directives have changed
@@ -629,11 +637,20 @@ namespace ts {
629637
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
630638
}
631639

640+
function isFileMissingOnHost(hostSourceFile: HostFileInfo): hostSourceFile is FileMissingOnHost {
641+
return typeof hostSourceFile === "number";
642+
}
643+
644+
function isFilePresentOnHost(hostSourceFile: FileMayBePresentOnHost): hostSourceFile is FilePresentOnHost {
645+
return !!(hostSourceFile as FilePresentOnHost).sourceFile;
646+
}
647+
632648
function fileExists(fileName: string) {
633649
const path = toPath(fileName);
634-
const hostSourceFileInfo = sourceFilesCache.get(path);
635-
if (hostSourceFileInfo !== undefined) {
636-
return !isString(hostSourceFileInfo);
650+
// If file is missing on host from cache, we can definitely say file doesnt exist
651+
// otherwise we need to ensure from the disk
652+
if (isFileMissingOnHost(sourceFilesCache.get(path))) {
653+
return true;
637654
}
638655

639656
return directoryStructureHost.fileExists(fileName);
@@ -642,39 +659,42 @@ namespace ts {
642659
function getVersionedSourceFileByPath(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile {
643660
const hostSourceFile = sourceFilesCache.get(path);
644661
// No source file on the host
645-
if (isString(hostSourceFile)) {
662+
if (isFileMissingOnHost(hostSourceFile)) {
646663
return undefined;
647664
}
648665

649666
// Create new source file if requested or the versions dont match
650-
if (!hostSourceFile || shouldCreateNewSourceFile || hostSourceFile.version.toString() !== hostSourceFile.sourceFile.version) {
667+
if (!hostSourceFile || shouldCreateNewSourceFile || !isFilePresentOnHost(hostSourceFile) || hostSourceFile.version.toString() !== hostSourceFile.sourceFile.version) {
651668
const sourceFile = getNewSourceFile();
652669
if (hostSourceFile) {
653670
if (shouldCreateNewSourceFile) {
654671
hostSourceFile.version++;
655672
}
673+
656674
if (sourceFile) {
657-
hostSourceFile.sourceFile = sourceFile;
675+
// Set the source file and create file watcher now that file was present on the disk
676+
(hostSourceFile as FilePresentOnHost).sourceFile = sourceFile;
658677
sourceFile.version = hostSourceFile.version.toString();
659-
if (!hostSourceFile.fileWatcher) {
660-
hostSourceFile.fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path);
678+
if (!(hostSourceFile as FilePresentOnHost).fileWatcher) {
679+
(hostSourceFile as FilePresentOnHost).fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path);
661680
}
662681
}
663682
else {
664683
// There is no source file on host any more, close the watch, missing file paths will track it
665-
hostSourceFile.fileWatcher.close();
666-
sourceFilesCache.set(path, hostSourceFile.version.toString());
684+
if (isFilePresentOnHost(hostSourceFile)) {
685+
hostSourceFile.fileWatcher.close();
686+
}
687+
sourceFilesCache.set(path, hostSourceFile.version);
667688
}
668689
}
669690
else {
670-
let fileWatcher: FileWatcher;
671691
if (sourceFile) {
672-
sourceFile.version = "1";
673-
fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path);
674-
sourceFilesCache.set(path, { sourceFile, version: 1, fileWatcher });
692+
sourceFile.version = initialVersion.toString();
693+
const fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path);
694+
sourceFilesCache.set(path, { sourceFile, version: initialVersion, fileWatcher });
675695
}
676696
else {
677-
sourceFilesCache.set(path, "0");
697+
sourceFilesCache.set(path, initialVersion);
678698
}
679699
}
680700
return sourceFile;
@@ -699,20 +719,22 @@ namespace ts {
699719
}
700720
}
701721

702-
function removeSourceFile(path: Path) {
722+
function nextSourceFileVersion(path: Path) {
703723
const hostSourceFile = sourceFilesCache.get(path);
704724
if (hostSourceFile !== undefined) {
705-
if (!isString(hostSourceFile)) {
706-
hostSourceFile.fileWatcher.close();
707-
resolutionCache.invalidateResolutionOfFile(path);
725+
if (isFileMissingOnHost(hostSourceFile)) {
726+
// The next version, lets set it as presence unknown file
727+
sourceFilesCache.set(path, { version: Number(hostSourceFile) + 1 });
728+
}
729+
else {
730+
hostSourceFile.version++;
708731
}
709-
sourceFilesCache.delete(path);
710732
}
711733
}
712734

713735
function getSourceVersion(path: Path): string {
714736
const hostSourceFile = sourceFilesCache.get(path);
715-
return !hostSourceFile || isString(hostSourceFile) ? undefined : hostSourceFile.version.toString();
737+
return !hostSourceFile || isFileMissingOnHost(hostSourceFile) ? undefined : hostSourceFile.version.toString();
716738
}
717739

718740
function onReleaseOldSourceFile(oldSourceFile: SourceFile, _oldOptions: CompilerOptions) {
@@ -723,10 +745,10 @@ namespace ts {
723745
// there was version update and new source file was created.
724746
if (hostSourceFileInfo) {
725747
// record the missing file paths so they can be removed later if watchers arent tracking them
726-
if (isString(hostSourceFileInfo)) {
748+
if (isFileMissingOnHost(hostSourceFileInfo)) {
727749
(missingFilePathsRequestedForRelease || (missingFilePathsRequestedForRelease = [])).push(oldSourceFile.path);
728750
}
729-
else if (hostSourceFileInfo.sourceFile === oldSourceFile) {
751+
else if ((hostSourceFileInfo as FilePresentOnHost).sourceFile === oldSourceFile) {
730752
sourceFilesCache.delete(oldSourceFile.path);
731753
resolutionCache.removeResolutionsOfFile(oldSourceFile.path);
732754
}
@@ -810,27 +832,12 @@ namespace ts {
810832

811833
function onSourceFileChange(fileName: string, eventKind: FileWatcherEventKind, path: Path) {
812834
updateCachedSystemWithFile(fileName, path, eventKind);
813-
const hostSourceFile = sourceFilesCache.get(path);
814-
if (hostSourceFile) {
815-
// Update the cache
816-
if (eventKind === FileWatcherEventKind.Deleted) {
817-
resolutionCache.invalidateResolutionOfFile(path);
818-
if (!isString(hostSourceFile)) {
819-
hostSourceFile.fileWatcher.close();
820-
sourceFilesCache.set(path, (++hostSourceFile.version).toString());
821-
}
822-
}
823-
else {
824-
// Deleted file created
825-
if (isString(hostSourceFile)) {
826-
sourceFilesCache.delete(path);
827-
}
828-
else {
829-
// file changed - just update the version
830-
hostSourceFile.version++;
831-
}
832-
}
835+
836+
// Update the source file cache
837+
if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.get(path)) {
838+
resolutionCache.invalidateResolutionOfFile(path);
833839
}
840+
nextSourceFileVersion(path);
834841

835842
// Update the program
836843
scheduleProgramUpdate();
@@ -858,7 +865,7 @@ namespace ts {
858865
missingFilesMap.delete(missingFilePath);
859866

860867
// Delete the entry in the source files cache so that new source file is created
861-
removeSourceFile(missingFilePath);
868+
nextSourceFileVersion(missingFilePath);
862869

863870
// When a missing file is created, we should update the graph.
864871
scheduleProgramUpdate();
@@ -887,17 +894,10 @@ namespace ts {
887894
const fileOrDirectoryPath = toPath(fileOrDirectory);
888895

889896
// Since the file existance changed, update the sourceFiles cache
890-
const result = cachedDirectoryStructureHost && cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
891-
892-
// Instead of deleting the file, mark it as changed instead
893-
// Many times node calls add/remove/file when watching directories recursively
894-
const hostSourceFile = sourceFilesCache.get(fileOrDirectoryPath);
895-
if (hostSourceFile && !isString(hostSourceFile) && (result ? result.fileExists : directoryStructureHost.fileExists(fileOrDirectory))) {
896-
hostSourceFile.version++;
897-
}
898-
else {
899-
removeSourceFile(fileOrDirectoryPath);
897+
if (cachedDirectoryStructureHost) {
898+
cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
900899
}
900+
nextSourceFileVersion(fileOrDirectoryPath);
901901

902902
// If the the added or created file or directory is not supported file name, ignore the file
903903
// But when watched directory is added/removed, we need to reload the file list

0 commit comments

Comments
 (0)