@rejot-dev/thalo-lsp 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +216 -0
- package/dist/capabilities.d.ts +12 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +54 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/handlers/completions/completions.js +33 -0
- package/dist/handlers/completions/completions.js.map +1 -0
- package/dist/handlers/completions/context.js +228 -0
- package/dist/handlers/completions/context.js.map +1 -0
- package/dist/handlers/completions/providers/directive.js +50 -0
- package/dist/handlers/completions/providers/directive.js.map +1 -0
- package/dist/handlers/completions/providers/entity.js +52 -0
- package/dist/handlers/completions/providers/entity.js.map +1 -0
- package/dist/handlers/completions/providers/link.js +113 -0
- package/dist/handlers/completions/providers/link.js.map +1 -0
- package/dist/handlers/completions/providers/metadata-key.js +43 -0
- package/dist/handlers/completions/providers/metadata-key.js.map +1 -0
- package/dist/handlers/completions/providers/metadata-value.js +71 -0
- package/dist/handlers/completions/providers/metadata-value.js.map +1 -0
- package/dist/handlers/completions/providers/providers.js +31 -0
- package/dist/handlers/completions/providers/providers.js.map +1 -0
- package/dist/handlers/completions/providers/schema-block.js +46 -0
- package/dist/handlers/completions/providers/schema-block.js.map +1 -0
- package/dist/handlers/completions/providers/section.js +37 -0
- package/dist/handlers/completions/providers/section.js.map +1 -0
- package/dist/handlers/completions/providers/tag.js +55 -0
- package/dist/handlers/completions/providers/tag.js.map +1 -0
- package/dist/handlers/completions/providers/timestamp.js +32 -0
- package/dist/handlers/completions/providers/timestamp.js.map +1 -0
- package/dist/handlers/completions/providers/type-expr.js +56 -0
- package/dist/handlers/completions/providers/type-expr.js.map +1 -0
- package/dist/handlers/definition.js +166 -0
- package/dist/handlers/definition.js.map +1 -0
- package/dist/handlers/diagnostics.js +77 -0
- package/dist/handlers/diagnostics.js.map +1 -0
- package/dist/handlers/hover.js +73 -0
- package/dist/handlers/hover.js.map +1 -0
- package/dist/handlers/references.js +233 -0
- package/dist/handlers/references.js.map +1 -0
- package/dist/handlers/semantic-tokens.js +36 -0
- package/dist/handlers/semantic-tokens.js.map +1 -0
- package/dist/mod.d.ts +2 -0
- package/dist/mod.js +3 -0
- package/dist/server.bundled.js +1764 -0
- package/dist/server.d.ts +18 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +367 -0
- package/dist/server.js.map +1 -0
- package/package.json +45 -0
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { tokenLegend } from "./capabilities.js";
|
|
2
|
+
import { Connection } from "vscode-languageserver/node.js";
|
|
3
|
+
|
|
4
|
+
//#region src/server.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Create a new LSP connection
|
|
8
|
+
*/
|
|
9
|
+
declare function createConnection(): Connection;
|
|
10
|
+
/**
|
|
11
|
+
* Start the LSP server
|
|
12
|
+
*
|
|
13
|
+
* @param connection - The LSP connection to use (defaults to stdio)
|
|
14
|
+
*/
|
|
15
|
+
declare function startServer(connection?: Connection): void;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { createConnection, startServer, tokenLegend };
|
|
18
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","names":[],"sources":["../src/server.ts"],"sourcesContent":[],"mappings":";;;;;;;AAsOA;AASgB,iBATA,gBAAA,CAAA,CASuD,EATnC,UASmC;;;;;;iBAAvD,WAAA,cAAwB"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { serverCapabilities, tokenLegend } from "./capabilities.js";
|
|
2
|
+
import { handleDefinition } from "./handlers/definition.js";
|
|
3
|
+
import { handleReferences } from "./handlers/references.js";
|
|
4
|
+
import { handleSemanticTokens } from "./handlers/semantic-tokens.js";
|
|
5
|
+
import { getDiagnostics } from "./handlers/diagnostics.js";
|
|
6
|
+
import { handleHover } from "./handlers/hover.js";
|
|
7
|
+
import { handleCompletion, handleCompletionResolve } from "./handlers/completions/completions.js";
|
|
8
|
+
import * as fs from "node:fs";
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
import { DidChangeConfigurationNotification, FileChangeType, ProposedFeatures, createConnection as createConnection$1 } from "vscode-languageserver/node.js";
|
|
11
|
+
import { TextDocument } from "vscode-languageserver-textdocument";
|
|
12
|
+
import { createWorkspace } from "@rejot-dev/thalo/native";
|
|
13
|
+
|
|
14
|
+
//#region src/server.ts
|
|
15
|
+
/**
|
|
16
|
+
* Create the initial server state
|
|
17
|
+
*/
|
|
18
|
+
function createServerState(connection) {
|
|
19
|
+
return {
|
|
20
|
+
workspace: createWorkspace(),
|
|
21
|
+
documents: /* @__PURE__ */ new Map(),
|
|
22
|
+
connection,
|
|
23
|
+
workspaceFolders: []
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get the file type from a URI
|
|
28
|
+
*/
|
|
29
|
+
function getFileType(uri) {
|
|
30
|
+
if (uri.endsWith(".thalo")) return "thalo";
|
|
31
|
+
if (uri.endsWith(".md")) return "markdown";
|
|
32
|
+
return "thalo";
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Convert a URI to a file path
|
|
36
|
+
*/
|
|
37
|
+
function uriToPath(uri) {
|
|
38
|
+
if (uri.startsWith("file://")) return decodeURIComponent(uri.slice(7));
|
|
39
|
+
return uri;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Collect all .thalo and .md files from a directory recursively
|
|
43
|
+
*/
|
|
44
|
+
function collectThaloFiles(dir) {
|
|
45
|
+
const files = [];
|
|
46
|
+
function walk(currentDir) {
|
|
47
|
+
let entries;
|
|
48
|
+
try {
|
|
49
|
+
entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
50
|
+
} catch {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
for (const entry of entries) {
|
|
54
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
55
|
+
if (entry.isDirectory()) {
|
|
56
|
+
if (!entry.name.startsWith(".") && entry.name !== "node_modules") walk(fullPath);
|
|
57
|
+
} else if (entry.isFile()) {
|
|
58
|
+
if (entry.name.endsWith(".thalo") || entry.name.endsWith(".md")) files.push(fullPath);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
walk(dir);
|
|
63
|
+
return files;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Load all thalo files from the workspace folders into the workspace.
|
|
67
|
+
* This ensures cross-file features work correctly even for files not yet opened.
|
|
68
|
+
*/
|
|
69
|
+
function loadWorkspaceFiles(state) {
|
|
70
|
+
for (const folder of state.workspaceFolders) {
|
|
71
|
+
const files = collectThaloFiles(folder);
|
|
72
|
+
for (const file of files) {
|
|
73
|
+
if (state.workspace.getModel(file)) continue;
|
|
74
|
+
try {
|
|
75
|
+
const source = fs.readFileSync(file, "utf-8");
|
|
76
|
+
const fileType = getFileType(file);
|
|
77
|
+
state.workspace.addDocument(source, {
|
|
78
|
+
filename: file,
|
|
79
|
+
fileType
|
|
80
|
+
});
|
|
81
|
+
} catch (err) {
|
|
82
|
+
console.error(`[thalo-lsp] Error loading ${file}: ${err instanceof Error ? err.message : err}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
console.error(`[thalo-lsp] Loaded ${files.length} files from ${folder}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Publish diagnostics for a single document
|
|
90
|
+
*/
|
|
91
|
+
function publishDiagnosticsForDocument(state, doc) {
|
|
92
|
+
try {
|
|
93
|
+
const diagnostics = getDiagnostics(state.workspace, doc);
|
|
94
|
+
state.connection.sendDiagnostics({
|
|
95
|
+
uri: doc.uri,
|
|
96
|
+
diagnostics
|
|
97
|
+
});
|
|
98
|
+
} catch (error) {
|
|
99
|
+
const path$1 = uriToPath(doc.uri);
|
|
100
|
+
console.error(`[thalo-lsp] Error getting diagnostics for ${path$1}:`, error);
|
|
101
|
+
state.connection.sendDiagnostics({
|
|
102
|
+
uri: doc.uri,
|
|
103
|
+
diagnostics: [{
|
|
104
|
+
range: {
|
|
105
|
+
start: {
|
|
106
|
+
line: 0,
|
|
107
|
+
character: 0
|
|
108
|
+
},
|
|
109
|
+
end: {
|
|
110
|
+
line: 0,
|
|
111
|
+
character: 0
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
severity: 1,
|
|
115
|
+
source: "thalo",
|
|
116
|
+
message: `Diagnostic error: ${error instanceof Error ? error.message : String(error)}`
|
|
117
|
+
}]
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Refresh diagnostics for specific files based on invalidation result.
|
|
123
|
+
* Only refreshes open documents that are in the affected files list.
|
|
124
|
+
*/
|
|
125
|
+
function refreshDiagnosticsForFiles(state, affectedFiles, changedFile) {
|
|
126
|
+
const affectedSet = new Set(affectedFiles);
|
|
127
|
+
for (const doc of state.documents.values()) {
|
|
128
|
+
const docPath = uriToPath(doc.uri);
|
|
129
|
+
if (docPath === changedFile || affectedSet.has(docPath)) publishDiagnosticsForDocument(state, doc);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Update a document in the workspace and publish diagnostics
|
|
134
|
+
*/
|
|
135
|
+
function updateDocument(state, doc) {
|
|
136
|
+
const filePath = uriToPath(doc.uri);
|
|
137
|
+
try {
|
|
138
|
+
const invalidation = state.workspace.updateDocument(filePath, doc.getText());
|
|
139
|
+
if (invalidation.schemasChanged || invalidation.linksChanged) refreshDiagnosticsForFiles(state, invalidation.affectedFiles, filePath);
|
|
140
|
+
else publishDiagnosticsForDocument(state, doc);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
console.error(`[thalo-lsp] Parse error in ${filePath}:`, error);
|
|
143
|
+
state.connection.sendDiagnostics({
|
|
144
|
+
uri: doc.uri,
|
|
145
|
+
diagnostics: [{
|
|
146
|
+
range: {
|
|
147
|
+
start: {
|
|
148
|
+
line: 0,
|
|
149
|
+
character: 0
|
|
150
|
+
},
|
|
151
|
+
end: {
|
|
152
|
+
line: 0,
|
|
153
|
+
character: 0
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
severity: 1,
|
|
157
|
+
source: "thalo",
|
|
158
|
+
message: `Parse error: ${error instanceof Error ? error.message : String(error)}`
|
|
159
|
+
}]
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Create a new LSP connection
|
|
165
|
+
*/
|
|
166
|
+
function createConnection() {
|
|
167
|
+
return createConnection$1(ProposedFeatures.all);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Start the LSP server
|
|
171
|
+
*
|
|
172
|
+
* @param connection - The LSP connection to use (defaults to stdio)
|
|
173
|
+
*/
|
|
174
|
+
function startServer(connection = createConnection()) {
|
|
175
|
+
const state = createServerState(connection);
|
|
176
|
+
connection.onInitialize((params) => {
|
|
177
|
+
console.error(`[thalo-lsp] Initializing with workspace: ${params.workspaceFolders?.[0]?.uri}`);
|
|
178
|
+
if (params.workspaceFolders) state.workspaceFolders = params.workspaceFolders.map((folder) => uriToPath(folder.uri));
|
|
179
|
+
else if (params.rootUri) state.workspaceFolders = [uriToPath(params.rootUri)];
|
|
180
|
+
return {
|
|
181
|
+
capabilities: serverCapabilities,
|
|
182
|
+
serverInfo: {
|
|
183
|
+
name: "thalo-lsp",
|
|
184
|
+
version: "0.0.0"
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
});
|
|
188
|
+
connection.onInitialized(() => {
|
|
189
|
+
console.error("[thalo-lsp] Server initialized");
|
|
190
|
+
connection.client.register(DidChangeConfigurationNotification.type, void 0);
|
|
191
|
+
loadWorkspaceFiles(state);
|
|
192
|
+
});
|
|
193
|
+
connection.onDidOpenTextDocument((params) => {
|
|
194
|
+
const doc = TextDocument.create(params.textDocument.uri, params.textDocument.languageId, params.textDocument.version, params.textDocument.text);
|
|
195
|
+
state.documents.set(params.textDocument.uri, doc);
|
|
196
|
+
updateDocument(state, doc);
|
|
197
|
+
console.error(`[thalo-lsp] Opened: ${params.textDocument.uri}`);
|
|
198
|
+
});
|
|
199
|
+
connection.onDidChangeTextDocument((params) => {
|
|
200
|
+
const doc = state.documents.get(params.textDocument.uri);
|
|
201
|
+
if (doc) {
|
|
202
|
+
const updated = TextDocument.update(doc, params.contentChanges, params.textDocument.version);
|
|
203
|
+
state.documents.set(params.textDocument.uri, updated);
|
|
204
|
+
updateDocument(state, updated);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
connection.onDidCloseTextDocument((params) => {
|
|
208
|
+
state.documents.delete(params.textDocument.uri);
|
|
209
|
+
const filePath = uriToPath(params.textDocument.uri);
|
|
210
|
+
try {
|
|
211
|
+
if (fs.existsSync(filePath)) {
|
|
212
|
+
const source = fs.readFileSync(filePath, "utf-8");
|
|
213
|
+
const fileType = getFileType(params.textDocument.uri);
|
|
214
|
+
state.workspace.addDocument(source, {
|
|
215
|
+
filename: filePath,
|
|
216
|
+
fileType
|
|
217
|
+
});
|
|
218
|
+
} else state.workspace.removeDocument(filePath);
|
|
219
|
+
} catch {
|
|
220
|
+
state.workspace.removeDocument(filePath);
|
|
221
|
+
}
|
|
222
|
+
connection.sendDiagnostics({
|
|
223
|
+
uri: params.textDocument.uri,
|
|
224
|
+
diagnostics: []
|
|
225
|
+
});
|
|
226
|
+
console.error(`[thalo-lsp] Closed: ${params.textDocument.uri}`);
|
|
227
|
+
});
|
|
228
|
+
connection.onDidChangeWatchedFiles((params) => {
|
|
229
|
+
const allAffectedFiles = [];
|
|
230
|
+
for (const change of params.changes) {
|
|
231
|
+
const filePath = uriToPath(change.uri);
|
|
232
|
+
if (!filePath.endsWith(".thalo") && !filePath.endsWith(".md")) continue;
|
|
233
|
+
if (change.type === FileChangeType.Deleted) {
|
|
234
|
+
const affected = state.workspace.getAffectedFiles(filePath);
|
|
235
|
+
allAffectedFiles.push(...affected);
|
|
236
|
+
state.workspace.removeDocument(filePath);
|
|
237
|
+
state.documents.delete(change.uri);
|
|
238
|
+
connection.sendDiagnostics({
|
|
239
|
+
uri: change.uri,
|
|
240
|
+
diagnostics: []
|
|
241
|
+
});
|
|
242
|
+
console.error(`[thalo-lsp] Removed deleted file: ${filePath}`);
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
if (state.documents.has(change.uri)) continue;
|
|
246
|
+
switch (change.type) {
|
|
247
|
+
case FileChangeType.Created:
|
|
248
|
+
case FileChangeType.Changed:
|
|
249
|
+
try {
|
|
250
|
+
if (fs.existsSync(filePath)) {
|
|
251
|
+
const source = fs.readFileSync(filePath, "utf-8");
|
|
252
|
+
const invalidation = state.workspace.updateDocument(filePath, source);
|
|
253
|
+
allAffectedFiles.push(...invalidation.affectedFiles);
|
|
254
|
+
console.error(`[thalo-lsp] Loaded external file: ${filePath}`);
|
|
255
|
+
}
|
|
256
|
+
} catch (err) {
|
|
257
|
+
console.error(`[thalo-lsp] Error loading ${filePath}: ${err instanceof Error ? err.message : err}`);
|
|
258
|
+
}
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (allAffectedFiles.length > 0) {
|
|
263
|
+
const affectedSet = new Set(allAffectedFiles);
|
|
264
|
+
for (const doc of state.documents.values()) if (affectedSet.has(uriToPath(doc.uri))) publishDiagnosticsForDocument(state, doc);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
connection.workspace.onDidCreateFiles((params) => {
|
|
268
|
+
const allAffectedFiles = [];
|
|
269
|
+
for (const file of params.files) {
|
|
270
|
+
const filePath = uriToPath(file.uri);
|
|
271
|
+
if (!filePath.endsWith(".thalo") && !filePath.endsWith(".md")) continue;
|
|
272
|
+
try {
|
|
273
|
+
if (fs.existsSync(filePath)) {
|
|
274
|
+
const source = fs.readFileSync(filePath, "utf-8");
|
|
275
|
+
const invalidation = state.workspace.updateDocument(filePath, source);
|
|
276
|
+
allAffectedFiles.push(...invalidation.affectedFiles);
|
|
277
|
+
console.error(`[thalo-lsp] Loaded created file: ${filePath}`);
|
|
278
|
+
}
|
|
279
|
+
} catch (err) {
|
|
280
|
+
console.error(`[thalo-lsp] Error loading created file ${filePath}: ${err instanceof Error ? err.message : err}`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (allAffectedFiles.length > 0) {
|
|
284
|
+
const affectedSet = new Set(allAffectedFiles);
|
|
285
|
+
for (const doc of state.documents.values()) if (affectedSet.has(uriToPath(doc.uri))) publishDiagnosticsForDocument(state, doc);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
connection.workspace.onDidDeleteFiles((params) => {
|
|
289
|
+
const allAffectedFiles = [];
|
|
290
|
+
for (const file of params.files) {
|
|
291
|
+
const filePath = uriToPath(file.uri);
|
|
292
|
+
if (!filePath.endsWith(".thalo") && !filePath.endsWith(".md")) continue;
|
|
293
|
+
const affected = state.workspace.getAffectedFiles(filePath);
|
|
294
|
+
allAffectedFiles.push(...affected);
|
|
295
|
+
state.workspace.removeDocument(filePath);
|
|
296
|
+
console.error(`[thalo-lsp] Removed file: ${filePath}`);
|
|
297
|
+
}
|
|
298
|
+
if (allAffectedFiles.length > 0) {
|
|
299
|
+
const affectedSet = new Set(allAffectedFiles);
|
|
300
|
+
for (const doc of state.documents.values()) if (affectedSet.has(uriToPath(doc.uri))) publishDiagnosticsForDocument(state, doc);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
connection.workspace.onDidRenameFiles((params) => {
|
|
304
|
+
const allAffectedFiles = [];
|
|
305
|
+
for (const file of params.files) {
|
|
306
|
+
const oldPath = uriToPath(file.oldUri);
|
|
307
|
+
const newPath = uriToPath(file.newUri);
|
|
308
|
+
const oldIsThalo = oldPath.endsWith(".thalo") || oldPath.endsWith(".md");
|
|
309
|
+
const newIsThalo = newPath.endsWith(".thalo") || newPath.endsWith(".md");
|
|
310
|
+
if (oldIsThalo) {
|
|
311
|
+
const affected = state.workspace.getAffectedFiles(oldPath);
|
|
312
|
+
allAffectedFiles.push(...affected);
|
|
313
|
+
state.workspace.removeDocument(oldPath);
|
|
314
|
+
console.error(`[thalo-lsp] Removed renamed file: ${oldPath}`);
|
|
315
|
+
}
|
|
316
|
+
if (newIsThalo) try {
|
|
317
|
+
if (fs.existsSync(newPath)) {
|
|
318
|
+
const source = fs.readFileSync(newPath, "utf-8");
|
|
319
|
+
const invalidation = state.workspace.updateDocument(newPath, source);
|
|
320
|
+
allAffectedFiles.push(...invalidation.affectedFiles);
|
|
321
|
+
console.error(`[thalo-lsp] Loaded renamed file: ${newPath}`);
|
|
322
|
+
}
|
|
323
|
+
} catch (err) {
|
|
324
|
+
console.error(`[thalo-lsp] Error loading renamed file ${newPath}: ${err instanceof Error ? err.message : err}`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (allAffectedFiles.length > 0) {
|
|
328
|
+
const affectedSet = new Set(allAffectedFiles);
|
|
329
|
+
for (const doc of state.documents.values()) if (affectedSet.has(uriToPath(doc.uri))) publishDiagnosticsForDocument(state, doc);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
connection.onDefinition((params) => {
|
|
333
|
+
const doc = state.documents.get(params.textDocument.uri);
|
|
334
|
+
if (!doc) return null;
|
|
335
|
+
return handleDefinition(state.workspace, doc, params.position);
|
|
336
|
+
});
|
|
337
|
+
connection.onReferences((params) => {
|
|
338
|
+
const doc = state.documents.get(params.textDocument.uri);
|
|
339
|
+
if (!doc) return null;
|
|
340
|
+
return handleReferences(state.workspace, doc, params.position, params.context);
|
|
341
|
+
});
|
|
342
|
+
connection.onHover((params) => {
|
|
343
|
+
const doc = state.documents.get(params.textDocument.uri);
|
|
344
|
+
if (!doc) return null;
|
|
345
|
+
return handleHover(state.workspace, doc, params.position);
|
|
346
|
+
});
|
|
347
|
+
connection.onCompletion((params) => {
|
|
348
|
+
const doc = state.documents.get(params.textDocument.uri);
|
|
349
|
+
if (!doc) return [];
|
|
350
|
+
return handleCompletion(state.workspace, doc, params);
|
|
351
|
+
});
|
|
352
|
+
connection.onCompletionResolve((item) => {
|
|
353
|
+
return handleCompletionResolve(item);
|
|
354
|
+
});
|
|
355
|
+
connection.onRequest("textDocument/semanticTokens/full", (params) => {
|
|
356
|
+
const doc = state.documents.get(params.textDocument.uri);
|
|
357
|
+
if (!doc) return { data: [] };
|
|
358
|
+
return handleSemanticTokens(doc);
|
|
359
|
+
});
|
|
360
|
+
connection.listen();
|
|
361
|
+
console.error("[thalo-lsp] Server started");
|
|
362
|
+
}
|
|
363
|
+
if (import.meta.url === `file://${process.argv[1]}`) startServer();
|
|
364
|
+
|
|
365
|
+
//#endregion
|
|
366
|
+
export { createConnection, startServer, tokenLegend };
|
|
367
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","names":["files: string[]","path","createLspConnection","allAffectedFiles: string[]"],"sources":["../src/server.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n createConnection as createLspConnection,\n ProposedFeatures,\n InitializeParams,\n InitializeResult,\n type Connection,\n DidChangeConfigurationNotification,\n FileChangeType,\n} from \"vscode-languageserver/node.js\";\nimport { TextDocument } from \"vscode-languageserver-textdocument\";\nimport type { FileType } from \"@rejot-dev/thalo\";\nimport { createWorkspace, Workspace } from \"@rejot-dev/thalo/native\";\n\nimport { serverCapabilities, tokenLegend } from \"./capabilities.js\";\nimport { handleDefinition } from \"./handlers/definition.js\";\nimport { handleReferences } from \"./handlers/references.js\";\nimport { handleSemanticTokens } from \"./handlers/semantic-tokens.js\";\nimport { getDiagnostics } from \"./handlers/diagnostics.js\";\nimport { handleHover } from \"./handlers/hover.js\";\nimport { handleCompletion, handleCompletionResolve } from \"./handlers/completions/completions.js\";\n\n/**\n * Server state\n */\ninterface ServerState {\n /** The thalo workspace for cross-file features */\n workspace: Workspace;\n /** Text documents managed by the server */\n documents: Map<string, TextDocument>;\n /** The LSP connection */\n connection: Connection;\n /** Workspace folder paths (file system paths, not URIs) */\n workspaceFolders: string[];\n}\n\n/**\n * Create the initial server state\n */\nfunction createServerState(connection: Connection): ServerState {\n return {\n workspace: createWorkspace(),\n documents: new Map(),\n connection,\n workspaceFolders: [],\n };\n}\n\n/**\n * Get the file type from a URI\n */\nfunction getFileType(uri: string): FileType {\n if (uri.endsWith(\".thalo\")) {\n return \"thalo\";\n }\n if (uri.endsWith(\".md\")) {\n return \"markdown\";\n }\n // Default to thalo\n return \"thalo\";\n}\n\n/**\n * Convert a URI to a file path\n */\nfunction uriToPath(uri: string): string {\n // Remove file:// prefix\n if (uri.startsWith(\"file://\")) {\n return decodeURIComponent(uri.slice(7));\n }\n return uri;\n}\n\n/**\n * Collect all .thalo and .md files from a directory recursively\n */\nfunction collectThaloFiles(dir: string): string[] {\n const files: string[] = [];\n\n function walk(currentDir: string): void {\n let entries;\n try {\n entries = fs.readdirSync(currentDir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(currentDir, entry.name);\n\n if (entry.isDirectory()) {\n // Skip hidden directories and node_modules\n if (!entry.name.startsWith(\".\") && entry.name !== \"node_modules\") {\n walk(fullPath);\n }\n } else if (entry.isFile()) {\n if (entry.name.endsWith(\".thalo\") || entry.name.endsWith(\".md\")) {\n files.push(fullPath);\n }\n }\n }\n }\n\n walk(dir);\n return files;\n}\n\n/**\n * Load all thalo files from the workspace folders into the workspace.\n * This ensures cross-file features work correctly even for files not yet opened.\n */\nfunction loadWorkspaceFiles(state: ServerState): void {\n for (const folder of state.workspaceFolders) {\n const files = collectThaloFiles(folder);\n\n for (const file of files) {\n // Skip if already loaded (e.g., from an open document)\n if (state.workspace.getModel(file)) {\n continue;\n }\n\n try {\n const source = fs.readFileSync(file, \"utf-8\");\n const fileType = getFileType(file);\n state.workspace.addDocument(source, { filename: file, fileType });\n } catch (err) {\n console.error(\n `[thalo-lsp] Error loading ${file}: ${err instanceof Error ? err.message : err}`,\n );\n }\n }\n\n console.error(`[thalo-lsp] Loaded ${files.length} files from ${folder}`);\n }\n}\n\n/**\n * Publish diagnostics for a single document\n */\nfunction publishDiagnosticsForDocument(state: ServerState, doc: TextDocument): void {\n try {\n const diagnostics = getDiagnostics(state.workspace, doc);\n state.connection.sendDiagnostics({\n uri: doc.uri,\n diagnostics,\n });\n } catch (error) {\n const path = uriToPath(doc.uri);\n console.error(`[thalo-lsp] Error getting diagnostics for ${path}:`, error);\n state.connection.sendDiagnostics({\n uri: doc.uri,\n diagnostics: [\n {\n range: {\n start: { line: 0, character: 0 },\n end: { line: 0, character: 0 },\n },\n severity: 1, // Error\n source: \"thalo\",\n message: `Diagnostic error: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n });\n }\n}\n\n/**\n * Refresh diagnostics for specific files based on invalidation result.\n * Only refreshes open documents that are in the affected files list.\n */\nfunction refreshDiagnosticsForFiles(\n state: ServerState,\n affectedFiles: string[],\n changedFile: string,\n): void {\n const affectedSet = new Set(affectedFiles);\n\n // Always refresh the changed file\n for (const doc of state.documents.values()) {\n const docPath = uriToPath(doc.uri);\n if (docPath === changedFile || affectedSet.has(docPath)) {\n publishDiagnosticsForDocument(state, doc);\n }\n }\n}\n\n/**\n * Update a document in the workspace and publish diagnostics\n */\nfunction updateDocument(state: ServerState, doc: TextDocument): void {\n const filePath = uriToPath(doc.uri);\n\n try {\n // Use the new updateDocument method which returns affected files\n const invalidation = state.workspace.updateDocument(filePath, doc.getText());\n\n // Refresh diagnostics for affected files only (more efficient)\n if (invalidation.schemasChanged || invalidation.linksChanged) {\n // If schemas or links changed, we might affect other files\n refreshDiagnosticsForFiles(state, invalidation.affectedFiles, filePath);\n } else {\n // Only the changed file is affected\n publishDiagnosticsForDocument(state, doc);\n }\n } catch (error) {\n // Log parse errors but don't crash\n console.error(`[thalo-lsp] Parse error in ${filePath}:`, error);\n\n // Send a parse error diagnostic for the changed document\n state.connection.sendDiagnostics({\n uri: doc.uri,\n diagnostics: [\n {\n range: {\n start: { line: 0, character: 0 },\n end: { line: 0, character: 0 },\n },\n severity: 1, // Error\n source: \"thalo\",\n message: `Parse error: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n });\n }\n}\n\n/**\n * Create a new LSP connection\n */\nexport function createConnection(): Connection {\n return createLspConnection(ProposedFeatures.all);\n}\n\n/**\n * Start the LSP server\n *\n * @param connection - The LSP connection to use (defaults to stdio)\n */\nexport function startServer(connection: Connection = createConnection()): void {\n const state = createServerState(connection);\n\n // Initialize handler\n connection.onInitialize((params: InitializeParams): InitializeResult => {\n console.error(`[thalo-lsp] Initializing with workspace: ${params.workspaceFolders?.[0]?.uri}`);\n\n // Store workspace folders for later file scanning\n if (params.workspaceFolders) {\n state.workspaceFolders = params.workspaceFolders.map((folder) => uriToPath(folder.uri));\n } else if (params.rootUri) {\n state.workspaceFolders = [uriToPath(params.rootUri)];\n }\n\n return {\n capabilities: serverCapabilities,\n serverInfo: {\n name: \"thalo-lsp\",\n version: \"0.0.0\",\n },\n };\n });\n\n connection.onInitialized(() => {\n console.error(\"[thalo-lsp] Server initialized\");\n\n // Register for configuration changes\n connection.client.register(DidChangeConfigurationNotification.type, undefined);\n\n // Load all workspace files for cross-file features (entity definitions, links, etc.)\n loadWorkspaceFiles(state);\n });\n\n // Document lifecycle\n connection.onDidOpenTextDocument((params) => {\n const doc = TextDocument.create(\n params.textDocument.uri,\n params.textDocument.languageId,\n params.textDocument.version,\n params.textDocument.text,\n );\n state.documents.set(params.textDocument.uri, doc);\n updateDocument(state, doc);\n\n console.error(`[thalo-lsp] Opened: ${params.textDocument.uri}`);\n });\n\n connection.onDidChangeTextDocument((params) => {\n const doc = state.documents.get(params.textDocument.uri);\n if (doc) {\n const updated = TextDocument.update(doc, params.contentChanges, params.textDocument.version);\n state.documents.set(params.textDocument.uri, updated);\n updateDocument(state, updated);\n }\n });\n\n connection.onDidCloseTextDocument((params) => {\n state.documents.delete(params.textDocument.uri);\n const filePath = uriToPath(params.textDocument.uri);\n\n // Reload from disk to pick up saved changes and keep cross-file features working\n try {\n if (fs.existsSync(filePath)) {\n const source = fs.readFileSync(filePath, \"utf-8\");\n const fileType = getFileType(params.textDocument.uri);\n state.workspace.addDocument(source, { filename: filePath, fileType });\n } else {\n // File was deleted, remove from workspace\n state.workspace.removeDocument(filePath);\n }\n } catch {\n // If we can't read the file, remove it from the workspace\n state.workspace.removeDocument(filePath);\n }\n\n // Clear diagnostics for closed document (not actively editing it)\n connection.sendDiagnostics({\n uri: params.textDocument.uri,\n diagnostics: [],\n });\n\n console.error(`[thalo-lsp] Closed: ${params.textDocument.uri}`);\n });\n\n // File watcher notifications - handles external file changes\n connection.onDidChangeWatchedFiles((params) => {\n const allAffectedFiles: string[] = [];\n\n for (const change of params.changes) {\n const filePath = uriToPath(change.uri);\n\n // Only process thalo and markdown files\n if (!filePath.endsWith(\".thalo\") && !filePath.endsWith(\".md\")) {\n continue;\n }\n\n // For delete events, always process - even if file is open in editor\n // (VSCode may keep deleted file tabs open, but workspace should reflect reality)\n if (change.type === FileChangeType.Deleted) {\n // Get affected files before removing\n const affected = state.workspace.getAffectedFiles(filePath);\n allAffectedFiles.push(...affected);\n state.workspace.removeDocument(filePath);\n state.documents.delete(change.uri);\n // Clear diagnostics for the deleted file\n connection.sendDiagnostics({ uri: change.uri, diagnostics: [] });\n console.error(`[thalo-lsp] Removed deleted file: ${filePath}`);\n continue;\n }\n\n // Skip create/change if the file is currently open (handled by document lifecycle)\n if (state.documents.has(change.uri)) {\n continue;\n }\n\n switch (change.type) {\n case FileChangeType.Created:\n case FileChangeType.Changed: {\n // Load/reload the file into workspace\n try {\n if (fs.existsSync(filePath)) {\n const source = fs.readFileSync(filePath, \"utf-8\");\n const invalidation = state.workspace.updateDocument(filePath, source);\n allAffectedFiles.push(...invalidation.affectedFiles);\n console.error(`[thalo-lsp] Loaded external file: ${filePath}`);\n }\n } catch (err) {\n console.error(\n `[thalo-lsp] Error loading ${filePath}: ${err instanceof Error ? err.message : err}`,\n );\n }\n break;\n }\n }\n }\n\n // Refresh diagnostics only for affected open documents\n if (allAffectedFiles.length > 0) {\n const affectedSet = new Set(allAffectedFiles);\n for (const doc of state.documents.values()) {\n if (affectedSet.has(uriToPath(doc.uri))) {\n publishDiagnosticsForDocument(state, doc);\n }\n }\n }\n });\n\n // File operation notifications - handles user-initiated file operations in the editor\n connection.workspace.onDidCreateFiles((params) => {\n const allAffectedFiles: string[] = [];\n\n for (const file of params.files) {\n const filePath = uriToPath(file.uri);\n\n // Only process thalo and markdown files\n if (!filePath.endsWith(\".thalo\") && !filePath.endsWith(\".md\")) {\n continue;\n }\n\n // Load the new file into workspace\n try {\n if (fs.existsSync(filePath)) {\n const source = fs.readFileSync(filePath, \"utf-8\");\n const invalidation = state.workspace.updateDocument(filePath, source);\n allAffectedFiles.push(...invalidation.affectedFiles);\n console.error(`[thalo-lsp] Loaded created file: ${filePath}`);\n }\n } catch (err) {\n console.error(\n `[thalo-lsp] Error loading created file ${filePath}: ${err instanceof Error ? err.message : err}`,\n );\n }\n }\n\n // Refresh diagnostics for affected files\n if (allAffectedFiles.length > 0) {\n const affectedSet = new Set(allAffectedFiles);\n for (const doc of state.documents.values()) {\n if (affectedSet.has(uriToPath(doc.uri))) {\n publishDiagnosticsForDocument(state, doc);\n }\n }\n }\n });\n\n connection.workspace.onDidDeleteFiles((params) => {\n const allAffectedFiles: string[] = [];\n\n for (const file of params.files) {\n const filePath = uriToPath(file.uri);\n\n // Only process thalo and markdown files\n if (!filePath.endsWith(\".thalo\") && !filePath.endsWith(\".md\")) {\n continue;\n }\n\n // Get affected files before removing\n const affected = state.workspace.getAffectedFiles(filePath);\n allAffectedFiles.push(...affected);\n state.workspace.removeDocument(filePath);\n console.error(`[thalo-lsp] Removed file: ${filePath}`);\n }\n\n // Refresh diagnostics for affected files\n if (allAffectedFiles.length > 0) {\n const affectedSet = new Set(allAffectedFiles);\n for (const doc of state.documents.values()) {\n if (affectedSet.has(uriToPath(doc.uri))) {\n publishDiagnosticsForDocument(state, doc);\n }\n }\n }\n });\n\n connection.workspace.onDidRenameFiles((params) => {\n const allAffectedFiles: string[] = [];\n\n for (const file of params.files) {\n const oldPath = uriToPath(file.oldUri);\n const newPath = uriToPath(file.newUri);\n\n // Only process thalo and markdown files\n const oldIsThalo = oldPath.endsWith(\".thalo\") || oldPath.endsWith(\".md\");\n const newIsThalo = newPath.endsWith(\".thalo\") || newPath.endsWith(\".md\");\n\n if (oldIsThalo) {\n // Get affected files before removing\n const affected = state.workspace.getAffectedFiles(oldPath);\n allAffectedFiles.push(...affected);\n state.workspace.removeDocument(oldPath);\n console.error(`[thalo-lsp] Removed renamed file: ${oldPath}`);\n }\n\n if (newIsThalo) {\n // Load the file at its new location\n try {\n if (fs.existsSync(newPath)) {\n const source = fs.readFileSync(newPath, \"utf-8\");\n const invalidation = state.workspace.updateDocument(newPath, source);\n allAffectedFiles.push(...invalidation.affectedFiles);\n console.error(`[thalo-lsp] Loaded renamed file: ${newPath}`);\n }\n } catch (err) {\n console.error(\n `[thalo-lsp] Error loading renamed file ${newPath}: ${err instanceof Error ? err.message : err}`,\n );\n }\n }\n }\n\n // Refresh diagnostics for affected files\n if (allAffectedFiles.length > 0) {\n const affectedSet = new Set(allAffectedFiles);\n for (const doc of state.documents.values()) {\n if (affectedSet.has(uriToPath(doc.uri))) {\n publishDiagnosticsForDocument(state, doc);\n }\n }\n }\n });\n\n // Go to Definition\n connection.onDefinition((params) => {\n const doc = state.documents.get(params.textDocument.uri);\n if (!doc) {\n return null;\n }\n\n return handleDefinition(state.workspace, doc, params.position);\n });\n\n // Find All References\n connection.onReferences((params) => {\n const doc = state.documents.get(params.textDocument.uri);\n if (!doc) {\n return null;\n }\n\n return handleReferences(state.workspace, doc, params.position, params.context);\n });\n\n // Hover\n connection.onHover((params) => {\n const doc = state.documents.get(params.textDocument.uri);\n if (!doc) {\n return null;\n }\n\n return handleHover(state.workspace, doc, params.position);\n });\n\n // Completion\n connection.onCompletion((params) => {\n const doc = state.documents.get(params.textDocument.uri);\n if (!doc) {\n return [];\n }\n\n return handleCompletion(state.workspace, doc, params);\n });\n\n // Completion resolve\n connection.onCompletionResolve((item) => {\n return handleCompletionResolve(item);\n });\n\n // Semantic Tokens (full)\n connection.onRequest(\"textDocument/semanticTokens/full\", (params) => {\n const doc = state.documents.get(params.textDocument.uri);\n if (!doc) {\n return { data: [] };\n }\n\n return handleSemanticTokens(doc);\n });\n\n // Start listening\n connection.listen();\n console.error(\"[thalo-lsp] Server started\");\n}\n\n// Run server when executed directly\nif (import.meta.url === `file://${process.argv[1]}`) {\n startServer();\n}\n\n// Export for testing\nexport { tokenLegend };\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rejot-dev/thalo-lsp",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/rejot-dev/thalo.git",
|
|
8
|
+
"directory": "packages/thalo-lsp"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"development": "./src/mod.ts",
|
|
17
|
+
"types": "./dist/mod.d.ts",
|
|
18
|
+
"default": "./dist/mod.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"main": "./dist/mod.js",
|
|
22
|
+
"types": "./dist/mod.d.ts",
|
|
23
|
+
"bin": {
|
|
24
|
+
"thalo-lsp": "./dist/server.js"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"vscode-languageserver": "^9.0.1",
|
|
28
|
+
"vscode-languageserver-textdocument": "^1.0.12",
|
|
29
|
+
"@rejot-dev/thalo": "0.0.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^24",
|
|
33
|
+
"tsdown": "^0.15.12",
|
|
34
|
+
"typescript": "^5.7.3",
|
|
35
|
+
"vitest": "^3.2.4",
|
|
36
|
+
"@rejot-private/typescript-config": "0.0.1"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsdown",
|
|
40
|
+
"build:watch": "tsdown --watch",
|
|
41
|
+
"types:check": "tsc --noEmit",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"test:watch": "vitest --watch"
|
|
44
|
+
}
|
|
45
|
+
}
|