Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 4 additions & 3 deletions internal/format/indent.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,12 +341,13 @@ func getVisualListRange(node *ast.Node, list core.TextRange, sourceFile *ast.Sou
} else {
priorEnd = prior.End()
}
next := astnav.FindNextToken(prior, node, sourceFile)
// Find the token that starts at or after list.End() using the scanner
scan := scanner.GetScannerForSourceFile(sourceFile, list.End())
var nextStart int
if next == nil {
if scan.Token() == ast.KindEndOfFile {
nextStart = list.End()
} else {
nextStart = next.Pos()
nextStart = scan.TokenStart()
}
return core.NewTextRange(priorEnd, nextStart)
}
Expand Down
50 changes: 50 additions & 0 deletions internal/format/indent_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package format_test

import (
"testing"

"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/format"
"github.com/microsoft/typescript-go/internal/parser"
"gotest.tools/v3/assert"
)

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

text := `import type {
AAA,
BBB,
} from "./bar";`

sourceFile := parser.ParseSourceFile(ast.SourceFileParseOptions{
FileName: "/test.ts",
Path: "/test.ts",
}, text, core.ScriptKindTS)

// Find ImportSpecifier nodes (AAA and BBB)
var importSpecifiers []*ast.Node
forEachDescendantOfKind(sourceFile.AsNode(), ast.KindImportSpecifier, func(node *ast.Node) {
importSpecifiers = append(importSpecifiers, node)
})

assert.Assert(t, len(importSpecifiers) == 2, "Expected 2 import specifiers, got %d", len(importSpecifiers))

// Test GetContainingList for each import specifier
for _, specifier := range importSpecifiers {
list := format.GetContainingList(specifier, sourceFile)
assert.Assert(t, list != nil, "GetContainingList should return non-nil for import specifier")
assert.Assert(t, len(list.Nodes) == 2, "Expected list with 2 elements, got %d", len(list.Nodes))
}
}

func forEachDescendantOfKind(node *ast.Node, kind ast.Kind, action func(*ast.Node)) {
node.ForEachChild(func(child *ast.Node) bool {
if child.Kind == kind {
action(child)
}
forEachDescendantOfKind(child, kind, action)
return false
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package fourslash_test

import (
"testing"

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

// Test case for crash when promoting type-only import to value import
// when existing type imports precede the new value import
// https://github.com/microsoft/typescript-go/issues/XXX
func TestCodeFixPromoteTypeOnlyOrderingCrash(t *testing.T) {
fourslash.SkipIfFailing(t)
t.Parallel()
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
const content = `// @module: node18
// @verbatimModuleSyntax: true
// @Filename: /bar.ts
export interface AAA {}
export class BBB {}
// @Filename: /foo.ts
import type {
AAA,
BBB,
} from "./bar";

let x: AAA = new BBB()`
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
defer done()
f.GoToFile(t, "/foo.ts")
f.VerifyImportFixAtPosition(t, []string{
`import {
BBB,
type AAA,
} from "./bar";

let x: AAA = new BBB()`,
}, nil /*preferences*/)
}
Loading