@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
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { PRIMITIVE_TYPES } from "@rejot-dev/thalo";
|
|
2
|
+
|
|
3
|
+
//#region src/handlers/completions/providers/type-expr.ts
|
|
4
|
+
/**
|
|
5
|
+
* Get description for a primitive type.
|
|
6
|
+
*/
|
|
7
|
+
function getPrimitiveTypeDescription(type) {
|
|
8
|
+
switch (type) {
|
|
9
|
+
case "string": return "Any text value";
|
|
10
|
+
case "datetime": return "Date value (YYYY-MM-DD)";
|
|
11
|
+
case "daterange": return "Date range (YYYY ~ YYYY, YYYY-MM, YYYY Q1, etc.)";
|
|
12
|
+
case "link": return "Reference to another entry (^link-id)";
|
|
13
|
+
case "number": return "Numeric value (integer or float)";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Provider for type expression completion in schema field definitions.
|
|
18
|
+
*/
|
|
19
|
+
const typeExprProvider = {
|
|
20
|
+
name: "type-expr",
|
|
21
|
+
contextKinds: ["field_type"],
|
|
22
|
+
getCompletions(ctx, _workspace) {
|
|
23
|
+
const partial = ctx.partial.toLowerCase();
|
|
24
|
+
const items = [];
|
|
25
|
+
for (const type of PRIMITIVE_TYPES) {
|
|
26
|
+
if (partial && !type.toLowerCase().startsWith(partial)) continue;
|
|
27
|
+
items.push({
|
|
28
|
+
label: type,
|
|
29
|
+
kind: 25,
|
|
30
|
+
detail: "Primitive type",
|
|
31
|
+
documentation: {
|
|
32
|
+
kind: "markdown",
|
|
33
|
+
value: getPrimitiveTypeDescription(type)
|
|
34
|
+
},
|
|
35
|
+
insertText: type,
|
|
36
|
+
filterText: type
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (!partial || "\"".startsWith(partial)) items.push({
|
|
40
|
+
label: "\"...\"",
|
|
41
|
+
kind: 12,
|
|
42
|
+
detail: "Literal type",
|
|
43
|
+
documentation: {
|
|
44
|
+
kind: "markdown",
|
|
45
|
+
value: "Define a literal value type (e.g., \"article\" | \"video\")"
|
|
46
|
+
},
|
|
47
|
+
insertText: "\"",
|
|
48
|
+
filterText: "\""
|
|
49
|
+
});
|
|
50
|
+
return items;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
export { typeExprProvider };
|
|
56
|
+
//# sourceMappingURL=type-expr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-expr.js","names":["typeExprProvider: CompletionProvider","items: CompletionItem[]"],"sources":["../../../../src/handlers/completions/providers/type-expr.ts"],"sourcesContent":["import type { CompletionItem, CompletionItemKind } from \"vscode-languageserver\";\nimport type { Workspace } from \"@rejot-dev/thalo\";\nimport { PRIMITIVE_TYPES, type PrimitiveType } from \"@rejot-dev/thalo\";\nimport type { CompletionContext } from \"../context.js\";\nimport type { CompletionProvider } from \"../completions.js\";\n\n/**\n * Get description for a primitive type.\n */\nfunction getPrimitiveTypeDescription(type: PrimitiveType): string {\n switch (type) {\n case \"string\":\n return \"Any text value\";\n case \"datetime\":\n return \"Date value (YYYY-MM-DD)\";\n case \"daterange\":\n return \"Date range (YYYY ~ YYYY, YYYY-MM, YYYY Q1, etc.)\";\n case \"link\":\n return \"Reference to another entry (^link-id)\";\n case \"number\":\n return \"Numeric value (integer or float)\";\n }\n}\n\n/**\n * Provider for type expression completion in schema field definitions.\n */\nexport const typeExprProvider: CompletionProvider = {\n name: \"type-expr\",\n contextKinds: [\"field_type\"],\n\n getCompletions(ctx: CompletionContext, _workspace: Workspace): CompletionItem[] {\n const partial = ctx.partial.toLowerCase();\n const items: CompletionItem[] = [];\n\n // Suggest primitive types\n for (const type of PRIMITIVE_TYPES) {\n if (partial && !type.toLowerCase().startsWith(partial)) {\n continue;\n }\n\n items.push({\n label: type,\n kind: 25 as CompletionItemKind, // TypeParameter\n detail: \"Primitive type\",\n documentation: {\n kind: \"markdown\",\n value: getPrimitiveTypeDescription(type),\n },\n insertText: type,\n filterText: type,\n });\n }\n\n // Suggest starting a literal type with quote\n if (!partial || '\"'.startsWith(partial)) {\n items.push({\n label: '\"...\"',\n kind: 12 as CompletionItemKind, // Value\n detail: \"Literal type\",\n documentation: {\n kind: \"markdown\",\n value: 'Define a literal value type (e.g., \"article\" | \"video\")',\n },\n insertText: '\"',\n filterText: '\"',\n });\n }\n\n return items;\n },\n};\n"],"mappings":";;;;;;AASA,SAAS,4BAA4B,MAA6B;AAChE,SAAQ,MAAR;EACE,KAAK,SACH,QAAO;EACT,KAAK,WACH,QAAO;EACT,KAAK,YACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,SACH,QAAO;;;;;;AAOb,MAAaA,mBAAuC;CAClD,MAAM;CACN,cAAc,CAAC,aAAa;CAE5B,eAAe,KAAwB,YAAyC;EAC9E,MAAM,UAAU,IAAI,QAAQ,aAAa;EACzC,MAAMC,QAA0B,EAAE;AAGlC,OAAK,MAAM,QAAQ,iBAAiB;AAClC,OAAI,WAAW,CAAC,KAAK,aAAa,CAAC,WAAW,QAAQ,CACpD;AAGF,SAAM,KAAK;IACT,OAAO;IACP,MAAM;IACN,QAAQ;IACR,eAAe;KACb,MAAM;KACN,OAAO,4BAA4B,KAAK;KACzC;IACD,YAAY;IACZ,YAAY;IACb,CAAC;;AAIJ,MAAI,CAAC,WAAW,KAAI,WAAW,QAAQ,CACrC,OAAM,KAAK;GACT,OAAO;GACP,MAAM;GACN,QAAQ;GACR,eAAe;IACb,MAAM;IACN,OAAO;IACR;GACD,YAAY;GACZ,YAAY;GACb,CAAC;AAGJ,SAAO;;CAEV"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { parseDocument } from "@rejot-dev/thalo/native";
|
|
2
|
+
import { findDefinition, findEntityDefinition, findFieldDefinition, findNodeAtPosition, findSectionDefinition } from "@rejot-dev/thalo";
|
|
3
|
+
|
|
4
|
+
//#region src/handlers/definition.ts
|
|
5
|
+
/**
|
|
6
|
+
* Convert a file path to a URI
|
|
7
|
+
*/
|
|
8
|
+
function pathToUri(path) {
|
|
9
|
+
if (!path.startsWith("file://")) return `file://${encodeURIComponent(path).replace(/%2F/g, "/")}`;
|
|
10
|
+
return path;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get the file type from a URI
|
|
14
|
+
*/
|
|
15
|
+
function getFileType(uri) {
|
|
16
|
+
if (uri.endsWith(".thalo")) return "thalo";
|
|
17
|
+
if (uri.endsWith(".md")) return "markdown";
|
|
18
|
+
return "thalo";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Convert LSP Position to thalo Position (both are 0-based).
|
|
22
|
+
*/
|
|
23
|
+
function lspToThaloPosition(pos) {
|
|
24
|
+
return {
|
|
25
|
+
line: pos.line,
|
|
26
|
+
column: pos.character
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Handle textDocument/definition request
|
|
31
|
+
*
|
|
32
|
+
* Finds the definition location for various syntax elements at the given position:
|
|
33
|
+
* - ^link-id → Entry definition
|
|
34
|
+
* - Entity name in instance/alter-entity → define-entity
|
|
35
|
+
* - Metadata key → Field definition in schema
|
|
36
|
+
* - Section header → Section definition in schema
|
|
37
|
+
*
|
|
38
|
+
* Supports both standalone .thalo files and thalo blocks embedded in markdown.
|
|
39
|
+
*
|
|
40
|
+
* @param workspace - The thalo workspace
|
|
41
|
+
* @param document - The text document
|
|
42
|
+
* @param position - The position in the document (line/character)
|
|
43
|
+
* @returns The definition location, or null if not found
|
|
44
|
+
*/
|
|
45
|
+
function handleDefinition(workspace, document, position) {
|
|
46
|
+
const fileType = getFileType(document.uri);
|
|
47
|
+
try {
|
|
48
|
+
const context = findNodeAtPosition(parseDocument(document.getText(), {
|
|
49
|
+
fileType,
|
|
50
|
+
filename: document.uri
|
|
51
|
+
}), lspToThaloPosition(position));
|
|
52
|
+
switch (context.kind) {
|
|
53
|
+
case "link": {
|
|
54
|
+
const result = findDefinition(workspace, context.linkId);
|
|
55
|
+
if (result) return {
|
|
56
|
+
uri: pathToUri(result.file),
|
|
57
|
+
range: {
|
|
58
|
+
start: {
|
|
59
|
+
line: result.location.startPosition.row,
|
|
60
|
+
character: result.location.startPosition.column
|
|
61
|
+
},
|
|
62
|
+
end: {
|
|
63
|
+
line: result.location.endPosition.row,
|
|
64
|
+
character: result.location.endPosition.column
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
case "entity":
|
|
71
|
+
case "schema_entity": {
|
|
72
|
+
const result = findEntityDefinition(workspace, context.kind === "entity" ? context.entityName : context.entityName);
|
|
73
|
+
if (result) return {
|
|
74
|
+
uri: pathToUri(result.file),
|
|
75
|
+
range: {
|
|
76
|
+
start: {
|
|
77
|
+
line: result.location.startPosition.row,
|
|
78
|
+
character: result.location.startPosition.column
|
|
79
|
+
},
|
|
80
|
+
end: {
|
|
81
|
+
line: result.location.endPosition.row,
|
|
82
|
+
character: result.location.endPosition.column
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
case "metadata_key": {
|
|
89
|
+
const result = findFieldDefinition(workspace, context.key, context.entityContext);
|
|
90
|
+
if (result) return {
|
|
91
|
+
uri: pathToUri(result.file),
|
|
92
|
+
range: {
|
|
93
|
+
start: {
|
|
94
|
+
line: result.location.startPosition.row,
|
|
95
|
+
character: result.location.startPosition.column
|
|
96
|
+
},
|
|
97
|
+
end: {
|
|
98
|
+
line: result.location.endPosition.row,
|
|
99
|
+
character: result.location.endPosition.column
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
case "section_header": {
|
|
106
|
+
const result = findSectionDefinition(workspace, context.sectionName, context.entityContext);
|
|
107
|
+
if (result) return {
|
|
108
|
+
uri: pathToUri(result.file),
|
|
109
|
+
range: {
|
|
110
|
+
start: {
|
|
111
|
+
line: result.location.startPosition.row,
|
|
112
|
+
character: result.location.startPosition.column
|
|
113
|
+
},
|
|
114
|
+
end: {
|
|
115
|
+
line: result.location.endPosition.row,
|
|
116
|
+
character: result.location.endPosition.column
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
case "field_name": {
|
|
123
|
+
const result = findFieldDefinition(workspace, context.fieldName, context.entityContext);
|
|
124
|
+
if (result) return {
|
|
125
|
+
uri: pathToUri(result.file),
|
|
126
|
+
range: {
|
|
127
|
+
start: {
|
|
128
|
+
line: result.location.startPosition.row,
|
|
129
|
+
character: result.location.startPosition.column
|
|
130
|
+
},
|
|
131
|
+
end: {
|
|
132
|
+
line: result.location.endPosition.row,
|
|
133
|
+
character: result.location.endPosition.column
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
case "section_name": {
|
|
140
|
+
const result = findSectionDefinition(workspace, context.sectionName, context.entityContext);
|
|
141
|
+
if (result) return {
|
|
142
|
+
uri: pathToUri(result.file),
|
|
143
|
+
range: {
|
|
144
|
+
start: {
|
|
145
|
+
line: result.location.startPosition.row,
|
|
146
|
+
character: result.location.startPosition.column
|
|
147
|
+
},
|
|
148
|
+
end: {
|
|
149
|
+
line: result.location.endPosition.row,
|
|
150
|
+
character: result.location.endPosition.column
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
default: return null;
|
|
157
|
+
}
|
|
158
|
+
} catch (error) {
|
|
159
|
+
console.error(`[thalo-lsp] Error in definition handler:`, error);
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
//#endregion
|
|
165
|
+
export { handleDefinition };
|
|
166
|
+
//# sourceMappingURL=definition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition.js","names":[],"sources":["../../src/handlers/definition.ts"],"sourcesContent":["import type { Position, Location } from \"vscode-languageserver\";\nimport type { TextDocument } from \"vscode-languageserver-textdocument\";\nimport {\n findNodeAtPosition,\n findDefinition,\n findEntityDefinition,\n findFieldDefinition,\n findSectionDefinition,\n type Workspace,\n type Position as ThaloPosition,\n} from \"@rejot-dev/thalo\";\nimport { parseDocument } from \"@rejot-dev/thalo/native\";\n\n/**\n * Convert a file path to a URI\n */\nfunction pathToUri(path: string): string {\n // Add file:// prefix if not present\n if (!path.startsWith(\"file://\")) {\n return `file://${encodeURIComponent(path).replace(/%2F/g, \"/\")}`;\n }\n return path;\n}\n\n/**\n * Get the file type from a URI\n */\nfunction getFileType(uri: string): \"thalo\" | \"markdown\" {\n if (uri.endsWith(\".thalo\")) {\n return \"thalo\";\n }\n if (uri.endsWith(\".md\")) {\n return \"markdown\";\n }\n return \"thalo\";\n}\n\n/**\n * Convert LSP Position to thalo Position (both are 0-based).\n */\nfunction lspToThaloPosition(pos: Position): ThaloPosition {\n return { line: pos.line, column: pos.character };\n}\n\n/**\n * Handle textDocument/definition request\n *\n * Finds the definition location for various syntax elements at the given position:\n * - ^link-id → Entry definition\n * - Entity name in instance/alter-entity → define-entity\n * - Metadata key → Field definition in schema\n * - Section header → Section definition in schema\n *\n * Supports both standalone .thalo files and thalo blocks embedded in markdown.\n *\n * @param workspace - The thalo workspace\n * @param document - The text document\n * @param position - The position in the document (line/character)\n * @returns The definition location, or null if not found\n */\nexport function handleDefinition(\n workspace: Workspace,\n document: TextDocument,\n position: Position,\n): Location | null {\n const fileType = getFileType(document.uri);\n\n try {\n // Parse the document\n const parsed = parseDocument(document.getText(), {\n fileType,\n filename: document.uri,\n });\n\n // Find what element is at the position using the AST\n const context = findNodeAtPosition(parsed, lspToThaloPosition(position));\n\n switch (context.kind) {\n case \"link\": {\n // Find the definition for this link\n const result = findDefinition(workspace, context.linkId);\n if (result) {\n return {\n uri: pathToUri(result.file),\n range: {\n start: {\n line: result.location.startPosition.row,\n character: result.location.startPosition.column,\n },\n end: {\n line: result.location.endPosition.row,\n character: result.location.endPosition.column,\n },\n },\n };\n }\n return null;\n }\n\n case \"entity\":\n case \"schema_entity\": {\n // Find the define-entity for this entity\n const entityName = context.kind === \"entity\" ? context.entityName : context.entityName;\n const result = findEntityDefinition(workspace, entityName);\n if (result) {\n return {\n uri: pathToUri(result.file),\n range: {\n start: {\n line: result.location.startPosition.row,\n character: result.location.startPosition.column,\n },\n end: {\n line: result.location.endPosition.row,\n character: result.location.endPosition.column,\n },\n },\n };\n }\n return null;\n }\n\n case \"metadata_key\": {\n // Find the field definition in the schema\n const result = findFieldDefinition(workspace, context.key, context.entityContext);\n if (result) {\n return {\n uri: pathToUri(result.file),\n range: {\n start: {\n line: result.location.startPosition.row,\n character: result.location.startPosition.column,\n },\n end: {\n line: result.location.endPosition.row,\n character: result.location.endPosition.column,\n },\n },\n };\n }\n return null;\n }\n\n case \"section_header\": {\n // Find the section definition in the schema\n const result = findSectionDefinition(workspace, context.sectionName, context.entityContext);\n if (result) {\n return {\n uri: pathToUri(result.file),\n range: {\n start: {\n line: result.location.startPosition.row,\n character: result.location.startPosition.column,\n },\n end: {\n line: result.location.endPosition.row,\n character: result.location.endPosition.column,\n },\n },\n };\n }\n return null;\n }\n\n case \"field_name\": {\n // In schema definitions, go to the field definition itself\n const result = findFieldDefinition(workspace, context.fieldName, context.entityContext);\n if (result) {\n return {\n uri: pathToUri(result.file),\n range: {\n start: {\n line: result.location.startPosition.row,\n character: result.location.startPosition.column,\n },\n end: {\n line: result.location.endPosition.row,\n character: result.location.endPosition.column,\n },\n },\n };\n }\n return null;\n }\n\n case \"section_name\": {\n // In schema definitions, go to the section definition itself\n const result = findSectionDefinition(workspace, context.sectionName, context.entityContext);\n if (result) {\n return {\n uri: pathToUri(result.file),\n range: {\n start: {\n line: result.location.startPosition.row,\n character: result.location.startPosition.column,\n },\n end: {\n line: result.location.endPosition.row,\n character: result.location.endPosition.column,\n },\n },\n };\n }\n return null;\n }\n\n default:\n return null;\n }\n } catch (error) {\n console.error(`[thalo-lsp] Error in definition handler:`, error);\n return null;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { checkDocument } from "@rejot-dev/thalo";
|
|
2
|
+
|
|
3
|
+
//#region src/handlers/diagnostics.ts
|
|
4
|
+
/**
|
|
5
|
+
* Map thalo severity to LSP DiagnosticSeverity
|
|
6
|
+
*/
|
|
7
|
+
function mapSeverity(severity) {
|
|
8
|
+
switch (severity) {
|
|
9
|
+
case "error": return 1;
|
|
10
|
+
case "warning": return 2;
|
|
11
|
+
case "info": return 3;
|
|
12
|
+
default: return 3;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Convert a URI to a file path
|
|
17
|
+
*/
|
|
18
|
+
function uriToPath(uri) {
|
|
19
|
+
if (uri.startsWith("file://")) return decodeURIComponent(uri.slice(7));
|
|
20
|
+
return uri;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Convert a thalo Diagnostic to an LSP Diagnostic
|
|
24
|
+
*/
|
|
25
|
+
function convertDiagnostic(diagnostic) {
|
|
26
|
+
return {
|
|
27
|
+
range: {
|
|
28
|
+
start: {
|
|
29
|
+
line: diagnostic.location.startPosition.row,
|
|
30
|
+
character: diagnostic.location.startPosition.column
|
|
31
|
+
},
|
|
32
|
+
end: {
|
|
33
|
+
line: diagnostic.location.endPosition.row,
|
|
34
|
+
character: diagnostic.location.endPosition.column
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
severity: mapSeverity(diagnostic.severity),
|
|
38
|
+
code: diagnostic.code,
|
|
39
|
+
source: "thalo",
|
|
40
|
+
message: diagnostic.message
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get diagnostics for a document
|
|
45
|
+
*
|
|
46
|
+
* @param workspace - The thalo workspace
|
|
47
|
+
* @param textDocument - The LSP text document
|
|
48
|
+
* @returns Array of LSP diagnostics
|
|
49
|
+
*/
|
|
50
|
+
function getDiagnostics(workspace, textDocument) {
|
|
51
|
+
const path = uriToPath(textDocument.uri);
|
|
52
|
+
if (!workspace.getModel(path)) return [];
|
|
53
|
+
try {
|
|
54
|
+
return checkDocument(path, workspace).map(convertDiagnostic);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error(`[thalo-lsp] Error checking ${path}:`, error);
|
|
57
|
+
return [{
|
|
58
|
+
range: {
|
|
59
|
+
start: {
|
|
60
|
+
line: 0,
|
|
61
|
+
character: 0
|
|
62
|
+
},
|
|
63
|
+
end: {
|
|
64
|
+
line: 0,
|
|
65
|
+
character: 0
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
severity: 1,
|
|
69
|
+
source: "thalo",
|
|
70
|
+
message: `Parse error: ${error instanceof Error ? error.message : String(error)}`
|
|
71
|
+
}];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
export { getDiagnostics };
|
|
77
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.js","names":[],"sources":["../../src/handlers/diagnostics.ts"],"sourcesContent":["import type { Diagnostic as LspDiagnostic, DiagnosticSeverity } from \"vscode-languageserver\";\nimport type { TextDocument } from \"vscode-languageserver-textdocument\";\nimport {\n checkDocument,\n type Workspace,\n type Diagnostic as ThaloDiagnostic,\n type Severity,\n} from \"@rejot-dev/thalo\";\n\n/**\n * Map thalo severity to LSP DiagnosticSeverity\n */\nfunction mapSeverity(severity: Severity): DiagnosticSeverity {\n switch (severity) {\n case \"error\":\n return 1; // DiagnosticSeverity.Error\n case \"warning\":\n return 2; // DiagnosticSeverity.Warning\n case \"info\":\n return 3; // DiagnosticSeverity.Information\n default:\n return 3;\n }\n}\n\n/**\n * Convert a URI to a file path\n */\nfunction uriToPath(uri: string): string {\n if (uri.startsWith(\"file://\")) {\n return decodeURIComponent(uri.slice(7));\n }\n return uri;\n}\n\n/**\n * Convert a thalo Diagnostic to an LSP Diagnostic\n */\nfunction convertDiagnostic(diagnostic: ThaloDiagnostic): LspDiagnostic {\n return {\n range: {\n start: {\n line: diagnostic.location.startPosition.row,\n character: diagnostic.location.startPosition.column,\n },\n end: {\n line: diagnostic.location.endPosition.row,\n character: diagnostic.location.endPosition.column,\n },\n },\n severity: mapSeverity(diagnostic.severity),\n code: diagnostic.code,\n source: \"thalo\",\n message: diagnostic.message,\n };\n}\n\n/**\n * Get diagnostics for a document\n *\n * @param workspace - The thalo workspace\n * @param textDocument - The LSP text document\n * @returns Array of LSP diagnostics\n */\nexport function getDiagnostics(workspace: Workspace, textDocument: TextDocument): LspDiagnostic[] {\n const path = uriToPath(textDocument.uri);\n const model = workspace.getModel(path);\n\n if (!model) {\n return [];\n }\n\n try {\n const thaloDiagnostics = checkDocument(path, workspace);\n return thaloDiagnostics.map(convertDiagnostic);\n } catch (error) {\n // Return a diagnostic for parse errors\n console.error(`[thalo-lsp] Error checking ${path}:`, error);\n return [\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"],"mappings":";;;;;;AAYA,SAAS,YAAY,UAAwC;AAC3D,SAAQ,UAAR;EACE,KAAK,QACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,QACE,QAAO;;;;;;AAOb,SAAS,UAAU,KAAqB;AACtC,KAAI,IAAI,WAAW,UAAU,CAC3B,QAAO,mBAAmB,IAAI,MAAM,EAAE,CAAC;AAEzC,QAAO;;;;;AAMT,SAAS,kBAAkB,YAA4C;AACrE,QAAO;EACL,OAAO;GACL,OAAO;IACL,MAAM,WAAW,SAAS,cAAc;IACxC,WAAW,WAAW,SAAS,cAAc;IAC9C;GACD,KAAK;IACH,MAAM,WAAW,SAAS,YAAY;IACtC,WAAW,WAAW,SAAS,YAAY;IAC5C;GACF;EACD,UAAU,YAAY,WAAW,SAAS;EAC1C,MAAM,WAAW;EACjB,QAAQ;EACR,SAAS,WAAW;EACrB;;;;;;;;;AAUH,SAAgB,eAAe,WAAsB,cAA6C;CAChG,MAAM,OAAO,UAAU,aAAa,IAAI;AAGxC,KAAI,CAFU,UAAU,SAAS,KAAK,CAGpC,QAAO,EAAE;AAGX,KAAI;AAEF,SADyB,cAAc,MAAM,UAAU,CAC/B,IAAI,kBAAkB;UACvC,OAAO;AAEd,UAAQ,MAAM,8BAA8B,KAAK,IAAI,MAAM;AAC3D,SAAO,CACL;GACE,OAAO;IACL,OAAO;KAAE,MAAM;KAAG,WAAW;KAAG;IAChC,KAAK;KAAE,MAAM;KAAG,WAAW;KAAG;IAC/B;GACD,UAAU;GACV,QAAQ;GACR,SAAS,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GAChF,CACF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { parseDocument } from "@rejot-dev/thalo/native";
|
|
2
|
+
import { findNodeAtPosition, getHoverInfo } from "@rejot-dev/thalo";
|
|
3
|
+
|
|
4
|
+
//#region src/handlers/hover.ts
|
|
5
|
+
/**
|
|
6
|
+
* Get the file type from a URI
|
|
7
|
+
*/
|
|
8
|
+
function getFileType(uri) {
|
|
9
|
+
if (uri.endsWith(".thalo")) return "thalo";
|
|
10
|
+
if (uri.endsWith(".md")) return "markdown";
|
|
11
|
+
return "thalo";
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Convert LSP Position to thalo Position (both are 0-based).
|
|
15
|
+
*/
|
|
16
|
+
function lspToThaloPosition(pos) {
|
|
17
|
+
return {
|
|
18
|
+
line: pos.line,
|
|
19
|
+
column: pos.character
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Handle textDocument/hover request
|
|
24
|
+
*
|
|
25
|
+
* Provides hover information for various syntax elements:
|
|
26
|
+
* - ^link-id: Shows target entry details
|
|
27
|
+
* - #tag: Shows tag usage statistics
|
|
28
|
+
* - Directives: Shows documentation
|
|
29
|
+
* - Entity names: Shows schema with fields and sections
|
|
30
|
+
* - Metadata keys: Shows field type and description
|
|
31
|
+
* - Type expressions: Shows type documentation
|
|
32
|
+
* - Section headers: Shows section description
|
|
33
|
+
* - Timestamps: Shows entry info or link reference hint
|
|
34
|
+
*
|
|
35
|
+
* Supports both standalone .thalo files and thalo blocks embedded in markdown.
|
|
36
|
+
*
|
|
37
|
+
* @param workspace - The thalo workspace
|
|
38
|
+
* @param document - The text document
|
|
39
|
+
* @param position - The hover position
|
|
40
|
+
* @returns Hover information, or null if nothing to show
|
|
41
|
+
*/
|
|
42
|
+
function handleHover(workspace, document, position) {
|
|
43
|
+
const fileType = getFileType(document.uri);
|
|
44
|
+
try {
|
|
45
|
+
const result = getHoverInfo(workspace, findNodeAtPosition(parseDocument(document.getText(), {
|
|
46
|
+
fileType,
|
|
47
|
+
filename: document.uri
|
|
48
|
+
}), lspToThaloPosition(position)));
|
|
49
|
+
if (!result) return null;
|
|
50
|
+
const hover = { contents: {
|
|
51
|
+
kind: "markdown",
|
|
52
|
+
value: result.content
|
|
53
|
+
} };
|
|
54
|
+
if (result.range) hover.range = {
|
|
55
|
+
start: {
|
|
56
|
+
line: result.range.startPosition.row,
|
|
57
|
+
character: result.range.startPosition.column
|
|
58
|
+
},
|
|
59
|
+
end: {
|
|
60
|
+
line: result.range.endPosition.row,
|
|
61
|
+
character: result.range.endPosition.column
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
return hover;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error(`[thalo-lsp] Error in hover handler:`, error);
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
export { handleHover };
|
|
73
|
+
//# sourceMappingURL=hover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hover.js","names":["hover: Hover"],"sources":["../../src/handlers/hover.ts"],"sourcesContent":["import type { Hover, Position } from \"vscode-languageserver\";\nimport type { TextDocument } from \"vscode-languageserver-textdocument\";\nimport {\n findNodeAtPosition,\n getHoverInfo,\n type Workspace,\n type Position as ThaloPosition,\n} from \"@rejot-dev/thalo\";\nimport { parseDocument } from \"@rejot-dev/thalo/native\";\n\n/**\n * Get the file type from a URI\n */\nfunction getFileType(uri: string): \"thalo\" | \"markdown\" {\n if (uri.endsWith(\".thalo\")) {\n return \"thalo\";\n }\n if (uri.endsWith(\".md\")) {\n return \"markdown\";\n }\n return \"thalo\";\n}\n\n/**\n * Convert LSP Position to thalo Position (both are 0-based).\n */\nfunction lspToThaloPosition(pos: Position): ThaloPosition {\n return { line: pos.line, column: pos.character };\n}\n\n/**\n * Handle textDocument/hover request\n *\n * Provides hover information for various syntax elements:\n * - ^link-id: Shows target entry details\n * - #tag: Shows tag usage statistics\n * - Directives: Shows documentation\n * - Entity names: Shows schema with fields and sections\n * - Metadata keys: Shows field type and description\n * - Type expressions: Shows type documentation\n * - Section headers: Shows section description\n * - Timestamps: Shows entry info or link reference hint\n *\n * Supports both standalone .thalo files and thalo blocks embedded in markdown.\n *\n * @param workspace - The thalo workspace\n * @param document - The text document\n * @param position - The hover position\n * @returns Hover information, or null if nothing to show\n */\nexport function handleHover(\n workspace: Workspace,\n document: TextDocument,\n position: Position,\n): Hover | null {\n const fileType = getFileType(document.uri);\n\n try {\n // Parse the document\n const parsed = parseDocument(document.getText(), {\n fileType,\n filename: document.uri,\n });\n\n // Find what element is at the position using the AST\n const context = findNodeAtPosition(parsed, lspToThaloPosition(position));\n\n // Get hover info from the service\n const result = getHoverInfo(workspace, context);\n\n if (!result) {\n return null;\n }\n\n // Convert to LSP Hover format\n const hover: Hover = {\n contents: {\n kind: \"markdown\",\n value: result.content,\n },\n };\n\n // Add range if available\n if (result.range) {\n hover.range = {\n start: {\n line: result.range.startPosition.row,\n character: result.range.startPosition.column,\n },\n end: {\n line: result.range.endPosition.row,\n character: result.range.endPosition.column,\n },\n };\n }\n\n return hover;\n } catch (error) {\n console.error(`[thalo-lsp] Error in hover handler:`, error);\n return null;\n }\n}\n"],"mappings":";;;;;;;AAaA,SAAS,YAAY,KAAmC;AACtD,KAAI,IAAI,SAAS,SAAS,CACxB,QAAO;AAET,KAAI,IAAI,SAAS,MAAM,CACrB,QAAO;AAET,QAAO;;;;;AAMT,SAAS,mBAAmB,KAA8B;AACxD,QAAO;EAAE,MAAM,IAAI;EAAM,QAAQ,IAAI;EAAW;;;;;;;;;;;;;;;;;;;;;;AAuBlD,SAAgB,YACd,WACA,UACA,UACc;CACd,MAAM,WAAW,YAAY,SAAS,IAAI;AAE1C,KAAI;EAWF,MAAM,SAAS,aAAa,WAHZ,mBAND,cAAc,SAAS,SAAS,EAAE;GAC/C;GACA,UAAU,SAAS;GACpB,CAAC,EAGyC,mBAAmB,SAAS,CAAC,CAGzB;AAE/C,MAAI,CAAC,OACH,QAAO;EAIT,MAAMA,QAAe,EACnB,UAAU;GACR,MAAM;GACN,OAAO,OAAO;GACf,EACF;AAGD,MAAI,OAAO,MACT,OAAM,QAAQ;GACZ,OAAO;IACL,MAAM,OAAO,MAAM,cAAc;IACjC,WAAW,OAAO,MAAM,cAAc;IACvC;GACD,KAAK;IACH,MAAM,OAAO,MAAM,YAAY;IAC/B,WAAW,OAAO,MAAM,YAAY;IACrC;GACF;AAGH,SAAO;UACA,OAAO;AACd,UAAQ,MAAM,uCAAuC,MAAM;AAC3D,SAAO"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { parseDocument } from "@rejot-dev/thalo/native";
|
|
2
|
+
import { findEntityReferences, findFieldReferences, findNodeAtPosition, findReferences, findSectionReferences, findTagReferences } from "@rejot-dev/thalo";
|
|
3
|
+
|
|
4
|
+
//#region src/handlers/references.ts
|
|
5
|
+
/**
|
|
6
|
+
* Convert a file path to a URI
|
|
7
|
+
*/
|
|
8
|
+
function pathToUri(path) {
|
|
9
|
+
if (!path.startsWith("file://")) return `file://${encodeURIComponent(path).replace(/%2F/g, "/")}`;
|
|
10
|
+
return path;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get the file type from a URI
|
|
14
|
+
*/
|
|
15
|
+
function getFileType(uri) {
|
|
16
|
+
if (uri.endsWith(".thalo")) return "thalo";
|
|
17
|
+
if (uri.endsWith(".md")) return "markdown";
|
|
18
|
+
return "thalo";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Convert LSP Position to thalo Position (both are 0-based).
|
|
22
|
+
*/
|
|
23
|
+
function lspToThaloPosition(pos) {
|
|
24
|
+
return {
|
|
25
|
+
line: pos.line,
|
|
26
|
+
column: pos.character
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Handle textDocument/references request
|
|
31
|
+
*
|
|
32
|
+
* Finds all references to various syntax elements at the given position:
|
|
33
|
+
* - ^link-id → All usages of that link
|
|
34
|
+
* - #tag → All entries with that tag
|
|
35
|
+
* - Entity name → All entries using that entity type
|
|
36
|
+
* - Metadata key → All entries using that field
|
|
37
|
+
* - Section header → All entries with that section
|
|
38
|
+
*
|
|
39
|
+
* Supports both standalone .thalo files and thalo blocks embedded in markdown.
|
|
40
|
+
*
|
|
41
|
+
* @param workspace - The thalo workspace
|
|
42
|
+
* @param document - The text document
|
|
43
|
+
* @param position - The position in the document (line/character)
|
|
44
|
+
* @param context - Reference context (includeDeclaration)
|
|
45
|
+
* @returns Array of reference locations, or null if not found
|
|
46
|
+
*/
|
|
47
|
+
function handleReferences(workspace, document, position, context) {
|
|
48
|
+
const fileType = getFileType(document.uri);
|
|
49
|
+
try {
|
|
50
|
+
const nodeContext = findNodeAtPosition(parseDocument(document.getText(), {
|
|
51
|
+
fileType,
|
|
52
|
+
filename: document.uri
|
|
53
|
+
}), lspToThaloPosition(position));
|
|
54
|
+
switch (nodeContext.kind) {
|
|
55
|
+
case "link": {
|
|
56
|
+
const result = findReferences(workspace, nodeContext.linkId, context.includeDeclaration);
|
|
57
|
+
if (result) return result.locations.map((loc) => ({
|
|
58
|
+
uri: pathToUri(loc.file),
|
|
59
|
+
range: {
|
|
60
|
+
start: {
|
|
61
|
+
line: loc.location.startPosition.row,
|
|
62
|
+
character: loc.location.startPosition.column
|
|
63
|
+
},
|
|
64
|
+
end: {
|
|
65
|
+
line: loc.location.endPosition.row,
|
|
66
|
+
character: loc.location.endPosition.column
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}));
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
case "tag": return findTagReferences(workspace, nodeContext.tagName).references.map((ref) => ({
|
|
73
|
+
uri: pathToUri(ref.file),
|
|
74
|
+
range: {
|
|
75
|
+
start: {
|
|
76
|
+
line: ref.location.startPosition.row,
|
|
77
|
+
character: ref.location.startPosition.column
|
|
78
|
+
},
|
|
79
|
+
end: {
|
|
80
|
+
line: ref.location.endPosition.row,
|
|
81
|
+
character: ref.location.endPosition.column
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}));
|
|
85
|
+
case "entity":
|
|
86
|
+
case "schema_entity": return findEntityReferences(workspace, nodeContext.kind === "entity" ? nodeContext.entityName : nodeContext.entityName, context.includeDeclaration).locations.map((loc) => ({
|
|
87
|
+
uri: pathToUri(loc.file),
|
|
88
|
+
range: {
|
|
89
|
+
start: {
|
|
90
|
+
line: loc.location.startPosition.row,
|
|
91
|
+
character: loc.location.startPosition.column
|
|
92
|
+
},
|
|
93
|
+
end: {
|
|
94
|
+
line: loc.location.endPosition.row,
|
|
95
|
+
character: loc.location.endPosition.column
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}));
|
|
99
|
+
case "metadata_key": {
|
|
100
|
+
const result = findFieldReferences(workspace, nodeContext.key, nodeContext.entityContext);
|
|
101
|
+
const locations = [];
|
|
102
|
+
if (context.includeDeclaration && result.definition) locations.push({
|
|
103
|
+
uri: pathToUri(result.definition.file),
|
|
104
|
+
range: {
|
|
105
|
+
start: {
|
|
106
|
+
line: result.definition.location.startPosition.row,
|
|
107
|
+
character: result.definition.location.startPosition.column
|
|
108
|
+
},
|
|
109
|
+
end: {
|
|
110
|
+
line: result.definition.location.endPosition.row,
|
|
111
|
+
character: result.definition.location.endPosition.column
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
for (const ref of result.references) locations.push({
|
|
116
|
+
uri: pathToUri(ref.file),
|
|
117
|
+
range: {
|
|
118
|
+
start: {
|
|
119
|
+
line: ref.location.startPosition.row,
|
|
120
|
+
character: ref.location.startPosition.column
|
|
121
|
+
},
|
|
122
|
+
end: {
|
|
123
|
+
line: ref.location.endPosition.row,
|
|
124
|
+
character: ref.location.endPosition.column
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return locations;
|
|
129
|
+
}
|
|
130
|
+
case "section_header": {
|
|
131
|
+
const result = findSectionReferences(workspace, nodeContext.sectionName, nodeContext.entityContext);
|
|
132
|
+
const locations = [];
|
|
133
|
+
if (context.includeDeclaration && result.definition) locations.push({
|
|
134
|
+
uri: pathToUri(result.definition.file),
|
|
135
|
+
range: {
|
|
136
|
+
start: {
|
|
137
|
+
line: result.definition.location.startPosition.row,
|
|
138
|
+
character: result.definition.location.startPosition.column
|
|
139
|
+
},
|
|
140
|
+
end: {
|
|
141
|
+
line: result.definition.location.endPosition.row,
|
|
142
|
+
character: result.definition.location.endPosition.column
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
for (const ref of result.references) locations.push({
|
|
147
|
+
uri: pathToUri(ref.file),
|
|
148
|
+
range: {
|
|
149
|
+
start: {
|
|
150
|
+
line: ref.location.startPosition.row,
|
|
151
|
+
character: ref.location.startPosition.column
|
|
152
|
+
},
|
|
153
|
+
end: {
|
|
154
|
+
line: ref.location.endPosition.row,
|
|
155
|
+
character: ref.location.endPosition.column
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return locations;
|
|
160
|
+
}
|
|
161
|
+
case "field_name": {
|
|
162
|
+
const result = findFieldReferences(workspace, nodeContext.fieldName, nodeContext.entityContext);
|
|
163
|
+
const locations = [];
|
|
164
|
+
if (context.includeDeclaration && result.definition) locations.push({
|
|
165
|
+
uri: pathToUri(result.definition.file),
|
|
166
|
+
range: {
|
|
167
|
+
start: {
|
|
168
|
+
line: result.definition.location.startPosition.row,
|
|
169
|
+
character: result.definition.location.startPosition.column
|
|
170
|
+
},
|
|
171
|
+
end: {
|
|
172
|
+
line: result.definition.location.endPosition.row,
|
|
173
|
+
character: result.definition.location.endPosition.column
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
for (const ref of result.references) locations.push({
|
|
178
|
+
uri: pathToUri(ref.file),
|
|
179
|
+
range: {
|
|
180
|
+
start: {
|
|
181
|
+
line: ref.location.startPosition.row,
|
|
182
|
+
character: ref.location.startPosition.column
|
|
183
|
+
},
|
|
184
|
+
end: {
|
|
185
|
+
line: ref.location.endPosition.row,
|
|
186
|
+
character: ref.location.endPosition.column
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
return locations;
|
|
191
|
+
}
|
|
192
|
+
case "section_name": {
|
|
193
|
+
const result = findSectionReferences(workspace, nodeContext.sectionName, nodeContext.entityContext);
|
|
194
|
+
const locations = [];
|
|
195
|
+
if (context.includeDeclaration && result.definition) locations.push({
|
|
196
|
+
uri: pathToUri(result.definition.file),
|
|
197
|
+
range: {
|
|
198
|
+
start: {
|
|
199
|
+
line: result.definition.location.startPosition.row,
|
|
200
|
+
character: result.definition.location.startPosition.column
|
|
201
|
+
},
|
|
202
|
+
end: {
|
|
203
|
+
line: result.definition.location.endPosition.row,
|
|
204
|
+
character: result.definition.location.endPosition.column
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
for (const ref of result.references) locations.push({
|
|
209
|
+
uri: pathToUri(ref.file),
|
|
210
|
+
range: {
|
|
211
|
+
start: {
|
|
212
|
+
line: ref.location.startPosition.row,
|
|
213
|
+
character: ref.location.startPosition.column
|
|
214
|
+
},
|
|
215
|
+
end: {
|
|
216
|
+
line: ref.location.endPosition.row,
|
|
217
|
+
character: ref.location.endPosition.column
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
return locations;
|
|
222
|
+
}
|
|
223
|
+
default: return null;
|
|
224
|
+
}
|
|
225
|
+
} catch (error) {
|
|
226
|
+
console.error(`[thalo-lsp] Error in references handler:`, error);
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
//#endregion
|
|
232
|
+
export { handleReferences };
|
|
233
|
+
//# sourceMappingURL=references.js.map
|