Skip to content

Commit 7b12617

Browse files
committed
Merge branch 'master' into reachabilityChecks
2 parents 5532778 + 302db0a commit 7b12617

File tree

96 files changed

+1423
-381
lines changed

Some content is hidden

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

96 files changed

+1423
-381
lines changed

src/compiler/checker.ts

Lines changed: 64 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -385,20 +385,72 @@ namespace ts {
385385
// return undefined if we can't find a symbol.
386386
}
387387

388-
/** Returns true if node1 is defined before node 2**/
389-
function isDefinedBefore(node1: Node, node2: Node): boolean {
390-
let file1 = getSourceFileOfNode(node1);
391-
let file2 = getSourceFileOfNode(node2);
392-
if (file1 === file2) {
393-
return node1.pos <= node2.pos;
388+
function isBlockScopedNameDeclaredBeforeUse(declaration: Declaration, usage: Node): boolean {
389+
const declarationFile = getSourceFileOfNode(declaration);
390+
const useFile = getSourceFileOfNode(usage);
391+
if (declarationFile !== useFile) {
392+
if (modulekind || (!compilerOptions.outFile && !compilerOptions.out)) {
393+
// nodes are in different files and order cannot be determines
394+
return true;
395+
}
396+
397+
const sourceFiles = host.getSourceFiles();
398+
return indexOf(sourceFiles, declarationFile) <= indexOf(sourceFiles, useFile);
394399
}
395400

396-
if (!compilerOptions.outFile && !compilerOptions.out) {
397-
return true;
401+
if (declaration.pos <= usage.pos) {
402+
// declaration is before usage
403+
// still might be illegal if usage is in the initializer of the variable declaration
404+
return declaration.kind !== SyntaxKind.VariableDeclaration ||
405+
!isImmediatelyUsedInInitializerOfBlockScopedVariable(<VariableDeclaration>declaration, usage);
398406
}
399407

400-
let sourceFiles = host.getSourceFiles();
401-
return sourceFiles.indexOf(file1) <= sourceFiles.indexOf(file2);
408+
// declaration is after usage
409+
// can be legal if usage is deferred (i.e. inside function or in initializer of instance property)
410+
return isUsedInFunctionOrNonStaticProperty(declaration, usage);
411+
412+
function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean {
413+
const container = getEnclosingBlockScopeContainer(declaration);
414+
415+
if (declaration.parent.parent.kind === SyntaxKind.VariableStatement ||
416+
declaration.parent.parent.kind === SyntaxKind.ForStatement) {
417+
// variable statement/for statement case,
418+
// use site should not be inside variable declaration (initializer of declaration or binding element)
419+
return isSameScopeDescendentOf(usage, declaration, container);
420+
}
421+
else if (declaration.parent.parent.kind === SyntaxKind.ForOfStatement ||
422+
declaration.parent.parent.kind === SyntaxKind.ForInStatement) {
423+
// ForIn/ForOf case - use site should not be used in expression part
424+
let expression = (<ForInStatement | ForOfStatement>declaration.parent.parent).expression;
425+
return isSameScopeDescendentOf(usage, expression, container);
426+
}
427+
}
428+
429+
function isUsedInFunctionOrNonStaticProperty(declaration: Declaration, usage: Node): boolean {
430+
const container = getEnclosingBlockScopeContainer(declaration);
431+
let current = usage;
432+
while (current) {
433+
if (current === container) {
434+
return false;
435+
}
436+
437+
if (isFunctionLike(current)) {
438+
return true;
439+
}
440+
441+
const initializerOfNonStaticProperty = current.parent &&
442+
current.parent.kind === SyntaxKind.PropertyDeclaration &&
443+
(current.parent.flags & NodeFlags.Static) === 0 &&
444+
(<PropertyDeclaration>current.parent).initializer === current;
445+
446+
if (initializerOfNonStaticProperty) {
447+
return true;
448+
}
449+
450+
current = current.parent;
451+
}
452+
return false;
453+
}
402454
}
403455

404456
// Resolve a given name for a given meaning at a given location. An error is reported if the name was not found and
@@ -629,34 +681,7 @@ namespace ts {
629681

630682
Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined");
631683

632-
// first check if usage is lexically located after the declaration
633-
let isUsedBeforeDeclaration = !isDefinedBefore(declaration, errorLocation);
634-
if (!isUsedBeforeDeclaration) {
635-
// lexical check succeeded however code still can be illegal.
636-
// - block scoped variables cannot be used in its initializers
637-
// let x = x; // illegal but usage is lexically after definition
638-
// - in ForIn/ForOf statements variable cannot be contained in expression part
639-
// for (let x in x)
640-
// for (let x of x)
641-
642-
// climb up to the variable declaration skipping binding patterns
643-
let variableDeclaration = <VariableDeclaration>getAncestor(declaration, SyntaxKind.VariableDeclaration);
644-
let container = getEnclosingBlockScopeContainer(variableDeclaration);
645-
646-
if (variableDeclaration.parent.parent.kind === SyntaxKind.VariableStatement ||
647-
variableDeclaration.parent.parent.kind === SyntaxKind.ForStatement) {
648-
// variable statement/for statement case,
649-
// use site should not be inside variable declaration (initializer of declaration or binding element)
650-
isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, variableDeclaration, container);
651-
}
652-
else if (variableDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement ||
653-
variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement) {
654-
// ForIn/ForOf case - use site should not be used in expression part
655-
let expression = (<ForInStatement | ForOfStatement>variableDeclaration.parent.parent).expression;
656-
isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, expression, container);
657-
}
658-
}
659-
if (isUsedBeforeDeclaration) {
684+
if (!isBlockScopedNameDeclaredBeforeUse(<Declaration>getAncestor(declaration, SyntaxKind.VariableDeclaration), errorLocation)) {
660685
error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(declaration.name));
661686
}
662687
}
@@ -11758,10 +11783,6 @@ namespace ts {
1175811783
checkSignatureDeclaration(node);
1175911784
let isAsync = isAsyncFunctionLike(node);
1176011785
if (isAsync) {
11761-
if (!compilerOptions.experimentalAsyncFunctions) {
11762-
error(node, Diagnostics.Experimental_support_for_async_functions_is_a_feature_that_is_subject_to_change_in_a_future_release_Specify_experimentalAsyncFunctions_to_remove_this_warning);
11763-
}
11764-
1176511786
emitAwaiter = true;
1176611787
}
1176711788

@@ -13350,7 +13371,7 @@ namespace ts {
1335013371
}
1335113372

1335213373
// illegal case: forward reference
13353-
if (!isDefinedBefore(propertyDecl, member)) {
13374+
if (!isBlockScopedNameDeclaredBeforeUse(propertyDecl, member)) {
1335413375
reportError = false;
1335513376
error(e, Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums);
1335613377
return undefined;

src/compiler/commandLineParser.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ namespace ts {
7777
"system": ModuleKind.System,
7878
"umd": ModuleKind.UMD,
7979
"es6": ModuleKind.ES6,
80+
"es2015": ModuleKind.ES2015,
8081
},
8182
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es6,
8283
paramType: Diagnostics.KIND,
@@ -205,7 +206,12 @@ namespace ts {
205206
{
206207
name: "target",
207208
shortName: "t",
208-
type: { "es3": ScriptTarget.ES3, "es5": ScriptTarget.ES5, "es6": ScriptTarget.ES6 },
209+
type: {
210+
"es3": ScriptTarget.ES3,
211+
"es5": ScriptTarget.ES5,
212+
"es6": ScriptTarget.ES6,
213+
"es2015": ScriptTarget.ES2015,
214+
},
209215
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental,
210216
paramType: Diagnostics.VERSION,
211217
error: Diagnostics.Argument_for_target_option_must_be_ES3_ES5_or_ES6
@@ -222,11 +228,6 @@ namespace ts {
222228
type: "boolean",
223229
description: Diagnostics.Watch_input_files,
224230
},
225-
{
226-
name: "experimentalAsyncFunctions",
227-
type: "boolean",
228-
description: Diagnostics.Enables_experimental_support_for_ES7_async_functions
229-
},
230231
{
231232
name: "experimentalDecorators",
232233
type: "boolean",
@@ -409,15 +410,15 @@ namespace ts {
409410
catch (e) {
410411
return { error: createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message) };
411412
}
412-
return parseConfigFileText(fileName, text);
413+
return parseConfigFileTextToJson(fileName, text);
413414
}
414415

415416
/**
416417
* Parse the text of the tsconfig.json file
417418
* @param fileName The path to the config file
418419
* @param jsonText The text of the config file
419420
*/
420-
export function parseConfigFileText(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } {
421+
export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } {
421422
try {
422423
return { config: /\S/.test(jsonText) ? JSON.parse(jsonText) : {} };
423424
}
@@ -432,7 +433,7 @@ namespace ts {
432433
* @param basePath A root directory to resolve relative path entries in the config
433434
* file to. e.g. outDir
434435
*/
435-
export function parseConfigFile(json: any, host: ParseConfigHost, basePath: string): ParsedCommandLine {
436+
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string): ParsedCommandLine {
436437
let errors: Diagnostic[] = [];
437438

438439
return {

src/compiler/core.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -437,8 +437,12 @@ namespace ts {
437437
}
438438

439439
export function concatenateDiagnosticMessageChains(headChain: DiagnosticMessageChain, tailChain: DiagnosticMessageChain): DiagnosticMessageChain {
440-
Debug.assert(!headChain.next);
441-
headChain.next = tailChain;
440+
let lastChain = headChain;
441+
while (lastChain.next) {
442+
lastChain = lastChain.next;
443+
}
444+
445+
lastChain.next = tailChain;
442446
return headChain;
443447
}
444448

@@ -700,6 +704,9 @@ namespace ts {
700704
}
701705

702706
export function getBaseFileName(path: string) {
707+
if (!path) {
708+
return undefined;
709+
}
703710
let i = path.lastIndexOf(directorySeparator);
704711
return i < 0 ? path : path.substring(i + 1);
705712
}
@@ -729,6 +736,17 @@ namespace ts {
729736
*/
730737
export const moduleFileExtensions = supportedExtensions;
731738

739+
export function isSupportedSourceFileName(fileName: string) {
740+
if (!fileName) { return false; }
741+
742+
for (let extension of supportedExtensions) {
743+
if (fileExtensionIs(fileName, extension)) {
744+
return true;
745+
}
746+
}
747+
return false;
748+
}
749+
732750
const extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx"];
733751
export function removeFileExtension(path: string): string {
734752
for (let ext of extensionsToRemove) {
@@ -823,4 +841,14 @@ namespace ts {
823841
Debug.assert(false, message);
824842
}
825843
}
826-
}
844+
845+
export function copyListRemovingItem<T>(item: T, list: T[]) {
846+
let copiedList: T[] = [];
847+
for (var i = 0, len = list.length; i < len; i++) {
848+
if (list[i] !== item) {
849+
copiedList.push(list[i]);
850+
}
851+
}
852+
return copiedList;
853+
}
854+
}

src/compiler/diagnosticMessages.json

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -783,10 +783,6 @@
783783
"category": "Error",
784784
"code": 1245
785785
},
786-
"Experimental support for async functions is a feature that is subject to change in a future release. Specify '--experimentalAsyncFunctions' to remove this warning.": {
787-
"category": "Error",
788-
"code": 1246
789-
},
790786

791787
"'with' statements are not allowed in an async function block.": {
792788
"category": "Error",
@@ -2282,10 +2278,6 @@
22822278
"category": "Message",
22832279
"code": 6066
22842280
},
2285-
"Option 'experimentalAsyncFunctions' cannot be specified when targeting ES5 or lower.": {
2286-
"category": "Message",
2287-
"code": 6067
2288-
},
22892281
"Enables experimental support for ES7 async functions.": {
22902282
"category": "Message",
22912283
"code": 6068

src/compiler/program.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,11 +1071,6 @@ namespace ts {
10711071
!options.experimentalDecorators) {
10721072
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators"));
10731073
}
1074-
1075-
if (options.experimentalAsyncFunctions &&
1076-
options.target !== ScriptTarget.ES6) {
1077-
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_experimentalAsyncFunctions_cannot_be_specified_when_targeting_ES5_or_lower));
1078-
}
10791074
}
10801075
}
10811076
}

0 commit comments

Comments
 (0)