Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f1616c3
porting folding
navya9singh Jun 23, 2025
c32bbb7
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Jun 23, 2025
c691b7d
adding all tests
navya9singh Jun 30, 2025
02723d4
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Jun 30, 2025
1938da6
code clean up
navya9singh Jun 30, 2025
86df138
cleanup
navya9singh Jun 30, 2025
37babb6
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Jun 30, 2025
18a2737
adding check for binary expression
navya9singh Jul 1, 2025
b7b020f
addressing pr comments
navya9singh Jul 3, 2025
dd3f93d
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Jul 3, 2025
7435726
fixing test
navya9singh Jul 3, 2025
3527adb
using sourceFile.endOfFileToken
navya9singh Jul 3, 2025
3a1f476
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Jul 7, 2025
08fbeda
addressing pr comments
navya9singh Jul 7, 2025
30f9df7
addressing comments
navya9singh Jul 8, 2025
f68abaa
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Jul 8, 2025
60e21ce
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Jul 15, 2025
356383f
addressing comments
navya9singh Jul 15, 2025
65e981f
adding defined capacity
navya9singh Jul 15, 2025
35ea0dc
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Aug 5, 2025
c849009
addressing comments
navya9singh Aug 5, 2025
276316b
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Nov 6, 2025
404e94f
updating the pr
navya9singh Nov 25, 2025
633bc8b
adding fourslash tests
navya9singh Nov 25, 2025
4737bbd
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Nov 25, 2025
927e872
addressing pr comments
navya9singh Dec 2, 2025
2ba4dcf
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Dec 2, 2025
21cc988
fixing comparison function
navya9singh Dec 2, 2025
2592640
Merge branch 'main' of https://github.com/navya9singh/typescript-go-r…
navya9singh Dec 2, 2025
07d51aa
Porting differences copilot noticed
jakebailey Dec 2, 2025
6a54dbc
Remove spanForNodeWithHintSpan accidental addition
jakebailey Dec 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 78 additions & 7 deletions internal/fourslash/_scripts/convertFourslash.mts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ function parseFourslashStatement(statement: ts.Statement): Cmd[] | undefined {
return [{ kind: "verifyBaselineDiagnostics" }];
case "navigateTo":
return parseVerifyNavigateTo(callExpression.arguments);
case "outliningSpansInCurrentFile":
case "outliningHintSpansInCurrentFile":
return parseOutliningSpansArgs(callExpression.arguments);
}
}
// `goTo....`
Expand Down Expand Up @@ -274,14 +277,26 @@ function parseEditStatement(funcName: string, args: readonly ts.Expression[]): E
const arg = args[0];
if (args[0]) {
let arg0;
if (!(arg0 = getNumericLiteral(arg))) {
console.error(`Expected numeric literal argument in edit.backspace, got ${arg.getText()}`);
return undefined;
if (arg0 = getNumericLiteral(arg)) {
return {
kind: "edit",
goStatement: `f.Backspace(t, ${arg0.text})`,
};
}
// Handle test.marker("").position
if (ts.isPropertyAccessExpression(arg) && arg.name.text === "position") {
const expr = arg.expression;
if (ts.isCallExpression(expr) && expr.expression.getText() === "test.marker") {
if (expr.arguments.length === 1 && ts.isStringLiteralLike(expr.arguments[0])) {
return {
kind: "edit",
goStatement: `f.Backspace(t, 1)`,
};
}
}
}
return {
kind: "edit",
goStatement: `f.Backspace(t, ${arg0.text})`,
};
console.error(`Expected numeric literal or a test marker argument in edit.backspace, got ${arg.getText()}`);
return undefined;
}
return {
kind: "edit",
Expand Down Expand Up @@ -1689,6 +1704,46 @@ function parseBaselineSmartSelection(args: ts.NodeArray<ts.Expression>): Cmd {
};
}

function parseOutliningSpansArgs(args: readonly ts.Expression[]): [VerifyOutliningSpansCmd] | undefined {
if (args.length === 0) {
console.error("Expected at least one argument in verify.outliningSpansInCurrentFile");
return undefined;
}

let spans: string = "";
// Optional second argument for kind filter
let foldingRangeKind: string | undefined;
if (args.length > 1) {
const kindArg = getStringLiteralLike(args[1]);
if (!kindArg) {
console.error(`Expected string literal for outlining kind, got ${args[1].getText()}`);
return undefined;
}
switch (kindArg.text) {
case "comment":
foldingRangeKind = "lsproto.FoldingRangeKindComment";
break;
case "region":
foldingRangeKind = "lsproto.FoldingRangeKindRegion";
break;
case "imports":
foldingRangeKind = "lsproto.FoldingRangeKindImports";
break;
case "code":
break;
default:
console.error(`Unknown folding range kind: ${kindArg.text}`);
return undefined;
}
}

return [{
kind: "verifyOutliningSpans",
spans,
foldingRangeKind,
}];
}

function parseKind(expr: ts.Expression): string | undefined {
if (!ts.isStringLiteral(expr)) {
console.error(`Expected string literal for kind, got ${expr.getText()}`);
Expand Down Expand Up @@ -2126,6 +2181,12 @@ interface VerifyNavToCmd {
args: string[];
}

interface VerifyOutliningSpansCmd {
kind: "verifyOutliningSpans"
spans: string;
foldingRangeKind?: string;
}

type Cmd =
| VerifyCompletionsCmd
| VerifyApplyCodeActionFromCompletionCmd
Expand All @@ -2145,6 +2206,14 @@ type Cmd =
| VerifyImportFixAtPositionCmd
| VerifyDiagnosticsCmd
| VerifyBaselineDiagnosticsCmd;
| VerifyOutliningSpansCmd;

function generateVerifyOutliningSpans({ foldingRangeKind }: VerifyOutliningSpansCmd): string {
if (foldingRangeKind) {
return `f.VerifyOutliningSpans(t, ${foldingRangeKind})`;
}
return `f.VerifyOutliningSpans(t)`;
}

function generateVerifyCompletions({ marker, args, isNewIdentifierLocation, andApplyCodeActionArgs }: VerifyCompletionsCmd): string {
let expectedList: string;
Expand Down Expand Up @@ -2310,6 +2379,8 @@ function generateCmd(cmd: Cmd): string {
return `f.VerifyBaselineNonSuggestionDiagnostics(t)`;
case "verifyNavigateTo":
return generateNavigateTo(cmd);
case "verifyOutliningSpans":
return generateVerifyOutliningSpans(cmd);
default:
let neverCommand: never = cmd;
throw new Error(`Unknown command kind: ${neverCommand as Cmd["kind"]}`);
Expand Down
1 change: 1 addition & 0 deletions internal/fourslash/_scripts/manualTests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ quickInfoForOverloadOnConst1
renameDefaultKeyword
renameForDefaultExport01
tsxCompletion12
OutliningHintSpansForFunction
49 changes: 49 additions & 0 deletions internal/fourslash/fourslash.go
Original file line number Diff line number Diff line change
Expand Up @@ -1444,6 +1444,55 @@ func (f *FourslashTest) VerifyBaselineWorkspaceSymbol(t *testing.T, query string
))
}

func (f *FourslashTest) VerifyOutliningSpans(t *testing.T, foldingRangeKind ...lsproto.FoldingRangeKind) {
params := &lsproto.FoldingRangeParams{
TextDocument: lsproto.TextDocumentIdentifier{
Uri: lsconv.FileNameToDocumentURI(f.activeFilename),
},
}
result := sendRequest(t, f, lsproto.TextDocumentFoldingRangeInfo, params)
if result.FoldingRanges == nil {
t.Fatalf("Nil response received for folding range request")
}

// Extract actual folding ranges from the result and filter by kind if specified
var actualRanges []*lsproto.FoldingRange
if result.FoldingRanges != nil {
actualRanges = *result.FoldingRanges
}
if len(foldingRangeKind) > 0 {
targetKind := foldingRangeKind[0]
var filtered []*lsproto.FoldingRange
for _, r := range actualRanges {
if r.Kind != nil && *r.Kind == targetKind {
filtered = append(filtered, r)
}
}
actualRanges = filtered
}

if len(actualRanges) != len(f.Ranges()) {
t.Fatalf("verifyOutliningSpans failed - expected total spans to be %d, but was %d",
len(f.Ranges()), len(actualRanges))
}

slices.SortFunc(f.Ranges(), func(a, b *RangeMarker) int {
return lsproto.ComparePositions(a.LSPos(), b.LSPos())
})

for i, expectedRange := range f.Ranges() {
actualRange := actualRanges[i]
startPos := lsproto.Position{Line: actualRange.StartLine, Character: *actualRange.StartCharacter}
endPos := lsproto.Position{Line: actualRange.EndLine, Character: *actualRange.EndCharacter}

if lsproto.ComparePositions(startPos, expectedRange.LSRange.Start) != 0 ||
lsproto.ComparePositions(endPos, expectedRange.LSRange.End) != 0 {
t.Fatalf("verifyOutliningSpans failed - span %d has invalid positions: start (%d,%d), end (%d,%d)",
i+1, actualRange.StartLine, *actualRange.StartCharacter, actualRange.EndLine, *actualRange.EndCharacter)
}
}
}

func (f *FourslashTest) VerifyBaselineHover(t *testing.T) {
markersAndItems := core.MapFiltered(f.Markers(), func(marker *Marker) (markerAndItem[*lsproto.Hover], bool) {
if marker.Name == nil {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package fourslash_test

import (
"testing"

"github.com/microsoft/typescript-go/internal/fourslash"
"github.com/microsoft/typescript-go/internal/testutil"
)

func TestCorreuptedTryExpressionsDontCrashGettingOutlineSpans(t *testing.T) {
t.Parallel()

defer testutil.RecoverAndFail(t, "Panic on fourslash test")
const content = `try[| {
var x = [
{% try[||] %}|][|{% except %}|]
]
} catch (e)[| {
}|]`
f := fourslash.NewFourslash(t, nil /*capabilities*/, content)
f.VerifyOutliningSpans(t)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package fourslash_test

import (
"testing"

"github.com/microsoft/typescript-go/internal/fourslash"
"github.com/microsoft/typescript-go/internal/testutil"
)

func TestGetOutliningForArrayDestructuring(t *testing.T) {
t.Parallel()

defer testutil.RecoverAndFail(t, "Panic on fourslash test")
const content = `const[| [
a,
b,
c
]|] =[| [
1,
2,
3
]|];
const[| [
[|[
[|[
[|[
a,
b,
c
]|]
]|]
]|],
[|[
a1,
b1,
c1
]|]
]|] =[| [
[|[
[|[
[|[
1,
2,
3
]|]
]|]
]|],
[|[
1,
2,
3
]|]
]|]`
f := fourslash.NewFourslash(t, nil /*capabilities*/, content)
f.VerifyOutliningSpans(t)
}
Loading
Loading