From 3b8ad5c870d63d1f3577786f412bdb1d9915155d Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 17 Jun 2020 20:50:19 +0800 Subject: [PATCH 1/3] Add outlining spans for call expression or arrow body --- src/services/outliningElementsCollector.ts | 25 +++++++++++++++++++ .../fourslash/outliningSpansForArguments.ts | 18 +++++++++++++ .../outliningSpansForArrowFunctionBody.ts | 15 +++++++++++ 3 files changed, 58 insertions(+) create mode 100644 tests/cases/fourslash/outliningSpansForArguments.ts create mode 100644 tests/cases/fourslash/outliningSpansForArrowFunctionBody.ts diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 6830a6e0b40..a001d9c68f2 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -227,6 +227,31 @@ namespace ts.OutliningElementsCollector { return spanForTemplateLiteral(n); case SyntaxKind.ArrayBindingPattern: return spanForNode(n, /*autoCollapse*/ false, /*useFullStart*/ !isBindingElement(n.parent), SyntaxKind.OpenBracketToken); + case SyntaxKind.ArrowFunction: + return spanForArrowFunction(n); + case SyntaxKind.CallExpression: + return spanForCallExpression(n); + } + + function spanForCallExpression(node: CallExpression): OutliningSpan | undefined { + if (!node.arguments.length) { + return undefined; + } + const openToken = findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile); + const closeToken = findChildOfKind(node, SyntaxKind.CloseParenToken, sourceFile); + if (!openToken || !closeToken || positionsAreOnSameLine(openToken.pos, closeToken.pos, sourceFile)) { + return undefined; + } + + return spanBetweenTokens(openToken, closeToken, node, sourceFile, /*autoCollapse*/ false, /*useFullStart*/ true); + } + + function spanForArrowFunction(node: ArrowFunction): OutliningSpan | undefined { + if (isBlock(node.body) || positionsAreOnSameLine(node.body.getFullStart(), node.body.getEnd(), sourceFile)) { + return undefined; + } + const textSpan = createTextSpanFromBounds(node.body.getFullStart(), node.body.getEnd()); + return createOutliningSpan(textSpan, OutliningSpanKind.Code, createTextSpanFromNode(node)); } function spanForJSXElement(node: JsxElement): OutliningSpan | undefined { diff --git a/tests/cases/fourslash/outliningSpansForArguments.ts b/tests/cases/fourslash/outliningSpansForArguments.ts new file mode 100644 index 00000000000..56c3c21e77a --- /dev/null +++ b/tests/cases/fourslash/outliningSpansForArguments.ts @@ -0,0 +1,18 @@ +/// + +//// console.log(123, 456)l; +//// console.log( +//// ); +//// console.log[|( +//// 123, 456 +//// )|]; +//// console.log[|( +//// 123, +//// 456 +//// )|]; +//// () =>[| console.log[|( +//// 123, +//// 456 +//// )|]|]; + +verify.outliningSpansInCurrentFile(test.ranges()); diff --git a/tests/cases/fourslash/outliningSpansForArrowFunctionBody.ts b/tests/cases/fourslash/outliningSpansForArrowFunctionBody.ts new file mode 100644 index 00000000000..7dfc6e8ec27 --- /dev/null +++ b/tests/cases/fourslash/outliningSpansForArrowFunctionBody.ts @@ -0,0 +1,15 @@ +/// + +//// () => 42; +//// () => ( 42 ); +//// () =>[| { +//// 42 +//// }|]; +//// () =>[| ( +//// 42 +//// )|]; +//// () =>[| "foo" + +//// "bar" + +//// "baz"|]; + +verify.outliningSpansInCurrentFile(test.ranges()); From 98a74ddfe8b1cc20cafdb319c93d79024ca015dc Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 17 Jun 2020 22:41:08 +0800 Subject: [PATCH 2/3] Update baseline --- tests/cases/fourslash/getOutliningSpans.ts | 4 +- .../getOutliningSpansDepthChainedCalls.ts | 144 +++++++++--------- .../fourslash/outliningSpansForFunction.ts | 34 ++--- 3 files changed, 91 insertions(+), 91 deletions(-) diff --git a/tests/cases/fourslash/getOutliningSpans.ts b/tests/cases/fourslash/getOutliningSpans.ts index bec0f4f0d3b..f8bc10ad955 100644 --- a/tests/cases/fourslash/getOutliningSpans.ts +++ b/tests/cases/fourslash/getOutliningSpans.ts @@ -106,14 +106,14 @@ ////function f(x: number[], y: number[])[| { //// return 3; ////}|] -////f( +////f[|( ////// single line array literal span won't render in VS //// [|[0]|], //// [|[ //// 1, //// 2 //// ]|] -////); +////)|]; verify.outliningSpansInCurrentFile(test.ranges(), "code"); diff --git a/tests/cases/fourslash/getOutliningSpansDepthChainedCalls.ts b/tests/cases/fourslash/getOutliningSpansDepthChainedCalls.ts index 9fc8c50dd70..2dc01223c9a 100644 --- a/tests/cases/fourslash/getOutliningSpansDepthChainedCalls.ts +++ b/tests/cases/fourslash/getOutliningSpansDepthChainedCalls.ts @@ -4,113 +4,113 @@ ////declare var router: any; ////router -//// .get("/", async(ctx) =>[|{ +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) -//// .get("/", async(ctx) =>[|{ +//// }|])|] +//// .get[|("/", async(ctx) =>[|{ //// ctx.body = "base"; -//// }|]) -//// .post("/a", async(ctx) =>[|{ +//// }|])|] +//// .post[|("/a", async(ctx) =>[|{ //// //a -//// }|]) +//// }|])|] verify.outliningSpansInCurrentFile(test.ranges()); diff --git a/tests/cases/fourslash/outliningSpansForFunction.ts b/tests/cases/fourslash/outliningSpansForFunction.ts index f46886b7306..4fdf10f2c96 100644 --- a/tests/cases/fourslash/outliningSpansForFunction.ts +++ b/tests/cases/fourslash/outliningSpansForFunction.ts @@ -5,33 +5,33 @@ //// b: number ////) => { //// return a + b; -////}|] -///// -////(a: number, b: number) => [|{ +////}|]; +//// +////(a: number, b: number) =>[| { //// return a + b; -////}|] +////}|]; //// ////const f1 = function[| ( //// a: number //// b: number ////) { //// return a + b; -////}|] +////}|]; //// ////const f2 = function (a: number, b: number)[| { //// return a + b; -////}|] +////}|]; //// ////function f3[| ( //// a: number //// b: number ////) { //// return a + b; -////}|] +////}|]; //// ////function f4(a: number, b: number)[| { //// return a + b; -////}|] +////}|]; //// ////class Foo[| { //// constructor[|( @@ -52,33 +52,33 @@ //// m1(a: number, b: number)[| { //// return a + b; //// }|] -////}|] +////}|]; //// ////declare function foo(props: any): void; -////foo( +////foo[|( //// a =>[| { //// //// }|] -////) +////)|]; //// -////foo( +////foo[|( //// (a) =>[| { //// //// }|] -////) +////)|]; //// -////foo( +////foo[|( //// (a, b, c) =>[| { //// //// }|] -////) +////)|]; //// -////foo([| +////foo[|([| //// (a, //// b, //// c) => { //// //// }|] -////) +////)|]; verify.outliningSpansInCurrentFile(test.ranges()); From 4d57d591d2a66d1e2b71ad40028a03bbc018ef04 Mon Sep 17 00:00:00 2001 From: kingwl Date: Thu, 18 Jun 2020 10:33:17 +0800 Subject: [PATCH 3/3] Avoid semi --- .../fourslash/outliningSpansForFunction.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/cases/fourslash/outliningSpansForFunction.ts b/tests/cases/fourslash/outliningSpansForFunction.ts index 4fdf10f2c96..e89ecd6f843 100644 --- a/tests/cases/fourslash/outliningSpansForFunction.ts +++ b/tests/cases/fourslash/outliningSpansForFunction.ts @@ -9,29 +9,29 @@ //// ////(a: number, b: number) =>[| { //// return a + b; -////}|]; +////}|] //// ////const f1 = function[| ( //// a: number //// b: number ////) { //// return a + b; -////}|]; +////}|] //// ////const f2 = function (a: number, b: number)[| { //// return a + b; -////}|]; +////}|] //// ////function f3[| ( //// a: number //// b: number ////) { //// return a + b; -////}|]; +////}|] //// ////function f4(a: number, b: number)[| { //// return a + b; -////}|]; +////}|] //// ////class Foo[| { //// constructor[|( @@ -52,26 +52,26 @@ //// m1(a: number, b: number)[| { //// return a + b; //// }|] -////}|]; +////}|] //// ////declare function foo(props: any): void; ////foo[|( //// a =>[| { //// //// }|] -////)|]; +////)|] //// ////foo[|( //// (a) =>[| { //// //// }|] -////)|]; +////)|] //// ////foo[|( //// (a, b, c) =>[| { //// //// }|] -////)|]; +////)|] //// ////foo[|([| //// (a, @@ -79,6 +79,6 @@ //// c) => { //// //// }|] -////)|]; +////)|] verify.outliningSpansInCurrentFile(test.ranges());