Files
kjol/tools/tsgo/internal/ls/lsutil/utilities_test.go
2026-07-09 16:50:43 -04:00

201 lines
4.4 KiB
Go

package lsutil
import (
"testing"
"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/parser"
)
func parseTS(t *testing.T, text string) *ast.SourceFile {
t.Helper()
return parser.ParseSourceFile(ast.SourceFileParseOptions{
FileName: "/test.ts",
Path: "/test.ts",
}, text, core.ScriptKindTS)
}
func TestProbablyUsesSemicolons(t *testing.T) {
t.Parallel()
tests := []struct {
name string
src string
want bool
}{
{
name: "mixed semicolons and ASI favors semicolons when ratio exceeds one fifth",
// First five observations: 2 with semicolon, 3 without. Real ratio 2/3 > 1/5.
// Integer division bug compared against 1/5==0 and used with/without as ints,
// so the old check was effectively (with/without) > 0, which failed here.
src: `let a = 1;
let b = 2;
let c = 3
let d = 4
let e = 5
`,
want: true,
},
{
name: "consistent ASI with no semicolons",
src: `let a = 1
let b = 2
let c = 3
`,
want: false,
},
{
name: "consistent semicolons",
src: `let a = 1;
let b = 2;
let c = 3;
`,
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
file := parseTS(t, tt.src)
if got := ProbablyUsesSemicolons(file); got != tt.want {
t.Errorf("ProbablyUsesSemicolons() = %v, want %v", got, tt.want)
}
})
}
}
func TestResolveOrganizeImportsSort(t *testing.T) {
t.Parallel()
tests := []struct {
name string
preferences UserPreferences
want OrganizeImportsSort
}{
{
name: "explicit sort wins",
preferences: UserPreferences{
OrganizeImportsSort: OrganizeImportsSortOrdinal,
OrganizeImportsCollation: OrganizeImportsCollationUnicode,
OrganizeImportsIgnoreCase: core.TSTrue,
},
want: OrganizeImportsSortOrdinal,
},
{
name: "unicode case-sensitive maps to natural",
preferences: UserPreferences{
OrganizeImportsCollation: OrganizeImportsCollationUnicode,
OrganizeImportsIgnoreCase: core.TSFalse,
},
want: OrganizeImportsSortNatural,
},
{
name: "unicode ignore case maps to natural ignore case",
preferences: UserPreferences{
OrganizeImportsCollation: OrganizeImportsCollationUnicode,
OrganizeImportsIgnoreCase: core.TSTrue,
},
want: OrganizeImportsSortNaturalIgnoreCase,
},
{
name: "unicode unknown case sensitivity stays auto for detection",
preferences: UserPreferences{
OrganizeImportsCollation: OrganizeImportsCollationUnicode,
},
want: OrganizeImportsSortAuto,
},
{
name: "ordinal ignore case maps to ordinal ignore case",
preferences: UserPreferences{
OrganizeImportsIgnoreCase: core.TSTrue,
},
want: OrganizeImportsSortOrdinalIgnoreCase,
},
{
name: "ordinal case sensitive maps to ordinal",
preferences: UserPreferences{
OrganizeImportsIgnoreCase: core.TSFalse,
},
want: OrganizeImportsSortOrdinal,
},
{
name: "unknown ordinal stays auto",
want: OrganizeImportsSortAuto,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got := ResolveOrganizeImportsSort(tt.preferences); got != tt.want {
t.Fatalf("ResolveOrganizeImportsSort() = %v, want %v", got, tt.want)
}
})
}
}
func TestCompareOrganizeImportsNaturalStrings(t *testing.T) {
t.Parallel()
comparer := getOrganizeImportsPresetStringComparer(OrganizeImportsSortNaturalIgnoreCase)
tests := []struct {
name string
a string
b string
want int
}{
{
name: "numeric runs sort by numeric value",
a: "a2",
b: "a100",
want: -1,
},
{
name: "numeric runs with equal value use raw tie break",
a: "a02",
b: "a2",
want: -1,
},
{
name: "accents are folded for primary comparison",
a: "À",
b: "B",
want: -1,
},
{
name: "raw comparison breaks accent ties",
a: "A",
b: "À",
want: -1,
},
{
name: "hyphen sorts before slash like Intl.Collator fallback",
a: "app-init",
b: "app/app",
want: -1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got := cmpSign(comparer(tt.a, tt.b)); got != tt.want {
t.Fatalf("comparer(%q, %q) = %v, want sign %v", tt.a, tt.b, got, tt.want)
}
})
}
}
func cmpSign(value int) int {
switch {
case value < 0:
return -1
case value > 0:
return 1
default:
return 0
}
}