1package lsp
2
3import (
4 "os"
5 "path/filepath"
6 "testing"
7
8 powernapconfig "github.com/charmbracelet/x/powernap/pkg/config"
9 "github.com/stretchr/testify/require"
10)
11
12func TestFilterMatching(t *testing.T) {
13 t.Parallel()
14
15 t.Run("matches servers with existing root markers", func(t *testing.T) {
16 t.Parallel()
17 tmpDir := t.TempDir()
18
19 require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "go.mod"), []byte("module test"), 0o644))
20 require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "Cargo.toml"), []byte("[package]"), 0o644))
21
22 servers := map[string]*powernapconfig.ServerConfig{
23 "gopls": {RootMarkers: []string{"go.mod", "go.work"}},
24 "rust-analyzer": {RootMarkers: []string{"Cargo.toml"}},
25 "typescript-lsp": {RootMarkers: []string{"package.json", "tsconfig.json"}},
26 }
27
28 result := FilterMatching(tmpDir, servers)
29
30 require.Contains(t, result, "gopls")
31 require.Contains(t, result, "rust-analyzer")
32 require.NotContains(t, result, "typescript-lsp")
33 })
34
35 t.Run("returns empty for empty servers", func(t *testing.T) {
36 t.Parallel()
37 tmpDir := t.TempDir()
38
39 result := FilterMatching(tmpDir, map[string]*powernapconfig.ServerConfig{})
40
41 require.Empty(t, result)
42 })
43
44 t.Run("returns empty when no markers match", func(t *testing.T) {
45 t.Parallel()
46 tmpDir := t.TempDir()
47
48 servers := map[string]*powernapconfig.ServerConfig{
49 "gopls": {RootMarkers: []string{"go.mod"}},
50 "python": {RootMarkers: []string{"pyproject.toml"}},
51 }
52
53 result := FilterMatching(tmpDir, servers)
54
55 require.Empty(t, result)
56 })
57
58 t.Run("glob patterns work", func(t *testing.T) {
59 t.Parallel()
60 tmpDir := t.TempDir()
61
62 require.NoError(t, os.MkdirAll(filepath.Join(tmpDir, "src"), 0o755))
63 require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "src", "main.go"), []byte("package main"), 0o644))
64
65 servers := map[string]*powernapconfig.ServerConfig{
66 "gopls": {RootMarkers: []string{"**/*.go"}},
67 "python": {RootMarkers: []string{"**/*.py"}},
68 }
69
70 result := FilterMatching(tmpDir, servers)
71
72 require.Contains(t, result, "gopls")
73 require.NotContains(t, result, "python")
74 })
75
76 t.Run("servers with empty root markers are not included", func(t *testing.T) {
77 t.Parallel()
78 tmpDir := t.TempDir()
79
80 require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "go.mod"), []byte("module test"), 0o644))
81
82 servers := map[string]*powernapconfig.ServerConfig{
83 "gopls": {RootMarkers: []string{"go.mod"}},
84 "generic": {RootMarkers: []string{}},
85 }
86
87 result := FilterMatching(tmpDir, servers)
88
89 require.Contains(t, result, "gopls")
90 require.NotContains(t, result, "generic")
91 })
92
93 t.Run("stops early when all servers match", func(t *testing.T) {
94 t.Parallel()
95 tmpDir := t.TempDir()
96
97 require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "go.mod"), []byte("module test"), 0o644))
98 require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "Cargo.toml"), []byte("[package]"), 0o644))
99
100 servers := map[string]*powernapconfig.ServerConfig{
101 "gopls": {RootMarkers: []string{"go.mod"}},
102 "rust-analyzer": {RootMarkers: []string{"Cargo.toml"}},
103 }
104
105 result := FilterMatching(tmpDir, servers)
106
107 require.Len(t, result, 2)
108 require.Contains(t, result, "gopls")
109 require.Contains(t, result, "rust-analyzer")
110 })
111}