Merge pull request #2588 from acamq/refactor/doctor-lsp-extensions
refactor(doctor): show detected LSP extensions instead of hardcoded server counts
This commit is contained in:
@@ -1,25 +1,9 @@
|
||||
import type { LspServerInfo } from "../types"
|
||||
import { isServerInstalled } from "../../../tools/lsp/config"
|
||||
import { getAllServers } from "../../../tools/lsp/config"
|
||||
|
||||
const DEFAULT_LSP_SERVERS: Array<{ id: string; binary: string; extensions: string[] }> = [
|
||||
{ id: "typescript-language-server", binary: "typescript-language-server", extensions: [".ts", ".tsx", ".js", ".jsx"] },
|
||||
{ id: "pyright", binary: "pyright-langserver", extensions: [".py"] },
|
||||
{ id: "rust-analyzer", binary: "rust-analyzer", extensions: [".rs"] },
|
||||
{ id: "gopls", binary: "gopls", extensions: [".go"] },
|
||||
]
|
||||
export function getInstalledLspServers(): Array<{ id: string; extensions: string[] }> {
|
||||
const servers = getAllServers()
|
||||
|
||||
export function getLspServersInfo(): LspServerInfo[] {
|
||||
return DEFAULT_LSP_SERVERS.map((server) => ({
|
||||
id: server.id,
|
||||
installed: isServerInstalled([server.binary]),
|
||||
extensions: server.extensions,
|
||||
source: "builtin",
|
||||
}))
|
||||
}
|
||||
|
||||
export function getLspServerStats(servers: LspServerInfo[]): { installed: number; total: number } {
|
||||
return {
|
||||
installed: servers.filter((server) => server.installed).length,
|
||||
total: servers.length,
|
||||
}
|
||||
return servers
|
||||
.filter((s) => s.installed && !s.disabled)
|
||||
.map((s) => ({ id: s.id, extensions: s.extensions }))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { checkAstGrepCli, checkAstGrepNapi, checkCommentChecker } from "./dependencies"
|
||||
import { getGhCliInfo } from "./tools-gh"
|
||||
import { getLspServerStats, getLspServersInfo } from "./tools-lsp"
|
||||
import { getInstalledLspServers } from "./tools-lsp"
|
||||
import { getBuiltinMcpInfo, getUserMcpInfo } from "./tools-mcp"
|
||||
import { CHECK_IDS, CHECK_NAMES } from "../constants"
|
||||
import type { CheckResult, DoctorIssue, ToolsSummary } from "../types"
|
||||
@@ -13,14 +13,12 @@ export async function gatherToolsSummary(): Promise<ToolsSummary> {
|
||||
getGhCliInfo(),
|
||||
])
|
||||
|
||||
const lspServers = getLspServersInfo()
|
||||
const lspStats = getLspServerStats(lspServers)
|
||||
const lspServers = getInstalledLspServers()
|
||||
const builtinMcp = getBuiltinMcpInfo()
|
||||
const userMcp = getUserMcpInfo()
|
||||
|
||||
return {
|
||||
lspInstalled: lspStats.installed,
|
||||
lspTotal: lspStats.total,
|
||||
lspServers,
|
||||
astGrepCli: astGrepCliInfo.installed,
|
||||
astGrepNapi: astGrepNapiInfo.installed,
|
||||
commentChecker: commentCheckerInfo.installed,
|
||||
@@ -57,7 +55,7 @@ function buildToolIssues(summary: ToolsSummary): DoctorIssue[] {
|
||||
})
|
||||
}
|
||||
|
||||
if (summary.lspInstalled === 0) {
|
||||
if (summary.lspServers.length === 0) {
|
||||
issues.push({
|
||||
title: "No LSP servers detected",
|
||||
description: "LSP-dependent tools will be limited until at least one server is installed.",
|
||||
@@ -109,7 +107,7 @@ export async function checkTools(): Promise<CheckResult> {
|
||||
details: [
|
||||
`AST-Grep: cli=${summary.astGrepCli ? "yes" : "no"}, napi=${summary.astGrepNapi ? "yes" : "no"}`,
|
||||
`Comment checker: ${summary.commentChecker ? "yes" : "no"}`,
|
||||
`LSP: ${summary.lspInstalled}/${summary.lspTotal}`,
|
||||
`LSP: ${summary.lspServers.length > 0 ? `${summary.lspServers.length} server(s)` : "none"}`,
|
||||
`GH CLI: ${summary.ghCli.installed ? "installed" : "missing"}${summary.ghCli.authenticated ? " (authenticated)" : ""}`,
|
||||
`MCP: builtin=${summary.mcpBuiltin.length}, user=${summary.mcpUser.length}`,
|
||||
],
|
||||
|
||||
@@ -20,8 +20,7 @@ function createBaseResult(): DoctorResult {
|
||||
isLocalDev: false,
|
||||
},
|
||||
tools: {
|
||||
lspInstalled: 0,
|
||||
lspTotal: 0,
|
||||
lspServers: [],
|
||||
astGrepCli: false,
|
||||
astGrepNapi: false,
|
||||
commentChecker: false,
|
||||
|
||||
@@ -19,11 +19,13 @@ export function formatStatus(result: DoctorResult): string {
|
||||
const configStatus = systemInfo.configValid ? color.green("(valid)") : color.red("(invalid)")
|
||||
lines.push(` ${padding}Config ${configPath} ${configStatus}`)
|
||||
|
||||
const lspText = `LSP ${tools.lspInstalled}/${tools.lspTotal}`
|
||||
const serverCount = tools.lspServers.length
|
||||
const lspMark = formatStatusMark(serverCount > 0)
|
||||
const lspText = serverCount > 0 ? `${serverCount} server${serverCount === 1 ? "" : "s"}` : "none"
|
||||
const astGrepMark = formatStatusMark(tools.astGrepCli)
|
||||
const ghMark = formatStatusMark(tools.ghCli.installed && tools.ghCli.authenticated)
|
||||
const ghUser = tools.ghCli.username ?? ""
|
||||
lines.push(` ${padding}Tools ${lspText} · AST-Grep ${astGrepMark} · gh ${ghMark}${ghUser ? ` (${ghUser})` : ""}`)
|
||||
lines.push(` ${padding}Tools LSP ${lspMark} ${lspText} · AST-Grep ${astGrepMark} · gh ${ghMark}${ghUser ? ` (${ghUser})` : ""}`)
|
||||
|
||||
const builtinCount = tools.mcpBuiltin.length
|
||||
const userCount = tools.mcpUser.length
|
||||
|
||||
@@ -33,7 +33,15 @@ export function formatVerbose(result: DoctorResult): string {
|
||||
|
||||
lines.push(`${color.bold("Tools")}`)
|
||||
lines.push(`${color.dim("\u2500".repeat(40))}`)
|
||||
lines.push(` ${formatStatusSymbol("pass")} LSP ${tools.lspInstalled}/${tools.lspTotal} installed`)
|
||||
if (tools.lspServers.length === 0) {
|
||||
lines.push(` ${formatStatusSymbol("warn")} LSP none detected`)
|
||||
} else {
|
||||
const count = tools.lspServers.length
|
||||
lines.push(` ${formatStatusSymbol("pass")} LSP ${count} server${count === 1 ? "" : "s"}`)
|
||||
for (const server of tools.lspServers) {
|
||||
lines.push(`${" ".repeat(20)}${server.id} (${server.extensions.join(", ")})`)
|
||||
}
|
||||
}
|
||||
lines.push(` ${formatStatusSymbol(tools.astGrepCli ? "pass" : "fail")} ast-grep CLI ${tools.astGrepCli ? "installed" : "not found"}`)
|
||||
lines.push(` ${formatStatusSymbol(tools.astGrepNapi ? "pass" : "fail")} ast-grep napi ${tools.astGrepNapi ? "installed" : "not found"}`)
|
||||
lines.push(` ${formatStatusSymbol(tools.commentChecker ? "pass" : "fail")} comment-checker ${tools.commentChecker ? "installed" : "not found"}`)
|
||||
|
||||
@@ -19,8 +19,10 @@ function createDoctorResult(): DoctorResult {
|
||||
isLocalDev: false,
|
||||
},
|
||||
tools: {
|
||||
lspInstalled: 2,
|
||||
lspTotal: 4,
|
||||
lspServers: [
|
||||
{ id: "typescript", extensions: [".ts", ".tsx", ".js", ".jsx"] },
|
||||
{ id: "pyright", extensions: [".py", ".pyi"] },
|
||||
],
|
||||
astGrepCli: true,
|
||||
astGrepNapi: false,
|
||||
commentChecker: true,
|
||||
@@ -119,7 +121,7 @@ describe("formatDoctorOutput", () => {
|
||||
const output = stripAnsi(formatDoctorOutput(result, "status"))
|
||||
|
||||
//#then
|
||||
expect(output).toContain("LSP 2/4")
|
||||
expect(output).toContain("LSP")
|
||||
expect(output).toContain("context7")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -16,8 +16,7 @@ function createSystemInfo(): SystemInfo {
|
||||
|
||||
function createTools(): ToolsSummary {
|
||||
return {
|
||||
lspInstalled: 1,
|
||||
lspTotal: 4,
|
||||
lspServers: [{ id: "typescript", extensions: [".ts", ".tsx", ".js", ".jsx"] }],
|
||||
astGrepCli: true,
|
||||
astGrepNapi: false,
|
||||
commentChecker: true,
|
||||
|
||||
@@ -47,8 +47,7 @@ export interface SystemInfo {
|
||||
}
|
||||
|
||||
export interface ToolsSummary {
|
||||
lspInstalled: number
|
||||
lspTotal: number
|
||||
lspServers: Array<{ id: string; extensions: string[] }>
|
||||
astGrepCli: boolean
|
||||
astGrepNapi: boolean
|
||||
commentChecker: boolean
|
||||
@@ -126,13 +125,6 @@ export interface DependencyInfo {
|
||||
installHint?: string
|
||||
}
|
||||
|
||||
export interface LspServerInfo {
|
||||
id: string
|
||||
installed: boolean
|
||||
extensions: string[]
|
||||
source: "builtin" | "config" | "plugin"
|
||||
}
|
||||
|
||||
export interface McpServerInfo {
|
||||
id: string
|
||||
type: "builtin" | "user"
|
||||
|
||||
Reference in New Issue
Block a user