diff --git a/.travis.yml b/.travis.yml index 4a99aaf2237..27b14739d8b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ matrix: branches: only: - master + - release-2.5 install: - npm uninstall typescript --no-save diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6df6b1f9ce1..6febaf0052d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5657,17 +5657,12 @@ namespace ts { else { // Combinations of function, class, enum and module let members = emptySymbols; - let constructSignatures: Signature[] = emptyArray; let stringIndexInfo: IndexInfo = undefined; if (symbol.exports) { members = getExportsOfSymbol(symbol); } if (symbol.flags & SymbolFlags.Class) { const classType = getDeclaredTypeOfClassOrInterface(symbol); - constructSignatures = getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Constructor)); - if (!constructSignatures.length) { - constructSignatures = getDefaultConstructSignatures(classType); - } const baseConstructorType = getBaseConstructorTypeOfClass(classType); if (baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.TypeVariable)) { members = createSymbolTable(getNamedMembers(members)); @@ -5678,7 +5673,7 @@ namespace ts { } } const numberIndexInfo = symbol.flags & SymbolFlags.Enum ? enumNumberIndexInfo : undefined; - setStructuredTypeMembers(type, members, emptyArray, constructSignatures, stringIndexInfo, numberIndexInfo); + setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); // We resolve the members before computing the signatures because a signature may use // typeof with a qualified name expression that circularly references the type we are // in the process of resolving (see issue #6072). The temporarily empty signature list @@ -5686,6 +5681,15 @@ namespace ts { if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) { (type).callSignatures = getSignaturesOfSymbol(symbol); } + // And likewise for construct signatures for classes + if (symbol.flags & SymbolFlags.Class) { + const classType = getDeclaredTypeOfClassOrInterface(symbol); + let constructSignatures = getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Constructor)); + if (!constructSignatures.length) { + constructSignatures = getDefaultConstructSignatures(classType); + } + (type).constructSignatures = constructSignatures; + } } } diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 5099f8b66bd..e0d99d1d271 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -1,13 +1,20 @@ /* @internal */ namespace ts.OutliningElementsCollector { + const collapseText = "..."; + const maxDepth = 20; + export function collectElements(sourceFile: SourceFile, cancellationToken: CancellationToken): OutliningSpan[] { const elements: OutliningSpan[] = []; - const collapseText = "..."; + let depth = 0; - function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean) { + walk(sourceFile); + return elements; + + /** If useFullStart is true, then the collapsing span includes leading whitespace, including linebreaks. */ + function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean, useFullStart: boolean) { if (hintSpanNode && startElement && endElement) { const span: OutliningSpan = { - textSpan: createTextSpanFromBounds(startElement.pos, endElement.end), + textSpan: createTextSpanFromBounds(useFullStart ? startElement.getFullStart() : startElement.getStart(), endElement.getEnd()), hintSpan: createTextSpanFromNode(hintSpanNode, sourceFile), bannerText: collapseText, autoCollapse, @@ -82,8 +89,6 @@ namespace ts.OutliningElementsCollector { return isFunctionBlock(node) && node.parent.kind !== SyntaxKind.ArrowFunction; } - let depth = 0; - const maxDepth = 20; function walk(n: Node): void { cancellationToken.throwIfCancellationRequested(); if (depth > maxDepth) { @@ -113,7 +118,7 @@ namespace ts.OutliningElementsCollector { parent.kind === SyntaxKind.WithStatement || parent.kind === SyntaxKind.CatchClause) { - addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n)); + addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true); break; } @@ -121,13 +126,13 @@ namespace ts.OutliningElementsCollector { // Could be the try-block, or the finally-block. const tryStatement = parent; if (tryStatement.tryBlock === n) { - addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n)); + addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true); break; } else if (tryStatement.finallyBlock === n) { const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); if (finallyKeyword) { - addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n)); + addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true); break; } } @@ -151,31 +156,35 @@ namespace ts.OutliningElementsCollector { case SyntaxKind.ModuleBlock: { const openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile); const closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile); - addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n)); + addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true); break; } case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.EnumDeclaration: - case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.CaseBlock: { const openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile); const closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile); - addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n)); + addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true); break; } + // If the block has no leading keywords and is inside an array literal, + // we only want to collapse the span of the block. + // Otherwise, the collapsed section will include the end of the previous line. + case SyntaxKind.ObjectLiteralExpression: + const openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile); + const closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile); + addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ !isArrayLiteralExpression(n.parent)); + break; case SyntaxKind.ArrayLiteralExpression: const openBracket = findChildOfKind(n, SyntaxKind.OpenBracketToken, sourceFile); const closeBracket = findChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile); - addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n)); + addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n), /*useFullStart*/ !isArrayLiteralExpression(n.parent)); break; } depth++; forEachChild(n, walk); depth--; } - - walk(sourceFile); - return elements; } } \ No newline at end of file diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 303bb8395ee..05c451cc3f3 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -111,124 +111,123 @@ namespace ts.SymbolDisplay { let signature: Signature; type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol.exportSymbol || symbol, location); - if (type) { - if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { - const right = (location.parent).name; - // Either the location is on the right of a property access, or on the left and the right is missing - if (right === location || (right && right.getFullWidth() === 0)) { - location = location.parent; + + if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { + const right = (location.parent).name; + // Either the location is on the right of a property access, or on the left and the right is missing + if (right === location || (right && right.getFullWidth() === 0)) { + location = location.parent; + } + } + + // try get the call/construct signature from the type if it matches + let callExpressionLike: CallExpression | NewExpression | JsxOpeningLikeElement; + if (isCallOrNewExpression(location)) { + callExpressionLike = location; + } + else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) { + callExpressionLike = location.parent; + } + else if (location.parent && isJsxOpeningLikeElement(location.parent) && isFunctionLike(symbol.valueDeclaration)) { + callExpressionLike = location.parent; + } + + if (callExpressionLike) { + const candidateSignatures: Signature[] = []; + signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures); + if (!signature && candidateSignatures.length) { + // Use the first candidate: + signature = candidateSignatures[0]; + } + + const useConstructSignatures = callExpressionLike.kind === SyntaxKind.NewExpression || (isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === SyntaxKind.SuperKeyword); + + const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); + + if (!contains(allSignatures, signature.target) && !contains(allSignatures, signature)) { + // Get the first signature if there is one -- allSignatures may contain + // either the original signature or its target, so check for either + signature = allSignatures.length ? allSignatures[0] : undefined; + } + + if (signature) { + if (useConstructSignatures && (symbolFlags & SymbolFlags.Class)) { + // Constructor + symbolKind = ScriptElementKind.constructorImplementationElement; + addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); } - } - - // try get the call/construct signature from the type if it matches - let callExpressionLike: CallExpression | NewExpression | JsxOpeningLikeElement; - if (isCallOrNewExpression(location)) { - callExpressionLike = location; - } - else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) { - callExpressionLike = location.parent; - } - else if (location.parent && isJsxOpeningLikeElement(location.parent) && isFunctionLike(symbol.valueDeclaration)) { - callExpressionLike = location.parent; - } - - if (callExpressionLike) { - const candidateSignatures: Signature[] = []; - signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures); - if (!signature && candidateSignatures.length) { - // Use the first candidate: - signature = candidateSignatures[0]; - } - - const useConstructSignatures = callExpressionLike.kind === SyntaxKind.NewExpression || (isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === SyntaxKind.SuperKeyword); - - const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); - - if (!contains(allSignatures, signature.target) && !contains(allSignatures, signature)) { - // Get the first signature if there is one -- allSignatures may contain - // either the original signature or its target, so check for either - signature = allSignatures.length ? allSignatures[0] : undefined; - } - - if (signature) { - if (useConstructSignatures && (symbolFlags & SymbolFlags.Class)) { - // Constructor - symbolKind = ScriptElementKind.constructorImplementationElement; - addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); + else if (symbolFlags & SymbolFlags.Alias) { + symbolKind = ScriptElementKind.alias; + pushTypePart(symbolKind); + displayParts.push(spacePart()); + if (useConstructSignatures) { + displayParts.push(keywordPart(SyntaxKind.NewKeyword)); + displayParts.push(spacePart()); } - else if (symbolFlags & SymbolFlags.Alias) { - symbolKind = ScriptElementKind.alias; - pushTypePart(symbolKind); + addFullSymbolName(symbol); + } + else { + addPrefixForAnyFunctionOrVar(symbol, symbolKind); + } + + switch (symbolKind) { + case ScriptElementKind.jsxAttribute: + case ScriptElementKind.memberVariableElement: + case ScriptElementKind.variableElement: + case ScriptElementKind.constElement: + case ScriptElementKind.letElement: + case ScriptElementKind.parameterElement: + case ScriptElementKind.localVariableElement: + // If it is call or construct signature of lambda's write type name + displayParts.push(punctuationPart(SyntaxKind.ColonToken)); displayParts.push(spacePart()); if (useConstructSignatures) { displayParts.push(keywordPart(SyntaxKind.NewKeyword)); displayParts.push(spacePart()); } - addFullSymbolName(symbol); - } - else { - addPrefixForAnyFunctionOrVar(symbol, symbolKind); - } + if (!(type.flags & TypeFlags.Object && (type).objectFlags & ObjectFlags.Anonymous) && type.symbol) { + addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments)); + } + addSignatureDisplayParts(signature, allSignatures, TypeFormatFlags.WriteArrowStyleSignature); + break; - switch (symbolKind) { - case ScriptElementKind.jsxAttribute: - case ScriptElementKind.memberVariableElement: - case ScriptElementKind.variableElement: - case ScriptElementKind.constElement: - case ScriptElementKind.letElement: - case ScriptElementKind.parameterElement: - case ScriptElementKind.localVariableElement: - // If it is call or construct signature of lambda's write type name - displayParts.push(punctuationPart(SyntaxKind.ColonToken)); - displayParts.push(spacePart()); - if (useConstructSignatures) { - displayParts.push(keywordPart(SyntaxKind.NewKeyword)); - displayParts.push(spacePart()); - } - if (!(type.flags & TypeFlags.Object && (type).objectFlags & ObjectFlags.Anonymous) && type.symbol) { - addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments)); - } - addSignatureDisplayParts(signature, allSignatures, TypeFormatFlags.WriteArrowStyleSignature); - break; - - default: - // Just signature - addSignatureDisplayParts(signature, allSignatures); - } - hasAddedSymbolInfo = true; + default: + // Just signature + addSignatureDisplayParts(signature, allSignatures); } + hasAddedSymbolInfo = true; } - else if ((isNameOfFunctionDeclaration(location) && !(symbolFlags & SymbolFlags.Accessor)) || // name of function declaration - (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; - // Use function declaration to write the signatures only if the symbol corresponding to this declaration - const locationIsSymbolDeclaration = find(symbol.declarations, declaration => - declaration === (location.kind === SyntaxKind.ConstructorKeyword ? functionDeclaration.parent : functionDeclaration)); + } + else if ((isNameOfFunctionDeclaration(location) && !(symbolFlags & SymbolFlags.Accessor)) || // name of function declaration + (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; + // Use function declaration to write the signatures only if the symbol corresponding to this declaration + const locationIsSymbolDeclaration = find(symbol.declarations, declaration => + declaration === (location.kind === SyntaxKind.ConstructorKeyword ? functionDeclaration.parent : functionDeclaration)); - if (locationIsSymbolDeclaration) { - const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); - if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { - signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); - } - else { - signature = allSignatures[0]; - } - - if (functionDeclaration.kind === SyntaxKind.Constructor) { - // show (constructor) Type(...) signature - symbolKind = ScriptElementKind.constructorImplementationElement; - addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); - } - else { - // (function/method) symbol(..signature) - addPrefixForAnyFunctionOrVar(functionDeclaration.kind === SyntaxKind.CallSignature && - !(type.symbol.flags & SymbolFlags.TypeLiteral || type.symbol.flags & SymbolFlags.ObjectLiteral) ? type.symbol : symbol, symbolKind); - } - - addSignatureDisplayParts(signature, allSignatures); - hasAddedSymbolInfo = true; + if (locationIsSymbolDeclaration) { + const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); + if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { + signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); } + else { + signature = allSignatures[0]; + } + + if (functionDeclaration.kind === SyntaxKind.Constructor) { + // show (constructor) Type(...) signature + symbolKind = ScriptElementKind.constructorImplementationElement; + addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); + } + else { + // (function/method) symbol(..signature) + addPrefixForAnyFunctionOrVar(functionDeclaration.kind === SyntaxKind.CallSignature && + !(type.symbol.flags & SymbolFlags.TypeLiteral || type.symbol.flags & SymbolFlags.ObjectLiteral) ? type.symbol : symbol, symbolKind); + } + + addSignatureDisplayParts(signature, allSignatures); + hasAddedSymbolInfo = true; } } } @@ -417,7 +416,9 @@ namespace ts.SymbolDisplay { symbolFlags & SymbolFlags.Accessor || symbolKind === ScriptElementKind.memberFunctionElement) { const allSignatures = type.getNonNullableType().getCallSignatures(); - addSignatureDisplayParts(allSignatures[0], allSignatures); + if (allSignatures.length) { + addSignatureDisplayParts(allSignatures[0], allSignatures); + } } } } diff --git a/tests/baselines/reference/cloduleGenericOnSelfMember.js b/tests/baselines/reference/cloduleGenericOnSelfMember.js new file mode 100644 index 00000000000..972651f1045 --- /dev/null +++ b/tests/baselines/reference/cloduleGenericOnSelfMember.js @@ -0,0 +1,42 @@ +//// [cloduleGenericOnSelfMember.ts] +class ServiceBase { + field: T; +} +class Service extends ServiceBase { +} +namespace Service { + export const Base = { + name: "1", + value: 5 + }; +} + +//// [cloduleGenericOnSelfMember.js] +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var ServiceBase = /** @class */ (function () { + function ServiceBase() { + } + return ServiceBase; +}()); +var Service = /** @class */ (function (_super) { + __extends(Service, _super); + function Service() { + return _super !== null && _super.apply(this, arguments) || this; + } + return Service; +}(ServiceBase)); +(function (Service) { + Service.Base = { + name: "1", + value: 5 + }; +})(Service || (Service = {})); diff --git a/tests/baselines/reference/cloduleGenericOnSelfMember.symbols b/tests/baselines/reference/cloduleGenericOnSelfMember.symbols new file mode 100644 index 00000000000..c7e0126fa7a --- /dev/null +++ b/tests/baselines/reference/cloduleGenericOnSelfMember.symbols @@ -0,0 +1,30 @@ +=== tests/cases/compiler/cloduleGenericOnSelfMember.ts === +class ServiceBase { +>ServiceBase : Symbol(ServiceBase, Decl(cloduleGenericOnSelfMember.ts, 0, 0)) +>T : Symbol(T, Decl(cloduleGenericOnSelfMember.ts, 0, 18)) + + field: T; +>field : Symbol(ServiceBase.field, Decl(cloduleGenericOnSelfMember.ts, 0, 22)) +>T : Symbol(T, Decl(cloduleGenericOnSelfMember.ts, 0, 18)) +} +class Service extends ServiceBase { +>Service : Symbol(Service, Decl(cloduleGenericOnSelfMember.ts, 2, 1), Decl(cloduleGenericOnSelfMember.ts, 4, 1)) +>ServiceBase : Symbol(ServiceBase, Decl(cloduleGenericOnSelfMember.ts, 0, 0)) +>Service.Base : Symbol(Service.Base, Decl(cloduleGenericOnSelfMember.ts, 6, 16)) +>Service : Symbol(Service, Decl(cloduleGenericOnSelfMember.ts, 2, 1), Decl(cloduleGenericOnSelfMember.ts, 4, 1)) +>Base : Symbol(Service.Base, Decl(cloduleGenericOnSelfMember.ts, 6, 16)) +} +namespace Service { +>Service : Symbol(Service, Decl(cloduleGenericOnSelfMember.ts, 2, 1), Decl(cloduleGenericOnSelfMember.ts, 4, 1)) + + export const Base = { +>Base : Symbol(Base, Decl(cloduleGenericOnSelfMember.ts, 6, 16)) + + name: "1", +>name : Symbol(name, Decl(cloduleGenericOnSelfMember.ts, 6, 25)) + + value: 5 +>value : Symbol(value, Decl(cloduleGenericOnSelfMember.ts, 7, 18)) + + }; +} diff --git a/tests/baselines/reference/cloduleGenericOnSelfMember.types b/tests/baselines/reference/cloduleGenericOnSelfMember.types new file mode 100644 index 00000000000..87590745c6f --- /dev/null +++ b/tests/baselines/reference/cloduleGenericOnSelfMember.types @@ -0,0 +1,33 @@ +=== tests/cases/compiler/cloduleGenericOnSelfMember.ts === +class ServiceBase { +>ServiceBase : ServiceBase +>T : T + + field: T; +>field : T +>T : T +} +class Service extends ServiceBase { +>Service : Service +>ServiceBase : ServiceBase<{ name: string; value: number; }> +>Service.Base : { name: string; value: number; } +>Service : typeof Service +>Base : { name: string; value: number; } +} +namespace Service { +>Service : typeof Service + + export const Base = { +>Base : { name: string; value: number; } +>{ name: "1", value: 5 } : { name: string; value: number; } + + name: "1", +>name : string +>"1" : "1" + + value: 5 +>value : number +>5 : 5 + + }; +} diff --git a/tests/cases/compiler/cloduleGenericOnSelfMember.ts b/tests/cases/compiler/cloduleGenericOnSelfMember.ts new file mode 100644 index 00000000000..23f0e6af1b6 --- /dev/null +++ b/tests/cases/compiler/cloduleGenericOnSelfMember.ts @@ -0,0 +1,11 @@ +class ServiceBase { + field: T; +} +class Service extends ServiceBase { +} +namespace Service { + export const Base = { + name: "1", + value: 5 + }; +} \ No newline at end of file diff --git a/tests/cases/fourslash/getOutliningForObjectsInArray.ts b/tests/cases/fourslash/getOutliningForObjectsInArray.ts new file mode 100644 index 00000000000..89634224832 --- /dev/null +++ b/tests/cases/fourslash/getOutliningForObjectsInArray.ts @@ -0,0 +1,56 @@ +/// + +// objects in x should generate outlining spans that do not render in VS +//// const x =[| [ +//// [|{ a: 0 }|], +//// [|{ b: 1 }|], +//// [|{ c: 2 }|] +//// ]|]; +//// +// objects in y should generate outlining spans that render as expected +//// const y =[| [ +//// [|{ +//// a: 0 +//// }|], +//// [|{ +//// b: 1 +//// }|], +//// [|{ +//// c: 2 +//// }|] +//// ]|]; +//// +// same behavior for nested arrays +//// const w =[| [ +//// [|[ 0 ]|], +//// [|[ 1 ]|], +//// [|[ 2 ]|] +//// ]|]; +//// +//// const z =[| [ +//// [|[ +//// 0 +//// ]|], +//// [|[ +//// 1 +//// ]|], +//// [|[ +//// 2 +//// ]|] +//// ]|]; +//// +// multiple levels of nesting work as expected +//// const z =[| [ +//// [|[ +//// [|{ hello: 0 }|] +//// ]|], +//// [|[ +//// [|{ hello: 3 }|] +//// ]|], +//// [|[ +//// [|{ hello: 5 }|], +//// [|{ hello: 7 }|] +//// ]|] +//// ]|]; + +verify.outliningSpansInCurrentFile(test.ranges()); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoTypeError.ts b/tests/cases/fourslash/quickInfoTypeError.ts new file mode 100644 index 00000000000..7e0c9b20303 --- /dev/null +++ b/tests/cases/fourslash/quickInfoTypeError.ts @@ -0,0 +1,10 @@ +/// + +////foo({ +//// /**/f: function() {}, +//// f() {} +////}); + +// The symbol indicates that this is a funciton, but the type is `any`. +// Regression test that we don't crash (by trying to get signatures from `any`). +verify.quickInfoAt("", "(method) f");