Skip to content

Commit 85f0240

Browse files
author
Yui T
committed
Merge branch 'master' into release-1.7
2 parents b24c3a7 + 1244477 commit 85f0240

File tree

71 files changed

+626
-144
lines changed

Some content is hidden

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

71 files changed

+626
-144
lines changed

.travis.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
language: node_js
22

33
node_js:
4+
- '4'
45
- '0.10'
56

6-
sudo: false
7+
sudo: false

src/compiler/checker.ts

+64-43
Original file line numberDiff line numberDiff line change
@@ -383,20 +383,72 @@ namespace ts {
383383
// return undefined if we can't find a symbol.
384384
}
385385

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

394-
if (!compilerOptions.outFile && !compilerOptions.out) {
395-
return true;
399+
if (declaration.pos <= usage.pos) {
400+
// declaration is before usage
401+
// still might be illegal if usage is in the initializer of the variable declaration
402+
return declaration.kind !== SyntaxKind.VariableDeclaration ||
403+
!isImmediatelyUsedInInitializerOfBlockScopedVariable(<VariableDeclaration>declaration, usage);
396404
}
397405

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

402454
// Resolve a given name for a given meaning at a given location. An error is reported if the name was not found and
@@ -627,34 +679,7 @@ namespace ts {
627679

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

630-
// first check if usage is lexically located after the declaration
631-
let isUsedBeforeDeclaration = !isDefinedBefore(declaration, errorLocation);
632-
if (!isUsedBeforeDeclaration) {
633-
// lexical check succeeded however code still can be illegal.
634-
// - block scoped variables cannot be used in its initializers
635-
// let x = x; // illegal but usage is lexically after definition
636-
// - in ForIn/ForOf statements variable cannot be contained in expression part
637-
// for (let x in x)
638-
// for (let x of x)
639-
640-
// climb up to the variable declaration skipping binding patterns
641-
let variableDeclaration = <VariableDeclaration>getAncestor(declaration, SyntaxKind.VariableDeclaration);
642-
let container = getEnclosingBlockScopeContainer(variableDeclaration);
643-
644-
if (variableDeclaration.parent.parent.kind === SyntaxKind.VariableStatement ||
645-
variableDeclaration.parent.parent.kind === SyntaxKind.ForStatement) {
646-
// variable statement/for statement case,
647-
// use site should not be inside variable declaration (initializer of declaration or binding element)
648-
isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, variableDeclaration, container);
649-
}
650-
else if (variableDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement ||
651-
variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement) {
652-
// ForIn/ForOf case - use site should not be used in expression part
653-
let expression = (<ForInStatement | ForOfStatement>variableDeclaration.parent.parent).expression;
654-
isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, expression, container);
655-
}
656-
}
657-
if (isUsedBeforeDeclaration) {
682+
if (!isBlockScopedNameDeclaredBeforeUse(<Declaration>getAncestor(declaration, SyntaxKind.VariableDeclaration), errorLocation)) {
658683
error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(declaration.name));
659684
}
660685
}
@@ -11766,10 +11791,6 @@ namespace ts {
1176611791
checkSignatureDeclaration(node);
1176711792
let isAsync = isAsyncFunctionLike(node);
1176811793
if (isAsync) {
11769-
if (!compilerOptions.experimentalAsyncFunctions) {
11770-
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);
11771-
}
11772-
1177311794
emitAwaiter = true;
1177411795
}
1177511796

@@ -13358,7 +13379,7 @@ namespace ts {
1335813379
}
1335913380

1336013381
// illegal case: forward reference
13361-
if (!isDefinedBefore(propertyDecl, member)) {
13382+
if (!isBlockScopedNameDeclaredBeforeUse(propertyDecl, member)) {
1336213383
reportError = false;
1336313384
error(e, Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums);
1336413385
return undefined;

src/compiler/commandLineParser.ts

-5
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,6 @@ namespace ts {
222222
type: "boolean",
223223
description: Diagnostics.Watch_input_files,
224224
},
225-
{
226-
name: "experimentalAsyncFunctions",
227-
type: "boolean",
228-
description: Diagnostics.Enables_experimental_support_for_ES7_async_functions
229-
},
230225
{
231226
name: "experimentalDecorators",
232227
type: "boolean",

src/compiler/diagnosticMessages.json

-8
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

-5
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
}

src/compiler/types.ts

-1
Original file line numberDiff line numberDiff line change
@@ -2086,7 +2086,6 @@ namespace ts {
20862086
watch?: boolean;
20872087
isolatedModules?: boolean;
20882088
experimentalDecorators?: boolean;
2089-
experimentalAsyncFunctions?: boolean;
20902089
emitDecoratorMetadata?: boolean;
20912090
moduleResolution?: ModuleResolutionKind;
20922091
/* @internal */ stripInternal?: boolean;

src/harness/fourslash.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -591,14 +591,21 @@ namespace FourSlash {
591591
}
592592
}
593593

594-
public verifyCompletionListItemsCountIsGreaterThan(count: number) {
594+
public verifyCompletionListItemsCountIsGreaterThan(count: number, negative: boolean) {
595595
this.taoInvalidReason = "verifyCompletionListItemsCountIsGreaterThan NYI";
596596

597597
let completions = this.getCompletionListAtCaret();
598598
let itemsCount = completions.entries.length;
599599

600-
if (itemsCount <= count) {
601-
this.raiseError(`Expected completion list items count to be greater than ${count}, but is actually ${itemsCount}`);
600+
if (negative) {
601+
if (itemsCount > count) {
602+
this.raiseError(`Expected completion list items count to not be greater than ${count}, but is actually ${itemsCount}`);
603+
}
604+
}
605+
else {
606+
if (itemsCount <= count) {
607+
this.raiseError(`Expected completion list items count to be greater than ${count}, but is actually ${itemsCount}`);
608+
}
602609
}
603610
}
604611

src/services/services.ts

+35-4
Original file line numberDiff line numberDiff line change
@@ -3112,6 +3112,7 @@ namespace ts {
31123112
let node = currentToken;
31133113
let isRightOfDot = false;
31143114
let isRightOfOpenTag = false;
3115+
let isStartingCloseTag = false;
31153116

31163117
let location = getTouchingPropertyName(sourceFile, position);
31173118
if (contextToken) {
@@ -3137,9 +3138,14 @@ namespace ts {
31373138
return undefined;
31383139
}
31393140
}
3140-
else if (kind === SyntaxKind.LessThanToken && sourceFile.languageVariant === LanguageVariant.JSX) {
3141-
isRightOfOpenTag = true;
3142-
location = contextToken;
3141+
else if (sourceFile.languageVariant === LanguageVariant.JSX) {
3142+
if (kind === SyntaxKind.LessThanToken) {
3143+
isRightOfOpenTag = true;
3144+
location = contextToken;
3145+
}
3146+
else if (kind === SyntaxKind.SlashToken && contextToken.parent.kind === SyntaxKind.JsxClosingElement) {
3147+
isStartingCloseTag = true;
3148+
}
31433149
}
31443150
}
31453151

@@ -3162,6 +3168,13 @@ namespace ts {
31623168
isMemberCompletion = true;
31633169
isNewIdentifierLocation = false;
31643170
}
3171+
else if (isStartingCloseTag) {
3172+
let tagName = (<JsxElement>contextToken.parent.parent).openingElement.tagName;
3173+
symbols = [typeChecker.getSymbolAtLocation(tagName)];
3174+
3175+
isMemberCompletion = true;
3176+
isNewIdentifierLocation = false;
3177+
}
31653178
else {
31663179
// For JavaScript or TypeScript, if we're not after a dot, then just try to get the
31673180
// global symbols in scope. These results should be valid for either language as
@@ -3318,11 +3331,29 @@ namespace ts {
33183331
let start = new Date().getTime();
33193332
let result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) ||
33203333
isSolelyIdentifierDefinitionLocation(contextToken) ||
3321-
isDotOfNumericLiteral(contextToken);
3334+
isDotOfNumericLiteral(contextToken) ||
3335+
isInJsxText(contextToken);
33223336
log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start));
33233337
return result;
33243338
}
33253339

3340+
function isInJsxText(contextToken: Node): boolean {
3341+
if (contextToken.kind === SyntaxKind.JsxText) {
3342+
return true;
3343+
}
3344+
3345+
if (contextToken.kind === SyntaxKind.GreaterThanToken && contextToken.parent) {
3346+
if (contextToken.parent.kind === SyntaxKind.JsxOpeningElement) {
3347+
return true;
3348+
}
3349+
3350+
if (contextToken.parent.kind === SyntaxKind.JsxClosingElement || contextToken.parent.kind === SyntaxKind.JsxSelfClosingElement) {
3351+
return contextToken.parent.parent && contextToken.parent.parent.kind === SyntaxKind.JsxElement;
3352+
}
3353+
}
3354+
return false;
3355+
}
3356+
33263357
function isNewIdentifierDefinitionLocation(previousToken: Node): boolean {
33273358
if (previousToken) {
33283359
let containingNodeKind = previousToken.parent.kind;

0 commit comments

Comments
 (0)