mcp-lsp-driver 1.2.0 → 1.4.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.
|
@@ -252,6 +252,14 @@ interface DefinitionProvider {
|
|
|
252
252
|
* @returns Array of code snippets representing definition locations
|
|
253
253
|
*/
|
|
254
254
|
provideDefinition(uri: UnifiedUri, position: ExactPosition): Promise<CodeSnippet[]>;
|
|
255
|
+
/**
|
|
256
|
+
* Returns the type definition location for the symbol at the given position.
|
|
257
|
+
*
|
|
258
|
+
* @param uri - The URI of the file
|
|
259
|
+
* @param position - The exact position to find the type definition for
|
|
260
|
+
* @returns Array of code snippets representing type definition locations
|
|
261
|
+
*/
|
|
262
|
+
provideTypeDefinition?(uri: UnifiedUri, position: ExactPosition): Promise<CodeSnippet[]>;
|
|
255
263
|
}
|
|
256
264
|
/**
|
|
257
265
|
* Provides find-references functionality.
|
|
@@ -465,5 +473,10 @@ interface IdeCapabilities {
|
|
|
465
473
|
*/
|
|
466
474
|
onDiagnosticsChanged?: (callback: OnDiagnosticsChangedCallback) => void;
|
|
467
475
|
}
|
|
476
|
+
/**
|
|
477
|
+
* A partial set of IDE capabilities where all fields (including fileAccess) are optional.
|
|
478
|
+
* Used with `mergeCapabilities` to combine multiple partial providers into a single IdeCapabilities.
|
|
479
|
+
*/
|
|
480
|
+
type PartialIdeCapabilities = Partial<IdeCapabilities>;
|
|
468
481
|
|
|
469
|
-
export type { CodeSnippet as C, DiskRange as D, ExactPosition as E, FileAccessProvider as F, GlobalFindMatch as G, HierarchyProvider as H, IdeCapabilities as I, Link as L, OnDiagnosticsChangedCallback as O,
|
|
482
|
+
export type { CodeSnippet as C, DiskRange as D, ExactPosition as E, FileAccessProvider as F, GlobalFindMatch as G, HierarchyProvider as H, IdeCapabilities as I, Link as L, OnDiagnosticsChangedCallback as O, PartialIdeCapabilities as P, ReferencesProvider as R, SymbolKind as S, TextEdit as T, UnifiedUri as U, FuzzyPosition as a, DefinitionProvider as b, Diagnostic as c, DiagnosticSeverity as d, DiagnosticsProvider as e, DocumentSymbol as f, EditFailureReason as g, EditProvider as h, EditResult as i, Frontmatter as j, FrontmatterMatch as k, FrontmatterProvider as l, FrontmatterValue as m, GlobalFindOptions as n, GlobalFindProvider as o, GraphProvider as p, OutlineProvider as q, PendingEditOperation as r };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { C as CodeSnippet, b as DefinitionProvider, c as Diagnostic, d as DiagnosticSeverity, e as DiagnosticsProvider, f as DocumentSymbol, g as EditFailureReason, h as EditProvider, i as EditResult, j as Frontmatter, k as FrontmatterMatch, l as FrontmatterProvider, m as FrontmatterValue, G as GlobalFindMatch, n as GlobalFindOptions, o as GlobalFindProvider, p as GraphProvider, H as HierarchyProvider, L as Link, O as OnDiagnosticsChangedCallback, q as OutlineProvider,
|
|
1
|
+
import { P as PartialIdeCapabilities, F as FileAccessProvider, I as IdeCapabilities, U as UnifiedUri, a as FuzzyPosition, E as ExactPosition, D as DiskRange } from './capabilities-DM3FLRwy.js';
|
|
2
|
+
export { C as CodeSnippet, b as DefinitionProvider, c as Diagnostic, d as DiagnosticSeverity, e as DiagnosticsProvider, f as DocumentSymbol, g as EditFailureReason, h as EditProvider, i as EditResult, j as Frontmatter, k as FrontmatterMatch, l as FrontmatterProvider, m as FrontmatterValue, G as GlobalFindMatch, n as GlobalFindOptions, o as GlobalFindProvider, p as GraphProvider, H as HierarchyProvider, L as Link, O as OnDiagnosticsChangedCallback, q as OutlineProvider, r as PendingEditOperation, R as ReferencesProvider, S as SymbolKind, T as TextEdit } from './capabilities-DM3FLRwy.js';
|
|
3
3
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -10,17 +10,18 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Merges multiple IdeCapabilities objects into a single composite
|
|
13
|
+
* Merges multiple partial IdeCapabilities objects into a single composite,
|
|
14
|
+
* using a fallback FileAccessProvider when none of the partials supply one.
|
|
14
15
|
*
|
|
15
16
|
* - Read providers concat their results via Promise.all + flat.
|
|
16
17
|
* - Write/mutation providers use the first available ("first wins").
|
|
17
18
|
* - onDiagnosticsChanged registers the callback on every capability that provides it.
|
|
18
19
|
*
|
|
19
|
-
* @param capsList - Array of
|
|
20
|
+
* @param capsList - Array of PartialIdeCapabilities to merge
|
|
21
|
+
* @param fallbackFileAccess - FileAccessProvider used when no partial provides fileAccess
|
|
20
22
|
* @returns A single merged IdeCapabilities object
|
|
21
|
-
* @throws Error if capsList is empty or no fileAccess provider is present
|
|
22
23
|
*/
|
|
23
|
-
declare function mergeCapabilities(capsList:
|
|
24
|
+
declare function mergeCapabilities(capsList: PartialIdeCapabilities[], fallbackFileAccess: FileAccessProvider): IdeCapabilities;
|
|
24
25
|
|
|
25
26
|
interface ConnectLspPipeOptions {
|
|
26
27
|
pipeName: string;
|
|
@@ -141,9 +142,9 @@ interface McpLspDriverConfig {
|
|
|
141
142
|
/**
|
|
142
143
|
* Register LSP-based tools and resources on the provided MCP server.
|
|
143
144
|
*/
|
|
144
|
-
declare function installMcpLspDriver({ server, capabilities
|
|
145
|
+
declare function installMcpLspDriver({ server, capabilities, config, }: {
|
|
145
146
|
server: McpServer;
|
|
146
|
-
capabilities: IdeCapabilities
|
|
147
|
+
capabilities: IdeCapabilities;
|
|
147
148
|
config?: McpLspDriverConfig;
|
|
148
149
|
}): {
|
|
149
150
|
success: boolean;
|
|
@@ -155,4 +156,4 @@ declare function installMcpLspDriver({ server, capabilities: rawCapabilities, co
|
|
|
155
156
|
reason?: undefined;
|
|
156
157
|
};
|
|
157
158
|
|
|
158
|
-
export { type ConnectLspPipeOptions, DiskRange, ExactPosition, FileAccessProvider, FuzzyPosition, IdeCapabilities, type LspPipeConnection, type LspPipeServer, type McpLspDriverConfig, type ResolverConfig, type ServeLspPipeOptions, SymbolResolutionError, SymbolResolver, UnifiedUri, connectLspPipe, installMcpLspDriver, mergeCapabilities, serveLspPipe };
|
|
159
|
+
export { type ConnectLspPipeOptions, DiskRange, ExactPosition, FileAccessProvider, FuzzyPosition, IdeCapabilities, type LspPipeConnection, type LspPipeServer, type McpLspDriverConfig, PartialIdeCapabilities, type ResolverConfig, type ServeLspPipeOptions, SymbolResolutionError, SymbolResolver, UnifiedUri, connectLspPipe, installMcpLspDriver, mergeCapabilities, serveLspPipe };
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {connect,createServer}from'net';import {unlinkSync}from'fs';import {ResourceTemplate}from'@modelcontextprotocol/sdk/server/mcp.js';import {z as z$1}from'zod';function
|
|
1
|
+
import {connect,createServer}from'net';import {unlinkSync}from'fs';import {ResourceTemplate}from'@modelcontextprotocol/sdk/server/mcp.js';import {z as z$1}from'zod';function Y(t){return t[0]}function Z(t){return t[0]}function ee(t){if(t.length!==0)return t.length===1?t[0]:{async provideDefinition(e,r){return (await Promise.all(t.map(i=>i.provideDefinition(e,r)))).flat()}}}function te(t){if(t.length!==0)return t.length===1?t[0]:{async provideReferences(e,r){return (await Promise.all(t.map(i=>i.provideReferences(e,r)))).flat()}}}function re(t){if(t.length!==0)return t.length===1?t[0]:{async provideCallHierarchy(e,r,n){return (await Promise.all(t.map(o=>o.provideCallHierarchy(e,r,n)))).flat()}}}function ne(t){if(t.length===0)return;if(t.length===1)return t[0];let e={async provideDiagnostics(n){return (await Promise.all(t.map(o=>o.provideDiagnostics(n)))).flat()}},r=t.map(n=>n.getWorkspaceDiagnostics).filter(n=>n!=null);return r.length>0&&(e.getWorkspaceDiagnostics=async()=>(await Promise.all(r.map(i=>i()))).flat()),e}function ie(t){if(t.length!==0)return t.length===1?t[0]:{async provideDocumentSymbols(e){return (await Promise.all(t.map(n=>n.provideDocumentSymbols(e)))).flat()}}}function oe(t){if(t.length!==0)return t.length===1?t[0]:{async globalFind(e,r){return (await Promise.all(t.map(i=>i.globalFind(e,r)))).flat()},async globalReplace(e,r,n){return (await Promise.all(t.map(o=>o.globalReplace(e,r,n)))).reduce((o,s)=>o+s,0)}}}function se(t){if(t.length===1)return t[0];let[e]=t;if(e)return {async getLinkStructure(){return (await Promise.all(t.map(n=>n.getLinkStructure()))).flat()},async resolveOutlinks(r){return (await Promise.all(t.map(i=>i.resolveOutlinks(r)))).flat()},async resolveBacklinks(r){return (await Promise.all(t.map(i=>i.resolveBacklinks(r)))).flat()},addLink:(r,n,i)=>e.addLink(r,n,i)}}function ae(t){if(t.length===1)return t[0];let[e]=t;if(e)return {async getFrontmatterStructure(r,n){return (await Promise.all(t.map(o=>o.getFrontmatterStructure(r,n)))).flat()},async getFrontmatter(r){let n=await Promise.all(t.map(i=>i.getFrontmatter(r)));return Object.assign({},...n)},setFrontmatter:(r,n,i)=>e.setFrontmatter(r,n,i)}}function ce(t){if(t.length!==0)return t.length===1?t[0]:e=>{for(let r of t)r(e);}}function y(t,e){let r=[];for(let n of t){let i=n[e];i!=null&&r.push(i);}return r}function le(t,e){return t.length===0?{fileAccess:e}:{fileAccess:Y(y(t,"fileAccess"))??e,edit:Z(y(t,"edit")),definition:ee(y(t,"definition")),references:te(y(t,"references")),hierarchy:re(y(t,"hierarchy")),diagnostics:ne(y(t,"diagnostics")),outline:ie(y(t,"outline")),globalFind:oe(y(t,"globalFind")),graph:se(y(t,"graph")),frontmatter:ae(y(t,"frontmatter")),onDiagnosticsChanged:ce(y(t,"onDiagnosticsChanged"))}}var S=class{socket;requestHandler;notificationHandler;nextId=1;pending=new Map;buffer="";destroyed=false;constructor(e,r){this.socket=e,this.requestHandler=r?.onRequest,this.notificationHandler=r?.onNotification,e.on("data",n=>this.handleData(n)),e.on("close",()=>this.rejectAll(new Error("Connection closed"))),e.on("error",n=>this.rejectAll(n));}sendRequest(e,r){return this.destroyed?Promise.reject(new Error("Transport destroyed")):new Promise((n,i)=>{let o=this.nextId++;this.pending.set(o,{resolve:n,reject:i});let s={type:"request",id:o,method:e,params:r};this.socket.write(`${JSON.stringify(s)}
|
|
2
2
|
`);})}sendNotification(e,r){if(this.destroyed)return;let n={type:"notification",method:e,params:r};this.socket.write(`${JSON.stringify(n)}
|
|
3
3
|
`);}destroy(){this.destroyed||(this.destroyed=true,this.rejectAll(new Error("Transport destroyed")),this.socket.destroy());}handleData(e){this.buffer+=e.toString();let r=this.buffer.split(`
|
|
4
4
|
`);this.buffer=r.pop()??"";for(let n of r){let i=n.replace(/\r$/,"");if(i)try{let o=JSON.parse(i);this.dispatch(o);}catch{}}}dispatch(e){switch(e.type){case "response":{let r=this.pending.get(e.id);r&&(this.pending.delete(e.id),e.error?r.reject(new Error(e.error.message)):r.resolve(e.result));break}case "request":{this.requestHandler&&this.requestHandler(e.method,e.params).then(r=>{if(this.destroyed)return;let n={type:"response",id:e.id,result:r};this.socket.write(`${JSON.stringify(n)}
|
|
5
5
|
`);}).catch(r=>{if(this.destroyed)return;let n={type:"response",id:e.id,error:{message:r instanceof Error?r.message:String(r)}};this.socket.write(`${JSON.stringify(n)}
|
|
6
|
-
`);});break}case "notification":{this.notificationHandler?.(e.method,e.params);break}}}rejectAll(e){for(let[,r]of this.pending)r.reject(e);this.pending.clear();}};function T(t){return process.platform==="win32"?`\\\\.\\pipe\\${t}`:`/tmp/${t}.sock`}var R=[{providerKey:"fileAccess",methods:["readFile","readDirectory","getFileTree"]},{providerKey:"edit",methods:["applyEdits","previewAndApplyEdits"]},{providerKey:"definition",methods:["provideDefinition"]},{providerKey:"references",methods:["provideReferences"]},{providerKey:"hierarchy",methods:["provideCallHierarchy"]},{providerKey:"diagnostics",methods:["provideDiagnostics","getWorkspaceDiagnostics"]},{providerKey:"outline",methods:["provideDocumentSymbols"]},{providerKey:"globalFind",methods:["globalFind","globalReplace"]},{providerKey:"graph",methods:["getLinkStructure","resolveOutlinks","resolveBacklinks","addLink"]},{providerKey:"frontmatter",methods:["getFrontmatterStructure","getFrontmatter","setFrontmatter"]}];function de(t){let{pipeName:e,connectTimeout:r=5e3}=t,n=T(e);return new Promise((i,o)=>{let s=connect(n),a=false,l=setTimeout(()=>{a||(a=true,s.destroy(),o(new Error(`Connection timeout after ${r}ms`)));},r);s.on("error",c=>{a||(a=true,clearTimeout(l),o(c));}),s.on("connect",()=>{if(clearTimeout(l),a)return;let c,p=new
|
|
7
|
-
`?(n++,i=0):i++,o++;}return {line:n,character:i}}};var
|
|
6
|
+
`);});break}case "notification":{this.notificationHandler?.(e.method,e.params);break}}}rejectAll(e){for(let[,r]of this.pending)r.reject(e);this.pending.clear();}};function T(t){return process.platform==="win32"?`\\\\.\\pipe\\${t}`:`/tmp/${t}.sock`}var R=[{providerKey:"fileAccess",methods:["readFile","readDirectory","getFileTree"]},{providerKey:"edit",methods:["applyEdits","previewAndApplyEdits"]},{providerKey:"definition",methods:["provideDefinition"]},{providerKey:"references",methods:["provideReferences"]},{providerKey:"hierarchy",methods:["provideCallHierarchy"]},{providerKey:"diagnostics",methods:["provideDiagnostics","getWorkspaceDiagnostics"]},{providerKey:"outline",methods:["provideDocumentSymbols"]},{providerKey:"globalFind",methods:["globalFind","globalReplace"]},{providerKey:"graph",methods:["getLinkStructure","resolveOutlinks","resolveBacklinks","addLink"]},{providerKey:"frontmatter",methods:["getFrontmatterStructure","getFrontmatter","setFrontmatter"]}];function de(t){let{pipeName:e,connectTimeout:r=5e3}=t,n=T(e);return new Promise((i,o)=>{let s=connect(n),a=false,l=setTimeout(()=>{a||(a=true,s.destroy(),o(new Error(`Connection timeout after ${r}ms`)));},r);s.on("error",c=>{a||(a=true,clearTimeout(l),o(c));}),s.on("connect",()=>{if(clearTimeout(l),a)return;let c,p=new S(s,{onNotification:(f,g)=>{f==="onDiagnosticsChanged"&&c&&c(g[0]);}});p.sendRequest("_handshake",[]).then(f=>{if(a)return;let b=f.methods;if(!b.includes("fileAccess.readFile")||!b.includes("fileAccess.readDirectory"))throw p.destroy(),new Error("Server missing required methods: fileAccess.readFile, fileAccess.readDirectory");let x={};for(let{providerKey:v,methods:F}of R){let _=F.filter(C=>b.includes(`${v}.${C}`));if(_.length===0)continue;let O={};for(let C of _)O[C]=(...X)=>p.sendRequest(`${v}.${C}`,X);x[v]=O;}b.includes("onDiagnosticsChanged")&&(x.onDiagnosticsChanged=v=>{c=v;}),a=true,i({capabilities:x,availableMethods:b,disconnect(){p.destroy();}});}).catch(f=>{a||(a=true,p.destroy(),o(f instanceof Error?f:new Error(String(f))));});});})}function fe(t){let{capabilities:e,pipeName:r}=t,n=T(r),i=new Map;for(let{providerKey:l,methods:c}of R){let p=e[l];if(p)for(let f of c){let g=p[f];if(typeof g=="function"){let b=`${l}.${f}`;i.set(b,(...x)=>g.apply(p,x));}}}let o=[...i.keys()];e.onDiagnosticsChanged&&o.push("onDiagnosticsChanged");let s=new Set,a=createServer(l=>{let c=new S(l,{onRequest:async(p,f)=>{if(p==="_handshake")return {methods:o};let g=i.get(p);if(!g)throw new Error(`Unknown method: ${p}`);return g(...f)}});s.add(c),l.on("close",()=>s.delete(c));});return e.onDiagnosticsChanged&&e.onDiagnosticsChanged(l=>{for(let c of s)c.sendNotification("onDiagnosticsChanged",[l]);}),new Promise((l,c)=>{if(process.platform!=="win32")try{unlinkSync(n);}catch{}a.on("error",c),a.listen(n,()=>{a.removeListener("error",c),l({get pipePath(){return n},get connectionCount(){return s.size},async close(){for(let p of s)p.destroy();if(s.clear(),await new Promise((p,f)=>{a.close(g=>{g?f(g):p();});}),process.platform!=="win32")try{unlinkSync(n);}catch{}}});});})}var P=class extends Error{constructor(r,n,i){super(`Could not find symbol '${r}' at or near line ${n}. ${i}`);this.symbolName=r;this.lineHint=n;this.reason=i;this.name="SymbolResolutionError";}},k=class{constructor(e,r){this.fs=e;this.lineSearchRadius=r?.lineSearchRadius??2;}lineSearchRadius;async resolvePosition(e,r){let i=(await this.fs.readFile(e)).split(/\r?\n/),o=r.lineHint-1,s=r.orderHint??0,a=this.findSymbolInLine(i[o],r.symbolName,s);if(a!==null)return {line:o,character:a};for(let l=1;l<=this.lineSearchRadius;l++){let c=o-l;if(c>=0){let f=this.findSymbolInLine(i[c],r.symbolName,s);if(f!==null)return {line:c,character:f}}let p=o+l;if(p<i.length){let f=this.findSymbolInLine(i[p],r.symbolName,s);if(f!==null)return {line:p,character:f}}}throw new P(r.symbolName,r.lineHint,`Please verify the file content and try again. Searched lines ${Math.max(1,r.lineHint-this.lineSearchRadius)} to ${Math.min(i.length,r.lineHint+this.lineSearchRadius)}.`)}findSymbolInLine(e,r,n){if(e===void 0||e.length===0)return null;let i=0,o=0;for(;i<e.length;){let s=e.indexOf(r,i);if(s===-1)break;if(o===n)return s;o++,i=s+1;}return null}async findExactText(e,r){let n=await this.fs.readFile(e),i=[],o=0;for(;o<n.length;){let p=n.indexOf(r,o);if(p===-1)break;i.push(p),o=p+1;}if(i.length===0)throw new Error(`Text not found in file: "${r.slice(0,50)}${r.length>50?"...":""}"`);if(i.length>1)throw new Error(`Text appears ${i.length} times in file. Please provide more context to uniquely identify the location.`);let s=i[0],a=s+r.length,l=this.offsetToPosition(n,s),c=this.offsetToPosition(n,a);return {start:l,end:c}}offsetToPosition(e,r){let n=0,i=0,o=0;for(let s of e){if(o===r)break;s===`
|
|
7
|
+
`?(n++,i=0):i++,o++;}return {line:n,character:i}}};var h=t=>({content:[{type:"text",text:JSON.stringify(t??"")}],structuredContent:t});function m(t){if(t.includes(".."))throw new Error('URI could not include ".." operator');return t.replace(/\\/g,"/")}function j(){return `edit-${Date.now()}`}function $(t){return t.length===0?"No diagnostics found.":t.map(e=>{let r=e.range.start.line+1,n=e.severity.toUpperCase(),i=e.source?` [${e.source}]`:"",o=e.code!==void 0?` (${e.code})`:"";return `- **${n}**${i}${o} at line ${r}: ${e.message}`}).join(`
|
|
8
8
|
`)}function I(t,e=0){if(t.length===0&&e===0)return "No symbols found.";let r=" ".repeat(e);return t.map(n=>{let i=n.range.start.line+1,o=n.range.end.line+1,s=i===o?`line ${i}`:`lines ${i}-${o}`,a=n.detail?` - ${n.detail}`:"",l=`${r}- **${n.kind}** \`${n.name}\`${a} (${s})`;return n.children&&n.children.length>0?`${l}
|
|
9
9
|
${I(n.children,e+1)}`:l}).join(`
|
|
10
|
-
`)}var
|
|
11
|
-
`)}function he({server:t,capabilities:e,config:r}){let n=
|
|
10
|
+
`)}var M=z$1.string().describe("The relative file path"),N=z$1.string().describe("The text of the symbol to find"),A=z$1.number().int().positive().describe("Approximate 1-based line number where the symbol is expected"),H=z$1.number().int().min(0).default(0).describe("0-based index of which occurrence to target if symbol appears multiple times"),D=z$1.object({uri:M,symbol_name:N,line_hint:A,order_hint:H}),E=z$1.object({uri:M,search_text:z$1.string().describe("Exact text to replace (must exist uniquely in the file)"),replace_text:z$1.string().describe("New text to insert"),description:z$1.string().describe("Rationale for the edit")}),G=z$1.object({uri:z$1.string().describe("The file URI or path"),symbol_name:N,line_hint:A,order_hint:H,direction:z$1.enum(["incoming","outgoing"]).describe("Direction of the call hierarchy")}),U=z$1.string().describe("The search query"),z=z$1.boolean().default(false).describe("Whether the search is case-sensitive"),K=z$1.boolean().default(false).describe("Whether to match exact words only"),q=z$1.boolean().default(false).describe("Whether the query is a regular expression"),J=z$1.object({query:U,case_sensitive:z,exact_match:K,regex_mode:q}),W=z$1.object({query:U,case_sensitive:z,exact_match:K,regex_mode:q,replace_with:z$1.string().describe("The replacement text")}),B=z$1.object({path:z$1.string().describe("The path to the document to modify"),pattern:z$1.string().describe("The text pattern to find and replace with a link"),link_to:z$1.string().describe("The target URI the link should point to")}),V=z$1.object({property:z$1.string().describe("The frontmatter property name to search for"),path:z$1.string().optional().describe("Optional path to limit the search to a specific document. If not provided, searches all documents.")}),Q=z$1.object({path:z$1.string().describe("The path to the document to modify"),property:z$1.string().describe("The frontmatter property name to set"),value:z$1.union([z$1.string(),z$1.array(z$1.string()),z$1.number(),z$1.array(z$1.number()),z$1.boolean(),z$1.array(z$1.boolean()),z$1.null()]).describe("The value to set. Can be a string, number, boolean, array of these types, or null to remove.")});function me(t){if(!t)return null;let e=t.match(/^L(\d+)(?:-L(\d+))?$/);if(!e||!e[1])return null;let r=parseInt(e[1],10),n=e[2]?parseInt(e[2],10):r;return r<1||n<r?null:{start:r,end:n}}function ge(t,e){let r=t.split(/\r?\n/),n=e.start-1,i=e.end;return r.slice(n,i).join(`
|
|
11
|
+
`)}function he({server:t,capabilities:e,config:r}){let n=new k(e.fileAccess,r?.resolverConfig);try{ye(t,e,n);}catch(i){return {success:false,error:i,reason:"Error occured during registration of tools"}}try{be(t,e);}catch(i){return {success:false,error:i,reason:"Error occured during registration of resources"}}return {success:true}}function ye(t,e,r){e.definition&&ve(t,e,r),e.definition?.provideTypeDefinition&&Pe(t,e,r),e.references&&xe(t,e,r),e.hierarchy&&we(t,e,r),e.edit&&Ee(t,e,r),e.globalFind&&(Te(t,e),Re(t,e)),e.graph&&(Fe(t,e),$e(t,e)),e.frontmatter&&(Ie(t,e),_e(t,e));}function be(t,e){Ce(t,e),e.diagnostics&&Se(t,e),e.outline&&ke(t,e),e.graph&&De(t,e),e.frontmatter&&Oe(t,e);}function ve(t,e,r){let n=e.definition;n&&t.registerTool("goto_definition",{description:"Navigate to the definition of a symbol.",inputSchema:D,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async i=>{try{let o=m(i.uri),s={symbolName:i.symbol_name,lineHint:i.line_hint,orderHint:i.order_hint},a=await r.resolvePosition(o,s),l=(await n.provideDefinition(o,a)).map(c=>({uri:c.uri,startLine:c.range.start.line+1,endLine:c.range.end.line+1,content:c.content}));return h({snippets:l})}catch(o){let s=o instanceof P?o.message:`Error: ${o instanceof Error?o.message:String(o)}`;return {content:[{type:"text",text:s}],structuredContent:{error:s},isError:true}}});}function Pe(t,e,r){let n=e.definition?.provideTypeDefinition;n&&t.registerTool("goto_type_definition",{description:"Navigate to the type definition of a symbol.",inputSchema:D,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async i=>{try{let o=m(i.uri),s={symbolName:i.symbol_name,lineHint:i.line_hint,orderHint:i.order_hint},a=await r.resolvePosition(o,s),l=(await n(o,a)).map(c=>({uri:c.uri,startLine:c.range.start.line+1,endLine:c.range.end.line+1,content:c.content}));return h({snippets:l})}catch(o){let s=o instanceof P?o.message:`Error: ${o instanceof Error?o.message:String(o)}`;return {content:[{type:"text",text:s}],structuredContent:{error:s},isError:true}}});}function xe(t,e,r){let n=e.references;n&&t.registerTool("find_references",{description:"Find all references to a symbol. Returns a list of locations where the symbol is used.",inputSchema:D,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async i=>{try{let o=m(i.uri),s={symbolName:i.symbol_name,lineHint:i.line_hint,orderHint:i.order_hint},a=await r.resolvePosition(o,s),l=(await n.provideReferences(o,a)).map(c=>({uri:c.uri,startLine:c.range.start.line+1,endLine:c.range.end.line+1,content:c.content}));return h({snippets:l})}catch(o){let s=o instanceof P?o.message:`Error: ${o instanceof Error?o.message:String(o)}`;return {content:[{type:"text",text:s}],structuredContent:{error:s},isError:true}}});}function we(t,e,r){let n=e.hierarchy;n&&t.registerTool("call_hierarchy",{description:"Get call hierarchy for a function or method. Shows incoming or outgoing calls.",inputSchema:G,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async i=>{try{let o=m(i.uri),s={symbolName:i.symbol_name,lineHint:i.line_hint,orderHint:i.order_hint},a=await r.resolvePosition(o,s),l=(await n.provideCallHierarchy(o,a,i.direction)).map(c=>({uri:c.uri,startLine:c.range.start.line+1,endLine:c.range.end.line+1,content:c.content}));return h({snippets:l})}catch(o){let s=o instanceof P?o.message:`Error: ${o instanceof Error?o.message:String(o)}`;return {content:[{type:"text",text:s}],structuredContent:{error:s},isError:true}}});}function Se(t,e){let r=e.diagnostics;if(!r)return;let n=new ResourceTemplate("diagnostics://{+path}",{list:void 0});if(t.registerResource("diagnostics",n,{description:"Diagnostics (errors, warnings, hints) for a specific file. Use the file path after diagnostics://",mimeType:"text/markdown"},async(i,o)=>{try{let s=o.path,a=m(s),l=await r.provideDiagnostics(a),c=$(l);return {contents:[{uri:`diagnostics://${s}`,mimeType:"text/markdown",text:c}]}}catch(s){let a=`Error: ${s instanceof Error?s.message:String(s)}`;return {contents:[{uri:`diagnostics://${o.path}`,mimeType:"text/markdown",text:a}]}}}),r.getWorkspaceDiagnostics){let i=r.getWorkspaceDiagnostics.bind(r);t.registerResource("workspace-diagnostics","diagnostics://workspace",{description:"All diagnostics (errors, warnings, hints) across the entire workspace",mimeType:"text/markdown"},async()=>{try{let o=await i(),s=new Map;for(let l of o){let c=s.get(l.uri)??[];c.push(l),s.set(l.uri,c);}if(s.size===0)return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:"No diagnostics found in workspace."}]};let a=[];for(let[l,c]of s)a.push(`## ${l}
|
|
12
12
|
${$(c)}`);return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:a.join(`
|
|
13
13
|
|
|
14
|
-
`)}]}}catch(o){return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:`Error: ${o instanceof Error?o.message:String(o)}`}]}}});}e.onDiagnosticsChanged&&e.onDiagnosticsChanged(i=>{let o=m(i);t.server.sendResourceUpdated({uri:`diagnostics://${o}`}),r.getWorkspaceDiagnostics&&t.server.sendResourceUpdated({uri:"diagnostics://workspace"});});}function ke(t,e){let r=e.outline;if(!r)return;let n=new ResourceTemplate("outline://{+path}",{list:void 0});t.registerResource("outline",n,{description:"Document outline (symbols like classes, functions, variables) for a specific file. Use the file path after outline://",mimeType:"text/markdown"},async(i,o)=>{try{let s=o.path,a=m(s),l=await r.provideDocumentSymbols(a),c=I(l);return {contents:[{uri:`outline://${s}`,mimeType:"text/markdown",text:c}]}}catch(s){let a=`Error: ${s instanceof Error?s.message:String(s)}`;return {contents:[{uri:`outline://${o.path}`,mimeType:"text/markdown",text:a}]}}});}function
|
|
15
|
-
export{
|
|
14
|
+
`)}]}}catch(o){return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:`Error: ${o instanceof Error?o.message:String(o)}`}]}}});}e.onDiagnosticsChanged&&e.onDiagnosticsChanged(i=>{let o=m(i);t.server.sendResourceUpdated({uri:`diagnostics://${o}`}),r.getWorkspaceDiagnostics&&t.server.sendResourceUpdated({uri:"diagnostics://workspace"});});}function ke(t,e){let r=e.outline;if(!r)return;let n=new ResourceTemplate("outline://{+path}",{list:void 0});t.registerResource("outline",n,{description:"Document outline (symbols like classes, functions, variables) for a specific file. Use the file path after outline://",mimeType:"text/markdown"},async(i,o)=>{try{let s=o.path,a=m(s),l=await r.provideDocumentSymbols(a),c=I(l);return {contents:[{uri:`outline://${s}`,mimeType:"text/markdown",text:c}]}}catch(s){let a=`Error: ${s instanceof Error?s.message:String(s)}`;return {contents:[{uri:`outline://${o.path}`,mimeType:"text/markdown",text:a}]}}});}function Ee(t,e,r){let n=e.edit;if(!n)return;let i=n.previewAndApplyEdits?.bind(n)??n.applyEdits?.bind(n);i&&t.registerTool("apply_edit",{description:"Apply a text edit to a file. The edit must be approved by the user before being applied.",inputSchema:{uri:E.shape.uri,search_text:E.shape.search_text,replace_text:E.shape.replace_text,description:E.shape.description},outputSchema:{success:z$1.boolean(),message:z$1.string()}},async o=>{try{let s=m(o.uri),a=await r.findExactText(s,o.search_text),l={id:j(),uri:s,edits:[{range:a,newText:o.replace_text}],description:o.description},p=await i(l)?{success:!0,message:"Edit successfully applied and saved."}:{success:!1,message:"Edit rejected by user."};return h(p)}catch(s){let a=`Error: ${s instanceof Error?s.message:String(s)}`;return {content:[{type:"text",text:a}],structuredContent:{success:false,message:a},isError:true}}});}function Ce(t,e){let{readFile:r,readDirectory:n,getFileTree:i}=e.fileAccess;if(i!==void 0){let s=new ResourceTemplate("filetree://{+path}",{list:void 0});t.registerResource("filetree",s,{description:'Access file tree inside a relative path or use "." for root.'},async(a,{path:l})=>({contents:[{uri:a.toString(),mimeType:"application/json",text:JSON.stringify(await i(m(l))??"")}]}));}let o=new ResourceTemplate("files://{+path}",{list:void 0});t.registerResource("filesystem",o,{description:"Access filesystem resources. For directories: returns children (git-ignored files excluded). For files: returns file content. Supports line ranges with #L23 or #L23-L30 fragment."},async(s,a)=>{let l=s.toString();try{let c=a.path,p,f=c,g=c.indexOf("#");g!==-1&&(p=c.slice(g+1),f=c.slice(0,g));let b=m(f),x=me(p);try{let v=await r(b),F=x?ge(v,x):v;return {contents:[{uri:l,mimeType:"text/plain",text:F}]}}catch{let v=await n(b);return {contents:[{uri:l,mimeType:"application/json",text:JSON.stringify(v)}]}}}catch(c){let p=`Error: ${c instanceof Error?c.message:String(c)}`;return {contents:[{uri:l,mimeType:"text/plain",text:p}]}}});}function Te(t,e){let r=e.globalFind;r&&t.registerTool("global_find",{description:"Search for text across the entire workspace.",inputSchema:J,outputSchema:{matches:z$1.array(z$1.object({uri:z$1.string(),line:z$1.number(),column:z$1.number(),matchText:z$1.string(),context:z$1.string()})),count:z$1.number()}},async n=>{try{let i=n.case_sensitive??!1,o=n.exact_match??!1,s=n.regex_mode??!1,a=await r.globalFind(n.query,{caseSensitive:i,exactMatch:o,regexMode:s});return h({count:a.length,matches:a})}catch(i){let o=`Error: ${i instanceof Error?i.message:String(i)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function Re(t,e){let r=e.globalFind;r&&t.registerTool("global_replace",{description:"Replace all occurrences of text across the entire workspace.",inputSchema:W,outputSchema:{success:z$1.boolean(),count:z$1.number(),message:z$1.string().optional()}},async n=>{try{let i=n.case_sensitive??!1,o=n.exact_match??!1,s=n.regex_mode??!1,a=await r.globalReplace(n.query,n.replace_with,{caseSensitive:i,exactMatch:o,regexMode:s});return h({success:!0,count:a})}catch(i){let o=`Error: ${i instanceof Error?i.message:String(i)}`;return {content:[{type:"text",text:o}],structuredContent:{success:false,replacementCount:0,message:o},isError:true}}});}function De(t,e){let r=e.graph;if(!r)return;let n=new ResourceTemplate("outlinks://{+path}",{list:void 0});t.registerResource("outlinks",n,{description:"Outgoing links from a specific file. Use the file path after outlinks://",mimeType:"application/json"},async(o,s)=>{try{let a=s.path,l=m(a),c=await r.resolveOutlinks(l);return {contents:[{uri:`outlinks://${a}`,mimeType:"application/json",text:JSON.stringify(c,null,2)}]}}catch(a){let l=`Error: ${a instanceof Error?a.message:String(a)}`;return {contents:[{uri:`outlinks://${s.path}`,mimeType:"application/json",text:JSON.stringify({error:l})}]}}});let i=new ResourceTemplate("backlinks://{+path}",{list:void 0});t.registerResource("backlinks",i,{description:"Incoming links (backlinks) to a specific file. Use the file path after backlinks://",mimeType:"application/json"},async(o,s)=>{try{let a=s.path,l=m(a),c=await r.resolveBacklinks(l);return {contents:[{uri:`backlinks://${a}`,mimeType:"application/json",text:JSON.stringify(c,null,2)}]}}catch(a){let l=`Error: ${a instanceof Error?a.message:String(a)}`;return {contents:[{uri:`backlinks://${s.path}`,mimeType:"application/json",text:JSON.stringify({error:l})}]}}});}function Fe(t,e){let r=e.graph;r&&t.registerTool("get_link_structure",{description:"Get all links in the workspace, showing relationships between documents.",inputSchema:{},outputSchema:{links:z$1.array(z$1.object({sourceUri:z$1.string(),targetUri:z$1.string(),subpath:z$1.string().optional(),displayText:z$1.string().optional(),resolved:z$1.boolean(),line:z$1.number(),column:z$1.number()}))}},async()=>{try{let n=await r.getLinkStructure();return h({links:n})}catch(n){let i=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:i}],structuredContent:{error:i},isError:true}}});}function $e(t,e){let r=e.graph;r&&t.registerTool("add_link",{description:"Add a link to a document by finding a text pattern and replacing it with a link to the target.",inputSchema:B,outputSchema:{success:z$1.boolean(),message:z$1.string().optional()}},async n=>{try{let i=m(n.path),o=m(n.link_to);return await r.addLink(i,n.pattern,o),h({success:!0,message:"Link added successfully."})}catch(i){let o=`Error: ${i instanceof Error?i.message:String(i)}`;return {content:[{type:"text",text:o}],structuredContent:{success:false,message:o},isError:true}}});}function Ie(t,e){let r=e.frontmatter;r&&t.registerTool("get_frontmatter_structure",{description:"Get frontmatter property values across documents. If path is provided, searches only that document. Otherwise, searches all documents.",inputSchema:V,outputSchema:{matches:z$1.array(z$1.object({path:z$1.string(),value:z$1.unknown()}))}},async n=>{try{let i=n.path?m(n.path):void 0,o=await r.getFrontmatterStructure(n.property,i);return h({matches:o})}catch(i){let o=`Error: ${i instanceof Error?i.message:String(i)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function _e(t,e){let r=e.frontmatter;r&&t.registerTool("set_frontmatter",{description:"Set a frontmatter property on a document. Use null to remove the property.",inputSchema:Q,outputSchema:{success:z$1.boolean(),message:z$1.string().optional()}},async n=>{try{let i=m(n.path),o=n.value===null?void 0:n.value;return await r.setFrontmatter(i,n.property,o),h({success:!0,message:"Frontmatter updated successfully."})}catch(i){let o=`Error: ${i instanceof Error?i.message:String(i)}`;return {content:[{type:"text",text:o}],structuredContent:{success:false,message:o},isError:true}}});}function Oe(t,e){let r=e.frontmatter;if(!r)return;let n=new ResourceTemplate("frontmatter://{+path}",{list:void 0});t.registerResource("frontmatter",n,{description:"Frontmatter metadata for a specific file. Use the file path after frontmatter://",mimeType:"application/json"},async(i,o)=>{try{let s=o.path,a=m(s),l=await r.getFrontmatter(a);return {contents:[{uri:`frontmatter://${s}`,mimeType:"application/json",text:JSON.stringify(l,null,2)}]}}catch(s){let a=`Error: ${s instanceof Error?s.message:String(s)}`;return {contents:[{uri:`frontmatter://${o.path}`,mimeType:"application/json",text:JSON.stringify({error:a})}]}}});}
|
|
15
|
+
export{P as SymbolResolutionError,k as SymbolResolver,de as connectLspPipe,he as installMcpLspDriver,le as mergeCapabilities,fe as serveLspPipe};
|
package/dist/lsp/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ChildProcess } from 'node:child_process';
|
|
2
2
|
import { ProtocolConnection } from 'vscode-languageserver-protocol/node.js';
|
|
3
|
-
import { b as DefinitionProvider, R as ReferencesProvider, H as HierarchyProvider, q as OutlineProvider, e as DiagnosticsProvider, O as OnDiagnosticsChangedCallback, d as DiagnosticSeverity, C as CodeSnippet, c as Diagnostic$1, f as DocumentSymbol$1, E as ExactPosition, D as DiskRange, S as SymbolKind } from '../capabilities-
|
|
3
|
+
import { b as DefinitionProvider, R as ReferencesProvider, H as HierarchyProvider, q as OutlineProvider, e as DiagnosticsProvider, O as OnDiagnosticsChangedCallback, d as DiagnosticSeverity, C as CodeSnippet, c as Diagnostic$1, f as DocumentSymbol$1, E as ExactPosition, D as DiskRange, S as SymbolKind } from '../capabilities-DM3FLRwy.js';
|
|
4
4
|
import { Location, LocationLink, Diagnostic, DocumentSymbol, SymbolInformation } from 'vscode-languageserver-protocol';
|
|
5
5
|
|
|
6
6
|
interface LspClientOptions {
|
|
@@ -47,6 +47,7 @@ declare class LspClient {
|
|
|
47
47
|
private scheduleDocumentClose;
|
|
48
48
|
private closeDocument;
|
|
49
49
|
private provideDefinition;
|
|
50
|
+
private provideTypeDefinition;
|
|
50
51
|
private provideReferences;
|
|
51
52
|
private provideCallHierarchy;
|
|
52
53
|
private provideDocumentSymbols;
|
package/dist/lsp/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {spawn}from'child_process';import {InitializedNotification,ShutdownRequest,ExitNotification,StreamMessageReader,StreamMessageWriter,createProtocolConnection,InitializeRequest,CancellationTokenSource,DidOpenTextDocumentNotification,DidCloseTextDocumentNotification}from'vscode-languageserver-protocol/node.js';import D from'path';import {pathToFileURL,fileURLToPath}from'url';function c(o,t){let e=D.resolve(o,t);return pathToFileURL(e).toString()}function u(o,t){let e=fileURLToPath(t);return D.relative(o,e).replace(/\\/g,"/")}function p(o){return {start:{line:o.start.line,character:o.start.character},end:{line:o.end.line,character:o.end.character}}}function
|
|
2
|
-
`).slice(l.start.line,l.end.line+1);n.push({uri:
|
|
3
|
-
`)});}catch{n.push({uri:
|
|
1
|
+
import {spawn}from'child_process';import {InitializedNotification,ShutdownRequest,ExitNotification,StreamMessageReader,StreamMessageWriter,createProtocolConnection,InitializeRequest,CancellationTokenSource,DidOpenTextDocumentNotification,DidCloseTextDocumentNotification}from'vscode-languageserver-protocol/node.js';import D from'path';import {pathToFileURL,fileURLToPath}from'url';function c(o,t){let e=D.resolve(o,t);return pathToFileURL(e).toString()}function u(o,t){let e=fileURLToPath(t);return D.relative(o,e).replace(/\\/g,"/")}function p(o){return {start:{line:o.start.line,character:o.start.character},end:{line:o.end.line,character:o.end.character}}}function R(o){return {line:o.line,character:o.character}}var T={1:"error",2:"warning",3:"information",4:"hint"};function b(o){return T[o??1]??"error"}var O=["file","file","module","namespace","package","class","method","property","field","constructor","enum","interface","function","variable","constant","string","number","boolean","array","object","key","null","enumMember","struct","event","operator","typeParameter"];function P(o){return O[o]??"variable"}function g(o,t,e){return {uri:u(o,t),range:p(e.range),severity:b(e.severity),message:e.message,source:e.source,code:typeof e.code=="object"?String(e.code):e.code??void 0}}function f(o){return {name:o.name,detail:o.detail,kind:P(o.kind),range:p(o.range),selectionRange:p(o.selectionRange),children:o.children?.map(f)}}function C(o,t){return {name:t.name,kind:P(t.kind),range:p(t.location.range),selectionRange:p(t.location.range)}}async function h(o,t,e){if(!t)return [];let i=Array.isArray(t)?t:[t];if(i.length===0)return [];let n=[];for(let s of i){let r="targetUri"in s,a=r?s.targetUri:s.uri,d=r?s.targetRange:s.range,m=u(o,a),l=p(d);try{let S=(await e(m)).split(`
|
|
2
|
+
`).slice(l.start.line,l.end.line+1);n.push({uri:m,range:l,content:S.join(`
|
|
3
|
+
`)});}catch{n.push({uri:m,range:l,content:""});}}return n}var I={".ts":"typescript",".tsx":"typescriptreact",".js":"javascript",".jsx":"javascriptreact",".rs":"rust",".go":"go",".py":"python",".rb":"ruby",".java":"java",".kt":"kotlin",".kts":"kotlin",".c":"c",".h":"c",".cpp":"cpp",".cc":"cpp",".cxx":"cpp",".hpp":"cpp",".cs":"csharp",".swift":"swift",".lua":"lua",".zig":"zig",".json":"json",".yaml":"yaml",".yml":"yaml",".toml":"toml",".xml":"xml",".html":"html",".css":"css",".scss":"scss",".md":"markdown",".sql":"sql",".sh":"shellscript",".bash":"shellscript",".zsh":"shellscript",".ps1":"powershell",".dart":"dart",".ex":"elixir",".exs":"elixir",".erl":"erlang",".hs":"haskell",".ml":"ocaml",".mli":"ocaml",".scala":"scala",".r":"r",".R":"r",".php":"php",".pl":"perl",".vim":"vim"};function w(o){let t=D.extname(o);return I[t]??"plaintext"}var y=class{state="idle";process=null;connection=null;openDocuments=new Map;diagnosticsCache=new Map;diagnosticsListeners=[];definition;references;hierarchy;outline;diagnostics;options;constructor(t){this.options={documentIdleTimeout:3e4,requestTimeout:3e4,...t},this.definition=void 0,this.references=void 0,this.hierarchy=void 0,this.outline=void 0,this.diagnostics=void 0;}getState(){return this.state}get onDiagnosticsChanged(){return t=>{this.diagnosticsListeners.push(t);}}async start(){if(this.state!=="idle")throw new Error(`Cannot start: client is in "${this.state}" state`);this.state="starting";try{let t=this.spawnAndConnect();this.connection=t,t.onClose(()=>{(this.state==="running"||this.state==="starting")&&this.transitionToDead();}),t.listen();let i=(await this.sendInitialize()).capabilities;this.setupProviders(i),t.onNotification("textDocument/publishDiagnostics",n=>{let s=u(this.options.workspacePath,n.uri),r=n.diagnostics.map(a=>g(this.options.workspacePath,n.uri,a));this.diagnosticsCache.set(s,r);for(let a of this.diagnosticsListeners)a(s);}),await t.sendNotification(InitializedNotification.type,{}),this.state="running";}catch(t){throw this.transitionToDead(),t}}async stop(){if(this.state!=="running")return;let t=[...this.openDocuments.keys()].map(e=>this.closeDocument(e));await Promise.all(t);try{await this.connection?.sendRequest(ShutdownRequest.type),await this.connection?.sendNotification(ExitNotification.type);}catch{}this.cleanup();}async notifyFileChanged(t){if(this.state!=="running")return;let e=c(this.options.workspacePath,t);this.openDocuments.get(e)&&(await this.closeDocument(e),await this.ensureDocumentOpen(e));}startWithConnection(t,e){this.connection=t,this.process=e;}async initializeConnection(){let t=this.connection;if(!t)throw new Error("Connection not set");this.state="starting",t.onClose(()=>{(this.state==="running"||this.state==="starting")&&this.transitionToDead();}),t.listen();let i=(await this.sendInitialize()).capabilities;this.setupProviders(i),t.onNotification("textDocument/publishDiagnostics",n=>{let s=u(this.options.workspacePath,n.uri),r=n.diagnostics.map(a=>g(this.options.workspacePath,n.uri,a));this.diagnosticsCache.set(s,r);for(let a of this.diagnosticsListeners)a(s);}),await t.sendNotification(InitializedNotification.type,{}),this.state="running";}spawnAndConnect(){let t=spawn(this.options.command,this.options.args??[],{stdio:["pipe","pipe","pipe"],env:this.options.env?{...process.env,...this.options.env}:process.env});this.process=t,t.on("exit",()=>{(this.state==="running"||this.state==="starting")&&this.transitionToDead();});let e=new StreamMessageReader(t.stdout),i=new StreamMessageWriter(t.stdin);return createProtocolConnection(e,i)}async sendInitialize(){if(!this.connection)throw new Error("No connection");let t={textDocument:{synchronization:{dynamicRegistration:false,didSave:true},definition:{dynamicRegistration:false},references:{dynamicRegistration:false},callHierarchy:{dynamicRegistration:false},documentSymbol:{dynamicRegistration:false,hierarchicalDocumentSymbolSupport:true},publishDiagnostics:{relatedInformation:true}}};return await this.connection.sendRequest(InitializeRequest.type,{processId:process.pid,capabilities:t,rootUri:c(this.options.workspacePath,"."),initializationOptions:this.options.initializationOptions??null})}setupProviders(t){t.definitionProvider&&(this.definition={provideDefinition:(e,i)=>this.provideDefinition(e,i),provideTypeDefinition:(e,i)=>this.provideTypeDefinition(e,i)}),t.referencesProvider&&(this.references={provideReferences:(e,i)=>this.provideReferences(e,i)}),t.callHierarchyProvider&&(this.hierarchy={provideCallHierarchy:(e,i,n)=>this.provideCallHierarchy(e,i,n)}),t.documentSymbolProvider&&(this.outline={provideDocumentSymbols:e=>this.provideDocumentSymbols(e)}),this.diagnostics={provideDiagnostics:e=>this.provideDiagnostics(e),getWorkspaceDiagnostics:()=>this.getWorkspaceDiagnostics()};}assertRunning(){if(this.state!=="running")throw new Error(`Client is not running (state: "${this.state}")`);if(!this.connection)throw new Error("No connection");return this.connection}createTimeout(){let t=new CancellationTokenSource,e,i=new Promise((n,s)=>{e=setTimeout(()=>{t.cancel(),s(new Error("LSP request timed out"));},this.options.requestTimeout);});return {token:t,promise:i,clear:()=>{e&&clearTimeout(e);}}}async sendRequest(t,e){let i=this.assertRunning(),n=this.createTimeout();try{return await Promise.race([i.sendRequest(t,e,n.token.token),n.promise])}finally{n.clear();}}async ensureDocumentOpen(t){let e=this.openDocuments.get(t);if(e){e.closeTimer&&clearTimeout(e.closeTimer),e.closeTimer=this.scheduleDocumentClose(t);return}let i=u(this.options.workspacePath,t),n=await this.options.readFile(i),s=w(i),r={uri:t,version:1,closeTimer:this.scheduleDocumentClose(t)};this.openDocuments.set(t,r),await this.connection?.sendNotification(DidOpenTextDocumentNotification.type,{textDocument:{uri:t,languageId:s,version:r.version,text:n}});}scheduleDocumentClose(t){return setTimeout(()=>{this.closeDocument(t);},this.options.documentIdleTimeout)}async closeDocument(t){let e=this.openDocuments.get(t);if(e&&(e.closeTimer&&clearTimeout(e.closeTimer),this.openDocuments.delete(t),this.connection&&this.state==="running"))try{await this.connection.sendNotification(DidCloseTextDocumentNotification.type,{textDocument:{uri:t}});}catch{}}async provideDefinition(t,e){let i=c(this.options.workspacePath,t);await this.ensureDocumentOpen(i);let n=await this.sendRequest("textDocument/definition",{textDocument:{uri:i},position:{line:e.line,character:e.character}});return h(this.options.workspacePath,n,this.options.readFile)}async provideTypeDefinition(t,e){let i=c(this.options.workspacePath,t);await this.ensureDocumentOpen(i);let n=await this.sendRequest("textDocument/typeDefinition",{textDocument:{uri:i},position:{line:e.line,character:e.character}});return h(this.options.workspacePath,n,this.options.readFile)}async provideReferences(t,e){let i=c(this.options.workspacePath,t);await this.ensureDocumentOpen(i);let n=await this.sendRequest("textDocument/references",{textDocument:{uri:i},position:{line:e.line,character:e.character},context:{includeDeclaration:true}});return h(this.options.workspacePath,n,this.options.readFile)}async provideCallHierarchy(t,e,i){let n=c(this.options.workspacePath,t);await this.ensureDocumentOpen(n);let s=await this.sendRequest("textDocument/prepareCallHierarchy",{textDocument:{uri:n},position:{line:e.line,character:e.character}});if(!s||s.length===0)return [];let r=s[0],a=i==="incoming"?"callHierarchy/incomingCalls":"callHierarchy/outgoingCalls",d=await this.sendRequest(a,{item:r});if(!d||d.length===0)return [];let m=d.map(l=>{let v="from"in l?l.from:l.to;return {uri:v.uri,range:v.selectionRange}});return h(this.options.workspacePath,m,this.options.readFile)}async provideDocumentSymbols(t){let e=c(this.options.workspacePath,t);await this.ensureDocumentOpen(e);let i=await this.sendRequest("textDocument/documentSymbol",{textDocument:{uri:e}});if(!i||i.length===0)return [];let n=i[0];return n&&"range"in n&&"selectionRange"in n?i.map(f):i.map(s=>C(this.options.workspacePath,s))}async provideDiagnostics(t){this.assertRunning();let e=c(this.options.workspacePath,t);await this.ensureDocumentOpen(e);let i=this.diagnosticsCache.get(t);return i||(await new Promise(n=>setTimeout(n,200)),this.diagnosticsCache.get(t)??[])}async getWorkspaceDiagnostics(){this.assertRunning();let t=[];for(let e of this.diagnosticsCache.values())t.push(...e);return t}transitionToDead(){this.state="dead",this.cleanup();}cleanup(){for(let t of this.openDocuments.values())t.closeTimer&&clearTimeout(t.closeTimer);if(this.openDocuments.clear(),this.connection){try{this.connection.dispose();}catch{}this.connection=null;}if(this.process){try{this.process.kill();}catch{}this.process=null;}this.state="dead";}};function _(o){return new y(o)}export{y as LspClient,b as convertDiagnosticSeverity,h as convertLocationsToSnippets,g as convertLspDiagnostic,f as convertLspDocumentSymbol,R as convertLspPosition,p as convertLspRange,C as convertSymbolInformation,P as convertSymbolKind,_ as createLspClient,w as guessLanguageId,u as lspUriToPath,c as pathToLspUri};
|