From b85b0046c32573bf45b8bc0038e9498b3dd85e4a Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 28 Apr 2016 17:32:20 -0700 Subject: [PATCH 01/38] Fix indentation for array items --- src/services/formatting/formatting.ts | 66 ++++++++++--------- .../fourslash/formatArrayLiteralExpression.ts | 43 ++++++++++++ 2 files changed, 79 insertions(+), 30 deletions(-) create mode 100644 tests/cases/fourslash/formatArrayLiteralExpression.ts diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 58e3ed1b356..d49d135793b 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -20,13 +20,13 @@ namespace ts.formatting { Unknown = -1 } - /* + /* * Indentation for the scope that can be dynamically recomputed. - * i.e + * i.e * while(true) * { let x; * } - * Normally indentation is applied only to the first token in line so at glance 'var' should not be touched. + * Normally indentation is applied only to the first token in line so at glance 'var' should not be touched. * However if some format rule adds new line between '}' and 'var' 'var' will become * the first token in line so it should be indented */ @@ -48,15 +48,15 @@ namespace ts.formatting { * foo(bar({ * $ * })) - * Both 'foo', 'bar' introduce new indentation with delta = 4, but total indentation in $ is not 8. + * Both 'foo', 'bar' introduce new indentation with delta = 4, but total indentation in $ is not 8. * foo: { indentation: 0, delta: 4 } * bar: { indentation: foo.indentation + foo.delta = 4, delta: 4} however 'foo' and 'bar' are on the same line * so bar inherits indentation from foo and bar.delta will be 4 - * + * */ getDelta(child: TextRangeWithKind): number; /** - * Formatter calls this function when rule adds or deletes new lines from the text + * Formatter calls this function when rule adds or deletes new lines from the text * so indentation scope can adjust values of indentation and delta. */ recomputeIndentation(lineAddedByFormatting: boolean): void; @@ -130,9 +130,9 @@ namespace ts.formatting { function findOutermostParent(position: number, expectedTokenKind: SyntaxKind, sourceFile: SourceFile): Node { let precedingToken = findPrecedingToken(position, sourceFile); - // when it is claimed that trigger character was typed at given position + // when it is claimed that trigger character was typed at given position // we verify that there is a token with a matching kind whose end is equal to position (because the character was just typed). - // If this condition is not hold - then trigger character was typed in some other context, + // If this condition is not hold - then trigger character was typed in some other context, // i.e.in comment and thus should not trigger autoformatting if (!precedingToken || precedingToken.kind !== expectedTokenKind || @@ -142,12 +142,12 @@ namespace ts.formatting { // walk up and search for the parent node that ends at the same position with precedingToken. // for cases like this - // + // // let x = 1; // while (true) { - // } + // } // after typing close curly in while statement we want to reformat just the while statement. - // However if we just walk upwards searching for the parent that has the same end value - + // However if we just walk upwards searching for the parent that has the same end value - // we'll end up with the whole source file. isListElement allows to stop on the list element level let current = precedingToken; while (current && @@ -223,7 +223,7 @@ namespace ts.formatting { // 'index' tracks the index of the most recent error that was checked. while (true) { if (index >= sorted.length) { - // all errors in the range were already checked -> no error in specified range + // all errors in the range were already checked -> no error in specified range return false; } @@ -249,7 +249,7 @@ namespace ts.formatting { /** * Start of the original range might fall inside the comment - scanner will not yield appropriate results - * This function will look for token that is located before the start of target range + * This function will look for token that is located before the start of target range * and return its end as start position for the scanner. */ function getScanStartPosition(enclosingNode: Node, originalRange: TextRange, sourceFile: SourceFile): number { @@ -274,7 +274,7 @@ namespace ts.formatting { } /* - * For cases like + * For cases like * if (a || * b ||$ * c) {...} @@ -284,8 +284,8 @@ namespace ts.formatting { * Initial indentation for this node will be 0. * Binary expressions don't introduce new indentation scopes, however it is possible * that some parent node on the same line does - like if statement in this case. - * Note that we are considering parents only from the same line with initial node - - * if parent is on the different line - its delta was already contributed + * Note that we are considering parents only from the same line with initial node - + * if parent is on the different line - its delta was already contributed * to the initial indentation. */ function getOwnOrInheritedDelta(n: Node, options: FormatCodeOptions, sourceFile: SourceFile): number { @@ -364,10 +364,10 @@ namespace ts.formatting { // local functions /** Tries to compute the indentation for a list element. - * If list element is not in range then - * function will pick its actual indentation + * If list element is not in range then + * function will pick its actual indentation * so it can be pushed downstream as inherited indentation. - * If list element is in the range - its indentation will be equal + * If list element is in the range - its indentation will be equal * to inherited indentation from its predecessors. */ function tryComputeIndentationForListItem(startPos: number, @@ -378,7 +378,7 @@ namespace ts.formatting { if (rangeOverlapsWithStartEnd(range, startPos, endPos) || rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) { - + if (inheritedIndentation !== Constants.Unknown) { return inheritedIndentation; } @@ -529,12 +529,12 @@ namespace ts.formatting { // a useful observations when tracking context node // / // [a] - // / | \ + // / | \ // [b] [c] [d] - // node 'a' is a context node for nodes 'b', 'c', 'd' + // node 'a' is a context node for nodes 'b', 'c', 'd' // except for the leftmost leaf token in [b] - in this case context node ('e') is located somewhere above 'a' // this rule can be applied recursively to child nodes of 'a'. - // + // // context node is set to parent node value after processing every child node // context node is set to parent of the token after processing every token @@ -567,7 +567,8 @@ namespace ts.formatting { parentDynamicIndentation: DynamicIndentation, parentStartLine: number, undecoratedParentStartLine: number, - isListItem: boolean): number { + isListItem: boolean, + isFirstListItem?: boolean): number { let childStartPos = child.getStart(sourceFile); @@ -626,6 +627,10 @@ namespace ts.formatting { childContextNode = node; + if (isFirstListItem && parent.kind === SyntaxKind.ArrayLiteralExpression && inheritedIndentation === Constants.Unknown) { + inheritedIndentation = childIndentation.indentation; + } + return inheritedIndentation; } @@ -665,8 +670,9 @@ namespace ts.formatting { } let inheritedIndentation = Constants.Unknown; - for (let child of nodes) { - inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListElement*/ true) + for (let i = 0; i < nodes.length; i++) { + const child = nodes[i]; + inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListElement*/ true, /*isFirstListItem*/ i === 0); } if (listEndToken !== SyntaxKind.Unknown) { @@ -674,7 +680,7 @@ namespace ts.formatting { let tokenInfo = formattingScanner.readTokenInfo(parent); // consume the list end token only if it is still belong to the parent // there might be the case when current token matches end token but does not considered as one - // function (x: function) <-- + // function (x: function) <-- // without this check close paren will be interpreted as list end token for function expression which is wrong if (tokenInfo.token.kind === listEndToken && rangeContainsRange(parent, tokenInfo.token)) { // consume list end token @@ -733,7 +739,7 @@ namespace ts.formatting { let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container); for (let triviaItem of currentTokenInfo.leadingTrivia) { - const triviaInRange = rangeContainsRange(originalRange, triviaItem); + const triviaInRange = rangeContainsRange(originalRange, triviaItem); switch (triviaItem.kind) { case SyntaxKind.MultiLineCommentTrivia: if (triviaInRange) { @@ -826,7 +832,7 @@ namespace ts.formatting { if (rule.Operation.Action & (RuleAction.Space | RuleAction.Delete) && currentStartLine !== previousStartLine) { lineAdded = false; - // Handle the case where the next line is moved to be the end of this line. + // Handle the case where the next line is moved to be the end of this line. // In this case we don't indent the next line in the next pass. if (currentParent.getStart(sourceFile) === currentItem.pos) { dynamicIndentation.recomputeIndentation(/*lineAdded*/ false); @@ -834,7 +840,7 @@ namespace ts.formatting { } else if (rule.Operation.Action & RuleAction.NewLine && currentStartLine === previousStartLine) { lineAdded = true; - // Handle the case where token2 is moved to the new line. + // Handle the case where token2 is moved to the new line. // In this case we indent token2 in the next pass but we set // sameLineIndent flag to notify the indenter that the indentation is within the line. if (currentParent.getStart(sourceFile) === currentItem.pos) { diff --git a/tests/cases/fourslash/formatArrayLiteralExpression.ts b/tests/cases/fourslash/formatArrayLiteralExpression.ts new file mode 100644 index 00000000000..51594965a33 --- /dev/null +++ b/tests/cases/fourslash/formatArrayLiteralExpression.ts @@ -0,0 +1,43 @@ +/// + +////export let Things = [{ +//// Hat: 'hat', /*1*/ +//// Glove: 'glove', +//// Umbrella: 'umbrella' +////},{/*2*/ +//// Salad: 'salad', /*3*/ +//// Burrito: 'burrito', +//// Pie: 'pie' +//// }];/*4*/ +//// +////export let Things2 = [ +////{ +//// Hat: 'hat', /*5*/ +//// Glove: 'glove', +//// Umbrella: 'umbrella' +////}/*6*/, +//// { +//// Salad: 'salad', /*7*/ +//// Burrito: 'burrito', +//// Pie: 'pie' +//// }];/*8*/ + +format.document(); + +goTo.marker("1"); +verify.currentLineContentIs(" Hat: 'hat',"); +goTo.marker("2"); +verify.currentLineContentIs("}, {"); +goTo.marker("3"); +verify.currentLineContentIs(" Salad: 'salad',"); +goTo.marker("4"); +verify.currentLineContentIs("}];"); + +goTo.marker("5"); +verify.currentLineContentIs(" Hat: 'hat',"); +goTo.marker("6"); +verify.currentLineContentIs(" },"); +goTo.marker("7"); +verify.currentLineContentIs(" Salad: 'salad',"); +goTo.marker("8"); +verify.currentLineContentIs(" }];"); From 7706f3837eb9274a1508e0e6e3ac8bae3e034bcb Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 12 May 2016 14:59:45 -0700 Subject: [PATCH 02/38] Minor cleanup of getFlowTypeOfReference parameters --- src/compiler/checker.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f9b84e857dd..71c19e1214a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7615,11 +7615,12 @@ namespace ts { getInitialTypeOfBindingElement(node); } - function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType: Type) { + function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean) { let key: string; - if (!reference.flowNode || declaredType === initialType && !(declaredType.flags & TypeFlags.Narrowable)) { + if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) { return declaredType; } + const initialType = assumeInitialized ? declaredType : addNullableKind(declaredType, TypeFlags.Undefined); const visitedFlowStart = visitedFlowCount; const result = getTypeAtFlowNode(reference.flowNode); visitedFlowCount = visitedFlowStart; @@ -8093,11 +8094,11 @@ namespace ts { return type; } const declaration = localOrExportSymbol.valueDeclaration; - const defaultsToDeclaredType = !strictNullChecks || type.flags & TypeFlags.Any || !declaration || + const assumeInitialized = !strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || !declaration || getRootDeclaration(declaration).kind === SyntaxKind.Parameter || isInAmbientContext(declaration) || getContainingFunctionOrModule(declaration) !== getContainingFunctionOrModule(node); - const flowType = getFlowTypeOfReference(node, type, defaultsToDeclaredType ? type : addNullableKind(type, TypeFlags.Undefined)); - if (strictNullChecks && !(type.flags & TypeFlags.Any) && !(getNullableKind(type) & TypeFlags.Undefined) && getNullableKind(flowType) & TypeFlags.Undefined) { + const flowType = getFlowTypeOfReference(node, type, assumeInitialized); + if (!assumeInitialized && !(getNullableKind(type) & TypeFlags.Undefined) && getNullableKind(flowType) & TypeFlags.Undefined) { error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol)); // Return the declared type to reduce follow-on errors return type; @@ -8345,7 +8346,7 @@ namespace ts { if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); const type = container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; - return getFlowTypeOfReference(node, type, type); + return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true); } if (isInJavaScriptFile(node)) { @@ -9937,7 +9938,7 @@ namespace ts { return propType; } } - return getFlowTypeOfReference(node, propType, propType); + return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true); } function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean { From 3e32a6131bfdb26c34dfc0faeac5939e3499f7c7 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 13 May 2016 08:26:41 -0700 Subject: [PATCH 03/38] Include declaration expressions (class expressions and function expressions) in named declarations --- src/services/services.ts | 20 ++++++++++++++----- .../cases/fourslash/declarationExpressions.ts | 19 ++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 tests/cases/fourslash/declarationExpressions.ts diff --git a/src/services/services.ts b/src/services/services.ts index b2f7eb4bdba..6132f65ca61 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -904,6 +904,7 @@ namespace ts { function visit(node: Node): void { switch (node.kind) { case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: const functionDeclaration = node; @@ -930,6 +931,7 @@ namespace ts { break; case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.EnumDeclaration: @@ -967,11 +969,15 @@ namespace ts { } // fall through case SyntaxKind.VariableDeclaration: - case SyntaxKind.BindingElement: - if (isBindingPattern((node).name)) { - forEachChild((node).name, visit); + case SyntaxKind.BindingElement: { + const decl = node; + if (isBindingPattern(decl.name)) { + forEachChild(decl.name, visit); break; } + if (decl.initializer) + visit(decl.initializer); + } case SyntaxKind.EnumMember: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -2770,7 +2776,9 @@ namespace ts { /* @internal */ export function getNodeKind(node: Node): string { switch (node.kind) { case SyntaxKind.ModuleDeclaration: return ScriptElementKind.moduleElement; - case SyntaxKind.ClassDeclaration: return ScriptElementKind.classElement; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + return ScriptElementKind.classElement; case SyntaxKind.InterfaceDeclaration: return ScriptElementKind.interfaceElement; case SyntaxKind.TypeAliasDeclaration: return ScriptElementKind.typeElement; case SyntaxKind.EnumDeclaration: return ScriptElementKind.enumElement; @@ -2780,7 +2788,9 @@ namespace ts { : isLet(node) ? ScriptElementKind.letElement : ScriptElementKind.variableElement; - case SyntaxKind.FunctionDeclaration: return ScriptElementKind.functionElement; + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + return ScriptElementKind.functionElement; case SyntaxKind.GetAccessor: return ScriptElementKind.memberGetAccessorElement; case SyntaxKind.SetAccessor: return ScriptElementKind.memberSetAccessorElement; case SyntaxKind.MethodDeclaration: diff --git a/tests/cases/fourslash/declarationExpressions.ts b/tests/cases/fourslash/declarationExpressions.ts new file mode 100644 index 00000000000..764dab1521e --- /dev/null +++ b/tests/cases/fourslash/declarationExpressions.ts @@ -0,0 +1,19 @@ +/// + +////class A {} +////const B = class C { +//// public x; +////}; +////function D() {} +////const E = function F() {} + +// Search for properties defined in the constructor, but not other constructor paramters +var searchValue = "search"; +verify.navigationItemsListContains("A", "class", "A", "exact"); +verify.navigationItemsListContains("B", "const", "B", "exact"); +verify.navigationItemsListContains("C", "class", "C", "exact"); +verify.navigationItemsListContains("x", "property", "x", "exact"); + +verify.navigationItemsListContains("D", "function", "D", "exact"); +verify.navigationItemsListContains("E", "const", "E", "exact"); +verify.navigationItemsListContains("F", "function", "F", "exact") From 81a43f0c7e1453ad89ca448dca791262357d8c42 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 13 May 2016 08:36:51 -0700 Subject: [PATCH 04/38] Look for declaration expressions in nested expressions --- src/services/services.ts | 16 +++------------- tests/cases/fourslash/declarationExpressions.ts | 4 ++++ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 6132f65ca61..578e0166def 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -946,22 +946,9 @@ namespace ts { case SyntaxKind.SetAccessor: case SyntaxKind.TypeLiteral: addDeclaration(node); - // fall through - case SyntaxKind.Constructor: - case SyntaxKind.VariableStatement: - case SyntaxKind.VariableDeclarationList: - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ArrayBindingPattern: - case SyntaxKind.ModuleBlock: forEachChild(node, visit); break; - case SyntaxKind.Block: - if (isFunctionBlock(node)) { - forEachChild(node, visit); - } - break; - case SyntaxKind.Parameter: // Only consider parameter properties if (!(node.flags & NodeFlags.ParameterPropertyModifier)) { @@ -1014,6 +1001,9 @@ namespace ts { } } break; + + default: + forEachChild(node, visit); } } } diff --git a/tests/cases/fourslash/declarationExpressions.ts b/tests/cases/fourslash/declarationExpressions.ts index 764dab1521e..a7a08e92e59 100644 --- a/tests/cases/fourslash/declarationExpressions.ts +++ b/tests/cases/fourslash/declarationExpressions.ts @@ -6,6 +6,8 @@ ////}; ////function D() {} ////const E = function F() {} +////console.log(function inner() {}) + // Search for properties defined in the constructor, but not other constructor paramters var searchValue = "search"; @@ -17,3 +19,5 @@ verify.navigationItemsListContains("x", "property", "x", "exact"); verify.navigationItemsListContains("D", "function", "D", "exact"); verify.navigationItemsListContains("E", "const", "E", "exact"); verify.navigationItemsListContains("F", "function", "F", "exact") + +verify.navigationItemsListContains("inner", "function", "inner", "exact"); From 67beb002996754275d16fdcb69a9a0c9fa77f71d Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 13 May 2016 10:23:38 -0700 Subject: [PATCH 05/38] Improve test --- .../cases/fourslash/declarationExpressions.ts | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/cases/fourslash/declarationExpressions.ts b/tests/cases/fourslash/declarationExpressions.ts index a7a08e92e59..22d623c5573 100644 --- a/tests/cases/fourslash/declarationExpressions.ts +++ b/tests/cases/fourslash/declarationExpressions.ts @@ -7,17 +7,23 @@ ////function D() {} ////const E = function F() {} ////console.log(function inner() {}) +////String(function fun() { class cls { public prop; } })) +function navExact(name: string, kind: string) { + verify.navigationItemsListContains(name, kind, name, "exact"); +} -// Search for properties defined in the constructor, but not other constructor paramters -var searchValue = "search"; -verify.navigationItemsListContains("A", "class", "A", "exact"); -verify.navigationItemsListContains("B", "const", "B", "exact"); -verify.navigationItemsListContains("C", "class", "C", "exact"); -verify.navigationItemsListContains("x", "property", "x", "exact"); +navExact("A", "class"); +navExact("B", "const"); +navExact("C", "class"); +navExact("x", "property"); -verify.navigationItemsListContains("D", "function", "D", "exact"); -verify.navigationItemsListContains("E", "const", "E", "exact"); -verify.navigationItemsListContains("F", "function", "F", "exact") +navExact("D", "function"); +navExact("E", "const"); +navExact("F", "function") -verify.navigationItemsListContains("inner", "function", "inner", "exact"); +navExact("inner", "function"); + +navExact("fun", "function"); +navExact("cls", "class"); +navExact("prop", "property"); From a1cc88b08091cff5685a5a3b115d7f22dd8a54d5 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 13 May 2016 14:44:15 -0700 Subject: [PATCH 06/38] Fix bug: getTouchingPropertyName does not return undefined, but it may return the source file node --- src/services/services.ts | 2 +- tests/cases/fourslash/hoverOverComment.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/hoverOverComment.ts diff --git a/src/services/services.ts b/src/services/services.ts index b2f7eb4bdba..a24392024f0 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4645,7 +4645,7 @@ namespace ts { const sourceFile = getValidSourceFile(fileName); const node = getTouchingPropertyName(sourceFile, position); - if (!node) { + if (node === sourceFile) { return undefined; } diff --git a/tests/cases/fourslash/hoverOverComment.ts b/tests/cases/fourslash/hoverOverComment.ts new file mode 100644 index 00000000000..5b328b3a826 --- /dev/null +++ b/tests/cases/fourslash/hoverOverComment.ts @@ -0,0 +1,9 @@ +/// + +////export function f() {} +//////foo +/////**///moo + +goTo.marker(); +verify.quickInfoIs(""); + From b90761cf43cebccb5bb4bfcd14608ba94226f604 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 14 May 2016 13:34:00 -0700 Subject: [PATCH 07/38] Allow class properties and methods to be declared optional using '?' --- src/compiler/checker.ts | 17 ++++++++--------- src/compiler/diagnosticMessages.json | 4 ---- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 71c19e1214a..0f057e61667 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3216,7 +3216,9 @@ namespace ts { function getTypeOfFuncClassEnumModule(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { - links.type = createObjectType(TypeFlags.Anonymous, symbol); + const type = createObjectType(TypeFlags.Anonymous, symbol); + links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ? + addNullableKind(type, TypeFlags.Undefined) : type; } return links.type; } @@ -9921,7 +9923,8 @@ namespace ts { } const propType = getTypeOfSymbol(prop); - if (node.kind !== SyntaxKind.PropertyAccessExpression || !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) || isAssignmentTarget(node)) { + if (node.kind !== SyntaxKind.PropertyAccessExpression || isAssignmentTarget(node) || + !(propType.flags & TypeFlags.Union) && !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor))) { return propType; } const leftmostNode = getLeftmostIdentifierOrThis(node); @@ -13396,7 +13399,7 @@ namespace ts { // Abstract methods can't have an implementation -- in particular, they don't need one. if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && - !(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract)) { + !(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } @@ -18290,7 +18293,7 @@ namespace ts { } if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) { - if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional)) { + if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional)) { return true; } else if (node.body === undefined) { @@ -18299,9 +18302,6 @@ namespace ts { } if (isClassLike(node.parent)) { - if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional)) { - return true; - } // Technically, computed properties in ambient contexts is disallowed // for property declarations and accessors too, not just methods. // However, property declarations disallow computed names in general, @@ -18523,8 +18523,7 @@ namespace ts { function checkGrammarProperty(node: PropertyDeclaration) { if (isClassLike(node.parent)) { - if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional) || - checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol)) { + if (checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol)) { return true; } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 899b4292f04..cb347234ec7 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -315,10 +315,6 @@ "category": "Error", "code": 1110 }, - "A class member cannot be declared optional.": { - "category": "Error", - "code": 1112 - }, "A 'default' clause cannot appear more than once in a 'switch' statement.": { "category": "Error", "code": 1113 From 20e2be2d51f765e760b6668174976e9ac2ef2389 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 14 May 2016 13:34:54 -0700 Subject: [PATCH 08/38] Properly display optional methods in language service --- src/services/services.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/services/services.ts b/src/services/services.ts index 83f0d7152fd..39dd688254d 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4541,8 +4541,10 @@ namespace ts { } // For properties, variables and local vars: show the type + // Also handle methods that have a union type (i.e. that may be undefined) if (symbolKind === ScriptElementKind.memberVariableElement || symbolFlags & SymbolFlags.Variable || + symbolFlags & SymbolFlags.Method && type.flags & TypeFlags.Union || symbolKind === ScriptElementKind.localVariableElement || isThisExpression) { displayParts.push(punctuationPart(SyntaxKind.ColonToken)); From b8d2f2da9e3481760d6f145157ddf16d6bce12dd Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 14 May 2016 13:35:11 -0700 Subject: [PATCH 09/38] Accepting new baselines --- .../classWithOptionalParameter.errors.txt | 26 ------------------- .../classWithOptionalParameter.symbols | 26 +++++++++++++++++++ .../classWithOptionalParameter.types | 26 +++++++++++++++++++ ...tLiteralMemberWithQuestionMark1.errors.txt | 4 +-- ...jectTypesWithOptionalProperties.errors.txt | 8 +----- 5 files changed, 55 insertions(+), 35 deletions(-) delete mode 100644 tests/baselines/reference/classWithOptionalParameter.errors.txt create mode 100644 tests/baselines/reference/classWithOptionalParameter.symbols create mode 100644 tests/baselines/reference/classWithOptionalParameter.types diff --git a/tests/baselines/reference/classWithOptionalParameter.errors.txt b/tests/baselines/reference/classWithOptionalParameter.errors.txt deleted file mode 100644 index 6e512c2a02e..00000000000 --- a/tests/baselines/reference/classWithOptionalParameter.errors.txt +++ /dev/null @@ -1,26 +0,0 @@ -tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts(4,6): error TS1112: A class member cannot be declared optional. -tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts(5,6): error TS1112: A class member cannot be declared optional. -tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts(9,6): error TS1112: A class member cannot be declared optional. -tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts(10,6): error TS1112: A class member cannot be declared optional. - - -==== tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts (4 errors) ==== - // classes do not permit optional parameters, these are errors - - class C { - x?: string; - ~ -!!! error TS1112: A class member cannot be declared optional. - f?() {} - ~ -!!! error TS1112: A class member cannot be declared optional. - } - - class C2 { - x?: T; - ~ -!!! error TS1112: A class member cannot be declared optional. - f?(x: T) {} - ~ -!!! error TS1112: A class member cannot be declared optional. - } \ No newline at end of file diff --git a/tests/baselines/reference/classWithOptionalParameter.symbols b/tests/baselines/reference/classWithOptionalParameter.symbols new file mode 100644 index 00000000000..b85cd5d7a07 --- /dev/null +++ b/tests/baselines/reference/classWithOptionalParameter.symbols @@ -0,0 +1,26 @@ +=== tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts === +// classes do not permit optional parameters, these are errors + +class C { +>C : Symbol(C, Decl(classWithOptionalParameter.ts, 0, 0)) + + x?: string; +>x : Symbol(C.x, Decl(classWithOptionalParameter.ts, 2, 9)) + + f?() {} +>f : Symbol(C.f, Decl(classWithOptionalParameter.ts, 3, 15)) +} + +class C2 { +>C2 : Symbol(C2, Decl(classWithOptionalParameter.ts, 5, 1)) +>T : Symbol(T, Decl(classWithOptionalParameter.ts, 7, 9)) + + x?: T; +>x : Symbol(C2.x, Decl(classWithOptionalParameter.ts, 7, 13)) +>T : Symbol(T, Decl(classWithOptionalParameter.ts, 7, 9)) + + f?(x: T) {} +>f : Symbol(C2.f, Decl(classWithOptionalParameter.ts, 8, 10)) +>x : Symbol(x, Decl(classWithOptionalParameter.ts, 9, 7)) +>T : Symbol(T, Decl(classWithOptionalParameter.ts, 7, 9)) +} diff --git a/tests/baselines/reference/classWithOptionalParameter.types b/tests/baselines/reference/classWithOptionalParameter.types new file mode 100644 index 00000000000..2c62aee6fab --- /dev/null +++ b/tests/baselines/reference/classWithOptionalParameter.types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts === +// classes do not permit optional parameters, these are errors + +class C { +>C : C + + x?: string; +>x : string + + f?() {} +>f : () => void +} + +class C2 { +>C2 : C2 +>T : T + + x?: T; +>x : T +>T : T + + f?(x: T) {} +>f : (x: T) => void +>x : T +>T : T +} diff --git a/tests/baselines/reference/objectLiteralMemberWithQuestionMark1.errors.txt b/tests/baselines/reference/objectLiteralMemberWithQuestionMark1.errors.txt index b10ba701143..f77bad8664c 100644 --- a/tests/baselines/reference/objectLiteralMemberWithQuestionMark1.errors.txt +++ b/tests/baselines/reference/objectLiteralMemberWithQuestionMark1.errors.txt @@ -1,7 +1,7 @@ -tests/cases/compiler/objectLiteralMemberWithQuestionMark1.ts(1,14): error TS1112: A class member cannot be declared optional. +tests/cases/compiler/objectLiteralMemberWithQuestionMark1.ts(1,14): error TS1162: An object member cannot be declared optional. ==== tests/cases/compiler/objectLiteralMemberWithQuestionMark1.ts (1 errors) ==== var v = { foo?() { } } ~ -!!! error TS1112: A class member cannot be declared optional. \ No newline at end of file +!!! error TS1162: An object member cannot be declared optional. \ No newline at end of file diff --git a/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt b/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt index a2269c29d11..9fb2adc8c25 100644 --- a/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt +++ b/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt @@ -1,9 +1,7 @@ -tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts(12,6): error TS1112: A class member cannot be declared optional. -tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts(20,6): error TS1112: A class member cannot be declared optional. tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts(24,6): error TS1162: An object member cannot be declared optional. -==== tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts (3 errors) ==== +==== tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts (1 errors) ==== // Basic uses of optional properties var a: { @@ -16,8 +14,6 @@ tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWith class C { x?: number; // error - ~ -!!! error TS1112: A class member cannot be declared optional. } interface I2 { @@ -26,8 +22,6 @@ tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWith class C2 { x?: T; // error - ~ -!!! error TS1112: A class member cannot be declared optional. } var b = { From 8c5fe7d733e3a0cf39c2f6ff1f1c936c49e1c719 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 16 May 2016 06:37:49 -0700 Subject: [PATCH 10/38] Change other uses of getTouchingPropertyName to check for node === sourceFile instead of undefined. --- src/services/services.ts | 8 ++++---- tests/cases/fourslash/hoverOverComment.ts | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index a24392024f0..42c7ff8fc6c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4803,7 +4803,7 @@ namespace ts { const sourceFile = getValidSourceFile(fileName); const node = getTouchingPropertyName(sourceFile, position); - if (!node) { + if (node === sourceFile) { return undefined; } @@ -4891,7 +4891,7 @@ namespace ts { const sourceFile = getValidSourceFile(fileName); const node = getTouchingPropertyName(sourceFile, position); - if (!node) { + if (node === sourceFile) { return undefined; } @@ -5628,7 +5628,7 @@ namespace ts { const sourceFile = getValidSourceFile(fileName); const node = getTouchingPropertyName(sourceFile, position); - if (!node) { + if (node === sourceFile) { return undefined; } @@ -6795,7 +6795,7 @@ namespace ts { // Get node at the location const node = getTouchingPropertyName(sourceFile, startPos); - if (!node) { + if (node === sourceFile) { return; } diff --git a/tests/cases/fourslash/hoverOverComment.ts b/tests/cases/fourslash/hoverOverComment.ts index 5b328b3a826..574d9b5625d 100644 --- a/tests/cases/fourslash/hoverOverComment.ts +++ b/tests/cases/fourslash/hoverOverComment.ts @@ -6,4 +6,7 @@ goTo.marker(); verify.quickInfoIs(""); - +verify.verifyDefinitionsName("", ""); +verify.typeDefinitionCountIs(0); +verify.referencesCountIs(0); +verify.nameOrDottedNameSpanTextIs(undefined); From b91d14fd6cc0d4be8611451813ee7ecbea85f713 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 16 May 2016 06:41:39 -0700 Subject: [PATCH 11/38] Test expressions with no name --- tests/cases/fourslash/declarationExpressions.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/cases/fourslash/declarationExpressions.ts b/tests/cases/fourslash/declarationExpressions.ts index 22d623c5573..7f2a64d8ecf 100644 --- a/tests/cases/fourslash/declarationExpressions.ts +++ b/tests/cases/fourslash/declarationExpressions.ts @@ -6,8 +6,9 @@ ////}; ////function D() {} ////const E = function F() {} -////console.log(function inner() {}) -////String(function fun() { class cls { public prop; } })) +////console.log(function() {}, class {}); // Expression with no name should have no effect. +////console.log(function inner() {}); +////String(function fun() { class cls { public prop; } })); function navExact(name: string, kind: string) { verify.navigationItemsListContains(name, kind, name, "exact"); From 3a896d8ee79c97022ce67bfc84bcd9a9fe2c7a23 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 16 May 2016 09:20:42 -0700 Subject: [PATCH 12/38] Remove broken test --- tests/cases/fourslash/hoverOverComment.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cases/fourslash/hoverOverComment.ts b/tests/cases/fourslash/hoverOverComment.ts index 574d9b5625d..a9549a932f7 100644 --- a/tests/cases/fourslash/hoverOverComment.ts +++ b/tests/cases/fourslash/hoverOverComment.ts @@ -9,4 +9,3 @@ verify.quickInfoIs(""); verify.verifyDefinitionsName("", ""); verify.typeDefinitionCountIs(0); verify.referencesCountIs(0); -verify.nameOrDottedNameSpanTextIs(undefined); From bdd42eae9062a279801c297b73fcf84aa461db02 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 16 May 2016 09:21:15 -0700 Subject: [PATCH 13/38] Search for triple slash comments before getting a source node --- src/services/services.ts | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 42c7ff8fc6c..f49e85254b6 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4802,6 +4802,26 @@ namespace ts { const sourceFile = getValidSourceFile(fileName); + /// Triple slash reference comments + const comment = findReferenceInPosition(sourceFile.referencedFiles, position); + if (comment) { + const referenceFile = tryResolveScriptReference(program, sourceFile, comment); + if (referenceFile) { + return [getDefinitionInfoForFileReference(comment.fileName, referenceFile.fileName)]; + } + return undefined; + } + + // Type reference directives + const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); + if (typeReferenceDirective) { + const referenceFile = lookUp(program.getResolvedTypeReferenceDirectives(), typeReferenceDirective.fileName); + if (referenceFile && referenceFile.resolvedFileName) { + return [getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)]; + } + return undefined; + } + const node = getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { return undefined; @@ -4814,25 +4834,6 @@ namespace ts { return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; } - /// Triple slash reference comments - const comment = findReferenceInPosition(sourceFile.referencedFiles, position); - if (comment) { - const referenceFile = tryResolveScriptReference(program, sourceFile, comment); - if (referenceFile) { - return [getDefinitionInfoForFileReference(comment.fileName, referenceFile.fileName)]; - } - return undefined; - } - // Type reference directives - const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); - if (typeReferenceDirective) { - const referenceFile = lookUp(program.getResolvedTypeReferenceDirectives(), typeReferenceDirective.fileName); - if (referenceFile && referenceFile.resolvedFileName) { - return [getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)]; - } - return undefined; - } - const typeChecker = program.getTypeChecker(); let symbol = typeChecker.getSymbolAtLocation(node); From 6b3fc7f310d63792b17888e8b942dfcd0f594583 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 16 May 2016 09:23:29 -0700 Subject: [PATCH 14/38] Remove nullability from function types in language service --- src/compiler/checker.ts | 1 + src/compiler/types.ts | 1 + src/services/services.ts | 10 ++++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0f057e61667..e2b7efeac67 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -79,6 +79,7 @@ namespace ts { getIndexTypeOfType, getBaseTypes, getReturnTypeOfSignature, + getNonNullableType, getSymbolsInScope, getSymbolAtLocation, getShorthandAssignmentValueSymbol, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3a5602717c1..d924ac168c8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1770,6 +1770,7 @@ namespace ts { getIndexTypeOfType(type: Type, kind: IndexKind): Type; getBaseTypes(type: InterfaceType): ObjectType[]; getReturnTypeOfSignature(signature: Signature): Type; + getNonNullableType(type: Type): Type; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol; diff --git a/src/services/services.ts b/src/services/services.ts index 39dd688254d..d8abb4e6842 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -50,6 +50,7 @@ namespace ts { getStringIndexType(): Type; getNumberIndexType(): Type; getBaseTypes(): ObjectType[]; + getNonNullableType(): Type; } export interface Signature { @@ -735,6 +736,9 @@ namespace ts { ? this.checker.getBaseTypes(this) : undefined; } + getNonNullableType(): Type { + return this.checker.getNonNullableType(this); + } } class SignatureObject implements Signature { @@ -4366,7 +4370,7 @@ namespace ts { (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration // get the signature from the declaration and write it const functionDeclaration = location.parent; - const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); + const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); } @@ -4541,10 +4545,8 @@ namespace ts { } // For properties, variables and local vars: show the type - // Also handle methods that have a union type (i.e. that may be undefined) if (symbolKind === ScriptElementKind.memberVariableElement || symbolFlags & SymbolFlags.Variable || - symbolFlags & SymbolFlags.Method && type.flags & TypeFlags.Union || symbolKind === ScriptElementKind.localVariableElement || isThisExpression) { displayParts.push(punctuationPart(SyntaxKind.ColonToken)); @@ -4566,7 +4568,7 @@ namespace ts { symbolFlags & SymbolFlags.Signature || symbolFlags & SymbolFlags.Accessor || symbolKind === ScriptElementKind.memberFunctionElement) { - const allSignatures = type.getCallSignatures(); + const allSignatures = type.getNonNullableType().getCallSignatures(); addSignatureDisplayParts(allSignatures[0], allSignatures); } } From 3662c7b9cc6c278aa21d7587ddcfab74b8b4b80c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 16 May 2016 09:36:37 -0700 Subject: [PATCH 15/38] Adding test --- tests/baselines/reference/optionalMethods.js | 76 ++++++++ .../reference/optionalMethods.symbols | 160 ++++++++++++++++ .../baselines/reference/optionalMethods.types | 179 ++++++++++++++++++ .../types/namedTypes/optionalMethods.ts | 42 ++++ 4 files changed, 457 insertions(+) create mode 100644 tests/baselines/reference/optionalMethods.js create mode 100644 tests/baselines/reference/optionalMethods.symbols create mode 100644 tests/baselines/reference/optionalMethods.types create mode 100644 tests/cases/conformance/types/namedTypes/optionalMethods.ts diff --git a/tests/baselines/reference/optionalMethods.js b/tests/baselines/reference/optionalMethods.js new file mode 100644 index 00000000000..1cf09a588a7 --- /dev/null +++ b/tests/baselines/reference/optionalMethods.js @@ -0,0 +1,76 @@ +//// [optionalMethods.ts] + +interface Foo { + a: number; + b?: number; + f(): number; + g?(): number; +} + +function test1(x: Foo) { + x.a; + x.b; + x.f; + x.g; + let f1 = x.f(); + let g1 = x.g && x.g(); + let g2 = x.g ? x.g() : 0; +} + +class Bar { + a: number; + b?: number; + f() { + return 1; + } + g?(): number; // Body of optional method can be omitted + h?() { + return 2; + } +} + +function test2(x: Bar) { + x.a; + x.b; + x.f; + x.g; + let f1 = x.f(); + let g1 = x.g && x.g(); + let g2 = x.g ? x.g() : 0; + let h1 = x.h && x.h(); + let h2 = x.h ? x.h() : 0; +} + + +//// [optionalMethods.js] +function test1(x) { + x.a; + x.b; + x.f; + x.g; + var f1 = x.f(); + var g1 = x.g && x.g(); + var g2 = x.g ? x.g() : 0; +} +var Bar = (function () { + function Bar() { + } + Bar.prototype.f = function () { + return 1; + }; + Bar.prototype.h = function () { + return 2; + }; + return Bar; +}()); +function test2(x) { + x.a; + x.b; + x.f; + x.g; + var f1 = x.f(); + var g1 = x.g && x.g(); + var g2 = x.g ? x.g() : 0; + var h1 = x.h && x.h(); + var h2 = x.h ? x.h() : 0; +} diff --git a/tests/baselines/reference/optionalMethods.symbols b/tests/baselines/reference/optionalMethods.symbols new file mode 100644 index 00000000000..6b06e1902f4 --- /dev/null +++ b/tests/baselines/reference/optionalMethods.symbols @@ -0,0 +1,160 @@ +=== tests/cases/conformance/types/namedTypes/optionalMethods.ts === + +interface Foo { +>Foo : Symbol(Foo, Decl(optionalMethods.ts, 0, 0)) + + a: number; +>a : Symbol(Foo.a, Decl(optionalMethods.ts, 1, 15)) + + b?: number; +>b : Symbol(Foo.b, Decl(optionalMethods.ts, 2, 14)) + + f(): number; +>f : Symbol(Foo.f, Decl(optionalMethods.ts, 3, 15)) + + g?(): number; +>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16)) +} + +function test1(x: Foo) { +>test1 : Symbol(test1, Decl(optionalMethods.ts, 6, 1)) +>x : Symbol(x, Decl(optionalMethods.ts, 8, 15)) +>Foo : Symbol(Foo, Decl(optionalMethods.ts, 0, 0)) + + x.a; +>x.a : Symbol(Foo.a, Decl(optionalMethods.ts, 1, 15)) +>x : Symbol(x, Decl(optionalMethods.ts, 8, 15)) +>a : Symbol(Foo.a, Decl(optionalMethods.ts, 1, 15)) + + x.b; +>x.b : Symbol(Foo.b, Decl(optionalMethods.ts, 2, 14)) +>x : Symbol(x, Decl(optionalMethods.ts, 8, 15)) +>b : Symbol(Foo.b, Decl(optionalMethods.ts, 2, 14)) + + x.f; +>x.f : Symbol(Foo.f, Decl(optionalMethods.ts, 3, 15)) +>x : Symbol(x, Decl(optionalMethods.ts, 8, 15)) +>f : Symbol(Foo.f, Decl(optionalMethods.ts, 3, 15)) + + x.g; +>x.g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16)) +>x : Symbol(x, Decl(optionalMethods.ts, 8, 15)) +>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16)) + + let f1 = x.f(); +>f1 : Symbol(f1, Decl(optionalMethods.ts, 13, 7)) +>x.f : Symbol(Foo.f, Decl(optionalMethods.ts, 3, 15)) +>x : Symbol(x, Decl(optionalMethods.ts, 8, 15)) +>f : Symbol(Foo.f, Decl(optionalMethods.ts, 3, 15)) + + let g1 = x.g && x.g(); +>g1 : Symbol(g1, Decl(optionalMethods.ts, 14, 7)) +>x.g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16)) +>x : Symbol(x, Decl(optionalMethods.ts, 8, 15)) +>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16)) +>x.g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16)) +>x : Symbol(x, Decl(optionalMethods.ts, 8, 15)) +>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16)) + + let g2 = x.g ? x.g() : 0; +>g2 : Symbol(g2, Decl(optionalMethods.ts, 15, 7)) +>x.g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16)) +>x : Symbol(x, Decl(optionalMethods.ts, 8, 15)) +>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16)) +>x.g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16)) +>x : Symbol(x, Decl(optionalMethods.ts, 8, 15)) +>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16)) +} + +class Bar { +>Bar : Symbol(Bar, Decl(optionalMethods.ts, 16, 1)) + + a: number; +>a : Symbol(Bar.a, Decl(optionalMethods.ts, 18, 11)) + + b?: number; +>b : Symbol(Bar.b, Decl(optionalMethods.ts, 19, 14)) + + f() { +>f : Symbol(Bar.f, Decl(optionalMethods.ts, 20, 15)) + + return 1; + } + g?(): number; // Body of optional method can be omitted +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) + + h?() { +>h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) + + return 2; + } +} + +function test2(x: Bar) { +>test2 : Symbol(test2, Decl(optionalMethods.ts, 28, 1)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>Bar : Symbol(Bar, Decl(optionalMethods.ts, 16, 1)) + + x.a; +>x.a : Symbol(Bar.a, Decl(optionalMethods.ts, 18, 11)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>a : Symbol(Bar.a, Decl(optionalMethods.ts, 18, 11)) + + x.b; +>x.b : Symbol(Bar.b, Decl(optionalMethods.ts, 19, 14)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>b : Symbol(Bar.b, Decl(optionalMethods.ts, 19, 14)) + + x.f; +>x.f : Symbol(Bar.f, Decl(optionalMethods.ts, 20, 15)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>f : Symbol(Bar.f, Decl(optionalMethods.ts, 20, 15)) + + x.g; +>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) + + let f1 = x.f(); +>f1 : Symbol(f1, Decl(optionalMethods.ts, 35, 7)) +>x.f : Symbol(Bar.f, Decl(optionalMethods.ts, 20, 15)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>f : Symbol(Bar.f, Decl(optionalMethods.ts, 20, 15)) + + let g1 = x.g && x.g(); +>g1 : Symbol(g1, Decl(optionalMethods.ts, 36, 7)) +>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) +>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) + + let g2 = x.g ? x.g() : 0; +>g2 : Symbol(g2, Decl(optionalMethods.ts, 37, 7)) +>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) +>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) + + let h1 = x.h && x.h(); +>h1 : Symbol(h1, Decl(optionalMethods.ts, 38, 7)) +>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) +>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) + + let h2 = x.h ? x.h() : 0; +>h2 : Symbol(h2, Decl(optionalMethods.ts, 39, 7)) +>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) +>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) +>x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) +} + diff --git a/tests/baselines/reference/optionalMethods.types b/tests/baselines/reference/optionalMethods.types new file mode 100644 index 00000000000..528a2e23540 --- /dev/null +++ b/tests/baselines/reference/optionalMethods.types @@ -0,0 +1,179 @@ +=== tests/cases/conformance/types/namedTypes/optionalMethods.ts === + +interface Foo { +>Foo : Foo + + a: number; +>a : number + + b?: number; +>b : number | undefined + + f(): number; +>f : () => number + + g?(): number; +>g : (() => number) | undefined +} + +function test1(x: Foo) { +>test1 : (x: Foo) => void +>x : Foo +>Foo : Foo + + x.a; +>x.a : number +>x : Foo +>a : number + + x.b; +>x.b : number | undefined +>x : Foo +>b : number | undefined + + x.f; +>x.f : () => number +>x : Foo +>f : () => number + + x.g; +>x.g : (() => number) | undefined +>x : Foo +>g : (() => number) | undefined + + let f1 = x.f(); +>f1 : number +>x.f() : number +>x.f : () => number +>x : Foo +>f : () => number + + let g1 = x.g && x.g(); +>g1 : number | undefined +>x.g && x.g() : number | undefined +>x.g : (() => number) | undefined +>x : Foo +>g : (() => number) | undefined +>x.g() : number +>x.g : () => number +>x : Foo +>g : () => number + + let g2 = x.g ? x.g() : 0; +>g2 : number +>x.g ? x.g() : 0 : number +>x.g : (() => number) | undefined +>x : Foo +>g : (() => number) | undefined +>x.g() : number +>x.g : () => number +>x : Foo +>g : () => number +>0 : number +} + +class Bar { +>Bar : Bar + + a: number; +>a : number + + b?: number; +>b : number | undefined + + f() { +>f : () => number + + return 1; +>1 : number + } + g?(): number; // Body of optional method can be omitted +>g : (() => number) | undefined + + h?() { +>h : (() => number) | undefined + + return 2; +>2 : number + } +} + +function test2(x: Bar) { +>test2 : (x: Bar) => void +>x : Bar +>Bar : Bar + + x.a; +>x.a : number +>x : Bar +>a : number + + x.b; +>x.b : number | undefined +>x : Bar +>b : number | undefined + + x.f; +>x.f : () => number +>x : Bar +>f : () => number + + x.g; +>x.g : (() => number) | undefined +>x : Bar +>g : (() => number) | undefined + + let f1 = x.f(); +>f1 : number +>x.f() : number +>x.f : () => number +>x : Bar +>f : () => number + + let g1 = x.g && x.g(); +>g1 : number | undefined +>x.g && x.g() : number | undefined +>x.g : (() => number) | undefined +>x : Bar +>g : (() => number) | undefined +>x.g() : number +>x.g : () => number +>x : Bar +>g : () => number + + let g2 = x.g ? x.g() : 0; +>g2 : number +>x.g ? x.g() : 0 : number +>x.g : (() => number) | undefined +>x : Bar +>g : (() => number) | undefined +>x.g() : number +>x.g : () => number +>x : Bar +>g : () => number +>0 : number + + let h1 = x.h && x.h(); +>h1 : number | undefined +>x.h && x.h() : number | undefined +>x.h : (() => number) | undefined +>x : Bar +>h : (() => number) | undefined +>x.h() : number +>x.h : () => number +>x : Bar +>h : () => number + + let h2 = x.h ? x.h() : 0; +>h2 : number +>x.h ? x.h() : 0 : number +>x.h : (() => number) | undefined +>x : Bar +>h : (() => number) | undefined +>x.h() : number +>x.h : () => number +>x : Bar +>h : () => number +>0 : number +} + diff --git a/tests/cases/conformance/types/namedTypes/optionalMethods.ts b/tests/cases/conformance/types/namedTypes/optionalMethods.ts new file mode 100644 index 00000000000..47cd72fbae7 --- /dev/null +++ b/tests/cases/conformance/types/namedTypes/optionalMethods.ts @@ -0,0 +1,42 @@ +// @strictNullChecks: true + +interface Foo { + a: number; + b?: number; + f(): number; + g?(): number; +} + +function test1(x: Foo) { + x.a; + x.b; + x.f; + x.g; + let f1 = x.f(); + let g1 = x.g && x.g(); + let g2 = x.g ? x.g() : 0; +} + +class Bar { + a: number; + b?: number; + f() { + return 1; + } + g?(): number; // Body of optional method can be omitted + h?() { + return 2; + } +} + +function test2(x: Bar) { + x.a; + x.b; + x.f; + x.g; + let f1 = x.f(); + let g1 = x.g && x.g(); + let g2 = x.g ? x.g() : 0; + let h1 = x.h && x.h(); + let h2 = x.h ? x.h() : 0; +} From d66377d12506955a423203fbd510fa12bbbc5e1e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 16 May 2016 13:33:33 -0700 Subject: [PATCH 16/38] Add optionality to properties declared with '?' and initializer --- src/compiler/checker.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e2b7efeac67..bdfbc90c3e2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2886,6 +2886,10 @@ namespace ts { return undefined; } + function addOptionality(type: Type, optional: boolean): Type { + return strictNullChecks && optional ? addNullableKind(type, TypeFlags.Undefined) : type; + } + // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration): Type { if (declaration.flags & NodeFlags.JavaScriptFile) { @@ -2917,8 +2921,7 @@ namespace ts { // Use type from type annotation if one is present if (declaration.type) { - const type = getTypeFromTypeNode(declaration.type); - return strictNullChecks && declaration.questionToken ? addNullableKind(type, TypeFlags.Undefined) : type; + return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ !!declaration.questionToken); } if (declaration.kind === SyntaxKind.Parameter) { @@ -2940,13 +2943,13 @@ namespace ts { ? getContextuallyTypedThisType(func) : getContextuallyTypedParameterType(declaration); if (type) { - return strictNullChecks && declaration.questionToken ? addNullableKind(type, TypeFlags.Undefined) : type; + return addOptionality(type, /*optional*/ !!declaration.questionToken); } } // Use the type of the initializer expression if one is present if (declaration.initializer) { - return checkExpressionCached(declaration.initializer); + return addOptionality(checkExpressionCached(declaration.initializer), /*optional*/ !!declaration.questionToken); } // If it is a short-hand property assignment, use the type of the identifier From a11f72f9ab5de52b0f7c1bd7fdeb87489ae9e7f3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 16 May 2016 13:34:54 -0700 Subject: [PATCH 17/38] Emit '?' for optional parameter property in declaration file --- src/compiler/declarationEmitter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index aceec933227..a94c9a58d21 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1129,7 +1129,7 @@ namespace ts { // what we want, namely the name expression enclosed in brackets. writeTextOfNode(currentText, node.name); // If optional property emit ? - if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && hasQuestionToken(node)) { + if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.Parameter) && hasQuestionToken(node)) { write("?"); } if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && node.parent.kind === SyntaxKind.TypeLiteral) { From 0292eaac4a49061897d5851d451737acdbb5a05b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 16 May 2016 13:36:39 -0700 Subject: [PATCH 18/38] Accepting new baselines --- tests/baselines/reference/declFileConstructors.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/declFileConstructors.js b/tests/baselines/reference/declFileConstructors.js index 44e816712fb..8e92b1a36ae 100644 --- a/tests/baselines/reference/declFileConstructors.js +++ b/tests/baselines/reference/declFileConstructors.js @@ -247,7 +247,7 @@ export declare class ConstructorWithPrivateParameterProperty { constructor(x: string); } export declare class ConstructorWithOptionalParameterProperty { - x: string; + x?: string; constructor(x?: string); } export declare class ConstructorWithParameterInitializer { @@ -281,7 +281,7 @@ declare class GlobalConstructorWithPrivateParameterProperty { constructor(x: string); } declare class GlobalConstructorWithOptionalParameterProperty { - x: string; + x?: string; constructor(x?: string); } declare class GlobalConstructorWithParameterInitializer { From e82bbce28c9f2e4704133440ff9ab66948326219 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 16 May 2016 13:37:03 -0700 Subject: [PATCH 19/38] Fixing test --- .../reference/objectTypesWithOptionalProperties.errors.txt | 4 ++-- .../baselines/reference/objectTypesWithOptionalProperties.js | 4 ++-- .../methodSignatures/objectTypesWithOptionalProperties.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt b/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt index 9fb2adc8c25..74057195c64 100644 --- a/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt +++ b/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt @@ -13,7 +13,7 @@ tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWith } class C { - x?: number; // error + x?: number; // ok } interface I2 { @@ -21,7 +21,7 @@ tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWith } class C2 { - x?: T; // error + x?: T; // ok } var b = { diff --git a/tests/baselines/reference/objectTypesWithOptionalProperties.js b/tests/baselines/reference/objectTypesWithOptionalProperties.js index 98141c048dd..9b2ada010d9 100644 --- a/tests/baselines/reference/objectTypesWithOptionalProperties.js +++ b/tests/baselines/reference/objectTypesWithOptionalProperties.js @@ -10,7 +10,7 @@ interface I { } class C { - x?: number; // error + x?: number; // ok } interface I2 { @@ -18,7 +18,7 @@ interface I2 { } class C2 { - x?: T; // error + x?: T; // ok } var b = { diff --git a/tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts b/tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts index f80c3a5952d..7c05ff09e56 100644 --- a/tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts +++ b/tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts @@ -9,7 +9,7 @@ interface I { } class C { - x?: number; // error + x?: number; // ok } interface I2 { @@ -17,7 +17,7 @@ interface I2 { } class C2 { - x?: T; // error + x?: T; // ok } var b = { From 8498ef190e9382621ea4cfe4d392d878e5d052ac Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 16 May 2016 13:37:17 -0700 Subject: [PATCH 20/38] Adding more tests --- tests/baselines/reference/optionalMethods.js | 73 +++++++++- .../reference/optionalMethods.symbols | 133 ++++++++++++------ .../baselines/reference/optionalMethods.types | 47 +++++++ .../types/namedTypes/optionalMethods.ts | 16 +++ 4 files changed, 223 insertions(+), 46 deletions(-) diff --git a/tests/baselines/reference/optionalMethods.js b/tests/baselines/reference/optionalMethods.js index 1cf09a588a7..42decf512e4 100644 --- a/tests/baselines/reference/optionalMethods.js +++ b/tests/baselines/reference/optionalMethods.js @@ -20,6 +20,8 @@ function test1(x: Foo) { class Bar { a: number; b?: number; + c? = 2; + constructor(public d?: number, public e = 10) {} f() { return 1; } @@ -32,6 +34,9 @@ class Bar { function test2(x: Bar) { x.a; x.b; + x.c; + x.d; + x.e; x.f; x.g; let f1 = x.f(); @@ -40,9 +45,24 @@ function test2(x: Bar) { let h1 = x.h && x.h(); let h2 = x.h ? x.h() : 0; } + +class Base { + a?: number; + f?(): number; +} + +class Derived extends Base { + a = 1; + f(): number { return 1; } +} //// [optionalMethods.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; function test1(x) { x.a; x.b; @@ -53,7 +73,11 @@ function test1(x) { var g2 = x.g ? x.g() : 0; } var Bar = (function () { - function Bar() { + function Bar(d, e) { + if (e === void 0) { e = 10; } + this.d = d; + this.e = e; + this.c = 2; } Bar.prototype.f = function () { return 1; @@ -66,6 +90,9 @@ var Bar = (function () { function test2(x) { x.a; x.b; + x.c; + x.d; + x.e; x.f; x.g; var f1 = x.f(); @@ -74,3 +101,47 @@ function test2(x) { var h1 = x.h && x.h(); var h2 = x.h ? x.h() : 0; } +var Base = (function () { + function Base() { + } + return Base; +}()); +var Derived = (function (_super) { + __extends(Derived, _super); + function Derived() { + _super.apply(this, arguments); + this.a = 1; + } + Derived.prototype.f = function () { return 1; }; + return Derived; +}(Base)); + + +//// [optionalMethods.d.ts] +interface Foo { + a: number; + b?: number; + f(): number; + g?(): number; +} +declare function test1(x: Foo): void; +declare class Bar { + d?: number; + e: number; + a: number; + b?: number; + c?: number | undefined; + constructor(d?: number, e?: number); + f(): number; + g?(): number; + h?(): number; +} +declare function test2(x: Bar): void; +declare class Base { + a?: number; + f?(): number; +} +declare class Derived extends Base { + a: number; + f(): number; +} diff --git a/tests/baselines/reference/optionalMethods.symbols b/tests/baselines/reference/optionalMethods.symbols index 6b06e1902f4..55c5ec958da 100644 --- a/tests/baselines/reference/optionalMethods.symbols +++ b/tests/baselines/reference/optionalMethods.symbols @@ -75,86 +75,129 @@ class Bar { b?: number; >b : Symbol(Bar.b, Decl(optionalMethods.ts, 19, 14)) + c? = 2; +>c : Symbol(Bar.c, Decl(optionalMethods.ts, 20, 15)) + + constructor(public d?: number, public e = 10) {} +>d : Symbol(Bar.d, Decl(optionalMethods.ts, 22, 16)) +>e : Symbol(Bar.e, Decl(optionalMethods.ts, 22, 34)) + f() { ->f : Symbol(Bar.f, Decl(optionalMethods.ts, 20, 15)) +>f : Symbol(Bar.f, Decl(optionalMethods.ts, 22, 52)) return 1; } g?(): number; // Body of optional method can be omitted ->g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) h?() { ->h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) +>h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17)) return 2; } } function test2(x: Bar) { ->test2 : Symbol(test2, Decl(optionalMethods.ts, 28, 1)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>test2 : Symbol(test2, Decl(optionalMethods.ts, 30, 1)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) >Bar : Symbol(Bar, Decl(optionalMethods.ts, 16, 1)) x.a; >x.a : Symbol(Bar.a, Decl(optionalMethods.ts, 18, 11)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) >a : Symbol(Bar.a, Decl(optionalMethods.ts, 18, 11)) x.b; >x.b : Symbol(Bar.b, Decl(optionalMethods.ts, 19, 14)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) >b : Symbol(Bar.b, Decl(optionalMethods.ts, 19, 14)) + x.c; +>x.c : Symbol(Bar.c, Decl(optionalMethods.ts, 20, 15)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>c : Symbol(Bar.c, Decl(optionalMethods.ts, 20, 15)) + + x.d; +>x.d : Symbol(Bar.d, Decl(optionalMethods.ts, 22, 16)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>d : Symbol(Bar.d, Decl(optionalMethods.ts, 22, 16)) + + x.e; +>x.e : Symbol(Bar.e, Decl(optionalMethods.ts, 22, 34)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>e : Symbol(Bar.e, Decl(optionalMethods.ts, 22, 34)) + x.f; ->x.f : Symbol(Bar.f, Decl(optionalMethods.ts, 20, 15)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) ->f : Symbol(Bar.f, Decl(optionalMethods.ts, 20, 15)) +>x.f : Symbol(Bar.f, Decl(optionalMethods.ts, 22, 52)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>f : Symbol(Bar.f, Decl(optionalMethods.ts, 22, 52)) x.g; ->x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) ->g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) +>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) let f1 = x.f(); ->f1 : Symbol(f1, Decl(optionalMethods.ts, 35, 7)) ->x.f : Symbol(Bar.f, Decl(optionalMethods.ts, 20, 15)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) ->f : Symbol(Bar.f, Decl(optionalMethods.ts, 20, 15)) +>f1 : Symbol(f1, Decl(optionalMethods.ts, 40, 7)) +>x.f : Symbol(Bar.f, Decl(optionalMethods.ts, 22, 52)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>f : Symbol(Bar.f, Decl(optionalMethods.ts, 22, 52)) let g1 = x.g && x.g(); ->g1 : Symbol(g1, Decl(optionalMethods.ts, 36, 7)) ->x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) ->g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) ->x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) ->g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) +>g1 : Symbol(g1, Decl(optionalMethods.ts, 41, 7)) +>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) +>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) let g2 = x.g ? x.g() : 0; ->g2 : Symbol(g2, Decl(optionalMethods.ts, 37, 7)) ->x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) ->g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) ->x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) ->g : Symbol(Bar.g, Decl(optionalMethods.ts, 23, 5)) +>g2 : Symbol(g2, Decl(optionalMethods.ts, 42, 7)) +>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) +>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) let h1 = x.h && x.h(); ->h1 : Symbol(h1, Decl(optionalMethods.ts, 38, 7)) ->x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) ->h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) ->x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) ->h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) +>h1 : Symbol(h1, Decl(optionalMethods.ts, 43, 7)) +>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17)) +>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17)) let h2 = x.h ? x.h() : 0; ->h2 : Symbol(h2, Decl(optionalMethods.ts, 39, 7)) ->x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) ->h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) ->x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) ->x : Symbol(x, Decl(optionalMethods.ts, 30, 15)) ->h : Symbol(Bar.h, Decl(optionalMethods.ts, 24, 17)) +>h2 : Symbol(h2, Decl(optionalMethods.ts, 44, 7)) +>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17)) +>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17)) +>x : Symbol(x, Decl(optionalMethods.ts, 32, 15)) +>h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17)) +} + +class Base { +>Base : Symbol(Base, Decl(optionalMethods.ts, 45, 1)) + + a?: number; +>a : Symbol(Base.a, Decl(optionalMethods.ts, 47, 12)) + + f?(): number; +>f : Symbol(Base.f, Decl(optionalMethods.ts, 48, 15)) +} + +class Derived extends Base { +>Derived : Symbol(Derived, Decl(optionalMethods.ts, 50, 1)) +>Base : Symbol(Base, Decl(optionalMethods.ts, 45, 1)) + + a = 1; +>a : Symbol(Derived.a, Decl(optionalMethods.ts, 52, 28)) + + f(): number { return 1; } +>f : Symbol(Derived.f, Decl(optionalMethods.ts, 53, 10)) } diff --git a/tests/baselines/reference/optionalMethods.types b/tests/baselines/reference/optionalMethods.types index 528a2e23540..70fda27c012 100644 --- a/tests/baselines/reference/optionalMethods.types +++ b/tests/baselines/reference/optionalMethods.types @@ -81,6 +81,15 @@ class Bar { b?: number; >b : number | undefined + c? = 2; +>c : number | undefined +>2 : number + + constructor(public d?: number, public e = 10) {} +>d : number | undefined +>e : number +>10 : number + f() { >f : () => number @@ -113,6 +122,21 @@ function test2(x: Bar) { >x : Bar >b : number | undefined + x.c; +>x.c : number | undefined +>x : Bar +>c : number | undefined + + x.d; +>x.d : number | undefined +>x : Bar +>d : number | undefined + + x.e; +>x.e : number +>x : Bar +>e : number + x.f; >x.f : () => number >x : Bar @@ -177,3 +201,26 @@ function test2(x: Bar) { >0 : number } +class Base { +>Base : Base + + a?: number; +>a : number | undefined + + f?(): number; +>f : (() => number) | undefined +} + +class Derived extends Base { +>Derived : Derived +>Base : Base + + a = 1; +>a : number +>1 : number + + f(): number { return 1; } +>f : () => number +>1 : number +} + diff --git a/tests/cases/conformance/types/namedTypes/optionalMethods.ts b/tests/cases/conformance/types/namedTypes/optionalMethods.ts index 47cd72fbae7..932521425f9 100644 --- a/tests/cases/conformance/types/namedTypes/optionalMethods.ts +++ b/tests/cases/conformance/types/namedTypes/optionalMethods.ts @@ -1,4 +1,5 @@ // @strictNullChecks: true +// @declaration: true interface Foo { a: number; @@ -20,6 +21,8 @@ function test1(x: Foo) { class Bar { a: number; b?: number; + c? = 2; + constructor(public d?: number, public e = 10) {} f() { return 1; } @@ -32,6 +35,9 @@ class Bar { function test2(x: Bar) { x.a; x.b; + x.c; + x.d; + x.e; x.f; x.g; let f1 = x.f(); @@ -40,3 +46,13 @@ function test2(x: Bar) { let h1 = x.h && x.h(); let h2 = x.h ? x.h() : 0; } + +class Base { + a?: number; + f?(): number; +} + +class Derived extends Base { + a = 1; + f(): number { return 1; } +} From ae4a983c59d3e0e8036c6efa5ef4fa10be2a6531 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 16 May 2016 16:09:36 -0700 Subject: [PATCH 21/38] Use binding pattern for type inference result `{}` The binding pattern provides additional information when the contextual type is not found and would otherwise fix a type parameter to `{}`. --- src/compiler/checker.ts | 6 +++ ...allbackToBindingPatternForTypeInference.js | 25 ++++++++++++ ...ckToBindingPatternForTypeInference.symbols | 28 +++++++++++++ ...backToBindingPatternForTypeInference.types | 40 +++++++++++++++++++ ...allbackToBindingPatternForTypeInference.ts | 5 +++ 5 files changed, 104 insertions(+) create mode 100644 tests/baselines/reference/fallbackToBindingPatternForTypeInference.js create mode 100644 tests/baselines/reference/fallbackToBindingPatternForTypeInference.symbols create mode 100644 tests/baselines/reference/fallbackToBindingPatternForTypeInference.types create mode 100644 tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6a720d947df..079d942df4e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11455,6 +11455,12 @@ namespace ts { const links = getSymbolLinks(parameter); if (!links.type) { links.type = instantiateType(contextualType, mapper); + // if inference didn't come up with anything but {}, fall back to the binding pattern if present. + if (links.type === emptyObjectType && + (parameter.valueDeclaration.name.kind === SyntaxKind.ObjectBindingPattern || + parameter.valueDeclaration.name.kind === SyntaxKind.ArrayBindingPattern)) { + links.type = getTypeFromBindingPattern(parameter.valueDeclaration.name); + } assignBindingElementTypes(parameter.valueDeclaration); } else if (isInferentialContext(mapper)) { diff --git a/tests/baselines/reference/fallbackToBindingPatternForTypeInference.js b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.js new file mode 100644 index 00000000000..fd0632b2bea --- /dev/null +++ b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.js @@ -0,0 +1,25 @@ +//// [fallbackToBindingPatternForTypeInference.ts] +declare function trans(f: (x: T) => string): number; +trans(({a}) => a); +trans(([b,c]) => 'foo'); +trans(({d: [e,f]}) => 'foo'); +trans(([{g},{h}]) => 'foo'); + + +//// [fallbackToBindingPatternForTypeInference.js] +trans(function (_a) { + var a = _a.a; + return a; +}); +trans(function (_a) { + var b = _a[0], c = _a[1]; + return 'foo'; +}); +trans(function (_a) { + var _b = _a.d, e = _b[0], f = _b[1]; + return 'foo'; +}); +trans(function (_a) { + var g = _a[0].g, h = _a[1].h; + return 'foo'; +}); diff --git a/tests/baselines/reference/fallbackToBindingPatternForTypeInference.symbols b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.symbols new file mode 100644 index 00000000000..e7049d50e1b --- /dev/null +++ b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.symbols @@ -0,0 +1,28 @@ +=== tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts === +declare function trans(f: (x: T) => string): number; +>trans : Symbol(trans, Decl(fallbackToBindingPatternForTypeInference.ts, 0, 0)) +>T : Symbol(T, Decl(fallbackToBindingPatternForTypeInference.ts, 0, 23)) +>f : Symbol(f, Decl(fallbackToBindingPatternForTypeInference.ts, 0, 26)) +>x : Symbol(x, Decl(fallbackToBindingPatternForTypeInference.ts, 0, 30)) +>T : Symbol(T, Decl(fallbackToBindingPatternForTypeInference.ts, 0, 23)) + +trans(({a}) => a); +>trans : Symbol(trans, Decl(fallbackToBindingPatternForTypeInference.ts, 0, 0)) +>a : Symbol(a, Decl(fallbackToBindingPatternForTypeInference.ts, 1, 8)) +>a : Symbol(a, Decl(fallbackToBindingPatternForTypeInference.ts, 1, 8)) + +trans(([b,c]) => 'foo'); +>trans : Symbol(trans, Decl(fallbackToBindingPatternForTypeInference.ts, 0, 0)) +>b : Symbol(b, Decl(fallbackToBindingPatternForTypeInference.ts, 2, 8)) +>c : Symbol(c, Decl(fallbackToBindingPatternForTypeInference.ts, 2, 10)) + +trans(({d: [e,f]}) => 'foo'); +>trans : Symbol(trans, Decl(fallbackToBindingPatternForTypeInference.ts, 0, 0)) +>e : Symbol(e, Decl(fallbackToBindingPatternForTypeInference.ts, 3, 12)) +>f : Symbol(f, Decl(fallbackToBindingPatternForTypeInference.ts, 3, 14)) + +trans(([{g},{h}]) => 'foo'); +>trans : Symbol(trans, Decl(fallbackToBindingPatternForTypeInference.ts, 0, 0)) +>g : Symbol(g, Decl(fallbackToBindingPatternForTypeInference.ts, 4, 9)) +>h : Symbol(h, Decl(fallbackToBindingPatternForTypeInference.ts, 4, 13)) + diff --git a/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types new file mode 100644 index 00000000000..c8f01abaf82 --- /dev/null +++ b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types @@ -0,0 +1,40 @@ +=== tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts === +declare function trans(f: (x: T) => string): number; +>trans : (f: (x: T) => string) => number +>T : T +>f : (x: T) => string +>x : T +>T : T + +trans(({a}) => a); +>trans(({a}) => a) : number +>trans : (f: (x: T) => string) => number +>({a}) => a : ({a}: { a: any; }) => any +>a : any +>a : any + +trans(([b,c]) => 'foo'); +>trans(([b,c]) => 'foo') : number +>trans : (f: (x: T) => string) => number +>([b,c]) => 'foo' : ([b, c]: [any, any]) => string +>b : any +>c : any +>'foo' : string + +trans(({d: [e,f]}) => 'foo'); +>trans(({d: [e,f]}) => 'foo') : number +>trans : (f: (x: T) => string) => number +>({d: [e,f]}) => 'foo' : ({d: [e, f]}: { d: [any, any]; }) => string +>d : any +>e : any +>f : any +>'foo' : string + +trans(([{g},{h}]) => 'foo'); +>trans(([{g},{h}]) => 'foo') : number +>trans : (f: (x: T) => string) => number +>([{g},{h}]) => 'foo' : ([{g}, {h}]: [{ g: any; }, { h: any; }]) => string +>g : any +>h : any +>'foo' : string + diff --git a/tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts b/tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts new file mode 100644 index 00000000000..de6940110da --- /dev/null +++ b/tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts @@ -0,0 +1,5 @@ +declare function trans(f: (x: T) => string): number; +trans(({a}) => a); +trans(([b,c]) => 'foo'); +trans(({d: [e,f]}) => 'foo'); +trans(([{g},{h}]) => 'foo'); From d541d434ea331219b04cce2e7f20b07a32ba0df4 Mon Sep 17 00:00:00 2001 From: mihailik Date: Tue, 17 May 2016 09:09:46 +0100 Subject: [PATCH 22/38] Extra test for #8364 - non-breaking of one-liners --- tests/cases/fourslash/formatArrayLiteralExpression.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/cases/fourslash/formatArrayLiteralExpression.ts b/tests/cases/fourslash/formatArrayLiteralExpression.ts index 51594965a33..9c2224f8414 100644 --- a/tests/cases/fourslash/formatArrayLiteralExpression.ts +++ b/tests/cases/fourslash/formatArrayLiteralExpression.ts @@ -18,9 +18,9 @@ ////}/*6*/, //// { //// Salad: 'salad', /*7*/ -//// Burrito: 'burrito', +//// Burrito: ['burrito', 'carne asada', 'tinga de res', 'tinga de pollo'], /*8*/ //// Pie: 'pie' -//// }];/*8*/ +//// }];/*9*/ format.document(); @@ -40,4 +40,6 @@ verify.currentLineContentIs(" },"); goTo.marker("7"); verify.currentLineContentIs(" Salad: 'salad',"); goTo.marker("8"); +verify.currentLineContentIs(" Burrito: ['burrito', 'carne asada', 'tinga de res', 'tinga de pollo'],"); +goTo.marker("9"); verify.currentLineContentIs(" }];"); From c11d691d6f6e647babc0bd6bd95b95368d871abd Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 17 May 2016 06:15:57 -0700 Subject: [PATCH 23/38] Introduce 'never' type --- src/compiler/checker.ts | 33 ++++++++++++++++-------------- src/compiler/declarationEmitter.ts | 1 + src/compiler/parser.ts | 2 ++ src/compiler/scanner.ts | 1 + src/compiler/types.ts | 1 + src/compiler/utilities.ts | 1 + 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6a720d947df..95e33be8eb5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -122,7 +122,7 @@ namespace ts { const unknownType = createIntrinsicType(TypeFlags.Any, "unknown"); const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const nothingType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); + const neverType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); emptyGenericType.instantiations = {}; @@ -2029,8 +2029,8 @@ namespace ts { writeUnionOrIntersectionType(type, flags); } else if (type.flags & TypeFlags.Anonymous) { - if (type === nothingType) { - writer.writeKeyword("nothing"); + if (type === neverType) { + writer.writeKeyword("never"); } else { writeAnonymousType(type, flags); @@ -3670,6 +3670,7 @@ namespace ts { case SyntaxKind.VoidKeyword: case SyntaxKind.UndefinedKeyword: case SyntaxKind.NullKeyword: + case SyntaxKind.NeverKeyword: case SyntaxKind.StringLiteralType: return true; case SyntaxKind.ArrayType: @@ -5005,7 +5006,7 @@ namespace ts { if (type.flags & TypeFlags.Undefined) typeSet.containsUndefined = true; if (type.flags & TypeFlags.Null) typeSet.containsNull = true; } - else if (type !== nothingType && !contains(typeSet, type)) { + else if (type !== neverType && !contains(typeSet, type)) { typeSet.push(type); } } @@ -5046,7 +5047,7 @@ namespace ts { // a named type that circularly references itself. function getUnionType(types: Type[], noSubtypeReduction?: boolean): Type { if (types.length === 0) { - return nothingType; + return neverType; } if (types.length === 1) { return types[0]; @@ -5066,7 +5067,7 @@ namespace ts { if (typeSet.length === 0) { return typeSet.containsNull ? nullType : typeSet.containsUndefined ? undefinedType : - nothingType; + neverType; } else if (typeSet.length === 1) { return typeSet[0]; @@ -5214,6 +5215,8 @@ namespace ts { return undefinedType; case SyntaxKind.NullKeyword: return nullType; + case SyntaxKind.NeverKeyword: + return neverType; case SyntaxKind.ThisType: case SyntaxKind.ThisKeyword: return getTypeFromThisTypeNode(node); @@ -7485,7 +7488,7 @@ namespace ts { function getTypeWithFacts(type: Type, include: TypeFacts) { if (!(type.flags & TypeFlags.Union)) { - return getTypeFacts(type) & include ? type : nothingType; + return getTypeFacts(type) & include ? type : neverType; } let firstType: Type; let types: Type[]; @@ -7502,7 +7505,7 @@ namespace ts { } } } - return firstType ? types ? getUnionType(types, /*noSubtypeReduction*/ true) : firstType : nothingType; + return firstType ? types ? getUnionType(types, /*noSubtypeReduction*/ true) : firstType : neverType; } function getTypeWithDefault(type: Type, defaultExpression: Expression) { @@ -7622,7 +7625,7 @@ namespace ts { const visitedFlowStart = visitedFlowCount; const result = getTypeAtFlowNode(reference.flowNode); visitedFlowCount = visitedFlowStart; - if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull) === nothingType) { + if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull) === neverType) { return declaredType; } return result; @@ -7710,7 +7713,7 @@ namespace ts { function getTypeAtFlowCondition(flow: FlowCondition) { let type = getTypeAtFlowNode(flow.antecedent); - if (type !== nothingType) { + if (type !== neverType) { // If we have an antecedent type (meaning we're reachable in some way), we first // attempt to narrow the antecedent type. If that produces the nothing type, then // we take the type guard as an indication that control could reach here in a @@ -7720,7 +7723,7 @@ namespace ts { // narrow that. const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0; type = narrowType(type, flow.expression, assumeTrue); - if (type === nothingType) { + if (type === neverType) { type = narrowType(declaredType, flow.expression, assumeTrue); } } @@ -7942,7 +7945,7 @@ namespace ts { const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type; return isTypeAssignableTo(candidate, targetType) ? candidate : isTypeAssignableTo(type, candidate) ? type : - nothingType; + neverType; } function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type { @@ -11559,7 +11562,7 @@ namespace ts { return promiseType; } else { - return voidType; + return hasImplicitReturn ? voidType : neverType; } } } @@ -14747,7 +14750,7 @@ namespace ts { arrayType = getUnionType(filter((arrayOrStringType as UnionType).types, t => !(t.flags & TypeFlags.StringLike))); } else if (arrayOrStringType.flags & TypeFlags.StringLike) { - arrayType = nothingType; + arrayType = neverType; } const hasStringConstituent = arrayOrStringType !== arrayType; let reportedError = false; @@ -14759,7 +14762,7 @@ namespace ts { // Now that we've removed all the StringLike types, if no constituents remain, then the entire // arrayOrStringType was a string. - if (arrayType === nothingType) { + if (arrayType === neverType) { return stringType; } } diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index c24135ba52e..9e4f7896745 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -395,6 +395,7 @@ namespace ts { case SyntaxKind.VoidKeyword: case SyntaxKind.UndefinedKeyword: case SyntaxKind.NullKeyword: + case SyntaxKind.NeverKeyword: case SyntaxKind.ThisType: case SyntaxKind.StringLiteralType: return writeTextOfNode(currentText, type); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index daebf8a930b..b60082969db 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2368,6 +2368,7 @@ namespace ts { case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NeverKeyword: // If these are followed by a dot, then parse these out as a dotted type reference instead. const node = tryParse(parseKeywordAndNoDot); return node || parseTypeReference(); @@ -2410,6 +2411,7 @@ namespace ts { case SyntaxKind.NullKeyword: case SyntaxKind.ThisKeyword: case SyntaxKind.TypeOfKeyword: + case SyntaxKind.NeverKeyword: case SyntaxKind.OpenBraceToken: case SyntaxKind.OpenBracketToken: case SyntaxKind.LessThanToken: diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 8979814a7a2..1a2748b38b1 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -91,6 +91,7 @@ namespace ts { "let": SyntaxKind.LetKeyword, "module": SyntaxKind.ModuleKeyword, "namespace": SyntaxKind.NamespaceKeyword, + "never": SyntaxKind.NeverKeyword, "new": SyntaxKind.NewKeyword, "null": SyntaxKind.NullKeyword, "number": SyntaxKind.NumberKeyword, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 777141b45fb..fbe1f3c60c8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -164,6 +164,7 @@ namespace ts { IsKeyword, ModuleKeyword, NamespaceKeyword, + NeverKeyword, ReadonlyKeyword, RequireKeyword, NumberKeyword, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 42ba6b9d0fc..9a86e223ebd 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -613,6 +613,7 @@ namespace ts { case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NeverKeyword: return true; case SyntaxKind.VoidKeyword: return node.parent.kind !== SyntaxKind.VoidExpression; From aa028ca66054d4248a45593520a4bda7e70e37d5 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 17 May 2016 06:32:49 -0700 Subject: [PATCH 24/38] Handle 'never' in return type inference --- src/compiler/checker.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 95e33be8eb5..7aa83ad268e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11550,6 +11550,9 @@ namespace ts { else { const hasImplicitReturn = !!(func.flags & NodeFlags.HasImplicitReturn); types = checkAndAggregateReturnExpressionTypes(func.body, contextualMapper, isAsync, hasImplicitReturn); + if (!types) { + return neverType; + } if (types.length === 0) { if (isAsync) { // For an async function, the return type will not be void, but rather a Promise for void. @@ -11558,12 +11561,9 @@ namespace ts { error(func, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type); return unknownType; } - return promiseType; } - else { - return hasImplicitReturn ? voidType : neverType; - } + return voidType; } } // When yield/return statements are contextually typed we allow the return type to be a union type. @@ -11643,7 +11643,7 @@ namespace ts { // the native Promise type by the caller. type = checkAwaitedType(type, body.parent, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); } - if (!contains(aggregatedTypes, type)) { + if (type !== neverType && !contains(aggregatedTypes, type)) { aggregatedTypes.push(type); } } @@ -11651,6 +11651,9 @@ namespace ts { hasOmittedExpressions = true; } }); + if (aggregatedTypes.length === 0 && !hasOmittedExpressions && !hasImplicitReturn) { + return undefined; + } if (strictNullChecks && aggregatedTypes.length && (hasOmittedExpressions || hasImplicitReturn)) { if (!contains(aggregatedTypes, undefinedType)) { aggregatedTypes.push(undefinedType); From df8e7409c1f3ff67aea00df6d6b56391af5ff4fd Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 16 May 2016 08:18:33 -0700 Subject: [PATCH 25/38] Add test for #7301 --- src/harness/fourslash.ts | 53 +++++++++++++++++++ tests/cases/fourslash/fourslash.ts | 3 ++ .../cases/fourslash/getNavigationBarItems.ts | 11 ++++ 3 files changed, 67 insertions(+) create mode 100644 tests/cases/fourslash/getNavigationBarItems.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index d6035aaa026..cdef2554f96 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1912,6 +1912,47 @@ namespace FourSlash { } } + public verifyNavigationBarCount(count: number) { + const actual = this.navigationBarItems().length; + if (actual !== count) { + this.raiseError(`Expected ${count} items in navigation bar, got ${actual}`); + } + } + + public verifyNavigationBarItem(text: string, kind: string) { + this.verifyNavigationBarItemExists(this.navigationBarItems(), text, kind); + } + + public verifyNavigationBarChildItem(parent: string, text: string, kind: string) { + const items = this.navigationBarItems(); + + // TODO: ts.find? + for (let i = 0; i < items.length; i++) { + const item = items[i]; + if (item.text === parent) { + this.verifyNavigationBarItemExists(item.childItems, text, kind); + return; + } + } + + this.raiseError(`Could not find any parent named ${parent} in: ${JSON.stringify(items, undefined, 2)}`); + } + + private navigationBarItems() { + return this.languageService.getNavigationBarItems(this.activeFile.fileName); + } + + private verifyNavigationBarItemExists(items: ts.NavigationBarItem[], text: string, kind: string) { + for (let i = 0; i < items.length; i++) { + const item = items[i]; + if (item.text === text && item.kind === kind) { + return; + } + } + + this.raiseError(`Could not find ${JSON.stringify({text, kind}, undefined, 2)} in the navigation bar: ${JSON.stringify(items, undefined, 2)}`); + } + /* Check number of navigationItems which match both searchValue and matchKind. Report an error if expected value and actual value do not match. @@ -3044,6 +3085,18 @@ namespace FourSlashInterface { this.state.verifyGetScriptLexicalStructureListContains(name, kind); } + public navigationBarCount(count: number) { + this.state.verifyNavigationBarCount(count); + } + + public navigationBarItem(text: string, kind: string) { + this.state.verifyNavigationBarItem(text, kind); + } + + public navigationBarChildItem(parent: string, text: string, kind: string) { + this.state.verifyNavigationBarChildItem(parent, text, kind); + } + public navigationItemsListCount(count: number, searchValue: string, matchKind?: string) { this.state.verifyNavigationItemsCount(count, searchValue, matchKind); } diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 48d69f0a85e..86061b53e74 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -177,6 +177,9 @@ declare namespace FourSlashInterface { getScriptLexicalStructureListCount(count: number): void; getScriptLexicalStructureListContains(name: string, kind: string, fileName?: string, parentName?: string, isAdditionalSpan?: boolean, markerPosition?: number): void; + navigationBarCount(count: number); + navigationBarItem(text: string, kind: string): void; + navigationBarChildItem(parent: string, text: string, kind: string): void; navigationItemsListCount(count: number, searchValue: string, matchKind?: string): void; navigationItemsListContains(name: string, kind: string, searchValue: string, matchKind: string, fileName?: string, parentName?: string): void; occurrencesAtPositionContains(range: Range, isWriteAccess?: boolean): void; diff --git a/tests/cases/fourslash/getNavigationBarItems.ts b/tests/cases/fourslash/getNavigationBarItems.ts new file mode 100644 index 00000000000..665767916b4 --- /dev/null +++ b/tests/cases/fourslash/getNavigationBarItems.ts @@ -0,0 +1,11 @@ +/// + +////class C { +//// foo; +//// ["bar"]: string; +////} + +verify.navigationBarCount(1); +verify.navigationBarItem("C", "class"); +verify.navigationBarChildItem("C", "[\"bar\"]", "property"); +verify.navigationBarChildItem("C", "foo", "property"); From bbbe3666b63cc712aab9bf93575ff51bd29efcdb Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 16 May 2016 11:41:12 -0700 Subject: [PATCH 26/38] Rename "getScriptLexicalStructureList" to "navigationBar" in fourslash test helpers and remove unnecessary duplicate helpers --- src/harness/fourslash.ts | 93 ++++++------------- .../fourslash/deleteClassWithEnumPresent.ts | 2 +- tests/cases/fourslash/fourslash.ts | 6 +- .../cases/fourslash/getNavigationBarItems.ts | 4 +- tests/cases/fourslash/navbar_const.ts | 2 +- .../navbar_contains-no-duplicates.ts | 4 +- tests/cases/fourslash/navbar_exportDefault.ts | 2 +- tests/cases/fourslash/navbar_let.ts | 2 +- .../navigationBarItemsBindingPatterns.ts | 24 ++--- ...ionBarItemsBindingPatternsInConstructor.ts | 2 +- .../navigationBarItemsEmptyConstructors.ts | 6 +- .../fourslash/navigationBarItemsExports.ts | 4 +- .../fourslash/navigationBarItemsFunctions.ts | 4 +- .../navigationBarItemsFunctionsBroken.ts | 4 +- .../navigationBarItemsFunctionsBroken2.ts | 4 +- .../fourslash/navigationBarItemsImports.ts | 4 +- ...ionBarItemsInsideMethodsAndConstructors.ts | 4 +- .../fourslash/navigationBarItemsItems.ts | 4 +- .../fourslash/navigationBarItemsItems2.ts | 2 +- ...rItemsItemsContainsNoAnonymousFunctions.ts | 16 ++-- .../navigationBarItemsItemsExternalModules.ts | 4 +- ...navigationBarItemsItemsExternalModules2.ts | 4 +- ...navigationBarItemsItemsExternalModules3.ts | 4 +- .../navigationBarItemsItemsModuleVariables.ts | 12 +-- .../navigationBarItemsMissingName1.ts | 4 +- .../navigationBarItemsMissingName2.ts | 2 +- .../fourslash/navigationBarItemsModules.ts | 4 +- ...ationBarItemsMultilineStringIdentifiers.ts | 4 +- ...BarItemsPropertiesDefinedInConstructors.ts | 10 +- .../fourslash/navigationBarItemsSymbols1.ts | 4 +- .../fourslash/navigationBarItemsSymbols2.ts | 4 +- .../fourslash/navigationBarItemsSymbols3.ts | 4 +- tests/cases/fourslash/server/navbar01.ts | 4 +- .../shims-pp/getNavigationBarItems.ts | 2 +- .../fourslash/shims/getNavigationBarItems.ts | 2 +- 35 files changed, 112 insertions(+), 149 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index cdef2554f96..ce9e34771a6 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1912,47 +1912,6 @@ namespace FourSlash { } } - public verifyNavigationBarCount(count: number) { - const actual = this.navigationBarItems().length; - if (actual !== count) { - this.raiseError(`Expected ${count} items in navigation bar, got ${actual}`); - } - } - - public verifyNavigationBarItem(text: string, kind: string) { - this.verifyNavigationBarItemExists(this.navigationBarItems(), text, kind); - } - - public verifyNavigationBarChildItem(parent: string, text: string, kind: string) { - const items = this.navigationBarItems(); - - // TODO: ts.find? - for (let i = 0; i < items.length; i++) { - const item = items[i]; - if (item.text === parent) { - this.verifyNavigationBarItemExists(item.childItems, text, kind); - return; - } - } - - this.raiseError(`Could not find any parent named ${parent} in: ${JSON.stringify(items, undefined, 2)}`); - } - - private navigationBarItems() { - return this.languageService.getNavigationBarItems(this.activeFile.fileName); - } - - private verifyNavigationBarItemExists(items: ts.NavigationBarItem[], text: string, kind: string) { - for (let i = 0; i < items.length; i++) { - const item = items[i]; - if (item.text === text && item.kind === kind) { - return; - } - } - - this.raiseError(`Could not find ${JSON.stringify({text, kind}, undefined, 2)} in the navigation bar: ${JSON.stringify(items, undefined, 2)}`); - } - /* Check number of navigationItems which match both searchValue and matchKind. Report an error if expected value and actual value do not match. @@ -2009,12 +1968,12 @@ namespace FourSlash { } } - public verifyGetScriptLexicalStructureListCount(expected: number) { + public verifyNavigationBarCount(expected: number) { const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); const actual = this.getNavigationBarItemsCount(items); if (expected !== actual) { - this.raiseError(`verifyGetScriptLexicalStructureListCount failed - found: ${actual} navigation items, expected: ${expected}.`); + this.raiseError(`verifyNavigationBarCount failed - found: ${actual} navigation items, expected: ${expected}.`); } } @@ -2030,19 +1989,19 @@ namespace FourSlash { return result; } - public verifyGetScriptLexicalStructureListContains(name: string, kind: string) { + public verifyNavigationBarContains(name: string, kind: string) { const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); if (!items || items.length === 0) { - this.raiseError("verifyGetScriptLexicalStructureListContains failed - found 0 navigation items, expected at least one."); + this.raiseError("verifyNavigationBarContains failed - found 0 navigation items, expected at least one."); } if (this.navigationBarItemsContains(items, name, kind)) { return; } - const missingItem = { name: name, kind: kind }; - this.raiseError(`verifyGetScriptLexicalStructureListContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(items, undefined, 2)})`); + const missingItem = { name, kind }; + this.raiseError(`verifyNavigationBarContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(items, undefined, 2)})`); } private navigationBarItemsContains(items: ts.NavigationBarItem[], name: string, kind: string) { @@ -2062,6 +2021,20 @@ namespace FourSlash { return false; } + public verifyNavigationBarChildItem(parent: string, name: string, kind: string) { + const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); + + for (let i = 0; i < items.length; i++) { + const item = items[i]; + if (item.text === parent) { + if (this.navigationBarItemsContains(item.childItems, name, kind)) + return; + const missingItem = { name, kind }; + this.raiseError(`verifyNavigationBarChildItem failed - could not find the item: ${JSON.stringify(missingItem)} in the children list: (${JSON.stringify(item.childItems, undefined, 2)})`); + } + } + } + public printNavigationItems(searchValue: string) { const items = this.languageService.getNavigateToItems(searchValue); const length = items && items.length; @@ -2074,7 +2047,7 @@ namespace FourSlash { } } - public printScriptLexicalStructureItems() { + public printNavigationBar() { const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); const length = items && items.length; @@ -3070,31 +3043,23 @@ namespace FourSlashInterface { this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true); } - public getScriptLexicalStructureListCount(count: number) { - this.state.verifyGetScriptLexicalStructureListCount(count); + public navigationBarCount(count: number) { + this.state.verifyNavigationBarCount(count); } // TODO: figure out what to do with the unused arguments. - public getScriptLexicalStructureListContains( + public navigationBarContains( name: string, kind: string, fileName?: string, parentName?: string, isAdditionalSpan?: boolean, markerPosition?: number) { - this.state.verifyGetScriptLexicalStructureListContains(name, kind); + this.state.verifyNavigationBarContains(name, kind); } - public navigationBarCount(count: number) { - this.state.verifyNavigationBarCount(count); - } - - public navigationBarItem(text: string, kind: string) { - this.state.verifyNavigationBarItem(text, kind); - } - - public navigationBarChildItem(parent: string, text: string, kind: string) { - this.state.verifyNavigationBarChildItem(parent, text, kind); + public navigationBarChildItem(parent: string, name: string, kind: string) { + this.state.verifyNavigationBarChildItem(parent, name, kind); } public navigationItemsListCount(count: number, searchValue: string, matchKind?: string) { @@ -3287,8 +3252,8 @@ namespace FourSlashInterface { this.state.printNavigationItems(searchValue); } - public printScriptLexicalStructureItems() { - this.state.printScriptLexicalStructureItems(); + public printNavigationBar() { + this.state.printNavigationBar(); } public printReferences() { diff --git a/tests/cases/fourslash/deleteClassWithEnumPresent.ts b/tests/cases/fourslash/deleteClassWithEnumPresent.ts index 2b7a02ec717..29f7c61e259 100644 --- a/tests/cases/fourslash/deleteClassWithEnumPresent.ts +++ b/tests/cases/fourslash/deleteClassWithEnumPresent.ts @@ -5,4 +5,4 @@ goTo.marker(); edit.deleteAtCaret('class Bar { }'.length); -verify.getScriptLexicalStructureListContains('Foo', 'enum', 'tests/cases/fourslash/deleteClassWithEnumPresent.ts', ''); \ No newline at end of file +verify.navigationBarContains('Foo', 'enum', 'tests/cases/fourslash/deleteClassWithEnumPresent.ts', ''); \ No newline at end of file diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 86061b53e74..2b270dc73f3 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -175,10 +175,8 @@ declare namespace FourSlashInterface { DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean): void; noDocCommentTemplate(): void; - getScriptLexicalStructureListCount(count: number): void; - getScriptLexicalStructureListContains(name: string, kind: string, fileName?: string, parentName?: string, isAdditionalSpan?: boolean, markerPosition?: number): void; - navigationBarCount(count: number); - navigationBarItem(text: string, kind: string): void; + navigationBarCount(count: number): void; + navigationBarContains(name: string, kind: string, fileName?: string, parentName?: string, isAdditionalSpan?: boolean, markerPosition?: number): void; navigationBarChildItem(parent: string, text: string, kind: string): void; navigationItemsListCount(count: number, searchValue: string, matchKind?: string): void; navigationItemsListContains(name: string, kind: string, searchValue: string, matchKind: string, fileName?: string, parentName?: string): void; diff --git a/tests/cases/fourslash/getNavigationBarItems.ts b/tests/cases/fourslash/getNavigationBarItems.ts index 665767916b4..8e9b8de5b05 100644 --- a/tests/cases/fourslash/getNavigationBarItems.ts +++ b/tests/cases/fourslash/getNavigationBarItems.ts @@ -5,7 +5,7 @@ //// ["bar"]: string; ////} -verify.navigationBarCount(1); -verify.navigationBarItem("C", "class"); +verify.navigationBarCount(3); +verify.navigationBarContains("C", "class"); verify.navigationBarChildItem("C", "[\"bar\"]", "property"); verify.navigationBarChildItem("C", "foo", "property"); diff --git a/tests/cases/fourslash/navbar_const.ts b/tests/cases/fourslash/navbar_const.ts index 6c0738747f3..a2cdb80baef 100644 --- a/tests/cases/fourslash/navbar_const.ts +++ b/tests/cases/fourslash/navbar_const.ts @@ -3,7 +3,7 @@ //// {| "itemName": "c", "kind": "const", "parentName": "" |}const c = 0; test.markers().forEach(marker => { - verify.getScriptLexicalStructureListContains( + verify.navigationBarContains( marker.data.itemName, marker.data.kind, marker.fileName, diff --git a/tests/cases/fourslash/navbar_contains-no-duplicates.ts b/tests/cases/fourslash/navbar_contains-no-duplicates.ts index 49d570ed770..4c612136b55 100644 --- a/tests/cases/fourslash/navbar_contains-no-duplicates.ts +++ b/tests/cases/fourslash/navbar_contains-no-duplicates.ts @@ -29,7 +29,7 @@ test.markers().forEach(marker => { if (marker.data) { - verify.getScriptLexicalStructureListContains( + verify.navigationBarContains( marker.data.itemName, marker.data.kind, marker.fileName, @@ -38,4 +38,4 @@ test.markers().forEach(marker => { marker.position); } }); -verify.getScriptLexicalStructureListCount(12); \ No newline at end of file +verify.navigationBarCount(12); \ No newline at end of file diff --git a/tests/cases/fourslash/navbar_exportDefault.ts b/tests/cases/fourslash/navbar_exportDefault.ts index a8fe854fa28..a56eeb8b226 100644 --- a/tests/cases/fourslash/navbar_exportDefault.ts +++ b/tests/cases/fourslash/navbar_exportDefault.ts @@ -14,7 +14,7 @@ test.markers().forEach(marker => { goTo.file(marker.fileName); - verify.getScriptLexicalStructureListContains( + verify.navigationBarContains( marker.data.itemName, marker.data.kind, marker.fileName, diff --git a/tests/cases/fourslash/navbar_let.ts b/tests/cases/fourslash/navbar_let.ts index 841382abc53..c3b125526ef 100644 --- a/tests/cases/fourslash/navbar_let.ts +++ b/tests/cases/fourslash/navbar_let.ts @@ -3,7 +3,7 @@ //// {| "itemName": "c", "kind": "let", "parentName": "" |}let c = 0; test.markers().forEach(marker => { - verify.getScriptLexicalStructureListContains( + verify.navigationBarContains( marker.data.itemName, marker.data.kind, marker.fileName, diff --git a/tests/cases/fourslash/navigationBarItemsBindingPatterns.ts b/tests/cases/fourslash/navigationBarItemsBindingPatterns.ts index 2b363bfad3b..afac15daacc 100644 --- a/tests/cases/fourslash/navigationBarItemsBindingPatterns.ts +++ b/tests/cases/fourslash/navigationBarItemsBindingPatterns.ts @@ -6,16 +6,16 @@ ////const bar1, [c, d] ////var {e, x: [f, g]} = {a:1, x:[]}; -verify.getScriptLexicalStructureListCount(12); // global (1) + variable declarations (4) + binding patterns (7) -verify.getScriptLexicalStructureListContains("foo", "var"); -verify.getScriptLexicalStructureListContains("bar", "var"); -verify.getScriptLexicalStructureListContains("foo1", "let") -verify.getScriptLexicalStructureListContains("a", "let"); -verify.getScriptLexicalStructureListContains("b", "let"); -verify.getScriptLexicalStructureListContains("bar1", "const"); -verify.getScriptLexicalStructureListContains("c", "const"); -verify.getScriptLexicalStructureListContains("d", "const"); -verify.getScriptLexicalStructureListContains("e", "var"); -verify.getScriptLexicalStructureListContains("f", "var"); -verify.getScriptLexicalStructureListContains("g", "var"); +verify.navigationBarCount(12); // global (1) + variable declarations (4) + binding patterns (7) +verify.navigationBarContains("foo", "var"); +verify.navigationBarContains("bar", "var"); +verify.navigationBarContains("foo1", "let") +verify.navigationBarContains("a", "let"); +verify.navigationBarContains("b", "let"); +verify.navigationBarContains("bar1", "const"); +verify.navigationBarContains("c", "const"); +verify.navigationBarContains("d", "const"); +verify.navigationBarContains("e", "var"); +verify.navigationBarContains("f", "var"); +verify.navigationBarContains("g", "var"); diff --git a/tests/cases/fourslash/navigationBarItemsBindingPatternsInConstructor.ts b/tests/cases/fourslash/navigationBarItemsBindingPatternsInConstructor.ts index c496a0281e3..84c1d09efe7 100644 --- a/tests/cases/fourslash/navigationBarItemsBindingPatternsInConstructor.ts +++ b/tests/cases/fourslash/navigationBarItemsBindingPatternsInConstructor.ts @@ -11,4 +11,4 @@ //// } ////} -verify.getScriptLexicalStructureListCount(6); // 2x(class + field + constructor) +verify.navigationBarCount(6); // 2x(class + field + constructor) diff --git a/tests/cases/fourslash/navigationBarItemsEmptyConstructors.ts b/tests/cases/fourslash/navigationBarItemsEmptyConstructors.ts index 570b2f7518c..2255d29e293 100644 --- a/tests/cases/fourslash/navigationBarItemsEmptyConstructors.ts +++ b/tests/cases/fourslash/navigationBarItemsEmptyConstructors.ts @@ -5,8 +5,8 @@ //// } ////} -verify.getScriptLexicalStructureListContains("Test", "class"); -verify.getScriptLexicalStructureListContains("constructor", "constructor"); +verify.navigationBarContains("Test", "class"); +verify.navigationBarContains("constructor", "constructor"); // no other items -verify.getScriptLexicalStructureListCount(2); \ No newline at end of file +verify.navigationBarCount(2); \ No newline at end of file diff --git a/tests/cases/fourslash/navigationBarItemsExports.ts b/tests/cases/fourslash/navigationBarItemsExports.ts index d9db125b9b0..b88b60d0efb 100644 --- a/tests/cases/fourslash/navigationBarItemsExports.ts +++ b/tests/cases/fourslash/navigationBarItemsExports.ts @@ -11,8 +11,8 @@ test.markers().forEach((marker) => { if (marker.data) { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); } }); -verify.getScriptLexicalStructureListCount(4); +verify.navigationBarCount(4); diff --git a/tests/cases/fourslash/navigationBarItemsFunctions.ts b/tests/cases/fourslash/navigationBarItemsFunctions.ts index b683790c60d..0948923c046 100644 --- a/tests/cases/fourslash/navigationBarItemsFunctions.ts +++ b/tests/cases/fourslash/navigationBarItemsFunctions.ts @@ -17,7 +17,7 @@ ////} test.markers().forEach((marker) => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); -verify.getScriptLexicalStructureListCount(8); // 4 functions + global. Note: there are 8 because of the functions show up at the top level and as child items. +verify.navigationBarCount(8); // 4 functions + global. Note: there are 8 because of the functions show up at the top level and as child items. diff --git a/tests/cases/fourslash/navigationBarItemsFunctionsBroken.ts b/tests/cases/fourslash/navigationBarItemsFunctionsBroken.ts index 7846a9723d1..e8bf1d33fc3 100644 --- a/tests/cases/fourslash/navigationBarItemsFunctionsBroken.ts +++ b/tests/cases/fourslash/navigationBarItemsFunctionsBroken.ts @@ -6,7 +6,7 @@ ////} test.markers().forEach((marker) => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); -verify.getScriptLexicalStructureListCount(3); // and 'f'. \ No newline at end of file +verify.navigationBarCount(3); // and 'f'. \ No newline at end of file diff --git a/tests/cases/fourslash/navigationBarItemsFunctionsBroken2.ts b/tests/cases/fourslash/navigationBarItemsFunctionsBroken2.ts index 50bf91e02d6..9576d4dd789 100644 --- a/tests/cases/fourslash/navigationBarItemsFunctionsBroken2.ts +++ b/tests/cases/fourslash/navigationBarItemsFunctionsBroken2.ts @@ -7,7 +7,7 @@ ////} test.markers().forEach((marker) => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); -verify.getScriptLexicalStructureListCount(3); // and 'f' \ No newline at end of file +verify.navigationBarCount(3); // and 'f' \ No newline at end of file diff --git a/tests/cases/fourslash/navigationBarItemsImports.ts b/tests/cases/fourslash/navigationBarItemsImports.ts index 8b0d02bd9f5..53619da310a 100644 --- a/tests/cases/fourslash/navigationBarItemsImports.ts +++ b/tests/cases/fourslash/navigationBarItemsImports.ts @@ -18,8 +18,8 @@ test.markers().forEach((marker) => { if (marker.data) { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); } }); -verify.getScriptLexicalStructureListCount(9); +verify.navigationBarCount(9); diff --git a/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts b/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts index 4dcca43af35..7aaa3d7f5a2 100644 --- a/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts +++ b/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts @@ -35,8 +35,8 @@ ////} test.markers().forEach((marker) => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); // no other items -verify.getScriptLexicalStructureListCount(17); +verify.navigationBarCount(17); diff --git a/tests/cases/fourslash/navigationBarItemsItems.ts b/tests/cases/fourslash/navigationBarItemsItems.ts index 67e14fe1009..3804a0dab55 100644 --- a/tests/cases/fourslash/navigationBarItemsItems.ts +++ b/tests/cases/fourslash/navigationBarItemsItems.ts @@ -45,8 +45,8 @@ test.markers().forEach((marker) => { if (marker.data) { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); } }); -verify.getScriptLexicalStructureListCount(23); +verify.navigationBarCount(23); diff --git a/tests/cases/fourslash/navigationBarItemsItems2.ts b/tests/cases/fourslash/navigationBarItemsItems2.ts index 3b94260ddbd..d4ffde54051 100644 --- a/tests/cases/fourslash/navigationBarItemsItems2.ts +++ b/tests/cases/fourslash/navigationBarItemsItems2.ts @@ -8,5 +8,5 @@ edit.insertLine("module A"); edit.insert("export class "); // should not crash -verify.getScriptLexicalStructureListCount(2); +verify.navigationBarCount(2); diff --git a/tests/cases/fourslash/navigationBarItemsItemsContainsNoAnonymousFunctions.ts b/tests/cases/fourslash/navigationBarItemsItemsContainsNoAnonymousFunctions.ts index b7430ad03de..dac6e96ab93 100644 --- a/tests/cases/fourslash/navigationBarItemsItemsContainsNoAnonymousFunctions.ts +++ b/tests/cases/fourslash/navigationBarItemsItemsContainsNoAnonymousFunctions.ts @@ -30,15 +30,15 @@ ////} goTo.marker("file1"); -verify.getScriptLexicalStructureListCount(0); +verify.navigationBarCount(0); goTo.marker("file2"); -verify.getScriptLexicalStructureListContains("", "module"); -verify.getScriptLexicalStructureListContains("x", "var"); -verify.getScriptLexicalStructureListCount(2); +verify.navigationBarContains("", "module"); +verify.navigationBarContains("x", "var"); +verify.navigationBarCount(2); goTo.marker("file3"); -verify.getScriptLexicalStructureListContains("", "module"); -verify.getScriptLexicalStructureListContains("foo", "function"); -verify.getScriptLexicalStructureListContains("bar", "function"); -verify.getScriptLexicalStructureListCount(5); \ No newline at end of file +verify.navigationBarContains("", "module"); +verify.navigationBarContains("foo", "function"); +verify.navigationBarContains("bar", "function"); +verify.navigationBarCount(5); \ No newline at end of file diff --git a/tests/cases/fourslash/navigationBarItemsItemsExternalModules.ts b/tests/cases/fourslash/navigationBarItemsItemsExternalModules.ts index 550f1aed783..64a595cafb1 100644 --- a/tests/cases/fourslash/navigationBarItemsItemsExternalModules.ts +++ b/tests/cases/fourslash/navigationBarItemsItemsExternalModules.ts @@ -5,7 +5,7 @@ ////} test.markers().forEach((marker) => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); -verify.getScriptLexicalStructureListCount(2); // external module node + class + property +verify.navigationBarCount(2); // external module node + class + property diff --git a/tests/cases/fourslash/navigationBarItemsItemsExternalModules2.ts b/tests/cases/fourslash/navigationBarItemsItemsExternalModules2.ts index b0bf6eb3fa2..7c1c32cff76 100644 --- a/tests/cases/fourslash/navigationBarItemsItemsExternalModules2.ts +++ b/tests/cases/fourslash/navigationBarItemsItemsExternalModules2.ts @@ -9,7 +9,7 @@ ////export var x: number; test.markers().forEach((marker) => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); -verify.getScriptLexicalStructureListCount(4); // external module node + variable in module + class + property +verify.navigationBarCount(4); // external module node + variable in module + class + property diff --git a/tests/cases/fourslash/navigationBarItemsItemsExternalModules3.ts b/tests/cases/fourslash/navigationBarItemsItemsExternalModules3.ts index 9ef49e38776..193da9ff47b 100644 --- a/tests/cases/fourslash/navigationBarItemsItemsExternalModules3.ts +++ b/tests/cases/fourslash/navigationBarItemsItemsExternalModules3.ts @@ -9,7 +9,7 @@ ////export var x: number; test.markers().forEach((marker) => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); -verify.getScriptLexicalStructureListCount(4); // external module node + variable in module + class + property +verify.navigationBarCount(4); // external module node + variable in module + class + property diff --git a/tests/cases/fourslash/navigationBarItemsItemsModuleVariables.ts b/tests/cases/fourslash/navigationBarItemsItemsModuleVariables.ts index 85bf609105c..afc1acfb9cb 100644 --- a/tests/cases/fourslash/navigationBarItemsItemsModuleVariables.ts +++ b/tests/cases/fourslash/navigationBarItemsItemsModuleVariables.ts @@ -19,12 +19,12 @@ //// export var z = 0; ////} goTo.marker("file1"); -verify.getScriptLexicalStructureListContains("Module1", "module"); -verify.getScriptLexicalStructureListContains("x", "var"); +verify.navigationBarContains("Module1", "module"); +verify.navigationBarContains("x", "var"); // nothing else should show up -verify.getScriptLexicalStructureListCount(2); +verify.navigationBarCount(2); goTo.marker("file2"); -verify.getScriptLexicalStructureListContains("Module1.SubModule", "module"); -verify.getScriptLexicalStructureListContains("y", "var"); -verify.getScriptLexicalStructureListCount(2); +verify.navigationBarContains("Module1.SubModule", "module"); +verify.navigationBarContains("y", "var"); +verify.navigationBarCount(2); diff --git a/tests/cases/fourslash/navigationBarItemsMissingName1.ts b/tests/cases/fourslash/navigationBarItemsMissingName1.ts index c5282d696f3..98321039c5a 100644 --- a/tests/cases/fourslash/navigationBarItemsMissingName1.ts +++ b/tests/cases/fourslash/navigationBarItemsMissingName1.ts @@ -9,8 +9,8 @@ test.markers().forEach((marker) => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); /// Only have two named elements. -verify.getScriptLexicalStructureListCount(2); +verify.navigationBarCount(2); diff --git a/tests/cases/fourslash/navigationBarItemsMissingName2.ts b/tests/cases/fourslash/navigationBarItemsMissingName2.ts index bf0dc038991..d26aa0b553d 100644 --- a/tests/cases/fourslash/navigationBarItemsMissingName2.ts +++ b/tests/cases/fourslash/navigationBarItemsMissingName2.ts @@ -8,4 +8,4 @@ // The class is unnamed, so its method is not included either. -verify.getScriptLexicalStructureListCount(2); +verify.navigationBarCount(2); diff --git a/tests/cases/fourslash/navigationBarItemsModules.ts b/tests/cases/fourslash/navigationBarItemsModules.ts index a5fc9b641f9..2f6e1d7f844 100644 --- a/tests/cases/fourslash/navigationBarItemsModules.ts +++ b/tests/cases/fourslash/navigationBarItemsModules.ts @@ -39,10 +39,10 @@ test.markers().forEach((marker) => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); /// We have 8 module keywords, and 4 var keywords. /// The declarations of A.B.C.x do not get merged, so the 4 vars are independent. /// The two 'A' modules, however, do get merged, so in reality we have 7 modules. -verify.getScriptLexicalStructureListCount(11); +verify.navigationBarCount(11); diff --git a/tests/cases/fourslash/navigationBarItemsMultilineStringIdentifiers.ts b/tests/cases/fourslash/navigationBarItemsMultilineStringIdentifiers.ts index 59eca486b62..8856c4c044a 100644 --- a/tests/cases/fourslash/navigationBarItemsMultilineStringIdentifiers.ts +++ b/tests/cases/fourslash/navigationBarItemsMultilineStringIdentifiers.ts @@ -35,7 +35,7 @@ test.markers().forEach((marker) => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); -verify.getScriptLexicalStructureListCount(9); // interface w/ 2 properties, class w/ 2 properties, 3 modules \ No newline at end of file +verify.navigationBarCount(9); // interface w/ 2 properties, class w/ 2 properties, 3 modules \ No newline at end of file diff --git a/tests/cases/fourslash/navigationBarItemsPropertiesDefinedInConstructors.ts b/tests/cases/fourslash/navigationBarItemsPropertiesDefinedInConstructors.ts index adda43066a3..9b3f4aacd9c 100644 --- a/tests/cases/fourslash/navigationBarItemsPropertiesDefinedInConstructors.ts +++ b/tests/cases/fourslash/navigationBarItemsPropertiesDefinedInConstructors.ts @@ -6,10 +6,10 @@ //// } ////} -verify.getScriptLexicalStructureListContains("List", "class"); -verify.getScriptLexicalStructureListContains("constructor", "constructor"); -verify.getScriptLexicalStructureListContains("a", "property"); -verify.getScriptLexicalStructureListContains("b", "property"); +verify.navigationBarContains("List", "class"); +verify.navigationBarContains("constructor", "constructor"); +verify.navigationBarContains("a", "property"); +verify.navigationBarContains("b", "property"); // no other items -verify.getScriptLexicalStructureListCount(4); \ No newline at end of file +verify.navigationBarCount(4); \ No newline at end of file diff --git a/tests/cases/fourslash/navigationBarItemsSymbols1.ts b/tests/cases/fourslash/navigationBarItemsSymbols1.ts index e3dde6738e9..c9df85b3ece 100644 --- a/tests/cases/fourslash/navigationBarItemsSymbols1.ts +++ b/tests/cases/fourslash/navigationBarItemsSymbols1.ts @@ -11,7 +11,7 @@ ////} test.markers().forEach(marker => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); -verify.getScriptLexicalStructureListCount(test.markers().length); \ No newline at end of file +verify.navigationBarCount(test.markers().length); \ No newline at end of file diff --git a/tests/cases/fourslash/navigationBarItemsSymbols2.ts b/tests/cases/fourslash/navigationBarItemsSymbols2.ts index d048de895ec..579a6353c13 100644 --- a/tests/cases/fourslash/navigationBarItemsSymbols2.ts +++ b/tests/cases/fourslash/navigationBarItemsSymbols2.ts @@ -9,7 +9,7 @@ ////} test.markers().forEach(marker => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); -verify.getScriptLexicalStructureListCount(test.markers().length); \ No newline at end of file +verify.navigationBarCount(test.markers().length); \ No newline at end of file diff --git a/tests/cases/fourslash/navigationBarItemsSymbols3.ts b/tests/cases/fourslash/navigationBarItemsSymbols3.ts index 19f81037559..5677c0b6301 100644 --- a/tests/cases/fourslash/navigationBarItemsSymbols3.ts +++ b/tests/cases/fourslash/navigationBarItemsSymbols3.ts @@ -7,7 +7,7 @@ ////} test.markers().forEach(marker => { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); }); -verify.getScriptLexicalStructureListCount(test.markers().length); \ No newline at end of file +verify.navigationBarCount(test.markers().length); \ No newline at end of file diff --git a/tests/cases/fourslash/server/navbar01.ts b/tests/cases/fourslash/server/navbar01.ts index 82ded5e6f54..8e76e7c017e 100644 --- a/tests/cases/fourslash/server/navbar01.ts +++ b/tests/cases/fourslash/server/navbar01.ts @@ -45,8 +45,8 @@ test.markers().forEach((marker) => { if (marker.data) { - verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + verify.navigationBarContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); } }); -verify.getScriptLexicalStructureListCount(23); +verify.navigationBarCount(23); diff --git a/tests/cases/fourslash/shims-pp/getNavigationBarItems.ts b/tests/cases/fourslash/shims-pp/getNavigationBarItems.ts index 6c0738747f3..a2cdb80baef 100644 --- a/tests/cases/fourslash/shims-pp/getNavigationBarItems.ts +++ b/tests/cases/fourslash/shims-pp/getNavigationBarItems.ts @@ -3,7 +3,7 @@ //// {| "itemName": "c", "kind": "const", "parentName": "" |}const c = 0; test.markers().forEach(marker => { - verify.getScriptLexicalStructureListContains( + verify.navigationBarContains( marker.data.itemName, marker.data.kind, marker.fileName, diff --git a/tests/cases/fourslash/shims/getNavigationBarItems.ts b/tests/cases/fourslash/shims/getNavigationBarItems.ts index 6c0738747f3..a2cdb80baef 100644 --- a/tests/cases/fourslash/shims/getNavigationBarItems.ts +++ b/tests/cases/fourslash/shims/getNavigationBarItems.ts @@ -3,7 +3,7 @@ //// {| "itemName": "c", "kind": "const", "parentName": "" |}const c = 0; test.markers().forEach(marker => { - verify.getScriptLexicalStructureListContains( + verify.navigationBarContains( marker.data.itemName, marker.data.kind, marker.fileName, From cdc00086b2ccd0e805e1a5f0b90105bbec0e9e74 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 17 May 2016 07:59:09 -0700 Subject: [PATCH 27/38] Add printNavigationBar declaration --- tests/cases/fourslash/fourslash.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 2b270dc73f3..08883f163f2 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -237,6 +237,7 @@ declare namespace FourSlashInterface { printBreakpointAtCurrentLocation(): void; printNameOrDottedNameSpans(pos: number): void; printErrorList(): void; + printNavigationBar(): void; printNavigationItems(searchValue?: string): void; printScriptLexicalStructureItems(): void; printReferences(): void; From 53970afe25c6d8013cc2ee32482eeba883a55ac5 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 17 May 2016 09:24:51 -0700 Subject: [PATCH 28/38] Fix message text for printNavigationBar --- src/harness/fourslash.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index ce9e34771a6..c237734e1df 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2051,7 +2051,7 @@ namespace FourSlash { const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); const length = items && items.length; - Harness.IO.log(`NavigationItems list (${length} items)`); + Harness.IO.log(`Navigation bar (${length} items)`); for (let i = 0; i < length; i++) { const item = items[i]; From 70d8def398d9dfefa4d049152a3d801611aa2ff5 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 17 May 2016 09:33:55 -0700 Subject: [PATCH 29/38] Add test that infers 'number' from pattern --- .../fallbackToBindingPatternForTypeInference.js | 5 +++++ .../fallbackToBindingPatternForTypeInference.symbols | 6 ++++++ .../fallbackToBindingPatternForTypeInference.types | 9 +++++++++ .../compiler/fallbackToBindingPatternForTypeInference.ts | 1 + 4 files changed, 21 insertions(+) diff --git a/tests/baselines/reference/fallbackToBindingPatternForTypeInference.js b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.js index fd0632b2bea..1c02ae83982 100644 --- a/tests/baselines/reference/fallbackToBindingPatternForTypeInference.js +++ b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.js @@ -4,6 +4,7 @@ trans(({a}) => a); trans(([b,c]) => 'foo'); trans(({d: [e,f]}) => 'foo'); trans(([{g},{h}]) => 'foo'); +trans(({a, b = 10}) => a); //// [fallbackToBindingPatternForTypeInference.js] @@ -23,3 +24,7 @@ trans(function (_a) { var g = _a[0].g, h = _a[1].h; return 'foo'; }); +trans(function (_a) { + var a = _a.a, _b = _a.b, b = _b === void 0 ? 10 : _b; + return a; +}); diff --git a/tests/baselines/reference/fallbackToBindingPatternForTypeInference.symbols b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.symbols index e7049d50e1b..f57b234f39f 100644 --- a/tests/baselines/reference/fallbackToBindingPatternForTypeInference.symbols +++ b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.symbols @@ -26,3 +26,9 @@ trans(([{g},{h}]) => 'foo'); >g : Symbol(g, Decl(fallbackToBindingPatternForTypeInference.ts, 4, 9)) >h : Symbol(h, Decl(fallbackToBindingPatternForTypeInference.ts, 4, 13)) +trans(({a, b = 10}) => a); +>trans : Symbol(trans, Decl(fallbackToBindingPatternForTypeInference.ts, 0, 0)) +>a : Symbol(a, Decl(fallbackToBindingPatternForTypeInference.ts, 5, 8)) +>b : Symbol(b, Decl(fallbackToBindingPatternForTypeInference.ts, 5, 10)) +>a : Symbol(a, Decl(fallbackToBindingPatternForTypeInference.ts, 5, 8)) + diff --git a/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types index c8f01abaf82..fc41085098a 100644 --- a/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types +++ b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types @@ -38,3 +38,12 @@ trans(([{g},{h}]) => 'foo'); >h : any >'foo' : string +trans(({a, b = 10}) => a); +>trans(({a, b = 10}) => a) : number +>trans : (f: (x: T) => string) => number +>({a, b = 10}) => a : ({a, b}: { a: any; b?: number; }) => any +>a : any +>b : number +>10 : number +>a : any + diff --git a/tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts b/tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts index de6940110da..9aa979c1020 100644 --- a/tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts +++ b/tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts @@ -3,3 +3,4 @@ trans(({a}) => a); trans(([b,c]) => 'foo'); trans(({d: [e,f]}) => 'foo'); trans(([{g},{h}]) => 'foo'); +trans(({a, b = 10}) => a); From be7e2a837bcb7be529d7495062b795396e9efdf3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 17 May 2016 10:05:19 -0700 Subject: [PATCH 30/38] Make 'never' an intrinsic type --- src/compiler/checker.ts | 51 +++++++++++++++++++---------------------- src/compiler/types.ts | 3 ++- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7aa83ad268e..a916b898d80 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -120,9 +120,9 @@ namespace ts { const nullType = createIntrinsicType(TypeFlags.Null | nullableWideningFlags, "null"); const emptyArrayElementType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined"); const unknownType = createIntrinsicType(TypeFlags.Any, "unknown"); + const neverType = createIntrinsicType(TypeFlags.Never, "never"); const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const neverType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); emptyGenericType.instantiations = {}; @@ -2029,12 +2029,7 @@ namespace ts { writeUnionOrIntersectionType(type, flags); } else if (type.flags & TypeFlags.Anonymous) { - if (type === neverType) { - writer.writeKeyword("never"); - } - else { - writeAnonymousType(type, flags); - } + writeAnonymousType(type, flags); } else if (type.flags & TypeFlags.StringLiteral) { writer.writeStringLiteral(`"${escapeString((type).text)}"`); @@ -5862,28 +5857,28 @@ namespace ts { return isIdenticalTo(source, target); } - if (target.flags & TypeFlags.Any) return Ternary.True; - if (source.flags & TypeFlags.Undefined) { - if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void) || source === emptyArrayElementType) return Ternary.True; - } - if (source.flags & TypeFlags.Null) { - if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True; - } - if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True; - if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) { - if (result = enumRelatedTo(source, target, reportErrors)) { - return result; + if (!(target.flags & TypeFlags.Never)) { + if (target.flags & TypeFlags.Any) return Ternary.True; + if (source.flags & TypeFlags.Undefined) { + if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void) || source === emptyArrayElementType) return Ternary.True; + } + if (source.flags & TypeFlags.Null) { + if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True; + } + if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True; + if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) { + if (result = enumRelatedTo(source, target, reportErrors)) { + return result; + } + } + if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True; + if (relation === assignableRelation || relation === comparableRelation) { + if (source.flags & (TypeFlags.Any | TypeFlags.Never)) return Ternary.True; + if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True; + } + if (source.flags & TypeFlags.Boolean && target.flags & TypeFlags.Boolean) { + return Ternary.True; } - } - if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True; - - if (relation === assignableRelation || relation === comparableRelation) { - if (isTypeAny(source)) return Ternary.True; - if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True; - } - - if (source.flags & TypeFlags.Boolean && target.flags & TypeFlags.Boolean) { - return Ternary.True; } if (source.flags & TypeFlags.FreshObjectLiteral) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index fbe1f3c60c8..b23c2fa3a67 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2171,11 +2171,12 @@ namespace ts { ESSymbol = 0x01000000, // Type of symbol primitive introduced in ES6 ThisType = 0x02000000, // This type ObjectLiteralPatternWithComputedProperties = 0x04000000, // Object literal type implied by binding pattern has computed properties + Never = 0x08000000, // Never type /* @internal */ Nullable = Undefined | Null, /* @internal */ - Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null, + Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null | Never, /* @internal */ Primitive = String | Number | Boolean | ESSymbol | Void | Undefined | Null | StringLiteral | Enum, StringLike = String | StringLiteral, From e028c0fd3d31abd68a00418548635ab7d2459cba Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 17 May 2016 10:06:32 -0700 Subject: [PATCH 31/38] Accepting new baselines --- tests/baselines/reference/controlFlowIteration.types | 2 +- tests/baselines/reference/duplicateLabel3.types | 2 +- .../reference/forStatementsMultipleValidDecl.types | 2 +- .../reference/instanceOfAssignability.types | 4 ++-- .../baselines/reference/narrowingOfDottedNames.types | 4 ++-- .../reference/nestedBlockScopedBindings3.types | 6 +++--- .../reference/nestedBlockScopedBindings4.types | 8 ++++---- .../reference/nestedBlockScopedBindings6.types | 8 ++++---- .../baselines/reference/parser_duplicateLabel3.types | 2 +- .../reference/promiseVoidErrorCallback.types | 2 +- .../reference/stringLiteralTypesAsTags01.types | 4 ++-- .../reference/stringLiteralTypesAsTags02.types | 4 ++-- .../reference/stringLiteralTypesAsTags03.types | 4 ++-- .../reference/throwInEnclosingStatements.types | 12 ++++++------ .../reference/typeGuardOfFormTypeOfBoolean.types | 4 ++-- .../reference/typeGuardOfFormTypeOfNumber.types | 4 ++-- .../reference/typeGuardOfFormTypeOfOther.types | 4 ++-- .../reference/typeGuardOfFormTypeOfString.types | 4 ++-- .../baselines/reference/typeGuardsAsAssertions.types | 2 +- .../reference/typeGuardsWithInstanceOf.errors.txt | 4 ++-- 20 files changed, 43 insertions(+), 43 deletions(-) diff --git a/tests/baselines/reference/controlFlowIteration.types b/tests/baselines/reference/controlFlowIteration.types index 52be501d68e..cefb250e01d 100644 --- a/tests/baselines/reference/controlFlowIteration.types +++ b/tests/baselines/reference/controlFlowIteration.types @@ -4,7 +4,7 @@ let cond: boolean; >cond : boolean function ff() { ->ff : () => void +>ff : () => never let x: string | undefined; >x : string | undefined diff --git a/tests/baselines/reference/duplicateLabel3.types b/tests/baselines/reference/duplicateLabel3.types index 920a077aa9e..bcbe11beee3 100644 --- a/tests/baselines/reference/duplicateLabel3.types +++ b/tests/baselines/reference/duplicateLabel3.types @@ -7,7 +7,7 @@ while (true) { >true : boolean function f() { ->f : () => void +>f : () => never target: >target : any diff --git a/tests/baselines/reference/forStatementsMultipleValidDecl.types b/tests/baselines/reference/forStatementsMultipleValidDecl.types index acb26f17312..ae5959f1bd3 100644 --- a/tests/baselines/reference/forStatementsMultipleValidDecl.types +++ b/tests/baselines/reference/forStatementsMultipleValidDecl.types @@ -16,7 +16,7 @@ for (var x = undefined; ;) { } // new declaration space, making redeclaring x as a string valid function declSpace() { ->declSpace : () => void +>declSpace : () => never for (var x = 'this is a string'; ;) { } >x : string diff --git a/tests/baselines/reference/instanceOfAssignability.types b/tests/baselines/reference/instanceOfAssignability.types index 0a9e1a3e996..70d068fb0cc 100644 --- a/tests/baselines/reference/instanceOfAssignability.types +++ b/tests/baselines/reference/instanceOfAssignability.types @@ -133,8 +133,8 @@ function fn5(x: Derived1) { // 1.5: y: Derived1 // Want: ??? let y = x; ->y : nothing ->x : nothing +>y : never +>x : never } } diff --git a/tests/baselines/reference/narrowingOfDottedNames.types b/tests/baselines/reference/narrowingOfDottedNames.types index 697e080b661..9ab15afbd08 100644 --- a/tests/baselines/reference/narrowingOfDottedNames.types +++ b/tests/baselines/reference/narrowingOfDottedNames.types @@ -42,7 +42,7 @@ function isB(x: any): x is B { } function f1(x: A | B) { ->f1 : (x: A | B) => void +>f1 : (x: A | B) => never >x : A | B >A : A >B : B @@ -78,7 +78,7 @@ function f1(x: A | B) { } function f2(x: A | B) { ->f2 : (x: A | B) => void +>f2 : (x: A | B) => never >x : A | B >A : A >B : B diff --git a/tests/baselines/reference/nestedBlockScopedBindings3.types b/tests/baselines/reference/nestedBlockScopedBindings3.types index 37b89242f3e..f153a9a7cea 100644 --- a/tests/baselines/reference/nestedBlockScopedBindings3.types +++ b/tests/baselines/reference/nestedBlockScopedBindings3.types @@ -1,6 +1,6 @@ === tests/cases/compiler/nestedBlockScopedBindings3.ts === function a0() { ->a0 : () => void +>a0 : () => never { for (let x = 0; x < 1; ) { >x : number @@ -26,7 +26,7 @@ function a0() { } function a1() { ->a1 : () => void +>a1 : () => never for (let x; x < 1;) { >x : any @@ -48,7 +48,7 @@ function a1() { } function a2() { ->a2 : () => void +>a2 : () => never for (let x; x < 1;) { >x : any diff --git a/tests/baselines/reference/nestedBlockScopedBindings4.types b/tests/baselines/reference/nestedBlockScopedBindings4.types index b38d61f3f44..5d0ed2a1d91 100644 --- a/tests/baselines/reference/nestedBlockScopedBindings4.types +++ b/tests/baselines/reference/nestedBlockScopedBindings4.types @@ -1,6 +1,6 @@ === tests/cases/compiler/nestedBlockScopedBindings4.ts === function a0() { ->a0 : () => void +>a0 : () => never for (let x; x < 1;) { >x : any @@ -28,7 +28,7 @@ function a0() { } function a1() { ->a1 : () => void +>a1 : () => never for (let x; x < 1;) { >x : any @@ -60,7 +60,7 @@ function a1() { } function a2() { ->a2 : () => void +>a2 : () => never for (let x; x < 1;) { >x : any @@ -93,7 +93,7 @@ function a2() { function a3() { ->a3 : () => void +>a3 : () => never for (let x; x < 1;) { >x : any diff --git a/tests/baselines/reference/nestedBlockScopedBindings6.types b/tests/baselines/reference/nestedBlockScopedBindings6.types index 5c8c1fa68fa..f6c918766ae 100644 --- a/tests/baselines/reference/nestedBlockScopedBindings6.types +++ b/tests/baselines/reference/nestedBlockScopedBindings6.types @@ -1,6 +1,6 @@ === tests/cases/compiler/nestedBlockScopedBindings6.ts === function a0() { ->a0 : () => void +>a0 : () => never for (let x of [1]) { >x : number @@ -27,7 +27,7 @@ function a0() { } function a1() { ->a1 : () => void +>a1 : () => never for (let x of [1]) { >x : number @@ -58,7 +58,7 @@ function a1() { } function a2() { ->a2 : () => void +>a2 : () => never for (let x of [1]) { >x : number @@ -89,7 +89,7 @@ function a2() { } function a3() { ->a3 : () => void +>a3 : () => never for (let x of [1]) { >x : number diff --git a/tests/baselines/reference/parser_duplicateLabel3.types b/tests/baselines/reference/parser_duplicateLabel3.types index 88ea435bf3e..cc420085ef0 100644 --- a/tests/baselines/reference/parser_duplicateLabel3.types +++ b/tests/baselines/reference/parser_duplicateLabel3.types @@ -7,7 +7,7 @@ while (true) { >true : boolean function f() { ->f : () => void +>f : () => never target: >target : any diff --git a/tests/baselines/reference/promiseVoidErrorCallback.types b/tests/baselines/reference/promiseVoidErrorCallback.types index 82b248f64bd..b536ab089bd 100644 --- a/tests/baselines/reference/promiseVoidErrorCallback.types +++ b/tests/baselines/reference/promiseVoidErrorCallback.types @@ -63,7 +63,7 @@ var x3 = f1() .then(f2, (e: Error) => { >then : { (onfulfilled?: (value: T1) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; (onfulfilled?: (value: T1) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; } >f2 : (x: T1) => T2 ->(e: Error) => { throw e;} : (e: Error) => void +>(e: Error) => { throw e;} : (e: Error) => never >e : Error >Error : Error diff --git a/tests/baselines/reference/stringLiteralTypesAsTags01.types b/tests/baselines/reference/stringLiteralTypesAsTags01.types index 9f273cf93a9..7b8ac0a8c02 100644 --- a/tests/baselines/reference/stringLiteralTypesAsTags01.types +++ b/tests/baselines/reference/stringLiteralTypesAsTags01.types @@ -116,6 +116,6 @@ if (!hasKind(x, "B")) { } else { let d = x; ->d : nothing ->x : nothing +>d : never +>x : never } diff --git a/tests/baselines/reference/stringLiteralTypesAsTags02.types b/tests/baselines/reference/stringLiteralTypesAsTags02.types index bcfa74ef55f..290402cd299 100644 --- a/tests/baselines/reference/stringLiteralTypesAsTags02.types +++ b/tests/baselines/reference/stringLiteralTypesAsTags02.types @@ -110,6 +110,6 @@ if (!hasKind(x, "B")) { } else { let d = x; ->d : nothing ->x : nothing +>d : never +>x : never } diff --git a/tests/baselines/reference/stringLiteralTypesAsTags03.types b/tests/baselines/reference/stringLiteralTypesAsTags03.types index c7fdfc7152e..9d004982dda 100644 --- a/tests/baselines/reference/stringLiteralTypesAsTags03.types +++ b/tests/baselines/reference/stringLiteralTypesAsTags03.types @@ -113,6 +113,6 @@ if (!hasKind(x, "B")) { } else { let d = x; ->d : nothing ->x : nothing +>d : never +>x : never } diff --git a/tests/baselines/reference/throwInEnclosingStatements.types b/tests/baselines/reference/throwInEnclosingStatements.types index 32f0fb093bc..26866ebb240 100644 --- a/tests/baselines/reference/throwInEnclosingStatements.types +++ b/tests/baselines/reference/throwInEnclosingStatements.types @@ -1,7 +1,7 @@ === tests/cases/conformance/statements/throwStatements/throwInEnclosingStatements.ts === function fn(x) { ->fn : (x: any) => void +>fn : (x: any) => never >x : any throw x; @@ -9,7 +9,7 @@ function fn(x) { } (x: T) => { throw x; } ->(x: T) => { throw x; } : (x: T) => void +>(x: T) => { throw x; } : (x: T) => never >T : T >x : T >T : T @@ -78,7 +78,7 @@ class C { >T : T biz() { ->biz : () => void +>biz : () => never throw this.value; >this.value : T @@ -93,15 +93,15 @@ class C { } var aa = { ->aa : { id: number; biz(): void; } ->{ id:12, biz() { throw this; }} : { id: number; biz(): void; } +>aa : { id: number; biz(): never; } +>{ id:12, biz() { throw this; }} : { id: number; biz(): never; } id:12, >id : number >12 : number biz() { ->biz : () => void +>biz : () => never throw this; >this : any diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfBoolean.types b/tests/baselines/reference/typeGuardOfFormTypeOfBoolean.types index 564c6ceaa72..7a4b279b572 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfBoolean.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfBoolean.types @@ -121,7 +121,7 @@ if (typeof strOrNum === "boolean") { let z1: {} = strOrNum; // {} >z1 : {} ->strOrNum : nothing +>strOrNum : never } else { let z2: string | number = strOrNum; // string | number @@ -215,6 +215,6 @@ if (typeof strOrNum !== "boolean") { else { let z2: {} = strOrNum; // {} >z2 : {} ->strOrNum : nothing +>strOrNum : never } diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfNumber.types b/tests/baselines/reference/typeGuardOfFormTypeOfNumber.types index 51326c68cd9..c6a5615e75a 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfNumber.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfNumber.types @@ -120,7 +120,7 @@ if (typeof strOrBool === "number") { let y1: {} = strOrBool; // {} >y1 : {} ->strOrBool : nothing +>strOrBool : never } else { let y2: string | boolean = strOrBool; // string | boolean @@ -212,6 +212,6 @@ if (typeof strOrBool !== "number") { else { let y2: {} = strOrBool; // {} >y2 : {} ->strOrBool : nothing +>strOrBool : never } diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfOther.types b/tests/baselines/reference/typeGuardOfFormTypeOfOther.types index c8c150b5a3b..8e42a8e0d8e 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfOther.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfOther.types @@ -105,7 +105,7 @@ if (typeof strOrNumOrBool === "Object") { let q1: {} = strOrNumOrBool; // {} >q1 : {} ->strOrNumOrBool : nothing +>strOrNumOrBool : never } else { let q2: string | number | boolean = strOrNumOrBool; // string | number | boolean @@ -178,6 +178,6 @@ if (typeof strOrNumOrBool !== "Object") { else { let q2: {} = strOrNumOrBool; // {} >q2 : {} ->strOrNumOrBool : nothing +>strOrNumOrBool : never } diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfString.types b/tests/baselines/reference/typeGuardOfFormTypeOfString.types index 23c789fb987..971109215f7 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfString.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfString.types @@ -121,7 +121,7 @@ if (typeof numOrBool === "string") { let x1: {} = numOrBool; // {} >x1 : {} ->numOrBool : nothing +>numOrBool : never } else { let x2: number | boolean = numOrBool; // number | boolean @@ -214,6 +214,6 @@ if (typeof numOrBool !== "string") { else { let x2: {} = numOrBool; // {} >x2 : {} ->numOrBool : nothing +>numOrBool : never } diff --git a/tests/baselines/reference/typeGuardsAsAssertions.types b/tests/baselines/reference/typeGuardsAsAssertions.types index 6ec84ada1f4..82e92a72d8d 100644 --- a/tests/baselines/reference/typeGuardsAsAssertions.types +++ b/tests/baselines/reference/typeGuardsAsAssertions.types @@ -259,7 +259,7 @@ function f4() { >"boolean" : string x; // nothing (boolean not in declared type) ->x : nothing +>x : never } x; // undefined >x : undefined diff --git a/tests/baselines/reference/typeGuardsWithInstanceOf.errors.txt b/tests/baselines/reference/typeGuardsWithInstanceOf.errors.txt index 662d3697159..dfcb8a598da 100644 --- a/tests/baselines/reference/typeGuardsWithInstanceOf.errors.txt +++ b/tests/baselines/reference/typeGuardsWithInstanceOf.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20): error TS2339: Property 'global' does not exist on type 'nothing'. +tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20): error TS2339: Property 'global' does not exist on type 'never'. ==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts (1 errors) ==== @@ -10,5 +10,5 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20) result = result2; } else if (!result.global) { ~~~~~~ -!!! error TS2339: Property 'global' does not exist on type 'nothing'. +!!! error TS2339: Property 'global' does not exist on type 'never'. } \ No newline at end of file From eabafc4b09908b6f4d90a6eb5b8c8dcc277d6f46 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 17 May 2016 07:55:25 -0700 Subject: [PATCH 32/38] Add type aliases to navigation bar --- src/services/navigationBar.ts | 13 +++++++++++++ .../cases/fourslash/navigationBarItemsTypeAlias.ts | 6 ++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/cases/fourslash/navigationBarItemsTypeAlias.ts diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index d83d0738ec8..0efdaf70954 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -176,6 +176,7 @@ namespace ts.NavigationBar { break; case SyntaxKind.EnumDeclaration: case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: topLevelNodes.push(node); break; @@ -422,6 +423,9 @@ namespace ts.NavigationBar { case SyntaxKind.FunctionDeclaration: return createFunctionItem(node); + + case SyntaxKind.TypeAliasDeclaration: + return createTypeAliasItem(node); } return undefined; @@ -474,6 +478,15 @@ namespace ts.NavigationBar { return undefined; } + function createTypeAliasItem(node: TypeAliasDeclaration): ts.NavigationBarItem { + return getNavigationBarItem(node.name.text, + ts.ScriptElementKind.typeElement, + getNodeModifiers(node), + [getNodeSpan(node)], + [], + getIndent(node)); + } + function createMemberFunctionLikeItem(node: MethodDeclaration | ConstructorDeclaration): ts.NavigationBarItem { if (node.body && node.body.kind === SyntaxKind.Block) { let childItems = getItemsWorker(sortNodes((node.body).statements), createChildItem); diff --git a/tests/cases/fourslash/navigationBarItemsTypeAlias.ts b/tests/cases/fourslash/navigationBarItemsTypeAlias.ts new file mode 100644 index 00000000000..50923256533 --- /dev/null +++ b/tests/cases/fourslash/navigationBarItemsTypeAlias.ts @@ -0,0 +1,6 @@ +/// + +////type T = number | string; + +verify.navigationBarCount(1); +verify.navigationBarContains("T", "type"); From e25927da57776d7d8f14baa12f4f069e20ca151a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 17 May 2016 13:05:03 -0700 Subject: [PATCH 33/38] Unescape string literal types starting with double underscore. String literal types starting with double underscore are escaped in the parser and need to be unescaped before the type is given the string literal as its name. --- src/compiler/checker.ts | 9 +++++---- .../doubleUnderStringLiteralAssignability.errors.txt | 9 +++++++++ .../reference/doubleUnderStringLiteralAssignability.js | 8 ++++++++ .../compiler/doubleUnderStringLiteralAssignability.ts | 2 ++ 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/doubleUnderStringLiteralAssignability.errors.txt create mode 100644 tests/baselines/reference/doubleUnderStringLiteralAssignability.js create mode 100644 tests/cases/compiler/doubleUnderStringLiteralAssignability.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6a720d947df..587235d5b8e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5138,12 +5138,13 @@ namespace ts { } function getStringLiteralTypeForText(text: string): StringLiteralType { - if (hasProperty(stringLiteralTypes, text)) { - return stringLiteralTypes[text]; + const unescaped = unescapeIdentifier(text); + if (hasProperty(stringLiteralTypes, unescaped)) { + return stringLiteralTypes[unescaped]; } - const type = stringLiteralTypes[text] = createType(TypeFlags.StringLiteral); - type.text = text; + const type = stringLiteralTypes[unescaped] = createType(TypeFlags.StringLiteral); + type.text = unescaped; return type; } diff --git a/tests/baselines/reference/doubleUnderStringLiteralAssignability.errors.txt b/tests/baselines/reference/doubleUnderStringLiteralAssignability.errors.txt new file mode 100644 index 00000000000..782f022faeb --- /dev/null +++ b/tests/baselines/reference/doubleUnderStringLiteralAssignability.errors.txt @@ -0,0 +1,9 @@ +tests/cases/compiler/doubleUnderStringLiteralAssignability.ts(2,5): error TS2322: Type '"no_dunder"' is not assignable to type '"__dunder"'. + + +==== tests/cases/compiler/doubleUnderStringLiteralAssignability.ts (1 errors) ==== + var shouldBeOk: '__dunder' = '__dunder'; + var bad: '__dunder' = 'no_dunder'; + ~~~ +!!! error TS2322: Type '"no_dunder"' is not assignable to type '"__dunder"'. + \ No newline at end of file diff --git a/tests/baselines/reference/doubleUnderStringLiteralAssignability.js b/tests/baselines/reference/doubleUnderStringLiteralAssignability.js new file mode 100644 index 00000000000..7911c3766e1 --- /dev/null +++ b/tests/baselines/reference/doubleUnderStringLiteralAssignability.js @@ -0,0 +1,8 @@ +//// [doubleUnderStringLiteralAssignability.ts] +var shouldBeOk: '__dunder' = '__dunder'; +var bad: '__dunder' = 'no_dunder'; + + +//// [doubleUnderStringLiteralAssignability.js] +var shouldBeOk = '__dunder'; +var bad = 'no_dunder'; diff --git a/tests/cases/compiler/doubleUnderStringLiteralAssignability.ts b/tests/cases/compiler/doubleUnderStringLiteralAssignability.ts new file mode 100644 index 00000000000..81149acc992 --- /dev/null +++ b/tests/cases/compiler/doubleUnderStringLiteralAssignability.ts @@ -0,0 +1,2 @@ +var shouldBeOk: '__dunder' = '__dunder'; +var bad: '__dunder' = 'no_dunder'; From a5585c544f471863241c002cd7801166160aae13 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 17 May 2016 13:42:15 -0700 Subject: [PATCH 34/38] Unescape only string literal type nodes. Not all string literal types, regardless of source, as in the last commit. --- src/compiler/checker.ts | 11 +++++------ .../doubleUnderStringLiteralAssignability.errors.txt | 2 ++ .../doubleUnderStringLiteralAssignability.js | 4 ++++ .../compiler/doubleUnderStringLiteralAssignability.ts | 2 ++ 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 587235d5b8e..00dfed5f9c1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5138,20 +5138,19 @@ namespace ts { } function getStringLiteralTypeForText(text: string): StringLiteralType { - const unescaped = unescapeIdentifier(text); - if (hasProperty(stringLiteralTypes, unescaped)) { - return stringLiteralTypes[unescaped]; + if (hasProperty(stringLiteralTypes, text)) { + return stringLiteralTypes[text]; } - const type = stringLiteralTypes[unescaped] = createType(TypeFlags.StringLiteral); - type.text = unescaped; + const type = stringLiteralTypes[text] = createType(TypeFlags.StringLiteral); + type.text = text; return type; } function getTypeFromStringLiteralTypeNode(node: StringLiteralTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = getStringLiteralTypeForText(node.text); + links.resolvedType = getStringLiteralTypeForText(unescapeIdentifier(node.text)); } return links.resolvedType; } diff --git a/tests/baselines/reference/doubleUnderStringLiteralAssignability.errors.txt b/tests/baselines/reference/doubleUnderStringLiteralAssignability.errors.txt index 782f022faeb..c4226a83bfc 100644 --- a/tests/baselines/reference/doubleUnderStringLiteralAssignability.errors.txt +++ b/tests/baselines/reference/doubleUnderStringLiteralAssignability.errors.txt @@ -6,4 +6,6 @@ tests/cases/compiler/doubleUnderStringLiteralAssignability.ts(2,5): error TS2322 var bad: '__dunder' = 'no_dunder'; ~~~ !!! error TS2322: Type '"no_dunder"' is not assignable to type '"__dunder"'. + var okok: '___thunder' = '___thunder'; + var alsoOk: '_sunder' = '_sunder'; \ No newline at end of file diff --git a/tests/baselines/reference/doubleUnderStringLiteralAssignability.js b/tests/baselines/reference/doubleUnderStringLiteralAssignability.js index 7911c3766e1..baf2b521948 100644 --- a/tests/baselines/reference/doubleUnderStringLiteralAssignability.js +++ b/tests/baselines/reference/doubleUnderStringLiteralAssignability.js @@ -1,8 +1,12 @@ //// [doubleUnderStringLiteralAssignability.ts] var shouldBeOk: '__dunder' = '__dunder'; var bad: '__dunder' = 'no_dunder'; +var okok: '___thunder' = '___thunder'; +var alsoOk: '_sunder' = '_sunder'; //// [doubleUnderStringLiteralAssignability.js] var shouldBeOk = '__dunder'; var bad = 'no_dunder'; +var okok = '___thunder'; +var alsoOk = '_sunder'; diff --git a/tests/cases/compiler/doubleUnderStringLiteralAssignability.ts b/tests/cases/compiler/doubleUnderStringLiteralAssignability.ts index 81149acc992..4a1ae75164c 100644 --- a/tests/cases/compiler/doubleUnderStringLiteralAssignability.ts +++ b/tests/cases/compiler/doubleUnderStringLiteralAssignability.ts @@ -1,2 +1,4 @@ var shouldBeOk: '__dunder' = '__dunder'; var bad: '__dunder' = 'no_dunder'; +var okok: '___thunder' = '___thunder'; +var alsoOk: '_sunder' = '_sunder'; From 88d7f23f10f2c5338b37d20bbbb5d6d42075c3b1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 17 May 2016 13:45:40 -0700 Subject: [PATCH 35/38] Add additional error checking --- src/compiler/checker.ts | 7 +++++-- src/compiler/diagnosticMessages.json | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a916b898d80..bf36b3abcfb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11684,7 +11684,10 @@ namespace ts { const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn; - if (returnType && !hasExplicitReturn) { + if (returnType === neverType) { + error(func.type, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); + } + else if (returnType && !hasExplicitReturn) { // minimal check: function has syntactic return type annotation and no explicit return statements in the body // this function does not conform to the specification. // NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present @@ -14821,7 +14824,7 @@ namespace ts { if (func) { const signature = getSignatureFromDeclaration(func); const returnType = getReturnTypeOfSignature(signature); - if (strictNullChecks || node.expression) { + if (strictNullChecks || node.expression || returnType === neverType) { const exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; if (func.asteriskToken) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 899b4292f04..4c9de081ac5 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1751,6 +1751,10 @@ "category": "Error", "code": 2533 }, + "A function returning 'never' cannot have a reachable end point.": { + "category": "Error", + "code": 2534 + }, "JSX element attributes type '{0}' may not be a union type.": { "category": "Error", "code": 2600 From bfd8704245b40c603128c73975c27c4ea3104433 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 17 May 2016 13:46:07 -0700 Subject: [PATCH 36/38] Adding tests --- tests/baselines/reference/neverType.js | 138 +++++++++++++ tests/baselines/reference/neverType.symbols | 137 +++++++++++++ tests/baselines/reference/neverType.types | 189 ++++++++++++++++++ .../reference/neverTypeErrors1.errors.txt | 50 +++++ tests/baselines/reference/neverTypeErrors1.js | 40 ++++ .../reference/neverTypeErrors2.errors.txt | 51 +++++ tests/baselines/reference/neverTypeErrors2.js | 41 ++++ .../conformance/types/never/neverType.ts | 68 +++++++ .../types/never/neverTypeErrors1.ts | 20 ++ .../types/never/neverTypeErrors2.ts | 22 ++ 10 files changed, 756 insertions(+) create mode 100644 tests/baselines/reference/neverType.js create mode 100644 tests/baselines/reference/neverType.symbols create mode 100644 tests/baselines/reference/neverType.types create mode 100644 tests/baselines/reference/neverTypeErrors1.errors.txt create mode 100644 tests/baselines/reference/neverTypeErrors1.js create mode 100644 tests/baselines/reference/neverTypeErrors2.errors.txt create mode 100644 tests/baselines/reference/neverTypeErrors2.js create mode 100644 tests/cases/conformance/types/never/neverType.ts create mode 100644 tests/cases/conformance/types/never/neverTypeErrors1.ts create mode 100644 tests/cases/conformance/types/never/neverTypeErrors2.ts diff --git a/tests/baselines/reference/neverType.js b/tests/baselines/reference/neverType.js new file mode 100644 index 00000000000..8c2c0293c21 --- /dev/null +++ b/tests/baselines/reference/neverType.js @@ -0,0 +1,138 @@ +//// [neverType.ts] + +function error(message: string) { + throw new Error(message); +} + +function fail() { + return error("Something failed"); +} + +function infiniteLoop() { + while (true) { + } +} + +function move1(direction: "up" | "down") { + switch (direction) { + case "up": + return 1; + case "down": + return -1; + } + return error("Should never get here"); +} + +function move2(direction: "up" | "down") { + return direction === "up" ? 1 : + direction === "down" ? -1 : + error("Should never get here"); +} + +function check(x: T | undefined) { + return x || error("Undefined value"); +} + +function f1(x: string | number) { + if (typeof x === "boolean") { + x; // never + } +} + +function f2(x: string | number) { + while (true) { + if (typeof x === "boolean") { + return x; // never + } + } +} + +function failOrThrow(shouldFail: boolean) { + if (shouldFail) { + return fail(); + } + throw new Error(); +} + +function test(cb: () => string) { + let s = cb(); + return s; +} + +let errorCallback = () => error("Error callback"); + +test(() => "hello"); +test(() => fail()); +test(() => { throw new Error(); }) +test(errorCallback); + + +//// [neverType.js] +function error(message) { + throw new Error(message); +} +function fail() { + return error("Something failed"); +} +function infiniteLoop() { + while (true) { + } +} +function move1(direction) { + switch (direction) { + case "up": + return 1; + case "down": + return -1; + } + return error("Should never get here"); +} +function move2(direction) { + return direction === "up" ? 1 : + direction === "down" ? -1 : + error("Should never get here"); +} +function check(x) { + return x || error("Undefined value"); +} +function f1(x) { + if (typeof x === "boolean") { + x; // never + } +} +function f2(x) { + while (true) { + if (typeof x === "boolean") { + return x; // never + } + } +} +function failOrThrow(shouldFail) { + if (shouldFail) { + return fail(); + } + throw new Error(); +} +function test(cb) { + var s = cb(); + return s; +} +var errorCallback = function () { return error("Error callback"); }; +test(function () { return "hello"; }); +test(function () { return fail(); }); +test(function () { throw new Error(); }); +test(errorCallback); + + +//// [neverType.d.ts] +declare function error(message: string): never; +declare function fail(): never; +declare function infiniteLoop(): never; +declare function move1(direction: "up" | "down"): number; +declare function move2(direction: "up" | "down"): number; +declare function check(x: T | undefined): T; +declare function f1(x: string | number): void; +declare function f2(x: string | number): never; +declare function failOrThrow(shouldFail: boolean): never; +declare function test(cb: () => string): string; +declare let errorCallback: () => never; diff --git a/tests/baselines/reference/neverType.symbols b/tests/baselines/reference/neverType.symbols new file mode 100644 index 00000000000..e1c4e98c24c --- /dev/null +++ b/tests/baselines/reference/neverType.symbols @@ -0,0 +1,137 @@ +=== tests/cases/conformance/types/never/neverType.ts === + +function error(message: string) { +>error : Symbol(error, Decl(neverType.ts, 0, 0)) +>message : Symbol(message, Decl(neverType.ts, 1, 15)) + + throw new Error(message); +>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>message : Symbol(message, Decl(neverType.ts, 1, 15)) +} + +function fail() { +>fail : Symbol(fail, Decl(neverType.ts, 3, 1)) + + return error("Something failed"); +>error : Symbol(error, Decl(neverType.ts, 0, 0)) +} + +function infiniteLoop() { +>infiniteLoop : Symbol(infiniteLoop, Decl(neverType.ts, 7, 1)) + + while (true) { + } +} + +function move1(direction: "up" | "down") { +>move1 : Symbol(move1, Decl(neverType.ts, 12, 1)) +>direction : Symbol(direction, Decl(neverType.ts, 14, 15)) + + switch (direction) { +>direction : Symbol(direction, Decl(neverType.ts, 14, 15)) + + case "up": + return 1; + case "down": + return -1; + } + return error("Should never get here"); +>error : Symbol(error, Decl(neverType.ts, 0, 0)) +} + +function move2(direction: "up" | "down") { +>move2 : Symbol(move2, Decl(neverType.ts, 22, 1)) +>direction : Symbol(direction, Decl(neverType.ts, 24, 15)) + + return direction === "up" ? 1 : +>direction : Symbol(direction, Decl(neverType.ts, 24, 15)) + + direction === "down" ? -1 : +>direction : Symbol(direction, Decl(neverType.ts, 24, 15)) + + error("Should never get here"); +>error : Symbol(error, Decl(neverType.ts, 0, 0)) +} + +function check(x: T | undefined) { +>check : Symbol(check, Decl(neverType.ts, 28, 1)) +>T : Symbol(T, Decl(neverType.ts, 30, 15)) +>x : Symbol(x, Decl(neverType.ts, 30, 18)) +>T : Symbol(T, Decl(neverType.ts, 30, 15)) + + return x || error("Undefined value"); +>x : Symbol(x, Decl(neverType.ts, 30, 18)) +>error : Symbol(error, Decl(neverType.ts, 0, 0)) +} + +function f1(x: string | number) { +>f1 : Symbol(f1, Decl(neverType.ts, 32, 1)) +>x : Symbol(x, Decl(neverType.ts, 34, 12)) + + if (typeof x === "boolean") { +>x : Symbol(x, Decl(neverType.ts, 34, 12)) + + x; // never +>x : Symbol(x, Decl(neverType.ts, 34, 12)) + } +} + +function f2(x: string | number) { +>f2 : Symbol(f2, Decl(neverType.ts, 38, 1)) +>x : Symbol(x, Decl(neverType.ts, 40, 12)) + + while (true) { + if (typeof x === "boolean") { +>x : Symbol(x, Decl(neverType.ts, 40, 12)) + + return x; // never +>x : Symbol(x, Decl(neverType.ts, 40, 12)) + } + } +} + +function failOrThrow(shouldFail: boolean) { +>failOrThrow : Symbol(failOrThrow, Decl(neverType.ts, 46, 1)) +>shouldFail : Symbol(shouldFail, Decl(neverType.ts, 48, 21)) + + if (shouldFail) { +>shouldFail : Symbol(shouldFail, Decl(neverType.ts, 48, 21)) + + return fail(); +>fail : Symbol(fail, Decl(neverType.ts, 3, 1)) + } + throw new Error(); +>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +} + +function test(cb: () => string) { +>test : Symbol(test, Decl(neverType.ts, 53, 1)) +>cb : Symbol(cb, Decl(neverType.ts, 55, 14)) + + let s = cb(); +>s : Symbol(s, Decl(neverType.ts, 56, 7)) +>cb : Symbol(cb, Decl(neverType.ts, 55, 14)) + + return s; +>s : Symbol(s, Decl(neverType.ts, 56, 7)) +} + +let errorCallback = () => error("Error callback"); +>errorCallback : Symbol(errorCallback, Decl(neverType.ts, 60, 3)) +>error : Symbol(error, Decl(neverType.ts, 0, 0)) + +test(() => "hello"); +>test : Symbol(test, Decl(neverType.ts, 53, 1)) + +test(() => fail()); +>test : Symbol(test, Decl(neverType.ts, 53, 1)) +>fail : Symbol(fail, Decl(neverType.ts, 3, 1)) + +test(() => { throw new Error(); }) +>test : Symbol(test, Decl(neverType.ts, 53, 1)) +>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +test(errorCallback); +>test : Symbol(test, Decl(neverType.ts, 53, 1)) +>errorCallback : Symbol(errorCallback, Decl(neverType.ts, 60, 3)) + diff --git a/tests/baselines/reference/neverType.types b/tests/baselines/reference/neverType.types new file mode 100644 index 00000000000..e6b36bcbace --- /dev/null +++ b/tests/baselines/reference/neverType.types @@ -0,0 +1,189 @@ +=== tests/cases/conformance/types/never/neverType.ts === + +function error(message: string) { +>error : (message: string) => never +>message : string + + throw new Error(message); +>new Error(message) : Error +>Error : ErrorConstructor +>message : string +} + +function fail() { +>fail : () => never + + return error("Something failed"); +>error("Something failed") : never +>error : (message: string) => never +>"Something failed" : string +} + +function infiniteLoop() { +>infiniteLoop : () => never + + while (true) { +>true : boolean + } +} + +function move1(direction: "up" | "down") { +>move1 : (direction: "up" | "down") => number +>direction : "up" | "down" + + switch (direction) { +>direction : "up" | "down" + + case "up": +>"up" : string + + return 1; +>1 : number + + case "down": +>"down" : string + + return -1; +>-1 : number +>1 : number + } + return error("Should never get here"); +>error("Should never get here") : never +>error : (message: string) => never +>"Should never get here" : string +} + +function move2(direction: "up" | "down") { +>move2 : (direction: "up" | "down") => number +>direction : "up" | "down" + + return direction === "up" ? 1 : +>direction === "up" ? 1 : direction === "down" ? -1 : error("Should never get here") : number +>direction === "up" : boolean +>direction : "up" | "down" +>"up" : string +>1 : number + + direction === "down" ? -1 : +>direction === "down" ? -1 : error("Should never get here") : number +>direction === "down" : boolean +>direction : "up" | "down" +>"down" : string +>-1 : number +>1 : number + + error("Should never get here"); +>error("Should never get here") : never +>error : (message: string) => never +>"Should never get here" : string +} + +function check(x: T | undefined) { +>check : (x: T | undefined) => T +>T : T +>x : T | undefined +>T : T + + return x || error("Undefined value"); +>x || error("Undefined value") : T +>x : T | undefined +>error("Undefined value") : never +>error : (message: string) => never +>"Undefined value" : string +} + +function f1(x: string | number) { +>f1 : (x: string | number) => void +>x : string | number + + if (typeof x === "boolean") { +>typeof x === "boolean" : boolean +>typeof x : string +>x : string | number +>"boolean" : string + + x; // never +>x : never + } +} + +function f2(x: string | number) { +>f2 : (x: string | number) => never +>x : string | number + + while (true) { +>true : boolean + + if (typeof x === "boolean") { +>typeof x === "boolean" : boolean +>typeof x : string +>x : string | number +>"boolean" : string + + return x; // never +>x : never + } + } +} + +function failOrThrow(shouldFail: boolean) { +>failOrThrow : (shouldFail: boolean) => never +>shouldFail : boolean + + if (shouldFail) { +>shouldFail : boolean + + return fail(); +>fail() : never +>fail : () => never + } + throw new Error(); +>new Error() : Error +>Error : ErrorConstructor +} + +function test(cb: () => string) { +>test : (cb: () => string) => string +>cb : () => string + + let s = cb(); +>s : string +>cb() : string +>cb : () => string + + return s; +>s : string +} + +let errorCallback = () => error("Error callback"); +>errorCallback : () => never +>() => error("Error callback") : () => never +>error("Error callback") : never +>error : (message: string) => never +>"Error callback" : string + +test(() => "hello"); +>test(() => "hello") : string +>test : (cb: () => string) => string +>() => "hello" : () => string +>"hello" : string + +test(() => fail()); +>test(() => fail()) : string +>test : (cb: () => string) => string +>() => fail() : () => never +>fail() : never +>fail : () => never + +test(() => { throw new Error(); }) +>test(() => { throw new Error(); }) : string +>test : (cb: () => string) => string +>() => { throw new Error(); } : () => never +>new Error() : Error +>Error : ErrorConstructor + +test(errorCallback); +>test(errorCallback) : string +>test : (cb: () => string) => string +>errorCallback : () => never + diff --git a/tests/baselines/reference/neverTypeErrors1.errors.txt b/tests/baselines/reference/neverTypeErrors1.errors.txt new file mode 100644 index 00000000000..8fd6f9c924e --- /dev/null +++ b/tests/baselines/reference/neverTypeErrors1.errors.txt @@ -0,0 +1,50 @@ +tests/cases/conformance/types/never/neverTypeErrors1.ts(3,5): error TS2322: Type 'number' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors1.ts(4,5): error TS2322: Type 'string' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors1.ts(5,5): error TS2322: Type 'boolean' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors1.ts(6,5): error TS2322: Type 'undefined' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors1.ts(7,5): error TS2322: Type 'null' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors1.ts(8,5): error TS2322: Type '{}' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors1.ts(12,5): error TS2322: Type 'undefined' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors1.ts(16,12): error TS2322: Type 'number' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors1.ts(19,16): error TS2534: A function returning 'never' cannot have a reachable end point. + + +==== tests/cases/conformance/types/never/neverTypeErrors1.ts (9 errors) ==== + function f1() { + let x: never; + x = 1; + ~ +!!! error TS2322: Type 'number' is not assignable to type 'never'. + x = "abc"; + ~ +!!! error TS2322: Type 'string' is not assignable to type 'never'. + x = false; + ~ +!!! error TS2322: Type 'boolean' is not assignable to type 'never'. + x = undefined; + ~ +!!! error TS2322: Type 'undefined' is not assignable to type 'never'. + x = null; + ~ +!!! error TS2322: Type 'null' is not assignable to type 'never'. + x = {}; + ~ +!!! error TS2322: Type '{}' is not assignable to type 'never'. + } + + function f2(): never { + return; + ~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'never'. + } + + function f3(): never { + return 1; + ~ +!!! error TS2322: Type 'number' is not assignable to type 'never'. + } + + function f4(): never { + ~~~~~ +!!! error TS2534: A function returning 'never' cannot have a reachable end point. + } \ No newline at end of file diff --git a/tests/baselines/reference/neverTypeErrors1.js b/tests/baselines/reference/neverTypeErrors1.js new file mode 100644 index 00000000000..81b3f8f9cdb --- /dev/null +++ b/tests/baselines/reference/neverTypeErrors1.js @@ -0,0 +1,40 @@ +//// [neverTypeErrors1.ts] +function f1() { + let x: never; + x = 1; + x = "abc"; + x = false; + x = undefined; + x = null; + x = {}; +} + +function f2(): never { + return; +} + +function f3(): never { + return 1; +} + +function f4(): never { +} + +//// [neverTypeErrors1.js] +function f1() { + var x; + x = 1; + x = "abc"; + x = false; + x = undefined; + x = null; + x = {}; +} +function f2() { + return; +} +function f3() { + return 1; +} +function f4() { +} diff --git a/tests/baselines/reference/neverTypeErrors2.errors.txt b/tests/baselines/reference/neverTypeErrors2.errors.txt new file mode 100644 index 00000000000..c6292657ad1 --- /dev/null +++ b/tests/baselines/reference/neverTypeErrors2.errors.txt @@ -0,0 +1,51 @@ +tests/cases/conformance/types/never/neverTypeErrors2.ts(4,5): error TS2322: Type 'number' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors2.ts(5,5): error TS2322: Type 'string' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors2.ts(6,5): error TS2322: Type 'boolean' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors2.ts(7,5): error TS2322: Type 'undefined' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors2.ts(8,5): error TS2322: Type 'null' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors2.ts(9,5): error TS2322: Type '{}' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors2.ts(13,5): error TS2322: Type 'undefined' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors2.ts(17,12): error TS2322: Type 'number' is not assignable to type 'never'. +tests/cases/conformance/types/never/neverTypeErrors2.ts(20,16): error TS2534: A function returning 'never' cannot have a reachable end point. + + +==== tests/cases/conformance/types/never/neverTypeErrors2.ts (9 errors) ==== + + function f1() { + let x: never; + x = 1; + ~ +!!! error TS2322: Type 'number' is not assignable to type 'never'. + x = "abc"; + ~ +!!! error TS2322: Type 'string' is not assignable to type 'never'. + x = false; + ~ +!!! error TS2322: Type 'boolean' is not assignable to type 'never'. + x = undefined; + ~ +!!! error TS2322: Type 'undefined' is not assignable to type 'never'. + x = null; + ~ +!!! error TS2322: Type 'null' is not assignable to type 'never'. + x = {}; + ~ +!!! error TS2322: Type '{}' is not assignable to type 'never'. + } + + function f2(): never { + return; + ~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'never'. + } + + function f3(): never { + return 1; + ~ +!!! error TS2322: Type 'number' is not assignable to type 'never'. + } + + function f4(): never { + ~~~~~ +!!! error TS2534: A function returning 'never' cannot have a reachable end point. + } \ No newline at end of file diff --git a/tests/baselines/reference/neverTypeErrors2.js b/tests/baselines/reference/neverTypeErrors2.js new file mode 100644 index 00000000000..18c92922bc1 --- /dev/null +++ b/tests/baselines/reference/neverTypeErrors2.js @@ -0,0 +1,41 @@ +//// [neverTypeErrors2.ts] + +function f1() { + let x: never; + x = 1; + x = "abc"; + x = false; + x = undefined; + x = null; + x = {}; +} + +function f2(): never { + return; +} + +function f3(): never { + return 1; +} + +function f4(): never { +} + +//// [neverTypeErrors2.js] +function f1() { + var x; + x = 1; + x = "abc"; + x = false; + x = undefined; + x = null; + x = {}; +} +function f2() { + return; +} +function f3() { + return 1; +} +function f4() { +} diff --git a/tests/cases/conformance/types/never/neverType.ts b/tests/cases/conformance/types/never/neverType.ts new file mode 100644 index 00000000000..d37528a022d --- /dev/null +++ b/tests/cases/conformance/types/never/neverType.ts @@ -0,0 +1,68 @@ +// @strictNullChecks: true +// @declaration: true + +function error(message: string) { + throw new Error(message); +} + +function fail() { + return error("Something failed"); +} + +function infiniteLoop() { + while (true) { + } +} + +function move1(direction: "up" | "down") { + switch (direction) { + case "up": + return 1; + case "down": + return -1; + } + return error("Should never get here"); +} + +function move2(direction: "up" | "down") { + return direction === "up" ? 1 : + direction === "down" ? -1 : + error("Should never get here"); +} + +function check(x: T | undefined) { + return x || error("Undefined value"); +} + +function f1(x: string | number) { + if (typeof x === "boolean") { + x; // never + } +} + +function f2(x: string | number) { + while (true) { + if (typeof x === "boolean") { + return x; // never + } + } +} + +function failOrThrow(shouldFail: boolean) { + if (shouldFail) { + return fail(); + } + throw new Error(); +} + +function test(cb: () => string) { + let s = cb(); + return s; +} + +let errorCallback = () => error("Error callback"); + +test(() => "hello"); +test(() => fail()); +test(() => { throw new Error(); }) +test(errorCallback); diff --git a/tests/cases/conformance/types/never/neverTypeErrors1.ts b/tests/cases/conformance/types/never/neverTypeErrors1.ts new file mode 100644 index 00000000000..8d78e863098 --- /dev/null +++ b/tests/cases/conformance/types/never/neverTypeErrors1.ts @@ -0,0 +1,20 @@ +function f1() { + let x: never; + x = 1; + x = "abc"; + x = false; + x = undefined; + x = null; + x = {}; +} + +function f2(): never { + return; +} + +function f3(): never { + return 1; +} + +function f4(): never { +} \ No newline at end of file diff --git a/tests/cases/conformance/types/never/neverTypeErrors2.ts b/tests/cases/conformance/types/never/neverTypeErrors2.ts new file mode 100644 index 00000000000..635d1c9c6ad --- /dev/null +++ b/tests/cases/conformance/types/never/neverTypeErrors2.ts @@ -0,0 +1,22 @@ +// @strictNullChecks: true + +function f1() { + let x: never; + x = 1; + x = "abc"; + x = false; + x = undefined; + x = null; + x = {}; +} + +function f2(): never { + return; +} + +function f3(): never { + return 1; +} + +function f4(): never { +} \ No newline at end of file From fffbbffef4dcb270668b4d3bf99780689d04cde5 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 18 May 2016 06:31:51 -0700 Subject: [PATCH 37/38] Lint navigationBar.ts --- Jakefile.js | 1 + src/services/navigationBar.ts | 72 +++++++++++++++++------------------ 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index 0da8e524686..ebea3375994 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -962,6 +962,7 @@ function lintFileAsync(options, path, cb) { var servicesLintTargets = [ "navigateTo.ts", + "navigationBar.ts", "outliningElementsCollector.ts", "patternMatcher.ts", "services.ts", diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 0efdaf70954..2cd93d3856c 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -46,7 +46,7 @@ namespace ts.NavigationBar { } function getChildNodes(nodes: Node[]): Node[] { - let childNodes: Node[] = []; + const childNodes: Node[] = []; function visit(node: Node) { switch (node.kind) { @@ -109,7 +109,7 @@ namespace ts.NavigationBar { } } - //for (let i = 0, n = nodes.length; i < n; i++) { + // for (let i = 0, n = nodes.length; i < n; i++) { // let node = nodes[i]; // if (node.kind === SyntaxKind.ClassDeclaration || @@ -123,13 +123,13 @@ namespace ts.NavigationBar { // else if (node.kind === SyntaxKind.VariableStatement) { // childNodes.push.apply(childNodes, (node).declarations); // } - //} + // } forEach(nodes, visit); return sortNodes(childNodes); } function getTopLevelNodes(node: SourceFile): Node[] { - let topLevelNodes: Node[] = []; + const topLevelNodes: Node[] = []; topLevelNodes.push(node); addTopLevelNodes(node.statements, topLevelNodes); @@ -157,7 +157,7 @@ namespace ts.NavigationBar { function addTopLevelNodes(nodes: Node[], topLevelNodes: Node[]): void { nodes = sortNodes(nodes); - for (let node of nodes) { + for (const node of nodes) { switch (node.kind) { case SyntaxKind.ClassDeclaration: topLevelNodes.push(node); @@ -198,7 +198,7 @@ namespace ts.NavigationBar { } function hasNamedFunctionDeclarations(nodes: NodeArray): boolean { - for (let s of nodes) { + for (const s of nodes) { if (s.kind === SyntaxKind.FunctionDeclaration && !isEmpty((s).name.text)) { return true; } @@ -238,17 +238,17 @@ namespace ts.NavigationBar { } function getItemsWorker(nodes: Node[], createItem: (n: Node) => ts.NavigationBarItem): ts.NavigationBarItem[] { - let items: ts.NavigationBarItem[] = []; + const items: ts.NavigationBarItem[] = []; - let keyToItem: Map = {}; + const keyToItem: Map = {}; - for (let child of nodes) { - let item = createItem(child); + for (const child of nodes) { + const item = createItem(child); if (item !== undefined) { if (item.text.length > 0) { - let key = item.text + "-" + item.kind + "-" + item.indent; + const key = item.text + "-" + item.kind + "-" + item.indent; - let itemWithSameName = keyToItem[key]; + const itemWithSameName = keyToItem[key]; if (itemWithSameName) { // We had an item with the same name. Merge these items together. merge(itemWithSameName, item); @@ -275,8 +275,8 @@ namespace ts.NavigationBar { // Next, recursively merge or add any children in the source as appropriate. outer: - for (let sourceChild of source.childItems) { - for (let targetChild of target.childItems) { + for (const sourceChild of source.childItems) { + for (const targetChild of target.childItems) { if (targetChild.text === sourceChild.text && targetChild.kind === sourceChild.kind) { // Found a match. merge them. merge(targetChild, sourceChild); @@ -383,7 +383,7 @@ namespace ts.NavigationBar { return !text || text.trim() === ""; } - function getNavigationBarItem(text: string, kind: string, kindModifiers: string, spans: TextSpan[], childItems: NavigationBarItem[] = [], indent: number = 0): NavigationBarItem { + function getNavigationBarItem(text: string, kind: string, kindModifiers: string, spans: TextSpan[], childItems: NavigationBarItem[] = [], indent = 0): NavigationBarItem { if (isEmpty(text)) { return undefined; } @@ -437,7 +437,7 @@ namespace ts.NavigationBar { } // Otherwise, we need to aggregate each identifier to build up the qualified name. - let result: string[] = []; + const result: string[] = []; result.push(moduleDeclaration.name.text); @@ -451,9 +451,9 @@ namespace ts.NavigationBar { } function createModuleItem(node: ModuleDeclaration): NavigationBarItem { - let moduleName = getModuleName(node); + const moduleName = getModuleName(node); - let childItems = getItemsWorker(getChildNodes((getInnermostModule(node).body).statements), createChildItem); + const childItems = getItemsWorker(getChildNodes((getInnermostModule(node).body).statements), createChildItem); return getNavigationBarItem(moduleName, ts.ScriptElementKind.moduleElement, @@ -465,9 +465,9 @@ namespace ts.NavigationBar { function createFunctionItem(node: FunctionDeclaration): ts.NavigationBarItem { if (node.body && node.body.kind === SyntaxKind.Block) { - let childItems = getItemsWorker(sortNodes((node.body).statements), createChildItem); + const childItems = getItemsWorker(sortNodes((node.body).statements), createChildItem); - return getNavigationBarItem(!node.name ? "default": node.name.text, + return getNavigationBarItem(!node.name ? "default" : node.name.text, ts.ScriptElementKind.functionElement, getNodeModifiers(node), [getNodeSpan(node)], @@ -489,7 +489,7 @@ namespace ts.NavigationBar { function createMemberFunctionLikeItem(node: MethodDeclaration | ConstructorDeclaration): ts.NavigationBarItem { if (node.body && node.body.kind === SyntaxKind.Block) { - let childItems = getItemsWorker(sortNodes((node.body).statements), createChildItem); + const childItems = getItemsWorker(sortNodes((node.body).statements), createChildItem); let scriptElementKind: string; let memberFunctionName: string; if (node.kind === SyntaxKind.MethodDeclaration) { @@ -513,16 +513,16 @@ namespace ts.NavigationBar { } function createSourceFileItem(node: SourceFile): ts.NavigationBarItem { - let childItems = getItemsWorker(getChildNodes(node.statements), createChildItem); + const childItems = getItemsWorker(getChildNodes(node.statements), createChildItem); if (childItems === undefined || childItems.length === 0) { return undefined; } hasGlobalNode = true; - let rootName = isExternalModule(node) + const rootName = isExternalModule(node) ? "\"" + escapeString(getBaseFileName(removeFileExtension(normalizePath(node.fileName)))) + "\"" - : "" + : ""; return getNavigationBarItem(rootName, ts.ScriptElementKind.moduleElement, @@ -535,14 +535,14 @@ namespace ts.NavigationBar { let childItems: NavigationBarItem[]; if (node.members) { - let constructor = forEach(node.members, member => { + const constructor = forEach(node.members, member => { return member.kind === SyntaxKind.Constructor && member; }); // Add the constructor parameters in as children of the class (for property parameters). // Note that *all non-binding pattern named* parameters will be added to the nodes array, but parameters that // are not properties will be filtered out later by createChildItem. - let nodes: Node[] = removeDynamicallyNamedProperties(node); + const nodes: Node[] = removeDynamicallyNamedProperties(node); if (constructor) { addRange(nodes, filter(constructor.parameters, p => !isBindingPattern(p.name))); } @@ -550,7 +550,7 @@ namespace ts.NavigationBar { childItems = getItemsWorker(sortNodes(nodes), createChildItem); } - var nodeName = !node.name ? "default" : node.name.text; + const nodeName = !node.name ? "default" : node.name.text; return getNavigationBarItem( nodeName, @@ -562,7 +562,7 @@ namespace ts.NavigationBar { } function createEnumItem(node: EnumDeclaration): ts.NavigationBarItem { - let childItems = getItemsWorker(sortNodes(removeComputedProperties(node)), createChildItem); + const childItems = getItemsWorker(sortNodes(removeComputedProperties(node)), createChildItem); return getNavigationBarItem( node.name.text, ts.ScriptElementKind.enumElement, @@ -573,7 +573,7 @@ namespace ts.NavigationBar { } function createInterfaceItem(node: InterfaceDeclaration): ts.NavigationBarItem { - let childItems = getItemsWorker(sortNodes(removeDynamicallyNamedProperties(node)), createChildItem); + const childItems = getItemsWorker(sortNodes(removeDynamicallyNamedProperties(node)), createChildItem); return getNavigationBarItem( node.name.text, ts.ScriptElementKind.interfaceElement, @@ -591,7 +591,7 @@ namespace ts.NavigationBar { /** * Like removeComputedProperties, but retains the properties with well known symbol names */ - function removeDynamicallyNamedProperties(node: ClassDeclaration | InterfaceDeclaration): Declaration[]{ + function removeDynamicallyNamedProperties(node: ClassDeclaration | InterfaceDeclaration): Declaration[] { return filter(node.members, member => !hasDynamicName(member)); } @@ -619,11 +619,11 @@ namespace ts.NavigationBar { const anonClassText = ""; let indent = 0; - let rootName = isExternalModule(sourceFile) ? + const rootName = isExternalModule(sourceFile) ? "\"" + escapeString(getBaseFileName(removeFileExtension(normalizePath(sourceFile.fileName)))) + "\"" : ""; - let sourceFileItem = getNavBarItem(rootName, ScriptElementKind.moduleElement, [getNodeSpan(sourceFile)]); + const sourceFileItem = getNavBarItem(rootName, ScriptElementKind.moduleElement, [getNodeSpan(sourceFile)]); let topItem = sourceFileItem; // Walk the whole file, because we want to also find function expressions - which may be in variable initializer, @@ -656,12 +656,12 @@ namespace ts.NavigationBar { } } - function createNavBarItem(node: Node) : NavigationBarItem { + function createNavBarItem(node: Node): NavigationBarItem { switch (node.kind) { case SyntaxKind.VariableDeclaration: // Only add to the navbar if at the top-level of the file // Note: "const" and "let" are also SyntaxKind.VariableDeclarations - if(node.parent/*VariableDeclarationList*/.parent/*VariableStatement*/ + if (node.parent/*VariableDeclarationList*/.parent/*VariableStatement*/ .parent/*SourceFile*/.kind !== SyntaxKind.SourceFile) { return undefined; } @@ -724,7 +724,7 @@ namespace ts.NavigationBar { function getNavBarItem(text: string, kind: string, spans: TextSpan[], kindModifiers = ScriptElementKindModifier.none): NavigationBarItem { return { text, kind, kindModifiers, spans, childItems: [], indent, bolded: false, grayed: false - } + }; } function getDefineModuleItem(node: Node): NavigationBarItem { @@ -737,7 +737,7 @@ namespace ts.NavigationBar { return undefined; } const callExpr = node.parent as CallExpression; - if (callExpr.expression.kind !== SyntaxKind.Identifier || callExpr.expression.getText() !== 'define') { + if (callExpr.expression.kind !== SyntaxKind.Identifier || callExpr.expression.getText() !== "define") { return undefined; } From b8692a7fea7fb9b12e59f5bd5fb4371088b811be Mon Sep 17 00:00:00 2001 From: Ethan Rubio Date: Wed, 18 May 2016 07:56:45 -1000 Subject: [PATCH 38/38] Fix minor comment grammatical errors This PR doesn't fix any particular issue. I cleaned up a variety of comment grammatical errors such as missing apostrophes and articles. Further, I made comment formatting more consistent with the rest of the project. --- src/services/breakpoints.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index c79a34b1bfa..02456f5add1 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -24,7 +24,7 @@ namespace ts.BreakpointResolver { // token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line tokenAtLocation = findPrecedingToken(tokenAtLocation.pos, sourceFile); - // Its a blank line + // It's a blank line if (!tokenAtLocation || sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getEnd()).line !== lineOfPosition) { return undefined; } @@ -312,7 +312,7 @@ namespace ts.BreakpointResolver { case SyntaxKind.BinaryExpression: if ((node.parent).operatorToken.kind === SyntaxKind.CommaToken) { - // if this is comma expression, the breakpoint is possible in this expression + // If this is a comma expression, the breakpoint is possible in this expression return textSpan(node); } break; @@ -387,7 +387,7 @@ namespace ts.BreakpointResolver { return spanInNode(variableDeclaration.parent.parent); } - // If this is a destructuring pattern set breakpoint in binding pattern + // If this is a destructuring pattern, set breakpoint in binding pattern if (isBindingPattern(variableDeclaration.name)) { return spanInBindingPattern(variableDeclaration.name); } @@ -402,9 +402,9 @@ namespace ts.BreakpointResolver { let declarations = variableDeclaration.parent.declarations; if (declarations && declarations[0] !== variableDeclaration) { - // If we cant set breakpoint on this declaration, set it on previous one + // If we cannot set breakpoint on this declaration, set it on previous one // Because the variable declaration may be binding pattern and - // we would like to set breakpoint in last binding element if thats the case, + // we would like to set breakpoint in last binding element if that's the case, // use preceding token instead return spanInNode(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent)); } @@ -418,7 +418,7 @@ namespace ts.BreakpointResolver { function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan { if (isBindingPattern(parameter.name)) { - // set breakpoint in binding pattern + // Set breakpoint in binding pattern return spanInBindingPattern(parameter.name); } else if (canHaveSpanInParameterDeclaration(parameter)) { @@ -492,7 +492,7 @@ namespace ts.BreakpointResolver { function spanInInitializerOfForLike(forLikeStatement: ForStatement | ForOfStatement | ForInStatement): TextSpan { if (forLikeStatement.initializer.kind === SyntaxKind.VariableDeclarationList) { - // declaration list, set breakpoint in first declaration + // Declaration list - set breakpoint in first declaration let variableDeclarationList = forLikeStatement.initializer; if (variableDeclarationList.declarations.length > 0) { return spanInNode(variableDeclarationList.declarations[0]); @@ -578,7 +578,7 @@ namespace ts.BreakpointResolver { function spanInCloseBraceToken(node: Node): TextSpan { switch (node.parent.kind) { case SyntaxKind.ModuleBlock: - // If this is not instantiated module block no bp span + // If this is not an instantiated module block, no bp span if (getModuleInstanceState(node.parent.parent) !== ModuleInstanceState.Instantiated) { return undefined; } @@ -593,7 +593,7 @@ namespace ts.BreakpointResolver { // Span on close brace token return textSpan(node); } - // fall through. + // fall through case SyntaxKind.CatchClause: return spanInNode(lastOrUndefined((node.parent).statements)); @@ -714,7 +714,7 @@ namespace ts.BreakpointResolver { function spanInOfKeyword(node: Node): TextSpan { if (node.parent.kind === SyntaxKind.ForOfStatement) { - // set using next token + // Set using next token return spanInNextNode(node); } @@ -723,4 +723,4 @@ namespace ts.BreakpointResolver { } } } -} \ No newline at end of file +}