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/compiler/checker.ts b/src/compiler/checker.ts index 6a720d947df..83dfdab423a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -79,6 +79,7 @@ namespace ts { getIndexTypeOfType, getBaseTypes, getReturnTypeOfSignature, + getNonNullableType, getSymbolsInScope, getSymbolAtLocation, getShorthandAssignmentValueSymbol, @@ -120,9 +121,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 nothingType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); emptyGenericType.instantiations = {}; @@ -2029,12 +2030,7 @@ namespace ts { writeUnionOrIntersectionType(type, flags); } else if (type.flags & TypeFlags.Anonymous) { - if (type === nothingType) { - writer.writeKeyword("nothing"); - } - else { - writeAnonymousType(type, flags); - } + writeAnonymousType(type, flags); } else if (type.flags & TypeFlags.StringLiteral) { writer.writeStringLiteral(`"${escapeString((type).text)}"`); @@ -2884,6 +2880,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) { @@ -2915,8 +2915,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) { @@ -2938,13 +2937,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 @@ -3215,7 +3214,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; } @@ -3670,6 +3671,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 +5007,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 +5048,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 +5068,7 @@ namespace ts { if (typeSet.length === 0) { return typeSet.containsNull ? nullType : typeSet.containsUndefined ? undefinedType : - nothingType; + neverType; } else if (typeSet.length === 1) { return typeSet[0]; @@ -5150,7 +5152,7 @@ namespace ts { 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; } @@ -5214,6 +5216,8 @@ namespace ts { return undefinedType; case SyntaxKind.NullKeyword: return nullType; + case SyntaxKind.NeverKeyword: + return neverType; case SyntaxKind.ThisType: case SyntaxKind.ThisKeyword: return getTypeFromThisTypeNode(node); @@ -5859,28 +5863,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) { @@ -7485,7 +7489,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 +7506,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) { @@ -7614,15 +7618,16 @@ 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; - 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 +7715,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 +7725,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 +7947,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 { @@ -8092,11 +8097,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; @@ -8344,7 +8349,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)) { @@ -9919,7 +9924,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); @@ -9936,7 +9942,7 @@ namespace ts { return propType; } } - return getFlowTypeOfReference(node, propType, propType); + return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true); } function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean { @@ -11455,6 +11461,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)) { @@ -11547,6 +11559,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. @@ -11555,12 +11570,9 @@ namespace ts { error(func, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type); return unknownType; } - return promiseType; } - else { - return voidType; - } + return voidType; } } // When yield/return statements are contextually typed we allow the return type to be a union type. @@ -11640,7 +11652,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); } } @@ -11648,6 +11660,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); @@ -11683,7 +11698,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 @@ -13394,7 +13412,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); } @@ -14747,7 +14765,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 +14777,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; } } @@ -14820,7 +14838,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) { @@ -18284,7 +18302,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) { @@ -18293,9 +18311,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, @@ -18517,8 +18532,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/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index c24135ba52e..397b135bf23 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); @@ -1129,7 +1130,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) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 899b4292f04..4eb16c5bcb0 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 @@ -1751,6 +1747,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 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 877a1a330fe..81f88098464 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -164,6 +164,7 @@ namespace ts { IsKeyword, ModuleKeyword, NamespaceKeyword, + NeverKeyword, ReadonlyKeyword, RequireKeyword, NumberKeyword, @@ -1772,6 +1773,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; @@ -2170,11 +2172,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, 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; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index d6035aaa026..c237734e1df 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1968,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}.`); } } @@ -1989,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) { @@ -2021,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; @@ -2033,11 +2047,11 @@ namespace FourSlash { } } - public printScriptLexicalStructureItems() { + public printNavigationBar() { 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]; @@ -3029,19 +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 navigationBarChildItem(parent: string, name: string, kind: string) { + this.state.verifyNavigationBarChildItem(parent, name, kind); } public navigationItemsListCount(count: number, searchValue: string, matchKind?: string) { @@ -3234,8 +3252,8 @@ namespace FourSlashInterface { this.state.printNavigationItems(searchValue); } - public printScriptLexicalStructureItems() { - this.state.printScriptLexicalStructureItems(); + public printNavigationBar() { + this.state.printNavigationBar(); } public printReferences() { 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 +} diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 7931f1ea733..20b20356907 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/src/services/navigationBar.ts b/src/services/navigationBar.ts index d83d0738ec8..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); @@ -176,6 +176,7 @@ namespace ts.NavigationBar { break; case SyntaxKind.EnumDeclaration: case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: topLevelNodes.push(node); break; @@ -197,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; } @@ -237,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); @@ -274,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); @@ -382,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; } @@ -422,6 +423,9 @@ namespace ts.NavigationBar { case SyntaxKind.FunctionDeclaration: return createFunctionItem(node); + + case SyntaxKind.TypeAliasDeclaration: + return createTypeAliasItem(node); } return undefined; @@ -433,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); @@ -447,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, @@ -461,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)], @@ -474,9 +478,18 @@ 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); + const childItems = getItemsWorker(sortNodes((node.body).statements), createChildItem); let scriptElementKind: string; let memberFunctionName: string; if (node.kind === SyntaxKind.MethodDeclaration) { @@ -500,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, @@ -522,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))); } @@ -537,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, @@ -549,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, @@ -560,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, @@ -578,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)); } @@ -606,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, @@ -643,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; } @@ -711,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 { @@ -724,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; } diff --git a/src/services/services.ts b/src/services/services.ts index b2f7eb4bdba..ef25fae7bba 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 { @@ -904,6 +908,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 +935,7 @@ namespace ts { break; case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.EnumDeclaration: @@ -944,22 +950,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)) { @@ -967,11 +960,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: @@ -1008,6 +1005,9 @@ namespace ts { } } break; + + default: + forEachChild(node, visit); } } } @@ -2770,7 +2770,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 +2782,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: @@ -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); } @@ -4564,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); } } @@ -4645,7 +4649,7 @@ namespace ts { const sourceFile = getValidSourceFile(fileName); const node = getTouchingPropertyName(sourceFile, position); - if (!node) { + if (node === sourceFile) { return undefined; } @@ -4802,18 +4806,6 @@ namespace ts { const sourceFile = getValidSourceFile(fileName); - const node = getTouchingPropertyName(sourceFile, position); - if (!node) { - return undefined; - } - - // Labels - if (isJumpStatementTarget(node)) { - const labelName = (node).text; - const label = getTargetLabel((node.parent), (node).text); - return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; - } - /// Triple slash reference comments const comment = findReferenceInPosition(sourceFile.referencedFiles, position); if (comment) { @@ -4823,6 +4815,7 @@ namespace ts { } return undefined; } + // Type reference directives const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); if (typeReferenceDirective) { @@ -4833,6 +4826,18 @@ namespace ts { return undefined; } + const node = getTouchingPropertyName(sourceFile, position); + if (node === sourceFile) { + return undefined; + } + + // Labels + if (isJumpStatementTarget(node)) { + const labelName = (node).text; + const label = getTargetLabel((node.parent), (node).text); + return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; + } + const typeChecker = program.getTypeChecker(); let symbol = typeChecker.getSymbolAtLocation(node); @@ -4891,7 +4896,7 @@ namespace ts { const sourceFile = getValidSourceFile(fileName); const node = getTouchingPropertyName(sourceFile, position); - if (!node) { + if (node === sourceFile) { return undefined; } @@ -5628,7 +5633,7 @@ namespace ts { const sourceFile = getValidSourceFile(fileName); const node = getTouchingPropertyName(sourceFile, position); - if (!node) { + if (node === sourceFile) { return undefined; } @@ -6795,7 +6800,7 @@ namespace ts { // Get node at the location const node = getTouchingPropertyName(sourceFile, startPos); - if (!node) { + if (node === sourceFile) { return; } 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/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/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 { diff --git a/tests/baselines/reference/doubleUnderStringLiteralAssignability.errors.txt b/tests/baselines/reference/doubleUnderStringLiteralAssignability.errors.txt new file mode 100644 index 00000000000..c4226a83bfc --- /dev/null +++ b/tests/baselines/reference/doubleUnderStringLiteralAssignability.errors.txt @@ -0,0 +1,11 @@ +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"'. + 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 new file mode 100644 index 00000000000..baf2b521948 --- /dev/null +++ b/tests/baselines/reference/doubleUnderStringLiteralAssignability.js @@ -0,0 +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/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/fallbackToBindingPatternForTypeInference.js b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.js new file mode 100644 index 00000000000..1c02ae83982 --- /dev/null +++ b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.js @@ -0,0 +1,30 @@ +//// [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'); +trans(({a, b = 10}) => a); + + +//// [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'; +}); +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 new file mode 100644 index 00000000000..f57b234f39f --- /dev/null +++ b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.symbols @@ -0,0 +1,34 @@ +=== 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)) + +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 new file mode 100644 index 00000000000..fc41085098a --- /dev/null +++ b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types @@ -0,0 +1,49 @@ +=== 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 + +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/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/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/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..74057195c64 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: { @@ -15,9 +13,7 @@ tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWith } class C { - x?: number; // error - ~ -!!! error TS1112: A class member cannot be declared optional. + x?: number; // ok } interface I2 { @@ -25,9 +21,7 @@ tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWith } class C2 { - x?: T; // error - ~ -!!! error TS1112: A class member cannot be declared optional. + 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/baselines/reference/optionalMethods.js b/tests/baselines/reference/optionalMethods.js new file mode 100644 index 00000000000..42decf512e4 --- /dev/null +++ b/tests/baselines/reference/optionalMethods.js @@ -0,0 +1,147 @@ +//// [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; + c? = 2; + constructor(public d?: number, public e = 10) {} + f() { + return 1; + } + g?(): number; // Body of optional method can be omitted + h?() { + return 2; + } +} + +function test2(x: Bar) { + x.a; + x.b; + x.c; + x.d; + x.e; + 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; +} + +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; + 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(d, e) { + if (e === void 0) { e = 10; } + this.d = d; + this.e = e; + this.c = 2; + } + Bar.prototype.f = function () { + return 1; + }; + Bar.prototype.h = function () { + return 2; + }; + return Bar; +}()); +function test2(x) { + x.a; + x.b; + x.c; + x.d; + x.e; + 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; +} +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 new file mode 100644 index 00000000000..55c5ec958da --- /dev/null +++ b/tests/baselines/reference/optionalMethods.symbols @@ -0,0 +1,203 @@ +=== 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)) + + 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, 22, 52)) + + return 1; + } + g?(): number; // Body of optional method can be omitted +>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5)) + + h?() { +>h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17)) + + return 2; + } +} + +function test2(x: Bar) { +>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, 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, 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, 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, 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, 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, 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, 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, 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, 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 new file mode 100644 index 00000000000..70fda27c012 --- /dev/null +++ b/tests/baselines/reference/optionalMethods.types @@ -0,0 +1,226 @@ +=== 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 + + c? = 2; +>c : number | undefined +>2 : number + + constructor(public d?: number, public e = 10) {} +>d : number | undefined +>e : number +>10 : number + + 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.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 +>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 +} + +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/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 diff --git a/tests/cases/compiler/doubleUnderStringLiteralAssignability.ts b/tests/cases/compiler/doubleUnderStringLiteralAssignability.ts new file mode 100644 index 00000000000..4a1ae75164c --- /dev/null +++ b/tests/cases/compiler/doubleUnderStringLiteralAssignability.ts @@ -0,0 +1,4 @@ +var shouldBeOk: '__dunder' = '__dunder'; +var bad: '__dunder' = 'no_dunder'; +var okok: '___thunder' = '___thunder'; +var alsoOk: '_sunder' = '_sunder'; diff --git a/tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts b/tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts new file mode 100644 index 00000000000..9aa979c1020 --- /dev/null +++ b/tests/cases/compiler/fallbackToBindingPatternForTypeInference.ts @@ -0,0 +1,6 @@ +declare function trans(f: (x: T) => string): number; +trans(({a}) => a); +trans(([b,c]) => 'foo'); +trans(({d: [e,f]}) => 'foo'); +trans(([{g},{h}]) => 'foo'); +trans(({a, b = 10}) => a); diff --git a/tests/cases/conformance/types/namedTypes/optionalMethods.ts b/tests/cases/conformance/types/namedTypes/optionalMethods.ts new file mode 100644 index 00000000000..932521425f9 --- /dev/null +++ b/tests/cases/conformance/types/namedTypes/optionalMethods.ts @@ -0,0 +1,58 @@ +// @strictNullChecks: true +// @declaration: 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; + c? = 2; + constructor(public d?: number, public e = 10) {} + f() { + return 1; + } + g?(): number; // Body of optional method can be omitted + h?() { + return 2; + } +} + +function test2(x: Bar) { + x.a; + x.b; + x.c; + x.d; + x.e; + 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; +} + +class Base { + a?: number; + f?(): number; +} + +class Derived extends Base { + a = 1; + f(): number { return 1; } +} 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 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 = { diff --git a/tests/cases/fourslash/declarationExpressions.ts b/tests/cases/fourslash/declarationExpressions.ts new file mode 100644 index 00000000000..7f2a64d8ecf --- /dev/null +++ b/tests/cases/fourslash/declarationExpressions.ts @@ -0,0 +1,30 @@ +/// + +////class A {} +////const B = class C { +//// public x; +////}; +////function D() {} +////const E = function F() {} +////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"); +} + +navExact("A", "class"); +navExact("B", "const"); +navExact("C", "class"); +navExact("x", "property"); + +navExact("D", "function"); +navExact("E", "const"); +navExact("F", "function") + +navExact("inner", "function"); + +navExact("fun", "function"); +navExact("cls", "class"); +navExact("prop", "property"); 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/formatArrayLiteralExpression.ts b/tests/cases/fourslash/formatArrayLiteralExpression.ts new file mode 100644 index 00000000000..9c2224f8414 --- /dev/null +++ b/tests/cases/fourslash/formatArrayLiteralExpression.ts @@ -0,0 +1,45 @@ +/// + +////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', 'carne asada', 'tinga de res', 'tinga de pollo'], /*8*/ +//// Pie: 'pie' +//// }];/*9*/ + +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(" Burrito: ['burrito', 'carne asada', 'tinga de res', 'tinga de pollo'],"); +goTo.marker("9"); +verify.currentLineContentIs(" }];"); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 48d69f0a85e..08883f163f2 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -175,8 +175,9 @@ 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): 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; occurrencesAtPositionContains(range: Range, isWriteAccess?: boolean): void; @@ -236,6 +237,7 @@ declare namespace FourSlashInterface { printBreakpointAtCurrentLocation(): void; printNameOrDottedNameSpans(pos: number): void; printErrorList(): void; + printNavigationBar(): void; printNavigationItems(searchValue?: string): void; printScriptLexicalStructureItems(): void; printReferences(): void; diff --git a/tests/cases/fourslash/getNavigationBarItems.ts b/tests/cases/fourslash/getNavigationBarItems.ts new file mode 100644 index 00000000000..8e9b8de5b05 --- /dev/null +++ b/tests/cases/fourslash/getNavigationBarItems.ts @@ -0,0 +1,11 @@ +/// + +////class C { +//// foo; +//// ["bar"]: string; +////} + +verify.navigationBarCount(3); +verify.navigationBarContains("C", "class"); +verify.navigationBarChildItem("C", "[\"bar\"]", "property"); +verify.navigationBarChildItem("C", "foo", "property"); diff --git a/tests/cases/fourslash/hoverOverComment.ts b/tests/cases/fourslash/hoverOverComment.ts new file mode 100644 index 00000000000..a9549a932f7 --- /dev/null +++ b/tests/cases/fourslash/hoverOverComment.ts @@ -0,0 +1,11 @@ +/// + +////export function f() {} +//////foo +/////**///moo + +goTo.marker(); +verify.quickInfoIs(""); +verify.verifyDefinitionsName("", ""); +verify.typeDefinitionCountIs(0); +verify.referencesCountIs(0); 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/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"); 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,