From 9c0e64d4434b68d29b9f8f9c8fb050b3285120da Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 27 Sep 2016 14:02:10 -0700 Subject: [PATCH] fix merge issues, restore tests --- src/compiler/binder.ts | 1 - src/compiler/checker.ts | 1 + src/compiler/core.ts | 72 ++++++++++++ src/compiler/emitter.ts | 13 ++- src/compiler/moduleNameResolver.ts | 69 ------------ src/services/services.ts | 9 ++ src/services/types.ts | 5 + ...assignmentTypeNarrowing_BACKUP_22380.types | 106 ------------------ .../assignmentTypeNarrowing_BASE_22380.types | 98 ---------------- .../assignmentTypeNarrowing_LOCAL_22380.types | 98 ---------------- ...assignmentTypeNarrowing_REMOTE_22380.types | 98 ---------------- 11 files changed, 97 insertions(+), 473 deletions(-) delete mode 100644 tests/baselines/reference/assignmentTypeNarrowing_BACKUP_22380.types delete mode 100644 tests/baselines/reference/assignmentTypeNarrowing_BASE_22380.types delete mode 100644 tests/baselines/reference/assignmentTypeNarrowing_LOCAL_22380.types delete mode 100644 tests/baselines/reference/assignmentTypeNarrowing_REMOTE_22380.types diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 1a0aabd97fd..49434e80aba 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1,5 +1,4 @@ /// -/// /// /* @internal */ diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 72d2ca92af0..d0781097f39 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1,3 +1,4 @@ +/// /// /* @internal */ diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 3967a867014..9de92cce3a5 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1889,6 +1889,78 @@ namespace ts { : ((fileName) => fileName.toLowerCase()); } + /** + * patternStrings contains both pattern strings (containing "*") and regular strings. + * Return an exact match if possible, or a pattern match, or undefined. + * (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.) + */ + /* @internal */ + export function matchPatternOrExact(patternStrings: string[], candidate: string): string | Pattern | undefined { + const patterns: Pattern[] = []; + for (const patternString of patternStrings) { + const pattern = tryParsePattern(patternString); + if (pattern) { + patterns.push(pattern); + } + else if (patternString === candidate) { + // pattern was matched as is - no need to search further + return patternString; + } + } + + return findBestPatternMatch(patterns, _ => _, candidate); + } + + /* @internal */ + export function patternText({prefix, suffix}: Pattern): string { + return `${prefix}*${suffix}`; + } + + /** + * Given that candidate matches pattern, returns the text matching the '*'. + * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" + */ + /* @internal */ + export function matchedText(pattern: Pattern, candidate: string): string { + Debug.assert(isPatternMatch(pattern, candidate)); + return candidate.substr(pattern.prefix.length, candidate.length - pattern.suffix.length); + } + + /** Return the object corresponding to the best pattern to match `candidate`. */ + /* @internal */ + export function findBestPatternMatch(values: T[], getPattern: (value: T) => Pattern, candidate: string): T | undefined { + let matchedValue: T | undefined = undefined; + // use length of prefix as betterness criteria + let longestMatchPrefixLength = -1; + + for (const v of values) { + const pattern = getPattern(v); + if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) { + longestMatchPrefixLength = pattern.prefix.length; + matchedValue = v; + } + } + + return matchedValue; + } + + function isPatternMatch({prefix, suffix}: Pattern, candidate: string) { + return candidate.length >= prefix.length + suffix.length && + startsWith(candidate, prefix) && + endsWith(candidate, suffix); + } + + /* @internal */ + export function tryParsePattern(pattern: string): Pattern | undefined { + // This should be verified outside of here and a proper error thrown. + Debug.assert(hasZeroOrOneAsteriskCharacter(pattern)); + const indexOfStar = pattern.indexOf("*"); + return indexOfStar === -1 ? undefined : { + prefix: pattern.substr(0, indexOfStar), + suffix: pattern.substr(indexOfStar + 1) + }; + } + export function positionIsSynthesized(pos: number): boolean { // This is a fast way of testing the following conditions: // pos === undefined || pos === null || isNaN(pos) || pos < 0; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 03de307f2f3..90742f30c16 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -13,6 +13,9 @@ namespace ts { _i = 0x10000000, // Use/preference flag for '_i' } + const id = (s: SourceFile) => s; + const nullTransformers: Transformer[] = [ctx => id]; + // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult { const delimiters = createDelimiterMap(); @@ -192,7 +195,7 @@ const _super = (function (geti, seti) { const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined; const emitterDiagnostics = createDiagnosticCollection(); const newLine = host.getNewLine(); - const transformers = getTransformers(compilerOptions); + const transformers: Transformer[] = emitOnlyDtsFiles ? nullTransformers : getTransformers(compilerOptions); const writer = createTextWriter(newLine); const { write, @@ -271,7 +274,9 @@ const _super = (function (geti, seti) { function emitFile(jsFilePath: string, sourceMapFilePath: string, declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) { // Make sure not to write js file and source map file if any of them cannot be written if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) { - printFile(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); + if (!emitOnlyDtsFiles) { + printFile(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); + } } else { emitSkipped = true; @@ -282,7 +287,9 @@ const _super = (function (geti, seti) { } if (!emitSkipped && emittedFilesList) { - emittedFilesList.push(jsFilePath); + if (!emitOnlyDtsFiles) { + emittedFilesList.push(jsFilePath); + } if (sourceMapFilePath) { emittedFilesList.push(sourceMapFilePath); } diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 6068cf55a7a..ca702173e79 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -512,75 +512,6 @@ namespace ts { } } - /** - * patternStrings contains both pattern strings (containing "*") and regular strings. - * Return an exact match if possible, or a pattern match, or undefined. - * (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.) - */ - function matchPatternOrExact(patternStrings: string[], candidate: string): string | Pattern | undefined { - const patterns: Pattern[] = []; - for (const patternString of patternStrings) { - const pattern = tryParsePattern(patternString); - if (pattern) { - patterns.push(pattern); - } - else if (patternString === candidate) { - // pattern was matched as is - no need to search further - return patternString; - } - } - - return findBestPatternMatch(patterns, _ => _, candidate); - } - - function patternText({prefix, suffix}: Pattern): string { - return `${prefix}*${suffix}`; - } - - /** - * Given that candidate matches pattern, returns the text matching the '*'. - * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" - */ - function matchedText(pattern: Pattern, candidate: string): string { - Debug.assert(isPatternMatch(pattern, candidate)); - return candidate.substr(pattern.prefix.length, candidate.length - pattern.suffix.length); - } - - /** Return the object corresponding to the best pattern to match `candidate`. */ - /* @internal */ - export function findBestPatternMatch(values: T[], getPattern: (value: T) => Pattern, candidate: string): T | undefined { - let matchedValue: T | undefined = undefined; - // use length of prefix as betterness criteria - let longestMatchPrefixLength = -1; - - for (const v of values) { - const pattern = getPattern(v); - if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) { - longestMatchPrefixLength = pattern.prefix.length; - matchedValue = v; - } - } - - return matchedValue; - } - - function isPatternMatch({prefix, suffix}: Pattern, candidate: string) { - return candidate.length >= prefix.length + suffix.length && - startsWith(candidate, prefix) && - endsWith(candidate, suffix); - } - - /* @internal */ - export function tryParsePattern(pattern: string): Pattern | undefined { - // This should be verified outside of here and a proper error thrown. - Debug.assert(hasZeroOrOneAsteriskCharacter(pattern)); - const indexOfStar = pattern.indexOf("*"); - return indexOfStar === -1 ? undefined : { - prefix: pattern.substr(0, indexOfStar), - suffix: pattern.substr(indexOfStar + 1) - }; - } - export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { const containingDirectory = getDirectoryPath(containingFile); const supportedExtensions = getSupportedExtensions(compilerOptions); diff --git a/src/services/services.ts b/src/services/services.ts index da8cb5e9c30..eb103cebb11 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -945,6 +945,8 @@ namespace ts { let program: Program; let lastProjectVersion: string; + let lastTypesRootVersion = 0; + const useCaseSensitivefileNames = false; const cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); @@ -993,6 +995,13 @@ namespace ts { } } + const typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0; + if (lastTypesRootVersion !== typeRootsVersion) { + log("TypeRoots version has changed; provide new program"); + program = undefined; + lastTypesRootVersion = typeRootsVersion; + } + // Get a fresh cache of the host information let hostCache = new HostCache(host, getCanonicalFileName); diff --git a/src/services/types.ts b/src/services/types.ts index a6fc92d5460..79bee8d1818 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -148,6 +148,11 @@ namespace ts { readFile?(path: string, encoding?: string): string; fileExists?(path: string): boolean; + /* + * LS host can optionally implement these methods to support automatic updating when new type libraries are installed + */ + getTypeRootsVersion?(): number; + /* * LS host can optionally implement this method if it wants to be completely in charge of module name resolution. * if implementation is omitted then language service will use built-in module resolution logic and get answers to diff --git a/tests/baselines/reference/assignmentTypeNarrowing_BACKUP_22380.types b/tests/baselines/reference/assignmentTypeNarrowing_BACKUP_22380.types deleted file mode 100644 index bb9805ca5ba..00000000000 --- a/tests/baselines/reference/assignmentTypeNarrowing_BACKUP_22380.types +++ /dev/null @@ -1,106 +0,0 @@ -=== tests/cases/conformance/expressions/assignmentOperator/assignmentTypeNarrowing.ts === -let x: string | number | boolean | RegExp; ->x : string | number | boolean | RegExp ->RegExp : RegExp - -x = ""; ->x = "" : "" ->x : string | number | boolean | RegExp ->"" : "" - -x; // string ->x : string - -[x] = [true]; ->[x] = [true] : [true] ->[x] : [string | number | boolean | RegExp] ->x : string | number | boolean | RegExp ->[true] : [true] ->true : true - -x; // boolean ->x : true - -[x = ""] = [1]; ->[x = ""] = [1] : [number] ->[x = ""] : [string] ->x = "" : "" ->x : string | number | boolean | RegExp ->"" : "" ->[1] : [number] ->1 : 1 - -x; // string | number ->x : string | number - -({x} = {x: true}); ->({x} = {x: true}) : { x: true; } ->{x} = {x: true} : { x: true; } ->{x} : { x: string | number | boolean | RegExp; } ->x : string | number | boolean | RegExp ->{x: true} : { x: true; } -<<<<<<< HEAD ->x : true -======= ->x : boolean ->>>>>>> origin/master ->true : true - -x; // boolean ->x : true - -({y: x} = {y: 1}); ->({y: x} = {y: 1}) : { y: 1; } ->{y: x} = {y: 1} : { y: 1; } ->{y: x} : { y: string | number | boolean | RegExp; } ->y : string | number | boolean | RegExp ->x : string | number | boolean | RegExp ->{y: 1} : { y: 1; } ->y : number ->1 : 1 - -x; // number ->x : number - -({x = ""} = {x: true}); ->({x = ""} = {x: true}) : { x?: true; } ->{x = ""} = {x: true} : { x?: true; } ->{x = ""} : { x?: string | number | boolean | RegExp; } ->x : string | number | boolean | RegExp ->{x: true} : { x?: true; } -<<<<<<< HEAD ->x : true -======= ->x : boolean ->>>>>>> origin/master ->true : true - -x; // string | boolean ->x : string | true - -({y: x = /a/} = {y: 1}); ->({y: x = /a/} = {y: 1}) : { y?: number; } ->{y: x = /a/} = {y: 1} : { y?: number; } ->{y: x = /a/} : { y?: RegExp; } ->y : RegExp ->x = /a/ : RegExp ->x : string | number | boolean | RegExp ->/a/ : RegExp ->{y: 1} : { y?: number; } ->y : number ->1 : 1 - -x; // number | RegExp ->x : number | RegExp - -let a: string[]; ->a : string[] - -for (x of a) { ->x : string | number | boolean | RegExp ->a : string[] - - x; // string ->x : string -} - diff --git a/tests/baselines/reference/assignmentTypeNarrowing_BASE_22380.types b/tests/baselines/reference/assignmentTypeNarrowing_BASE_22380.types deleted file mode 100644 index be99a31501d..00000000000 --- a/tests/baselines/reference/assignmentTypeNarrowing_BASE_22380.types +++ /dev/null @@ -1,98 +0,0 @@ -=== tests/cases/conformance/expressions/assignmentOperator/assignmentTypeNarrowing.ts === -let x: string | number | boolean | RegExp; ->x : string | number | boolean | RegExp ->RegExp : RegExp - -x = ""; ->x = "" : string ->x : string | number | boolean | RegExp ->"" : string - -x; // string ->x : string - -[x] = [true]; ->[x] = [true] : [boolean] ->[x] : [string | number | boolean | RegExp] ->x : string | number | boolean | RegExp ->[true] : [boolean] ->true : boolean - -x; // boolean ->x : boolean - -[x = ""] = [1]; ->[x = ""] = [1] : [number] ->[x = ""] : [string] ->x = "" : string ->x : string | number | boolean | RegExp ->"" : string ->[1] : [number] ->1 : number - -x; // string | number ->x : string | number - -({x} = {x: true}); ->({x} = {x: true}) : { x: boolean; } ->{x} = {x: true} : { x: boolean; } ->{x} : { x: string | number | boolean | RegExp; } ->x : string | number | boolean | RegExp ->{x: true} : { x: boolean; } ->x : boolean ->true : boolean - -x; // boolean ->x : boolean - -({y: x} = {y: 1}); ->({y: x} = {y: 1}) : { y: number; } ->{y: x} = {y: 1} : { y: number; } ->{y: x} : { y: string | number | boolean | RegExp; } ->y : string | number | boolean | RegExp ->x : string | number | boolean | RegExp ->{y: 1} : { y: number; } ->y : number ->1 : number - -x; // number ->x : number - -({x = ""} = {x: true}); ->({x = ""} = {x: true}) : { x?: boolean; } ->{x = ""} = {x: true} : { x?: boolean; } ->{x = ""} : { x?: string | number | boolean | RegExp; } ->x : string | number | boolean | RegExp ->{x: true} : { x?: boolean; } ->x : boolean ->true : boolean - -x; // string | boolean ->x : string | boolean - -({y: x = /a/} = {y: 1}); ->({y: x = /a/} = {y: 1}) : { y?: number; } ->{y: x = /a/} = {y: 1} : { y?: number; } ->{y: x = /a/} : { y?: RegExp; } ->y : RegExp ->x = /a/ : RegExp ->x : string | number | boolean | RegExp ->/a/ : RegExp ->{y: 1} : { y?: number; } ->y : number ->1 : number - -x; // number | RegExp ->x : number | RegExp - -let a: string[]; ->a : string[] - -for (x of a) { ->x : string | number | boolean | RegExp ->a : string[] - - x; // string ->x : string -} - diff --git a/tests/baselines/reference/assignmentTypeNarrowing_LOCAL_22380.types b/tests/baselines/reference/assignmentTypeNarrowing_LOCAL_22380.types deleted file mode 100644 index f46b2a16c3b..00000000000 --- a/tests/baselines/reference/assignmentTypeNarrowing_LOCAL_22380.types +++ /dev/null @@ -1,98 +0,0 @@ -=== tests/cases/conformance/expressions/assignmentOperator/assignmentTypeNarrowing.ts === -let x: string | number | boolean | RegExp; ->x : string | number | boolean | RegExp ->RegExp : RegExp - -x = ""; ->x = "" : string ->x : string | number | boolean | RegExp ->"" : string - -x; // string ->x : string - -[x] = [true]; ->[x] = [true] : [true] ->[x] : [string | number | boolean | RegExp] ->x : string | number | boolean | RegExp ->[true] : [true] ->true : true - -x; // boolean ->x : true - -[x = ""] = [1]; ->[x = ""] = [1] : [number] ->[x = ""] : [string] ->x = "" : string ->x : string | number | boolean | RegExp ->"" : string ->[1] : [number] ->1 : number - -x; // string | number ->x : string | number - -({x} = {x: true}); ->({x} = {x: true}) : { x: true; } ->{x} = {x: true} : { x: true; } ->{x} : { x: string | number | boolean | RegExp; } ->x : string | number | boolean | RegExp ->{x: true} : { x: true; } ->x : true ->true : true - -x; // boolean ->x : true - -({y: x} = {y: 1}); ->({y: x} = {y: 1}) : { y: number; } ->{y: x} = {y: 1} : { y: number; } ->{y: x} : { y: string | number | boolean | RegExp; } ->y : string | number | boolean | RegExp ->x : string | number | boolean | RegExp ->{y: 1} : { y: number; } ->y : number ->1 : number - -x; // number ->x : number - -({x = ""} = {x: true}); ->({x = ""} = {x: true}) : { x?: true; } ->{x = ""} = {x: true} : { x?: true; } ->{x = ""} : { x?: string | number | boolean | RegExp; } ->x : string | number | boolean | RegExp ->{x: true} : { x?: true; } ->x : true ->true : true - -x; // string | boolean ->x : string | true - -({y: x = /a/} = {y: 1}); ->({y: x = /a/} = {y: 1}) : { y?: number; } ->{y: x = /a/} = {y: 1} : { y?: number; } ->{y: x = /a/} : { y?: RegExp; } ->y : RegExp ->x = /a/ : RegExp ->x : string | number | boolean | RegExp ->/a/ : RegExp ->{y: 1} : { y?: number; } ->y : number ->1 : number - -x; // number | RegExp ->x : number | RegExp - -let a: string[]; ->a : string[] - -for (x of a) { ->x : string | number | boolean | RegExp ->a : string[] - - x; // string ->x : string -} - diff --git a/tests/baselines/reference/assignmentTypeNarrowing_REMOTE_22380.types b/tests/baselines/reference/assignmentTypeNarrowing_REMOTE_22380.types deleted file mode 100644 index 8c5fea315ce..00000000000 --- a/tests/baselines/reference/assignmentTypeNarrowing_REMOTE_22380.types +++ /dev/null @@ -1,98 +0,0 @@ -=== tests/cases/conformance/expressions/assignmentOperator/assignmentTypeNarrowing.ts === -let x: string | number | boolean | RegExp; ->x : string | number | boolean | RegExp ->RegExp : RegExp - -x = ""; ->x = "" : "" ->x : string | number | boolean | RegExp ->"" : "" - -x; // string ->x : string - -[x] = [true]; ->[x] = [true] : [true] ->[x] : [string | number | boolean | RegExp] ->x : string | number | boolean | RegExp ->[true] : [true] ->true : true - -x; // boolean ->x : true - -[x = ""] = [1]; ->[x = ""] = [1] : [number] ->[x = ""] : [string] ->x = "" : "" ->x : string | number | boolean | RegExp ->"" : "" ->[1] : [number] ->1 : 1 - -x; // string | number ->x : string | number - -({x} = {x: true}); ->({x} = {x: true}) : { x: true; } ->{x} = {x: true} : { x: true; } ->{x} : { x: string | number | boolean | RegExp; } ->x : string | number | boolean | RegExp ->{x: true} : { x: true; } ->x : boolean ->true : true - -x; // boolean ->x : true - -({y: x} = {y: 1}); ->({y: x} = {y: 1}) : { y: 1; } ->{y: x} = {y: 1} : { y: 1; } ->{y: x} : { y: string | number | boolean | RegExp; } ->y : string | number | boolean | RegExp ->x : string | number | boolean | RegExp ->{y: 1} : { y: 1; } ->y : number ->1 : 1 - -x; // number ->x : number - -({x = ""} = {x: true}); ->({x = ""} = {x: true}) : { x?: true; } ->{x = ""} = {x: true} : { x?: true; } ->{x = ""} : { x?: string | number | boolean | RegExp; } ->x : string | number | boolean | RegExp ->{x: true} : { x?: true; } ->x : boolean ->true : true - -x; // string | boolean ->x : string | true - -({y: x = /a/} = {y: 1}); ->({y: x = /a/} = {y: 1}) : { y?: number; } ->{y: x = /a/} = {y: 1} : { y?: number; } ->{y: x = /a/} : { y?: RegExp; } ->y : RegExp ->x = /a/ : RegExp ->x : string | number | boolean | RegExp ->/a/ : RegExp ->{y: 1} : { y?: number; } ->y : number ->1 : 1 - -x; // number | RegExp ->x : number | RegExp - -let a: string[]; ->a : string[] - -for (x of a) { ->x : string | number | boolean | RegExp ->a : string[] - - x; // string ->x : string -} -