All checks were successful
Run Test Suite / test (push) Successful in 31s
However, the colorscheme functions and tests do not work anymore, they need to be rebuilt.
243 lines
5.7 KiB
Go
243 lines
5.7 KiB
Go
package syntax
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.gophernest.net/azpect/TextEditor/internal/core"
|
|
"git.gophernest.net/azpect/TextEditor/internal/theme/themes"
|
|
"github.com/charmbracelet/lipgloss"
|
|
)
|
|
|
|
func TestTreeSitterEngineHighlightsGoKeywordAndString(t *testing.T) {
|
|
b := core.NewBufferBuilder().
|
|
WithFilename("sample.go").
|
|
WithFiletype("go").
|
|
WithLines([]string{
|
|
"package main",
|
|
"func main() {",
|
|
" s := \"hi\"",
|
|
"}",
|
|
}).
|
|
Build()
|
|
buf := &b
|
|
|
|
engine := NewTreeSitterEngine(themes.NewDefaultTheme())
|
|
engine.PrepareBuffer(buf)
|
|
|
|
base := engine.editorTheme.Line
|
|
|
|
line0 := buf.Line(0)
|
|
map0 := engine.LineStyleMap(buf, 0)
|
|
if len(map0) != len([]rune(line0)) {
|
|
t.Fatalf("line 0 style map length mismatch")
|
|
}
|
|
if len(map0) == 0 || styleEquivalent(map0[0], base) {
|
|
t.Fatalf("expected 'package' keyword to be highlighted")
|
|
}
|
|
|
|
line2 := buf.Line(2)
|
|
stringStart := strings.Index(line2, "\"hi\"")
|
|
if stringStart < 0 {
|
|
t.Fatalf("test setup failed: string literal not found")
|
|
}
|
|
map2 := engine.LineStyleMap(buf, 2)
|
|
if styleEquivalent(map2[stringStart+1], base) {
|
|
t.Fatalf("expected string contents to be highlighted")
|
|
}
|
|
}
|
|
|
|
func TestTreeSitterEngineHighlightsMultilineRawString(t *testing.T) {
|
|
b := core.NewBufferBuilder().
|
|
WithFilename("sample.go").
|
|
WithFiletype("go").
|
|
WithLines([]string{
|
|
"package main",
|
|
"func main() {",
|
|
" s := `hello",
|
|
"world`",
|
|
" println(s)",
|
|
"}",
|
|
}).
|
|
Build()
|
|
buf := &b
|
|
|
|
engine := NewTreeSitterEngine(themes.NewDefaultTheme())
|
|
engine.PrepareBuffer(buf)
|
|
|
|
base := engine.editorTheme.Line
|
|
map3 := engine.LineStyleMap(buf, 3)
|
|
if len(map3) == 0 {
|
|
t.Fatalf("expected style map on multiline raw string line")
|
|
}
|
|
if styleEquivalent(map3[0], base) {
|
|
t.Fatalf("expected multiline raw string line to be highlighted")
|
|
}
|
|
}
|
|
|
|
func TestTreeSitterEngineApplyEditUpdatesStyleCategory(t *testing.T) {
|
|
b := core.NewBufferBuilder().
|
|
WithFilename("sample.go").
|
|
WithFiletype("go").
|
|
WithLines([]string{
|
|
"package main",
|
|
"func main() {",
|
|
" x := 123",
|
|
"}",
|
|
}).
|
|
Build()
|
|
buf := &b
|
|
|
|
engine := NewTreeSitterEngine(themes.NewDefaultTheme())
|
|
engine.PrepareBuffer(buf)
|
|
|
|
oldLine := buf.Line(2)
|
|
oldIdx := strings.Index(oldLine, "123")
|
|
if oldIdx < 0 {
|
|
t.Fatalf("test setup failed: number not found")
|
|
}
|
|
oldMap := engine.LineStyleMap(buf, 2)
|
|
oldStyle := oldMap[oldIdx]
|
|
|
|
var edit *core.BufferEdit
|
|
buf.OnChange = func(change core.BufferChange) {
|
|
edit = change.Edit
|
|
}
|
|
|
|
buf.SetLine(2, " x := \"abc\"")
|
|
if edit == nil {
|
|
t.Fatalf("expected edit metadata from SetLine")
|
|
}
|
|
|
|
engine.ApplyEdit(buf, edit)
|
|
engine.PrepareBuffer(buf)
|
|
|
|
newLine := buf.Line(2)
|
|
newIdx := strings.Index(newLine, "abc")
|
|
if newIdx < 0 {
|
|
t.Fatalf("test setup failed: string not found")
|
|
}
|
|
newMap := engine.LineStyleMap(buf, 2)
|
|
newStyle := newMap[newIdx]
|
|
|
|
if styleEquivalent(newStyle, engine.editorTheme.Line) {
|
|
t.Fatalf("expected updated string to be highlighted")
|
|
}
|
|
if styleEquivalent(oldStyle, newStyle) {
|
|
t.Fatalf("expected style category to change from number to string")
|
|
}
|
|
}
|
|
|
|
func TestTreeSitterEngineApplyEditLineCountChangeForcesFullDirty(t *testing.T) {
|
|
b := core.NewBufferBuilder().
|
|
WithFilename("sample.go").
|
|
WithFiletype("go").
|
|
WithLines([]string{"package main", "func main() {}"}).
|
|
Build()
|
|
buf := &b
|
|
|
|
engine := NewTreeSitterEngine(themes.NewDefaultTheme())
|
|
engine.PrepareBuffer(buf)
|
|
bc := engine.getCache(buf)
|
|
|
|
var edit *core.BufferEdit
|
|
buf.OnChange = func(change core.BufferChange) {
|
|
edit = change.Edit
|
|
}
|
|
|
|
buf.InsertLine(1, "var x = 1")
|
|
if edit == nil {
|
|
t.Fatalf("expected edit metadata from InsertLine")
|
|
}
|
|
|
|
engine.ApplyEdit(buf, edit)
|
|
if !bc.dirtyAll {
|
|
t.Fatalf("expected line count change to set dirtyAll")
|
|
}
|
|
|
|
engine.PrepareBuffer(buf)
|
|
if !bc.built {
|
|
t.Fatalf("expected cache rebuilt after prepare")
|
|
}
|
|
if bc.count != buf.LineCount() {
|
|
t.Fatalf("expected cache line count to match buffer")
|
|
}
|
|
if bc.dirtyAll {
|
|
t.Fatalf("expected dirtyAll to clear after rebuild")
|
|
}
|
|
}
|
|
|
|
func TestTreeSitterEngineUnsupportedBufferFallsBackToDefaultStyles(t *testing.T) {
|
|
b := core.NewBufferBuilder().
|
|
WithFilename("notes.txt").
|
|
WithFiletype("txt").
|
|
WithLines([]string{"just text", "with no language"}).
|
|
Build()
|
|
buf := &b
|
|
|
|
engine := NewTreeSitterEngine(themes.NewDefaultTheme())
|
|
engine.PrepareBuffer(buf)
|
|
|
|
base := engine.editorTheme.Line
|
|
line := buf.Line(0)
|
|
m := engine.LineStyleMap(buf, 0)
|
|
if len(m) != len([]rune(line)) {
|
|
t.Fatalf("style map length mismatch on fallback buffer")
|
|
}
|
|
for i := range m {
|
|
if !styleEquivalent(m[i], base) {
|
|
t.Fatalf("expected default style for unsupported filetype at rune %d", i)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTreeSitterEngineLastLineEditDoesNotPanicAndRebuilds(t *testing.T) {
|
|
b := core.NewBufferBuilder().
|
|
WithFilename("sample.go").
|
|
WithFiletype("go").
|
|
WithLines([]string{"package main", "func main() {", " return", "}"}).
|
|
Build()
|
|
buf := &b
|
|
|
|
engine := NewTreeSitterEngine(themes.NewDefaultTheme())
|
|
engine.PrepareBuffer(buf)
|
|
bc := engine.getCache(buf)
|
|
|
|
var edit *core.BufferEdit
|
|
buf.OnChange = func(change core.BufferChange) {
|
|
edit = change.Edit
|
|
}
|
|
|
|
buf.SetLine(3, "// end")
|
|
if edit == nil {
|
|
t.Fatalf("expected edit metadata for last line change")
|
|
}
|
|
|
|
engine.ApplyEdit(buf, edit)
|
|
engine.PrepareBuffer(buf)
|
|
|
|
if !bc.built {
|
|
t.Fatalf("expected cache built after last-line edit")
|
|
}
|
|
if len(bc.dirty) != 0 {
|
|
t.Fatalf("expected dirty ranges cleared after rebuild")
|
|
}
|
|
}
|
|
|
|
func styleEquivalent(a, b lipgloss.Style) bool {
|
|
return styleSignature(a) == styleSignature(b)
|
|
}
|
|
|
|
func styleSignature(s lipgloss.Style) string {
|
|
return fmt.Sprintf(
|
|
"fg=%v,bg=%v,bold=%v,italic=%v,underline=%v,reverse=%v",
|
|
s.GetForeground(),
|
|
s.GetBackground(),
|
|
s.GetBold(),
|
|
s.GetItalic(),
|
|
s.GetUnderline(),
|
|
s.GetReverse(),
|
|
)
|
|
}
|