refactor(lsp): remove duplicate LSP tools already provided by OpenCode
Remove lsp_goto_definition, lsp_find_references, lsp_symbols as they duplicate OpenCode's built-in LspGotoDefinition, LspFindReferences, LspDocumentSymbols, and LspWorkspaceSymbols. Keep oh-my-opencode-specific tools: - lsp_diagnostics (OpenCode lacks pull diagnostics) - lsp_servers (server management) - lsp_prepare_rename / lsp_rename (OpenCode lacks rename) Clean up associated dead code: - Client methods: hover, definition, references, symbols, codeAction - Utils: formatLocation, formatSymbolKind, formatDocumentSymbol, etc. - Types: Location, LocationLink, SymbolInfo, DocumentSymbol, etc. - Constants: SYMBOL_KIND_MAP, DEFAULT_MAX_REFERENCES/SYMBOLS -418 lines removed.
This commit is contained in:
parent
207a39b17a
commit
48167a6920
@ -12,8 +12,6 @@ const TRUNCATABLE_TOOLS = [
|
|||||||
"glob",
|
"glob",
|
||||||
"Glob",
|
"Glob",
|
||||||
"safe_glob",
|
"safe_glob",
|
||||||
"lsp_find_references",
|
|
||||||
"lsp_symbols",
|
|
||||||
"lsp_diagnostics",
|
"lsp_diagnostics",
|
||||||
"ast_grep_search",
|
"ast_grep_search",
|
||||||
"interactive_bash",
|
"interactive_bash",
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
lsp_goto_definition,
|
|
||||||
lsp_find_references,
|
|
||||||
lsp_symbols,
|
|
||||||
lsp_diagnostics,
|
lsp_diagnostics,
|
||||||
lsp_servers,
|
lsp_servers,
|
||||||
lsp_prepare_rename,
|
lsp_prepare_rename,
|
||||||
@ -56,9 +53,6 @@ export function createBackgroundTools(manager: BackgroundManager, client: Openco
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const builtinTools: Record<string, ToolDefinition> = {
|
export const builtinTools: Record<string, ToolDefinition> = {
|
||||||
lsp_goto_definition,
|
|
||||||
lsp_find_references,
|
|
||||||
lsp_symbols,
|
|
||||||
lsp_diagnostics,
|
lsp_diagnostics,
|
||||||
lsp_servers,
|
lsp_servers,
|
||||||
lsp_prepare_rename,
|
lsp_prepare_rename,
|
||||||
|
|||||||
@ -509,46 +509,6 @@ export class LSPClient {
|
|||||||
await new Promise((r) => setTimeout(r, 1000))
|
await new Promise((r) => setTimeout(r, 1000))
|
||||||
}
|
}
|
||||||
|
|
||||||
async hover(filePath: string, line: number, character: number): Promise<unknown> {
|
|
||||||
const absPath = resolve(filePath)
|
|
||||||
await this.openFile(absPath)
|
|
||||||
return this.send("textDocument/hover", {
|
|
||||||
textDocument: { uri: pathToFileURL(absPath).href },
|
|
||||||
position: { line: line - 1, character },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async definition(filePath: string, line: number, character: number): Promise<unknown> {
|
|
||||||
const absPath = resolve(filePath)
|
|
||||||
await this.openFile(absPath)
|
|
||||||
return this.send("textDocument/definition", {
|
|
||||||
textDocument: { uri: pathToFileURL(absPath).href },
|
|
||||||
position: { line: line - 1, character },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async references(filePath: string, line: number, character: number, includeDeclaration = true): Promise<unknown> {
|
|
||||||
const absPath = resolve(filePath)
|
|
||||||
await this.openFile(absPath)
|
|
||||||
return this.send("textDocument/references", {
|
|
||||||
textDocument: { uri: pathToFileURL(absPath).href },
|
|
||||||
position: { line: line - 1, character },
|
|
||||||
context: { includeDeclaration },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async documentSymbols(filePath: string): Promise<unknown> {
|
|
||||||
const absPath = resolve(filePath)
|
|
||||||
await this.openFile(absPath)
|
|
||||||
return this.send("textDocument/documentSymbol", {
|
|
||||||
textDocument: { uri: pathToFileURL(absPath).href },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async workspaceSymbols(query: string): Promise<unknown> {
|
|
||||||
return this.send("workspace/symbol", { query })
|
|
||||||
}
|
|
||||||
|
|
||||||
async diagnostics(filePath: string): Promise<{ items: Diagnostic[] }> {
|
async diagnostics(filePath: string): Promise<{ items: Diagnostic[] }> {
|
||||||
const absPath = resolve(filePath)
|
const absPath = resolve(filePath)
|
||||||
const uri = pathToFileURL(absPath).href
|
const uri = pathToFileURL(absPath).href
|
||||||
@ -587,33 +547,6 @@ export class LSPClient {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async codeAction(
|
|
||||||
filePath: string,
|
|
||||||
startLine: number,
|
|
||||||
startChar: number,
|
|
||||||
endLine: number,
|
|
||||||
endChar: number,
|
|
||||||
only?: string[]
|
|
||||||
): Promise<unknown> {
|
|
||||||
const absPath = resolve(filePath)
|
|
||||||
await this.openFile(absPath)
|
|
||||||
return this.send("textDocument/codeAction", {
|
|
||||||
textDocument: { uri: pathToFileURL(absPath).href },
|
|
||||||
range: {
|
|
||||||
start: { line: startLine - 1, character: startChar },
|
|
||||||
end: { line: endLine - 1, character: endChar },
|
|
||||||
},
|
|
||||||
context: {
|
|
||||||
diagnostics: [],
|
|
||||||
only,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async codeActionResolve(codeAction: unknown): Promise<unknown> {
|
|
||||||
return this.send("codeAction/resolve", codeAction)
|
|
||||||
}
|
|
||||||
|
|
||||||
isAlive(): boolean {
|
isAlive(): boolean {
|
||||||
return this.proc !== null && !this.processExited && this.proc.exitCode === null
|
return this.proc !== null && !this.processExited && this.proc.exitCode === null
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,34 +1,5 @@
|
|||||||
import type { LSPServerConfig } from "./types"
|
import type { LSPServerConfig } from "./types"
|
||||||
|
|
||||||
export const SYMBOL_KIND_MAP: Record<number, string> = {
|
|
||||||
1: "File",
|
|
||||||
2: "Module",
|
|
||||||
3: "Namespace",
|
|
||||||
4: "Package",
|
|
||||||
5: "Class",
|
|
||||||
6: "Method",
|
|
||||||
7: "Property",
|
|
||||||
8: "Field",
|
|
||||||
9: "Constructor",
|
|
||||||
10: "Enum",
|
|
||||||
11: "Interface",
|
|
||||||
12: "Function",
|
|
||||||
13: "Variable",
|
|
||||||
14: "Constant",
|
|
||||||
15: "String",
|
|
||||||
16: "Number",
|
|
||||||
17: "Boolean",
|
|
||||||
18: "Array",
|
|
||||||
19: "Object",
|
|
||||||
20: "Key",
|
|
||||||
21: "Null",
|
|
||||||
22: "EnumMember",
|
|
||||||
23: "Struct",
|
|
||||||
24: "Event",
|
|
||||||
25: "Operator",
|
|
||||||
26: "TypeParameter",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SEVERITY_MAP: Record<number, string> = {
|
export const SEVERITY_MAP: Record<number, string> = {
|
||||||
1: "error",
|
1: "error",
|
||||||
2: "warning",
|
2: "warning",
|
||||||
@ -36,8 +7,6 @@ export const SEVERITY_MAP: Record<number, string> = {
|
|||||||
4: "hint",
|
4: "hint",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_MAX_REFERENCES = 200
|
|
||||||
export const DEFAULT_MAX_SYMBOLS = 200
|
|
||||||
export const DEFAULT_MAX_DIAGNOSTICS = 200
|
export const DEFAULT_MAX_DIAGNOSTICS = 200
|
||||||
|
|
||||||
export const LSP_INSTALL_HINTS: Record<string, string> = {
|
export const LSP_INSTALL_HINTS: Record<string, string> = {
|
||||||
|
|||||||
@ -1,15 +1,10 @@
|
|||||||
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
|
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
|
||||||
import { getAllServers } from "./config"
|
import { getAllServers } from "./config"
|
||||||
import {
|
import {
|
||||||
DEFAULT_MAX_REFERENCES,
|
|
||||||
DEFAULT_MAX_SYMBOLS,
|
|
||||||
DEFAULT_MAX_DIAGNOSTICS,
|
DEFAULT_MAX_DIAGNOSTICS,
|
||||||
} from "./constants"
|
} from "./constants"
|
||||||
import {
|
import {
|
||||||
withLspClient,
|
withLspClient,
|
||||||
formatLocation,
|
|
||||||
formatDocumentSymbol,
|
|
||||||
formatSymbolInfo,
|
|
||||||
formatDiagnostic,
|
formatDiagnostic,
|
||||||
filterDiagnosticsBySeverity,
|
filterDiagnosticsBySeverity,
|
||||||
formatPrepareRenameResult,
|
formatPrepareRenameResult,
|
||||||
@ -17,157 +12,14 @@ import {
|
|||||||
formatApplyResult,
|
formatApplyResult,
|
||||||
} from "./utils"
|
} from "./utils"
|
||||||
import type {
|
import type {
|
||||||
Location,
|
|
||||||
LocationLink,
|
|
||||||
DocumentSymbol,
|
|
||||||
SymbolInfo,
|
|
||||||
Diagnostic,
|
Diagnostic,
|
||||||
PrepareRenameResult,
|
PrepareRenameResult,
|
||||||
PrepareRenameDefaultBehavior,
|
PrepareRenameDefaultBehavior,
|
||||||
WorkspaceEdit,
|
WorkspaceEdit,
|
||||||
} from "./types"
|
} from "./types"
|
||||||
|
|
||||||
|
// NOTE: lsp_goto_definition, lsp_find_references, lsp_symbols are removed
|
||||||
|
// as they duplicate OpenCode's built-in LSP tools (LspGotoDefinition, LspFindReferences, LspDocumentSymbols, LspWorkspaceSymbols)
|
||||||
export const lsp_goto_definition: ToolDefinition = tool({
|
|
||||||
description: "Jump to symbol definition. Find WHERE something is defined.",
|
|
||||||
args: {
|
|
||||||
filePath: tool.schema.string(),
|
|
||||||
line: tool.schema.number().min(1).describe("1-based"),
|
|
||||||
character: tool.schema.number().min(0).describe("0-based"),
|
|
||||||
},
|
|
||||||
execute: async (args, context) => {
|
|
||||||
try {
|
|
||||||
const result = await withLspClient(args.filePath, async (client) => {
|
|
||||||
return (await client.definition(args.filePath, args.line, args.character)) as
|
|
||||||
| Location
|
|
||||||
| Location[]
|
|
||||||
| LocationLink[]
|
|
||||||
| null
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
const output = "No definition found"
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
const locations = Array.isArray(result) ? result : [result]
|
|
||||||
if (locations.length === 0) {
|
|
||||||
const output = "No definition found"
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = locations.map(formatLocation).join("\n")
|
|
||||||
return output
|
|
||||||
} catch (e) {
|
|
||||||
const output = `Error: ${e instanceof Error ? e.message : String(e)}`
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const lsp_find_references: ToolDefinition = tool({
|
|
||||||
description: "Find ALL usages/references of a symbol across the entire workspace.",
|
|
||||||
args: {
|
|
||||||
filePath: tool.schema.string(),
|
|
||||||
line: tool.schema.number().min(1).describe("1-based"),
|
|
||||||
character: tool.schema.number().min(0).describe("0-based"),
|
|
||||||
includeDeclaration: tool.schema.boolean().optional().describe("Include the declaration itself"),
|
|
||||||
},
|
|
||||||
execute: async (args, context) => {
|
|
||||||
try {
|
|
||||||
const result = await withLspClient(args.filePath, async (client) => {
|
|
||||||
return (await client.references(args.filePath, args.line, args.character, args.includeDeclaration ?? true)) as
|
|
||||||
| Location[]
|
|
||||||
| null
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!result || result.length === 0) {
|
|
||||||
const output = "No references found"
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
const total = result.length
|
|
||||||
const truncated = total > DEFAULT_MAX_REFERENCES
|
|
||||||
const limited = truncated ? result.slice(0, DEFAULT_MAX_REFERENCES) : result
|
|
||||||
const lines = limited.map(formatLocation)
|
|
||||||
if (truncated) {
|
|
||||||
lines.unshift(`Found ${total} references (showing first ${DEFAULT_MAX_REFERENCES}):`)
|
|
||||||
}
|
|
||||||
const output = lines.join("\n")
|
|
||||||
return output
|
|
||||||
} catch (e) {
|
|
||||||
const output = `Error: ${e instanceof Error ? e.message : String(e)}`
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const lsp_symbols: ToolDefinition = tool({
|
|
||||||
description: "Get symbols from file (document) or search across workspace. Use scope='document' for file outline, scope='workspace' for project-wide symbol search.",
|
|
||||||
args: {
|
|
||||||
filePath: tool.schema.string().describe("File path for LSP context"),
|
|
||||||
scope: tool.schema.enum(["document", "workspace"]).default("document").describe("'document' for file symbols, 'workspace' for project-wide search"),
|
|
||||||
query: tool.schema.string().optional().describe("Symbol name to search (required for workspace scope)"),
|
|
||||||
limit: tool.schema.number().optional().describe("Max results (default 50)"),
|
|
||||||
},
|
|
||||||
execute: async (args, context) => {
|
|
||||||
try {
|
|
||||||
const scope = args.scope ?? "document"
|
|
||||||
|
|
||||||
if (scope === "workspace") {
|
|
||||||
if (!args.query) {
|
|
||||||
return "Error: 'query' is required for workspace scope"
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await withLspClient(args.filePath, async (client) => {
|
|
||||||
return (await client.workspaceSymbols(args.query!)) as SymbolInfo[] | null
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!result || result.length === 0) {
|
|
||||||
return "No symbols found"
|
|
||||||
}
|
|
||||||
|
|
||||||
const total = result.length
|
|
||||||
const limit = Math.min(args.limit ?? DEFAULT_MAX_SYMBOLS, DEFAULT_MAX_SYMBOLS)
|
|
||||||
const truncated = total > limit
|
|
||||||
const limited = result.slice(0, limit)
|
|
||||||
const lines = limited.map(formatSymbolInfo)
|
|
||||||
if (truncated) {
|
|
||||||
lines.unshift(`Found ${total} symbols (showing first ${limit}):`)
|
|
||||||
}
|
|
||||||
return lines.join("\n")
|
|
||||||
} else {
|
|
||||||
const result = await withLspClient(args.filePath, async (client) => {
|
|
||||||
return (await client.documentSymbols(args.filePath)) as DocumentSymbol[] | SymbolInfo[] | null
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!result || result.length === 0) {
|
|
||||||
return "No symbols found"
|
|
||||||
}
|
|
||||||
|
|
||||||
const total = result.length
|
|
||||||
const limit = Math.min(args.limit ?? DEFAULT_MAX_SYMBOLS, DEFAULT_MAX_SYMBOLS)
|
|
||||||
const truncated = total > limit
|
|
||||||
const limited = truncated ? result.slice(0, limit) : result
|
|
||||||
|
|
||||||
const lines: string[] = []
|
|
||||||
if (truncated) {
|
|
||||||
lines.push(`Found ${total} symbols (showing first ${limit}):`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("range" in limited[0]) {
|
|
||||||
lines.push(...(limited as DocumentSymbol[]).map((s) => formatDocumentSymbol(s)))
|
|
||||||
} else {
|
|
||||||
lines.push(...(limited as SymbolInfo[]).map(formatSymbolInfo))
|
|
||||||
}
|
|
||||||
return lines.join("\n")
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return `Error: ${e instanceof Error ? e.message : String(e)}`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const lsp_diagnostics: ToolDefinition = tool({
|
export const lsp_diagnostics: ToolDefinition = tool({
|
||||||
description: "Get errors, warnings, hints from language server BEFORE running build.",
|
description: "Get errors, warnings, hints from language server BEFORE running build.",
|
||||||
|
|||||||
@ -17,33 +17,6 @@ export interface Range {
|
|||||||
end: Position
|
end: Position
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Location {
|
|
||||||
uri: string
|
|
||||||
range: Range
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LocationLink {
|
|
||||||
targetUri: string
|
|
||||||
targetRange: Range
|
|
||||||
targetSelectionRange: Range
|
|
||||||
originSelectionRange?: Range
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SymbolInfo {
|
|
||||||
name: string
|
|
||||||
kind: number
|
|
||||||
location: Location
|
|
||||||
containerName?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DocumentSymbol {
|
|
||||||
name: string
|
|
||||||
kind: number
|
|
||||||
range: Range
|
|
||||||
selectionRange: Range
|
|
||||||
children?: DocumentSymbol[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Diagnostic {
|
export interface Diagnostic {
|
||||||
range: Range
|
range: Range
|
||||||
severity?: number
|
severity?: number
|
||||||
@ -52,14 +25,6 @@ export interface Diagnostic {
|
|||||||
message: string
|
message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HoverResult {
|
|
||||||
contents:
|
|
||||||
| { kind?: string; value: string }
|
|
||||||
| string
|
|
||||||
| Array<{ kind?: string; value: string } | string>
|
|
||||||
range?: Range
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TextDocumentIdentifier {
|
export interface TextDocumentIdentifier {
|
||||||
uri: string
|
uri: string
|
||||||
}
|
}
|
||||||
@ -111,31 +76,6 @@ export interface PrepareRenameDefaultBehavior {
|
|||||||
defaultBehavior: boolean
|
defaultBehavior: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Command {
|
|
||||||
title: string
|
|
||||||
command: string
|
|
||||||
arguments?: unknown[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CodeActionContext {
|
|
||||||
diagnostics: Diagnostic[]
|
|
||||||
only?: string[]
|
|
||||||
triggerKind?: CodeActionTriggerKind
|
|
||||||
}
|
|
||||||
|
|
||||||
export type CodeActionTriggerKind = 1 | 2
|
|
||||||
|
|
||||||
export interface CodeAction {
|
|
||||||
title: string
|
|
||||||
kind?: string
|
|
||||||
diagnostics?: Diagnostic[]
|
|
||||||
isPreferred?: boolean
|
|
||||||
disabled?: { reason: string }
|
|
||||||
edit?: WorkspaceEdit
|
|
||||||
command?: Command
|
|
||||||
data?: unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ServerLookupInfo {
|
export interface ServerLookupInfo {
|
||||||
id: string
|
id: string
|
||||||
command: string[]
|
command: string[]
|
||||||
|
|||||||
@ -3,21 +3,14 @@ import { fileURLToPath } from "node:url"
|
|||||||
import { existsSync, readFileSync, writeFileSync } from "fs"
|
import { existsSync, readFileSync, writeFileSync } from "fs"
|
||||||
import { LSPClient, lspManager } from "./client"
|
import { LSPClient, lspManager } from "./client"
|
||||||
import { findServerForExtension } from "./config"
|
import { findServerForExtension } from "./config"
|
||||||
import { SYMBOL_KIND_MAP, SEVERITY_MAP } from "./constants"
|
import { SEVERITY_MAP } from "./constants"
|
||||||
import type {
|
import type {
|
||||||
HoverResult,
|
|
||||||
DocumentSymbol,
|
|
||||||
SymbolInfo,
|
|
||||||
Location,
|
|
||||||
LocationLink,
|
|
||||||
Diagnostic,
|
Diagnostic,
|
||||||
PrepareRenameResult,
|
PrepareRenameResult,
|
||||||
PrepareRenameDefaultBehavior,
|
PrepareRenameDefaultBehavior,
|
||||||
Range,
|
Range,
|
||||||
WorkspaceEdit,
|
WorkspaceEdit,
|
||||||
TextEdit,
|
TextEdit,
|
||||||
CodeAction,
|
|
||||||
Command,
|
|
||||||
ServerLookupResult,
|
ServerLookupResult,
|
||||||
} from "./types"
|
} from "./types"
|
||||||
|
|
||||||
@ -113,73 +106,11 @@ export async function withLspClient<T>(filePath: string, fn: (client: LSPClient)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatHoverResult(result: HoverResult | null): string {
|
|
||||||
if (!result) return "No hover information available"
|
|
||||||
|
|
||||||
const contents = result.contents
|
|
||||||
if (typeof contents === "string") {
|
|
||||||
return contents
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(contents)) {
|
|
||||||
return contents
|
|
||||||
.map((c) => (typeof c === "string" ? c : c.value))
|
|
||||||
.filter(Boolean)
|
|
||||||
.join("\n\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof contents === "object" && "value" in contents) {
|
|
||||||
return contents.value
|
|
||||||
}
|
|
||||||
|
|
||||||
return "No hover information available"
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatLocation(loc: Location | LocationLink): string {
|
|
||||||
if ("targetUri" in loc) {
|
|
||||||
const uri = uriToPath(loc.targetUri)
|
|
||||||
const line = loc.targetRange.start.line + 1
|
|
||||||
const char = loc.targetRange.start.character
|
|
||||||
return `${uri}:${line}:${char}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const uri = uriToPath(loc.uri)
|
|
||||||
const line = loc.range.start.line + 1
|
|
||||||
const char = loc.range.start.character
|
|
||||||
return `${uri}:${line}:${char}`
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatSymbolKind(kind: number): string {
|
|
||||||
return SYMBOL_KIND_MAP[kind] || `Unknown(${kind})`
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatSeverity(severity: number | undefined): string {
|
export function formatSeverity(severity: number | undefined): string {
|
||||||
if (!severity) return "unknown"
|
if (!severity) return "unknown"
|
||||||
return SEVERITY_MAP[severity] || `unknown(${severity})`
|
return SEVERITY_MAP[severity] || `unknown(${severity})`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatDocumentSymbol(symbol: DocumentSymbol, indent = 0): string {
|
|
||||||
const prefix = " ".repeat(indent)
|
|
||||||
const kind = formatSymbolKind(symbol.kind)
|
|
||||||
const line = symbol.range.start.line + 1
|
|
||||||
let result = `${prefix}${symbol.name} (${kind}) - line ${line}`
|
|
||||||
|
|
||||||
if (symbol.children && symbol.children.length > 0) {
|
|
||||||
for (const child of symbol.children) {
|
|
||||||
result += "\n" + formatDocumentSymbol(child, indent + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatSymbolInfo(symbol: SymbolInfo): string {
|
|
||||||
const kind = formatSymbolKind(symbol.kind)
|
|
||||||
const loc = formatLocation(symbol.location)
|
|
||||||
const container = symbol.containerName ? ` (in ${symbol.containerName})` : ""
|
|
||||||
return `${symbol.name} (${kind})${container} - ${loc}`
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatDiagnostic(diag: Diagnostic): string {
|
export function formatDiagnostic(diag: Diagnostic): string {
|
||||||
const severity = formatSeverity(diag.severity)
|
const severity = formatSeverity(diag.severity)
|
||||||
const line = diag.range.start.line + 1
|
const line = diag.range.start.line + 1
|
||||||
@ -292,38 +223,6 @@ export function formatWorkspaceEdit(edit: WorkspaceEdit | null): string {
|
|||||||
return lines.join("\n")
|
return lines.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatCodeAction(action: CodeAction): string {
|
|
||||||
let result = `[${action.kind || "action"}] ${action.title}`
|
|
||||||
|
|
||||||
if (action.isPreferred) {
|
|
||||||
result += " ⭐"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action.disabled) {
|
|
||||||
result += ` (disabled: ${action.disabled.reason})`
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatCodeActions(actions: (CodeAction | Command)[] | null): string {
|
|
||||||
if (!actions || actions.length === 0) return "No code actions available"
|
|
||||||
|
|
||||||
const lines: string[] = []
|
|
||||||
|
|
||||||
for (let i = 0; i < actions.length; i++) {
|
|
||||||
const action = actions[i]
|
|
||||||
|
|
||||||
if ("command" in action && typeof action.command === "string" && !("kind" in action)) {
|
|
||||||
lines.push(`${i + 1}. [command] ${(action as Command).title}`)
|
|
||||||
} else {
|
|
||||||
lines.push(`${i + 1}. ${formatCodeAction(action as CodeAction)}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lines.join("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ApplyResult {
|
export interface ApplyResult {
|
||||||
success: boolean
|
success: boolean
|
||||||
filesModified: string[]
|
filesModified: string[]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user