Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
When function parameters span multiple lines, make the function span …
…start at the `(` (#26907)

* When function parameters span multiple lines, make the function span start at the `(`

* Undo unnecessary change
  • Loading branch information
Andy Hanson authored and RyanCavanaugh committed Apr 25, 2019
1 parent 583edce commit 6e4c150
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 9 deletions.
4 changes: 4 additions & 0 deletions src/compiler/utilities.ts
Expand Up @@ -4330,6 +4330,10 @@ namespace ts {
return positionsAreOnSameLine(range1.end, getStartPositionOfRange(range2, sourceFile), sourceFile);
}

export function isNodeArrayMultiLine(list: NodeArray<Node>, sourceFile: SourceFile): boolean {
return !positionsAreOnSameLine(list.pos, list.end, sourceFile);
}

export function positionsAreOnSameLine(pos1: number, pos2: number, sourceFile: SourceFile) {
return pos1 === pos2 ||
getLineOfLocalPosition(sourceFile, pos1) === getLineOfLocalPosition(sourceFile, pos2);
Expand Down
26 changes: 17 additions & 9 deletions src/services/outliningElementsCollector.ts
Expand Up @@ -153,8 +153,8 @@ namespace ts.OutliningElementsCollector {
function getOutliningSpanForNode(n: Node, sourceFile: SourceFile): OutliningSpan | undefined {
switch (n.kind) {
case SyntaxKind.Block:
if (isFunctionBlock(n)) {
return spanForNode(n.parent, /*autoCollapse*/ n.parent.kind !== SyntaxKind.ArrowFunction);
if (isFunctionLike(n.parent)) {
return functionSpan(n.parent, n as Block, sourceFile);
}
// Check if the block is standalone, or 'attached' to some parent statement.
// If the latter, we want to collapse the block, but consider its hint span
Expand Down Expand Up @@ -225,18 +225,26 @@ namespace ts.OutliningElementsCollector {
return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !isArrayLiteralExpression(node.parent) && !isCallExpression(node.parent), open);
}

function spanForNode(hintSpanNode: Node, autoCollapse = false, useFullStart = true, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken): OutliningSpan | undefined {
function spanForNode(hintSpanNode: Node, autoCollapse = false, useFullStart = true, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken, close: SyntaxKind = open === SyntaxKind.OpenBraceToken ? SyntaxKind.CloseBraceToken : SyntaxKind.CloseBracketToken): OutliningSpan | undefined {
const openToken = findChildOfKind(n, open, sourceFile);
const close = open === SyntaxKind.OpenBraceToken ? SyntaxKind.CloseBraceToken : SyntaxKind.CloseBracketToken;
const closeToken = findChildOfKind(n, close, sourceFile);
if (!openToken || !closeToken) {
return undefined;
}
const textSpan = createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd());
return createOutliningSpan(textSpan, OutliningSpanKind.Code, createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse);
return openToken && closeToken && spanBetweenTokens(openToken, closeToken, hintSpanNode, sourceFile, autoCollapse, useFullStart);
}
}

function functionSpan(node: FunctionLike, body: Block, sourceFile: SourceFile): OutliningSpan | undefined {
const openToken = isNodeArrayMultiLine(node.parameters, sourceFile)
? findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile)
: findChildOfKind(body, SyntaxKind.OpenBraceToken, sourceFile);
const closeToken = findChildOfKind(body, SyntaxKind.CloseBraceToken, sourceFile);
return openToken && closeToken && spanBetweenTokens(openToken, closeToken, node.parent, sourceFile, /*autoCollapse*/ node.parent.kind !== SyntaxKind.ArrowFunction);
}

function spanBetweenTokens(openToken: Node, closeToken: Node, hintSpanNode: Node, sourceFile: SourceFile, autoCollapse = false, useFullStart = true): OutliningSpan {
const textSpan = createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd());
return createOutliningSpan(textSpan, OutliningSpanKind.Code, createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse);
}

function createOutliningSpan(textSpan: TextSpan, kind: OutliningSpanKind, hintSpan: TextSpan = textSpan, autoCollapse = false, bannerText = "..."): OutliningSpan {
return { textSpan, kind, hintSpan, bannerText, autoCollapse };
}
Expand Down
14 changes: 14 additions & 0 deletions tests/cases/fourslash/outliningSpansForFunction.ts
@@ -0,0 +1,14 @@
/// <reference path="fourslash.ts"/>

////function f(x: number, y: number)[| {
//// return x + y;
////}|]
////
////function g[|(
//// x: number,
//// y: number,
////): number {
//// return x + y;
////}|]

verify.outliningSpansInCurrentFile(test.ranges());

0 comments on commit 6e4c150

Please sign in to comment.