Skip to content

Commit 0d3f567

Browse files
committed
Merge branch 'master' into object-spread
2 parents df73579 + d34916a commit 0d3f567

File tree

55 files changed

+475
-222
lines changed

Some content is hidden

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

55 files changed

+475
-222
lines changed

scripts/tslint/preferConstRule.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ class PreferConstWalker extends Lint.RuleWalker {
126126
visitModuleDeclaration(node: ts.ModuleDeclaration) {
127127
if (node.body.kind === ts.SyntaxKind.ModuleBlock) {
128128
// For some reason module blocks are left out of the visit block traversal
129-
this.visitBlock(node.body as ts.ModuleBlock);
129+
this.visitBlock(node.body as any as ts.Block);
130130
}
131131
super.visitModuleDeclaration(node);
132132
}

src/compiler/core.ts

+14-2
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,9 @@ namespace ts {
10971097
return path.replace(/\\/g, "/");
10981098
}
10991099

1100-
// Returns length of path root (i.e. length of "/", "x:/", "//server/share/, file:///user/files")
1100+
/**
1101+
* Returns length of path root (i.e. length of "/", "x:/", "//server/share/, file:///user/files")
1102+
*/
11011103
export function getRootLength(path: string): number {
11021104
if (path.charCodeAt(0) === CharacterCodes.slash) {
11031105
if (path.charCodeAt(1) !== CharacterCodes.slash) return 1;
@@ -1126,9 +1128,14 @@ namespace ts {
11261128
return 0;
11271129
}
11281130

1131+
/**
1132+
* Internally, we represent paths as strings with '/' as the directory separator.
1133+
* When we make system calls (eg: LanguageServiceHost.getDirectory()),
1134+
* we expect the host to correctly handle paths in our specified format.
1135+
*/
11291136
export const directorySeparator = "/";
11301137
const directorySeparatorCharCode = CharacterCodes.slash;
1131-
function getNormalizedParts(normalizedSlashedPath: string, rootLength: number) {
1138+
function getNormalizedParts(normalizedSlashedPath: string, rootLength: number): string[] {
11321139
const parts = normalizedSlashedPath.substr(rootLength).split(directorySeparator);
11331140
const normalized: string[] = [];
11341141
for (const part of parts) {
@@ -1168,6 +1175,11 @@ namespace ts {
11681175
return path.charCodeAt(path.length - 1) === directorySeparatorCharCode;
11691176
}
11701177

1178+
/**
1179+
* Returns the path except for its basename. Eg:
1180+
*
1181+
* /path/to/file.ext -> /path/to
1182+
*/
11711183
export function getDirectoryPath(path: Path): Path;
11721184
export function getDirectoryPath(path: string): string;
11731185
export function getDirectoryPath(path: string): any {

src/compiler/emitter.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
6868
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6969
return new (P || (P = Promise))(function (resolve, reject) {
7070
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
71-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
71+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7272
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7373
step((generator = generator.apply(thisArg, _arguments)).next());
7474
});

src/compiler/program.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ namespace ts {
358358
// load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders
359359
const typeReferences: string[] = getAutomaticTypeDirectiveNames(options, host);
360360

361-
if (typeReferences) {
361+
if (typeReferences.length) {
362362
// This containingFilename needs to match with the one used in managed-side
363363
const containingFilename = combinePaths(host.getCurrentDirectory(), "__inferred type names__.ts");
364364
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename);
@@ -1311,7 +1311,6 @@ namespace ts {
13111311
for (let i = 0; i < moduleNames.length; i++) {
13121312
const resolution = resolutions[i];
13131313
setResolvedModule(file, moduleNames[i], resolution);
1314-
const resolvedPath = resolution ? toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName) : undefined;
13151314

13161315
// add file to program only if:
13171316
// - resolution was successful
@@ -1333,7 +1332,7 @@ namespace ts {
13331332
}
13341333
else if (shouldAddFile) {
13351334
findSourceFile(resolution.resolvedFileName,
1336-
resolvedPath,
1335+
toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName),
13371336
/*isDefaultLib*/ false, /*isReference*/ false,
13381337
file,
13391338
skipTrivia(file.text, file.imports[i].pos),

src/server/lsHost.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,16 @@ namespace ts.server {
171171
return this.host.fileExists(path);
172172
}
173173

174+
readFile(fileName: string): string {
175+
return this.host.readFile(fileName);
176+
}
177+
174178
directoryExists(path: string): boolean {
175179
return this.host.directoryExists(path);
176180
}
177181

178-
readFile(fileName: string): string {
179-
return this.host.readFile(fileName);
182+
readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[]): string[] {
183+
return this.host.readDirectory(path, extensions, exclude, include);
180184
}
181185

182186
getDirectories(path: string): string[] {

src/services/completions.ts

+51-18
Original file line numberDiff line numberDiff line change
@@ -325,15 +325,28 @@ namespace ts.Completions {
325325
return result;
326326
}
327327

328+
/**
329+
* Given a path ending at a directory, gets the completions for the path, and filters for those entries containing the basename.
330+
*/
328331
function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: string, extensions: string[], includeExtensions: boolean, span: TextSpan, exclude?: string, result: CompletionEntry[] = []): CompletionEntry[] {
329-
fragment = getDirectoryPath(fragment);
330-
if (!fragment) {
331-
fragment = "./";
332+
if (fragment === undefined) {
333+
fragment = "";
332334
}
333-
else {
334-
fragment = ensureTrailingDirectorySeparator(fragment);
335+
336+
fragment = normalizeSlashes(fragment);
337+
338+
/**
339+
* Remove the basename from the path. Note that we don't use the basename to filter completions;
340+
* the client is responsible for refining completions.
341+
*/
342+
fragment = getDirectoryPath(fragment);
343+
344+
if (fragment === "") {
345+
fragment = "." + directorySeparator;
335346
}
336347

348+
fragment = ensureTrailingDirectorySeparator(fragment);
349+
337350
const absolutePath = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment));
338351
const baseDirectory = getDirectoryPath(absolutePath);
339352
const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
@@ -343,6 +356,12 @@ namespace ts.Completions {
343356
const files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/undefined, /*include*/["./*"]);
344357

345358
if (files) {
359+
/**
360+
* Multiple file entries might map to the same truncated name once we remove extensions
361+
* (happens iff includeExtensions === false)so we use a set-like data structure. Eg:
362+
*
363+
* both foo.ts and foo.tsx become foo
364+
*/
346365
const foundFiles = createMap<boolean>();
347366
for (let filePath of files) {
348367
filePath = normalizePath(filePath);
@@ -539,36 +558,44 @@ namespace ts.Completions {
539558
return undefined;
540559
}
541560

561+
const completionInfo: CompletionInfo = {
562+
/**
563+
* We don't want the editor to offer any other completions, such as snippets, inside a comment.
564+
*/
565+
isGlobalCompletion: false,
566+
isMemberCompletion: false,
567+
/**
568+
* The user may type in a path that doesn't yet exist, creating a "new identifier"
569+
* with respect to the collection of identifiers the server is aware of.
570+
*/
571+
isNewIdentifierLocation: true,
572+
573+
entries: []
574+
};
575+
542576
const text = sourceFile.text.substr(range.pos, position - range.pos);
543577

544578
const match = tripleSlashDirectiveFragmentRegex.exec(text);
579+
545580
if (match) {
546581
const prefix = match[1];
547582
const kind = match[2];
548583
const toComplete = match[3];
549584

550585
const scriptPath = getDirectoryPath(sourceFile.path);
551-
let entries: CompletionEntry[];
552586
if (kind === "path") {
553587
// Give completions for a relative path
554588
const span: TextSpan = getDirectoryFragmentTextSpan(toComplete, range.pos + prefix.length);
555-
entries = getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getSupportedExtensions(compilerOptions), /*includeExtensions*/true, span, sourceFile.path);
589+
completionInfo.entries = getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getSupportedExtensions(compilerOptions), /*includeExtensions*/true, span, sourceFile.path);
556590
}
557591
else {
558592
// Give completions based on the typings available
559593
const span: TextSpan = { start: range.pos + prefix.length, length: match[0].length - prefix.length };
560-
entries = getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span);
594+
completionInfo.entries = getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span);
561595
}
562-
563-
return {
564-
isGlobalCompletion: false,
565-
isMemberCompletion: false,
566-
isNewIdentifierLocation: true,
567-
entries
568-
};
569596
}
570597

571-
return undefined;
598+
return completionInfo;
572599
}
573600

574601
function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, span: TextSpan, result: CompletionEntry[] = []): CompletionEntry[] {
@@ -1674,9 +1701,15 @@ namespace ts.Completions {
16741701
* Matches a triple slash reference directive with an incomplete string literal for its path. Used
16751702
* to determine if the caret is currently within the string literal and capture the literal fragment
16761703
* for completions.
1677-
* For example, this matches /// <reference path="fragment
1704+
* For example, this matches
1705+
*
1706+
* /// <reference path="fragment
1707+
*
1708+
* but not
1709+
*
1710+
* /// <reference path="fragment"
16781711
*/
1679-
const tripleSlashDirectiveFragmentRegex = /^(\/\/\/\s*<reference\s+(path|types)\s*=\s*(?:'|"))([^\3]*)$/;
1712+
const tripleSlashDirectiveFragmentRegex = /^(\/\/\/\s*<reference\s+(path|types)\s*=\s*(?:'|"))([^\3"]*)$/;
16801713

16811714
interface VisibleModuleInfo {
16821715
moduleName: string;

src/services/types.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,11 @@ namespace ts {
505505
export interface CompletionInfo {
506506
isGlobalCompletion: boolean;
507507
isMemberCompletion: boolean;
508-
isNewIdentifierLocation: boolean; // true when the current location also allows for a new identifier
508+
509+
/**
510+
* true when the current location also allows for a new identifier
511+
*/
512+
isNewIdentifierLocation: boolean;
509513
entries: CompletionEntry[];
510514
}
511515

tests/baselines/reference/asyncAwaitIsolatedModules_es5.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ module M {
4444
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4545
return new (P || (P = Promise))(function (resolve, reject) {
4646
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
47-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
47+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
4848
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
4949
step((generator = generator.apply(thisArg, _arguments)).next());
5050
});

tests/baselines/reference/asyncAwaitIsolatedModules_es6.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ module M {
4343
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4444
return new (P || (P = Promise))(function (resolve, reject) {
4545
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
46-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
46+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
4747
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
4848
step((generator = generator.apply(thisArg, _arguments)).next());
4949
});

tests/baselines/reference/asyncAwait_es5.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ module M {
4343
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4444
return new (P || (P = Promise))(function (resolve, reject) {
4545
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
46-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
46+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
4747
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
4848
step((generator = generator.apply(thisArg, _arguments)).next());
4949
});

tests/baselines/reference/asyncAwait_es6.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ module M {
4343
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4444
return new (P || (P = Promise))(function (resolve, reject) {
4545
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
46-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
46+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
4747
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
4848
step((generator = generator.apply(thisArg, _arguments)).next());
4949
});

tests/baselines/reference/asyncFunctionNoReturnType.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ async () => {
99
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
1010
return new (P || (P = Promise))(function (resolve, reject) {
1111
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
12-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
12+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1313
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
1414
step((generator = generator.apply(thisArg, _arguments)).next());
1515
});

tests/baselines/reference/asyncFunctionReturnType.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ async function fAsyncExplicit(): Promise<[number, boolean]> {
1414
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
1515
return new (P || (P = Promise))(function (resolve, reject) {
1616
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
17+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1818
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
1919
step((generator = generator.apply(thisArg, _arguments)).next());
2020
});

tests/baselines/reference/asyncFunctionsAcrossFiles.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const b = {
1919
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2020
return new (P || (P = Promise))(function (resolve, reject) {
2121
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
22-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
22+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
2323
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
2424
step((generator = generator.apply(thisArg, _arguments)).next());
2525
});
@@ -34,7 +34,7 @@ export const b = {
3434
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3535
return new (P || (P = Promise))(function (resolve, reject) {
3636
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
37-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
37+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
3838
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
3939
step((generator = generator.apply(thisArg, _arguments)).next());
4040
});

tests/baselines/reference/asyncFunctionsAndStrictNullChecks.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ async function sample2(x?: number) {
3030
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3131
return new (P || (P = Promise))(function (resolve, reject) {
3232
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
33-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
33+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
3434
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
3535
step((generator = generator.apply(thisArg, _arguments)).next());
3636
});

tests/baselines/reference/asyncImportedPromise_es5.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ exports.Task = Task;
2929
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3030
return new (P || (P = Promise))(function (resolve, reject) {
3131
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
32-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
32+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
3333
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
3434
step((generator = generator.apply(thisArg, _arguments)).next());
3535
});

tests/baselines/reference/asyncImportedPromise_es6.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ exports.Task = Task;
1919
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2020
return new (P || (P = Promise))(function (resolve, reject) {
2121
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
22-
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
22+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
2323
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
2424
step((generator = generator.apply(thisArg, _arguments)).next());
2525
});

0 commit comments

Comments
 (0)