Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
48 changes: 48 additions & 0 deletions internal/format/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,54 @@ func TestFormat(t *testing.T) {
})
}

func TestFormatNoTrailingNewline(t *testing.T) {
t.Parallel()
// Issue: Formatter adds extra space at end of line
// When formatting a file that has content "1;" with no trailing newline,
// an extra space should NOT be added at the end of the line

testCases := []struct {
name string
text string
}{
{"simple statement without trailing newline", "1;"},
{"function call without trailing newline", "console.log('hello');"},
{"variable declaration without trailing newline", "const x = 1;"},
{"multiple statements without trailing newline", "const x = 1;\nconst y = 2;"},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
ctx := format.WithFormatCodeSettings(t.Context(), &format.FormatCodeSettings{
EditorSettings: format.EditorSettings{
TabSize: 4,
IndentSize: 4,
BaseIndentSize: 4,
NewLineCharacter: "\n",
ConvertTabsToSpaces: true,
IndentStyle: format.IndentStyleSmart,
TrimTrailingWhitespace: true,
},
}, "\n")
sourceFile := parser.ParseSourceFile(ast.SourceFileParseOptions{
FileName: "/test.ts",
Path: "/test.ts",
}, tc.text, core.ScriptKindTS)
edits := format.FormatDocument(ctx, sourceFile)
newText := applyBulkEdits(tc.text, edits)

// The formatted text should not add extra space at the end
// It may add proper spacing within the code, but not after the last character
assert.Assert(t, !strings.HasSuffix(newText, " "), "Formatter should not add trailing space")
// Also check that no space was added at EOF position if text didn't end with newline
if !strings.HasSuffix(tc.text, "\n") {
assert.Assert(t, !strings.HasSuffix(newText, " "), "Formatter should not add space before EOF")
}
})
}
}

func BenchmarkFormat(b *testing.B) {
ctx := format.WithFormatCodeSettings(b.Context(), &format.FormatCodeSettings{
EditorSettings: format.EditorSettings{
Expand Down
4 changes: 3 additions & 1 deletion internal/format/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
func getAllRules() []ruleSpec {
allTokens := make([]ast.Kind, 0, ast.KindLastToken-ast.KindFirstToken+1)
for token := ast.KindFirstToken; token <= ast.KindLastToken; token++ {
allTokens = append(allTokens, token)
if token != ast.KindEndOfFile {
allTokens = append(allTokens, token)
}
Comment on lines +12 to +14
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is correct, reading Strada.

}

anyTokenExcept := func(tokens ...ast.Kind) tokenRange {
Expand Down
29 changes: 23 additions & 6 deletions internal/scanner/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2438,14 +2438,31 @@ func GetECMALineAndCharacterOfPosition(sourceFile ast.SourceFileLike, pos int) (
}

func GetECMAEndLinePosition(sourceFile *ast.SourceFile, line int) int {
pos := int(GetECMALineStarts(sourceFile)[line])
for {
ch, size := utf8.DecodeRuneInString(sourceFile.Text()[pos:])
if size == 0 || stringutil.IsLineBreak(ch) {
return pos
lineStarts := GetECMALineStarts(sourceFile)
text := sourceFile.Text()

// If this is the last line, return the index of the last character (or -1 for empty file)
if line+1 == len(lineStarts) {
if len(text) == 0 {
return -1
}
pos += size
return len(text) - 1
}

// For other lines, get the start of the next line and walk backwards to skip line breaks
start := int(lineStarts[line])
pos := int(lineStarts[line+1]) - 1

// Walk backwards while we're on line breaks, stopping at the beginning of the current line
for start <= pos {
ch, _ := utf8.DecodeLastRuneInString(text[:pos+1])
if !stringutil.IsLineBreak(ch) {
break
}
pos--
}

return pos
}

func GetECMAPositionOfLineAndCharacter(sourceFile *ast.SourceFile, line int, character int) int {
Expand Down