pi-lens 4.4.0 → 4.4.2
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/CHANGELOG.md +158 -0
- package/README.md +1 -0
- package/config/dependency-cruiser-eager-allowlist.json +3 -1
- package/dist/{chunk-IXEBJSUE.js → chunk-23WOO7TX.js} +11 -10
- package/dist/{chunk-E2WFBRHM.js → chunk-2B73ZPOK.js} +3 -3
- package/dist/{chunk-DQ2NZ7C4.js → chunk-2BBLFX75.js} +139 -11
- package/dist/{chunk-ZMOL6RQC.js → chunk-2CD5RS6M.js} +2 -2
- package/dist/{chunk-VD4JQCQC.js → chunk-2ZGIZPDG.js} +38 -37
- package/dist/{chunk-DIULIWKU.js → chunk-34WSVGEM.js} +29 -3
- package/dist/chunk-3JNKMP3B.js +17 -0
- package/dist/{chunk-HVUZXSWK.js → chunk-3UUPUE3O.js} +45 -41
- package/dist/{chunk-5RXBNSW2.js → chunk-3VPVG5SU.js} +16 -8
- package/dist/chunk-3WA4HP4I.js +55 -0
- package/dist/chunk-466Z26MG.js +30 -0
- package/dist/{chunk-34U7PLGE.js → chunk-4UNXBNE2.js} +12 -11
- package/dist/{chunk-E4MAEDPM.js → chunk-4W4VLAPJ.js} +12 -11
- package/dist/{chunk-GUOGVTCQ.js → chunk-52FUZI6K.js} +4 -2
- package/dist/chunk-5JM2524W.js +84 -0
- package/dist/{chunk-VHQLPIRJ.js → chunk-5NGR67U5.js} +2 -2
- package/dist/{chunk-DFVMIKMQ.js → chunk-66SXUJCA.js} +45 -9
- package/dist/{chunk-OQGFCZJ4.js → chunk-66VMUL7Q.js} +16 -16
- package/dist/{chunk-HWBZIGMJ.js → chunk-67WMNWEE.js} +9 -8
- package/dist/{chunk-6QIUX4EP.js → chunk-6C7JWPCP.js} +7 -7
- package/dist/{chunk-47D2BO4S.js → chunk-6GFRNVYR.js} +11 -10
- package/dist/{chunk-ZAWW3AF6.js → chunk-6SDEP3AJ.js} +9 -8
- package/dist/{chunk-TGPXLY2J.js → chunk-724UL2TJ.js} +38 -2
- package/dist/{chunk-YLF3PPT5.js → chunk-76MWC2K6.js} +3 -3
- package/dist/{chunk-F3P7VQ7H.js → chunk-7DYBLXYA.js} +3 -3
- package/dist/{chunk-AJ3QXTRQ.js → chunk-7ULNCDCO.js} +37 -35
- package/dist/{chunk-UK3CMEAL.js → chunk-AOHZU2BM.js} +1 -1
- package/dist/{chunk-F3AU2TMM.js → chunk-ARJ6PLFH.js} +44 -28
- package/dist/{chunk-U3VGR4VU.js → chunk-AW7R2GWG.js} +65 -8
- package/dist/{chunk-FJNKANOS.js → chunk-BKE7E7TC.js} +10 -9
- package/dist/{chunk-4W2PLC4J.js → chunk-BRGDSBJE.js} +13 -12
- package/dist/{chunk-VN2AXLEX.js → chunk-C34ZXZ7O.js} +102 -16
- package/dist/{chunk-T4ERT73Y.js → chunk-CF24OIYI.js} +21 -20
- package/dist/{chunk-NMABWBZN.js → chunk-CHOW74WE.js} +1 -1
- package/dist/{chunk-ARFCXG7S.js → chunk-CO2G5PHH.js} +2 -2
- package/dist/{chunk-AS44CFQ4.js → chunk-EETY4LF7.js} +24 -10
- package/dist/{chunk-I3R7GKDR.js → chunk-EJIUXPBX.js} +1 -1
- package/dist/{chunk-B3I2UUT4.js → chunk-ESBQHFMJ.js} +653 -251
- package/dist/{chunk-O5WILGMI.js → chunk-FLKWCIZH.js} +8 -5
- package/dist/{chunk-LNAKEO63.js → chunk-GAEGEPOC.js} +4 -4
- package/dist/{chunk-V7R425XG.js → chunk-GBPP5P7X.js} +4 -4
- package/dist/{chunk-XK4CIILI.js → chunk-GHB6AYCP.js} +27 -26
- package/dist/{chunk-7FBF7NPR.js → chunk-GOYRYZ2R.js} +29 -26
- package/dist/{chunk-JOLITGCC.js → chunk-GXW6K4YJ.js} +1 -1
- package/dist/{chunk-NXPS2L6U.js → chunk-GZYBXISR.js} +9 -9
- package/dist/{chunk-OAXNDZJ7.js → chunk-IBGIOBEE.js} +8 -4
- package/dist/{chunk-IIXOAGHR.js → chunk-IBRALRBR.js} +19 -15
- package/dist/{chunk-7F72PXY2.js → chunk-IXXDFY73.js} +3 -3
- package/dist/chunk-IZSHAIJ7.js +26 -0
- package/dist/{chunk-N3YQJI6O.js → chunk-JAU72XNY.js} +20 -15
- package/dist/chunk-JMYYOTQG.js +77 -0
- package/dist/{chunk-NL5GLMFI.js → chunk-JSQFTSC6.js} +12 -11
- package/dist/{chunk-IVP5KAB7.js → chunk-JWA5I3SR.js} +35 -21
- package/dist/{chunk-Y4T27COV.js → chunk-KBG47GHP.js} +4 -4
- package/dist/{chunk-PWFHBTSF.js → chunk-L3BLXZG7.js} +2 -2
- package/dist/chunk-LOP6GRPH.js +31 -0
- package/dist/chunk-MQLUAEOC.js +162 -0
- package/dist/{chunk-RPD5K5NC.js → chunk-MRXKYPCS.js} +2 -2
- package/dist/{chunk-Q5U6FMDI.js → chunk-N2H3ZPZY.js} +59 -7
- package/dist/{chunk-27BBHSZC.js → chunk-N3X6Q4YT.js} +3 -3
- package/dist/{chunk-UY752QSN.js → chunk-NW7BOILN.js} +19 -17
- package/dist/{chunk-TLGFBM3F.js → chunk-ODBNXWT4.js} +302 -113
- package/dist/{chunk-TT22N74J.js → chunk-OG5UUPN7.js} +13 -13
- package/dist/{chunk-C2AUYXQH.js → chunk-OXXKQCSV.js} +6 -6
- package/dist/{chunk-PAK6IDME.js → chunk-P7266HLM.js} +2 -2
- package/dist/{chunk-52H5B5TC.js → chunk-PFNSLWU5.js} +31 -30
- package/dist/{chunk-5ZEJHV35.js → chunk-PHDMFAKM.js} +12 -2
- package/dist/{chunk-3I5QFT3N.js → chunk-PNQDPDRC.js} +6 -3
- package/dist/{chunk-TVN5N6GY.js → chunk-PV6LR5P5.js} +6057 -1311
- package/dist/{chunk-AHDW3GPE.js → chunk-Q6ZWTCLY.js} +24 -22
- package/dist/{chunk-RUOG5D2C.js → chunk-Q7DUK4LX.js} +5 -5
- package/dist/{chunk-YSNFMJKN.js → chunk-QGQ5CCCG.js} +2 -2
- package/dist/{chunk-LW6XKDZQ.js → chunk-QHJ6DQ2R.js} +287 -38
- package/dist/{chunk-GVXA6CCE.js → chunk-QILIYSJF.js} +1 -1
- package/dist/{chunk-22AVIGXS.js → chunk-QOBUHWHX.js} +12 -7
- package/dist/{chunk-5THXD6X5.js → chunk-QQNQ7SJW.js} +2 -75
- package/dist/{chunk-4RERDEXR.js → chunk-QZVW3AAK.js} +50 -41
- package/dist/{chunk-AWE5TMPO.js → chunk-R3PCY3YS.js} +14 -13
- package/dist/{chunk-HHYAELLJ.js → chunk-RPLINGVB.js} +7 -7
- package/dist/{chunk-EOKRQ3SA.js → chunk-RWWYJ623.js} +10 -1
- package/dist/{chunk-YGVYKNSN.js → chunk-SAEFPSB6.js} +59 -12
- package/dist/{chunk-K6VYLB2U.js → chunk-TYM6OUIT.js} +13 -12
- package/dist/{chunk-AJXODZY6.js → chunk-UXGETRP4.js} +13 -12
- package/dist/{chunk-I7SPGOWI.js → chunk-UZ3TUTRV.js} +1 -1
- package/dist/{chunk-TO6WL3GM.js → chunk-VCHXCQFG.js} +12 -2
- package/dist/{chunk-BRJKOBZP.js → chunk-VITUCP5A.js} +17 -6
- package/dist/{chunk-WONERJTP.js → chunk-VRZP76YM.js} +1 -1
- package/dist/{chunk-OS32RNR2.js → chunk-VSSBEUFT.js} +16 -15
- package/dist/{chunk-VDBPVIKD.js → chunk-VWCXW2E7.js} +1 -1
- package/dist/{chunk-NKOUFPQF.js → chunk-WOA4LN2R.js} +2 -2
- package/dist/{chunk-RIISMHKN.js → chunk-WOKKRCJ5.js} +15 -13
- package/dist/{chunk-XECLWQZN.js → chunk-WU567RSC.js} +13 -10
- package/dist/{chunk-V5PXFSZK.js → chunk-XCJN5IJU.js} +4 -4
- package/dist/{chunk-ORTMY4Q4.js → chunk-XKIZ2HNN.js} +22 -14
- package/dist/{chunk-6VCD4VKZ.js → chunk-XMSXXAHW.js} +2 -2
- package/dist/chunk-XPZPXCBV.js +28 -0
- package/dist/{chunk-O6TQT6RI.js → chunk-XTMJ7XDT.js} +1 -1
- package/dist/{chunk-VNMT7C64.js → chunk-XVF2VVXP.js} +5 -3
- package/dist/chunk-Z527N6YQ.js +28 -0
- package/dist/{chunk-NTUJEGDZ.js → chunk-ZANLILYD.js} +22 -2
- package/dist/{chunk-6P62QVEA.js → chunk-ZGDGW2V3.js} +2 -2
- package/dist/{chunk-ODEEOXPH.js → chunk-ZHFZWTZV.js} +12 -11
- package/dist/{chunk-AJVLWNFN.js → chunk-ZXYDQ3TZ.js} +5 -5
- package/dist/index.js +102097 -97778
- package/dist/mcp/analyze-cli.js +18 -8
- package/dist/mcp/cli.js +48 -37
- package/dist/mcp/server.js +695 -426
- package/dist/mcp/worker.js +66 -55
- package/dist/probes/installer.js +20 -19
- package/docs/ast-grep_rules_catalog.md +2 -2
- package/docs/astplayground.md +1 -1
- package/docs/configuration.md +38 -2
- package/docs/custom-rules.md +25 -2
- package/docs/dependencies.md +3 -0
- package/docs/environment-variables.md +34 -6
- package/docs/features.md +39 -3
- package/docs/globalconfig.md +3 -1
- package/docs/language-coverage.md +2 -1
- package/docs/lsp-capability-matrix.md +29 -6
- package/docs/lsp-idle-eviction.md +38 -47
- package/docs/pi-lens-fixer.md +13 -5
- package/docs/pi-lens-merge-policy.md +48 -1
- package/docs/pi-lens-monitor.md +3 -1
- package/docs/pi-lens-retro.md +2 -1
- package/docs/pi-lens-reviewer.md +19 -3
- package/docs/pi-lens-subagent.md +2 -0
- package/docs/real-harness.md +17 -0
- package/docs/schema/pi-lens-config-v1.json +565 -0
- package/docs/servercapabilities.md +18 -4
- package/docs/settings.md +2 -1
- package/docs/word-index.md +6 -0
- package/package.json +1 -1
- package/rules/ast-grep-rules/rule-tests/no-identity-operator-on-literals-test.yml +12 -2
- package/rules/ast-grep-rules/rule-tests/throw-new-error-js-test.yml +2 -0
- package/rules/ast-grep-rules/rule-tests/throw-new-error-test.yml +2 -0
- package/rules/ast-grep-rules/rules/no-identity-operator-on-literals.yml +20 -12
- package/rules/ast-grep-rules/rules/throw-new-error-js.yml +2 -2
- package/rules/ast-grep-rules/rules/throw-new-error.yml +2 -2
- package/dist/chunk-54B42YRX.js +0 -27
- package/dist/chunk-CGGAIP7J.js +0 -29
- package/dist/chunk-D6QS3U6M.js +0 -30
- package/dist/chunk-HMFXILPV.js +0 -83
- package/dist/chunk-LSMJ6KBE.js +0 -4139
- package/dist/chunk-NTHH2J74.js +0 -27
- package/dist/chunk-RPD4ZSB7.js +0 -25
- package/dist/chunk-T6D4Q4AQ.js +0 -54
- package/dist/chunk-VCSRSYLF.js +0 -81
|
@@ -4,13 +4,15 @@ import {
|
|
|
4
4
|
detectPythonEnvironment,
|
|
5
5
|
detectPythonVenv,
|
|
6
6
|
pythonEnvironmentToolCandidates
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-34WSVGEM.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveOpengrepConfig
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-VWCXW2E7.js";
|
|
11
11
|
import {
|
|
12
|
-
extensionsForLanguage
|
|
13
|
-
|
|
12
|
+
extensionsForLanguage,
|
|
13
|
+
getUserRuleRoot,
|
|
14
|
+
ruleCorpusFingerprintForCycle
|
|
15
|
+
} from "./chunk-724UL2TJ.js";
|
|
14
16
|
import {
|
|
15
17
|
load,
|
|
16
18
|
resolvePackagePath
|
|
@@ -20,11 +22,11 @@ import {
|
|
|
20
22
|
readCargoWorkspaceExclude,
|
|
21
23
|
readCargoWorkspaceMembers,
|
|
22
24
|
readTextFileOrUndefined
|
|
23
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-P7266HLM.js";
|
|
24
26
|
import {
|
|
25
27
|
HOOK_WALL_BUDGET_MS,
|
|
26
28
|
bounded
|
|
27
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-52FUZI6K.js";
|
|
28
30
|
import {
|
|
29
31
|
ensureTool,
|
|
30
32
|
findManagedToolBinary,
|
|
@@ -34,20 +36,21 @@ import {
|
|
|
34
36
|
isZizmorAuditTarget,
|
|
35
37
|
logSessionStart,
|
|
36
38
|
resolveZizmorGitHubToken
|
|
37
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-66VMUL7Q.js";
|
|
38
40
|
import {
|
|
39
41
|
resolveToolCwd
|
|
40
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-Q7DUK4LX.js";
|
|
41
43
|
import {
|
|
42
|
-
findGlobalBinary
|
|
43
|
-
|
|
44
|
+
findGlobalBinary,
|
|
45
|
+
isProjectLocalBinPath
|
|
46
|
+
} from "./chunk-AW7R2GWG.js";
|
|
44
47
|
import {
|
|
45
48
|
classifyProbeFailure,
|
|
46
49
|
createAvailabilityLatch,
|
|
47
50
|
describeInstallAttempt,
|
|
48
51
|
logAvailabilityDecision,
|
|
49
52
|
startHostStallSampler
|
|
50
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-VRZP76YM.js";
|
|
51
54
|
import {
|
|
52
55
|
OWNER_TAG_ENV,
|
|
53
56
|
SpawnFailureError,
|
|
@@ -61,21 +64,25 @@ import {
|
|
|
61
64
|
isCommandAvailableAsync,
|
|
62
65
|
isPathIgnoredByProject,
|
|
63
66
|
ownerTagForChildren,
|
|
67
|
+
resolveWindowsCommandForEnvironment,
|
|
64
68
|
safeSpawnAsync
|
|
65
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-C34ZXZ7O.js";
|
|
66
70
|
import {
|
|
67
71
|
DOTNET_CSHARP_ROOT_MARKERS,
|
|
68
72
|
DOTNET_FSHARP_ROOT_MARKERS,
|
|
69
|
-
KIND_EXTENSIONS
|
|
70
|
-
|
|
73
|
+
KIND_EXTENSIONS,
|
|
74
|
+
LEAN_ROOT_MARKERS
|
|
75
|
+
} from "./chunk-PHDMFAKM.js";
|
|
71
76
|
import {
|
|
77
|
+
isRepoTier,
|
|
72
78
|
lspSectionOf,
|
|
73
79
|
migrationSubject,
|
|
80
|
+
provenanceFor,
|
|
74
81
|
reportConfigReadFailure,
|
|
75
82
|
reportPiLensConfigRecords,
|
|
76
83
|
resolvePiLensConfig,
|
|
77
84
|
summarizeConfigResolution
|
|
78
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-2BBLFX75.js";
|
|
79
86
|
import {
|
|
80
87
|
FRESHNESS_CADENCE_MS,
|
|
81
88
|
LSP_NAMESPACE_KEY,
|
|
@@ -83,23 +90,30 @@ import {
|
|
|
83
90
|
dirMtimesStillFreshAsync,
|
|
84
91
|
getPiLensGlobalConfigPath,
|
|
85
92
|
unknownDirMtimeRecords
|
|
86
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-XVF2VVXP.js";
|
|
87
94
|
import {
|
|
95
|
+
getProjectTrustState
|
|
96
|
+
} from "./chunk-ZANLILYD.js";
|
|
97
|
+
import {
|
|
98
|
+
getDegradationLedgerGeneration,
|
|
88
99
|
incrementDegradationCount,
|
|
89
100
|
recordDegradationOnce
|
|
90
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-JAU72XNY.js";
|
|
102
|
+
import {
|
|
103
|
+
logExtension
|
|
104
|
+
} from "./chunk-XTMJ7XDT.js";
|
|
91
105
|
import {
|
|
92
106
|
claimPhaseOncePerSession,
|
|
93
107
|
currentSessionRecordId,
|
|
94
108
|
logLatency,
|
|
95
109
|
releasePhaseClaim
|
|
96
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-QQNQ7SJW.js";
|
|
97
111
|
import {
|
|
98
112
|
getGlobalPiLensLogDir,
|
|
99
113
|
getProcessSingleton,
|
|
100
114
|
isTestMode,
|
|
101
115
|
redactSecrets
|
|
102
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-AOHZU2BM.js";
|
|
103
117
|
import {
|
|
104
118
|
STAGE_TMP_PATTERN
|
|
105
119
|
} from "./chunk-LJDODBBZ.js";
|
|
@@ -113,6 +127,7 @@ import {
|
|
|
113
127
|
findLocalToolConfig,
|
|
114
128
|
isAtOrAboveHomeDir,
|
|
115
129
|
isFullyQualified,
|
|
130
|
+
isUnderDir,
|
|
116
131
|
isWindowsPath,
|
|
117
132
|
matchesWorkspaceMemberPattern,
|
|
118
133
|
normalizeEphemeralMapKey,
|
|
@@ -120,7 +135,7 @@ import {
|
|
|
120
135
|
normalizeMapKey,
|
|
121
136
|
pathsEqual,
|
|
122
137
|
toPosix
|
|
123
|
-
} from "./chunk-
|
|
138
|
+
} from "./chunk-N2H3ZPZY.js";
|
|
124
139
|
import {
|
|
125
140
|
__require
|
|
126
141
|
} from "./chunk-NXL4FFQQ.js";
|
|
@@ -129,7 +144,7 @@ import {
|
|
|
129
144
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, statSync as statSync3 } from "node:fs";
|
|
130
145
|
import { access, readFile, readdir, stat } from "node:fs/promises";
|
|
131
146
|
import os6 from "node:os";
|
|
132
|
-
import
|
|
147
|
+
import path6 from "node:path";
|
|
133
148
|
|
|
134
149
|
// dist/clients/sgconfig.js
|
|
135
150
|
import { createHash } from "node:crypto";
|
|
@@ -162,6 +177,18 @@ function getAstGrepRuleSources(projectRoot = process.cwd()) {
|
|
|
162
177
|
tier: "secondary"
|
|
163
178
|
});
|
|
164
179
|
}
|
|
180
|
+
const userRoot = getUserRuleRoot();
|
|
181
|
+
if (canonicalDir(userRoot) !== canonicalDir(root)) {
|
|
182
|
+
candidates.push({
|
|
183
|
+
dir: path.join(userRoot, "ast-grep-rules", "rules"),
|
|
184
|
+
origin: "user",
|
|
185
|
+
tier: "primary"
|
|
186
|
+
}, {
|
|
187
|
+
dir: path.join(userRoot, "ast-grep-rules", "coderabbit", "rules"),
|
|
188
|
+
origin: "user",
|
|
189
|
+
tier: "secondary"
|
|
190
|
+
});
|
|
191
|
+
}
|
|
165
192
|
candidates.push({
|
|
166
193
|
dir: path.join(packageRoot, "rules", "ast-grep-rules", "rules"),
|
|
167
194
|
origin: "bundled",
|
|
@@ -246,7 +273,15 @@ function snapshotRuleSource(source) {
|
|
|
246
273
|
}
|
|
247
274
|
hash.update(content);
|
|
248
275
|
hash.update("\0");
|
|
249
|
-
|
|
276
|
+
const documents = parseRuleDocuments(content);
|
|
277
|
+
if (source.origin === "user" && documents.some((document) => !document.id)) {
|
|
278
|
+
recordDegradationOnce({
|
|
279
|
+
kind: "ast-grep-rule-invalid",
|
|
280
|
+
subject: file,
|
|
281
|
+
reason: "user ast-grep rule has no valid rule id"
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
files.push({ file, relativePath, documents });
|
|
250
285
|
}
|
|
251
286
|
const snapshot = { ...source, files, digest: hash.digest("hex") };
|
|
252
287
|
if (source.origin === "bundled")
|
|
@@ -267,6 +302,10 @@ function sourceFingerprint(sources) {
|
|
|
267
302
|
}
|
|
268
303
|
return hash.digest("hex");
|
|
269
304
|
}
|
|
305
|
+
function getAstGrepRuleFingerprint(projectRoot = process.cwd(), options = {}) {
|
|
306
|
+
const root = path.resolve(projectRoot || process.cwd());
|
|
307
|
+
return ruleCorpusFingerprintForCycle("ast-grep", root, (fingerprintRoot) => sourceFingerprint(getAstGrepRuleSources(fingerprintRoot).map(snapshotRuleSource)), options.force);
|
|
308
|
+
}
|
|
270
309
|
function materializeMergedRuleDir(sources, mergedDir) {
|
|
271
310
|
fs.rmSync(mergedDir, { recursive: true, force: true });
|
|
272
311
|
fs.mkdirSync(mergedDir, { recursive: true });
|
|
@@ -302,14 +341,14 @@ function rootArtifactKey(root) {
|
|
|
302
341
|
}
|
|
303
342
|
function resolveBaselineSgconfig(projectRoot = process.cwd()) {
|
|
304
343
|
const root = canonicalDir(path.resolve(projectRoot || process.cwd()));
|
|
305
|
-
const
|
|
306
|
-
if (sources.length === 0)
|
|
307
|
-
return void 0;
|
|
308
|
-
const fingerprint = sourceFingerprint(sources);
|
|
344
|
+
const fingerprint = getAstGrepRuleFingerprint(root, { force: true });
|
|
309
345
|
const cached = cachedBaselines.get(root);
|
|
310
346
|
if (cached?.fingerprint === fingerprint && fs.existsSync(cached.path) && fs.existsSync(cached.mergedDir)) {
|
|
311
347
|
return cached.path;
|
|
312
348
|
}
|
|
349
|
+
const sources = getAstGrepRuleSources(root).map(snapshotRuleSource);
|
|
350
|
+
if (sources.length === 0)
|
|
351
|
+
return void 0;
|
|
313
352
|
const dir = path.join(os.tmpdir(), "pi-lens-ast-grep");
|
|
314
353
|
fs.mkdirSync(dir, { recursive: true });
|
|
315
354
|
const artifactKey = rootArtifactKey(root);
|
|
@@ -417,9 +456,44 @@ function findLocalTyposConfig(startDir) {
|
|
|
417
456
|
return findLocalToolConfig(startDir, LOCAL_TYPOS_CONFIG_NAMES);
|
|
418
457
|
}
|
|
419
458
|
|
|
459
|
+
// dist/clients/lsp/server-traits.js
|
|
460
|
+
var ROLE_MEMBERS = {
|
|
461
|
+
language: "language",
|
|
462
|
+
auxiliary: "auxiliary"
|
|
463
|
+
};
|
|
464
|
+
var DEFAULT_LSP_SERVER_ROLE = "language";
|
|
465
|
+
function isAuxiliary(bearer) {
|
|
466
|
+
const declared = bearer?.role;
|
|
467
|
+
const role = typeof declared === "string" && Object.hasOwn(ROLE_MEMBERS, declared) ? ROLE_MEMBERS[declared] : DEFAULT_LSP_SERVER_ROLE;
|
|
468
|
+
switch (role) {
|
|
469
|
+
case "auxiliary":
|
|
470
|
+
return true;
|
|
471
|
+
case "language":
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
var DEFAULT_NOTIFY_INFLIGHT_LIMIT = 8;
|
|
476
|
+
var DEFAULT_REPLY_ORDERING = "unmeasured";
|
|
477
|
+
function serverTraits(declaration) {
|
|
478
|
+
const declaredLimit = declaration.notifyInflightLimit;
|
|
479
|
+
if (typeof declaredLimit === "number" && Number.isFinite(declaredLimit) && declaredLimit > 0) {
|
|
480
|
+
return {
|
|
481
|
+
role: declaration.role,
|
|
482
|
+
notifyInflightLimit: Math.floor(declaredLimit),
|
|
483
|
+
replyOrdering: declaration.replyOrdering ?? DEFAULT_REPLY_ORDERING
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
const envLimit = Number(process.env.PI_LENS_LSP_AUX_NOTIFY_INFLIGHT);
|
|
487
|
+
return {
|
|
488
|
+
role: declaration.role,
|
|
489
|
+
notifyInflightLimit: Number.isFinite(envLimit) && envLimit > 0 ? Math.floor(envLimit) : DEFAULT_NOTIFY_INFLIGHT_LIMIT,
|
|
490
|
+
replyOrdering: declaration.replyOrdering ?? DEFAULT_REPLY_ORDERING
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
|
|
420
494
|
// dist/clients/lsp/config.js
|
|
421
495
|
import * as os3 from "node:os";
|
|
422
|
-
import
|
|
496
|
+
import path3 from "node:path";
|
|
423
497
|
|
|
424
498
|
// dist/clients/dispatch/known-runner-ids.js
|
|
425
499
|
var knownRunnerIds = /* @__PURE__ */ new Set();
|
|
@@ -434,6 +508,7 @@ function isKnownRunnerId(id) {
|
|
|
434
508
|
}
|
|
435
509
|
|
|
436
510
|
// dist/clients/lsp/launch.js
|
|
511
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
437
512
|
import { execFileSync, spawn as nodeSpawn } from "node:child_process";
|
|
438
513
|
import fs3 from "node:fs";
|
|
439
514
|
import os2 from "node:os";
|
|
@@ -628,6 +703,16 @@ function isCmdShimValid(cmdPath) {
|
|
|
628
703
|
return true;
|
|
629
704
|
}
|
|
630
705
|
}
|
|
706
|
+
function isMissingWindowsStartupCommand(command, spawnCommand, cwd, env) {
|
|
707
|
+
if (!isWindows)
|
|
708
|
+
return false;
|
|
709
|
+
if (/\.(cmd|bat)$/i.test(spawnCommand) && !isCmdShimValid(spawnCommand)) {
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
if (spawnCommand !== command)
|
|
713
|
+
return false;
|
|
714
|
+
return resolveWindowsCommandForEnvironment(command, cwd, env) === null;
|
|
715
|
+
}
|
|
631
716
|
function bypassPs1OnWindows(ps1Path, args) {
|
|
632
717
|
const cmdPath = `${ps1Path.slice(0, -4)}.cmd`;
|
|
633
718
|
if (fs3.existsSync(cmdPath)) {
|
|
@@ -675,6 +760,65 @@ function findBinaryOnPath(command, env) {
|
|
|
675
760
|
}
|
|
676
761
|
return void 0;
|
|
677
762
|
}
|
|
763
|
+
var lspProjectCodePermission = new AsyncLocalStorage();
|
|
764
|
+
function withLspProjectCodePermission(allowed, spawn) {
|
|
765
|
+
return lspProjectCodePermission.run(allowed, spawn);
|
|
766
|
+
}
|
|
767
|
+
var unknownProjectLocalNoticeGeneration = -1;
|
|
768
|
+
function recordUntrustedLspExecution(request, trust) {
|
|
769
|
+
const generation = getDegradationLedgerGeneration();
|
|
770
|
+
const subject = request.kind === "project-code-server" ? `project-code-server:g${generation}:${request.serverId}:${request.root}` : `project-local-binary:g${generation}:${path2.basename(request.command)}`;
|
|
771
|
+
const metadata = request.kind === "project-code-server" ? {
|
|
772
|
+
field: request.kind,
|
|
773
|
+
serverId: request.serverId,
|
|
774
|
+
root: request.root,
|
|
775
|
+
trust
|
|
776
|
+
} : {
|
|
777
|
+
field: request.kind,
|
|
778
|
+
trust
|
|
779
|
+
};
|
|
780
|
+
recordDegradationOnce({
|
|
781
|
+
kind: "lsp-registry-decision",
|
|
782
|
+
subject,
|
|
783
|
+
reason: (request.kind === "project-local-binary" ? request.reason : void 0) ?? `LSP execution refused: ${request.kind} and project trust is ${trust}`,
|
|
784
|
+
metadata
|
|
785
|
+
});
|
|
786
|
+
if (unknownProjectLocalNoticeGeneration !== generation) {
|
|
787
|
+
unknownProjectLocalNoticeGeneration = generation;
|
|
788
|
+
const label = request.kind === "project-code-server" ? "project-code LSP server" : "project-local LSP binary";
|
|
789
|
+
logExtension({
|
|
790
|
+
subsystem: "lsp-registry",
|
|
791
|
+
level: "warn",
|
|
792
|
+
message: `${label} refused: mark the project trusted in pi or upgrade pi`,
|
|
793
|
+
metadata: { field: request.kind }
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
function refuseUntrustedLspExecution(request) {
|
|
798
|
+
const trust = getProjectTrustState();
|
|
799
|
+
const needsTrust = request.kind === "project-code-server" ? trust !== "trusted" : !admitProjectSuppliedTsserver(request.resolvedCommand, request.cwd, true);
|
|
800
|
+
if (!needsTrust)
|
|
801
|
+
return;
|
|
802
|
+
if (request.kind === "project-code-server")
|
|
803
|
+
recordUntrustedLspExecution(request, trust);
|
|
804
|
+
throw new SpawnFailureError("spawn-failed", `LSP ${request.kind === "project-code-server" ? "project-code server" : "project-local binary"} refused: project trust is ${trust}`, new Error(`project trust is ${trust}`));
|
|
805
|
+
}
|
|
806
|
+
function admitProjectSuppliedTsserver(tsserverPath, cwd, projectSupplied, projectCodeAllowed = lspProjectCodePermission.getStore() ?? false) {
|
|
807
|
+
const trust = getProjectTrustState();
|
|
808
|
+
if (tsserverPath && (!projectSupplied || projectCodeAllowed && trust === "trusted"))
|
|
809
|
+
return tsserverPath;
|
|
810
|
+
recordUntrustedLspExecution({
|
|
811
|
+
kind: "project-local-binary",
|
|
812
|
+
command: tsserverPath ?? "tsserver.js",
|
|
813
|
+
resolvedCommand: tsserverPath ?? "tsserver.js",
|
|
814
|
+
cwd,
|
|
815
|
+
reason: tsserverPath ? "LSP execution refused: project compiler requires trusted session ownership" : "LSP execution refused: no admitted absolute TypeScript compiler"
|
|
816
|
+
}, trust);
|
|
817
|
+
return void 0;
|
|
818
|
+
}
|
|
819
|
+
function isProjectLocalLspBinary(resolvedCommand, cwd) {
|
|
820
|
+
return isProjectLocalBinPath(resolvedCommand, cwd);
|
|
821
|
+
}
|
|
678
822
|
function trySpawn(command, args, cwd, env, needsShell) {
|
|
679
823
|
let proc;
|
|
680
824
|
if (needsShell) {
|
|
@@ -703,9 +847,6 @@ function trySpawn(command, args, cwd, env, needsShell) {
|
|
|
703
847
|
if (!proc.stdin || !proc.stdout || !proc.stderr) {
|
|
704
848
|
throw new Error(`Failed to spawn LSP server: ${command}`);
|
|
705
849
|
}
|
|
706
|
-
if (proc.exitCode !== null || proc.killed) {
|
|
707
|
-
throw new Error(`LSP server ${command} exited immediately (code: ${proc.exitCode}). The binary may be missing or corrupted.`);
|
|
708
|
-
}
|
|
709
850
|
holdOwnChildPid(proc.pid, "lsp-spawn");
|
|
710
851
|
return proc;
|
|
711
852
|
}
|
|
@@ -781,6 +922,14 @@ async function launchLSP(command, args = [], options = {}) {
|
|
|
781
922
|
needsShell = computeNeedsShell(spawnCommand);
|
|
782
923
|
}
|
|
783
924
|
}
|
|
925
|
+
if (isProjectLocalLspBinary(spawnCommand, cwd)) {
|
|
926
|
+
refuseUntrustedLspExecution({
|
|
927
|
+
kind: "project-local-binary",
|
|
928
|
+
command,
|
|
929
|
+
resolvedCommand: spawnCommand,
|
|
930
|
+
cwd
|
|
931
|
+
});
|
|
932
|
+
}
|
|
784
933
|
if (isWindows && /\.(cmd|bat)$/i.test(spawnCommand) && !isCmdShimValid(spawnCommand)) {
|
|
785
934
|
logSessionStart2(`lsp cmd-shim-invalid: ${spawnCommand} target missing \u2014 skipping candidate`);
|
|
786
935
|
const cause = Object.assign(new Error(`LSP .cmd shim target not found: ${spawnCommand}`), { code: "ENOENT" });
|
|
@@ -817,7 +966,12 @@ async function launchLSP(command, args = [], options = {}) {
|
|
|
817
966
|
throw new Error(`Failed to spawn LSP server: ${command}`);
|
|
818
967
|
}
|
|
819
968
|
if (proc.exitCode !== null || proc.killed) {
|
|
820
|
-
|
|
969
|
+
const message = `LSP server ${command} exited immediately (code: ${proc.exitCode}). The binary may be missing or corrupted.`;
|
|
970
|
+
const failure = new Error(message);
|
|
971
|
+
if (proc.exitCode === 1 && isMissingWindowsStartupCommand(command, spawnCommand, cwd, env)) {
|
|
972
|
+
throw new SpawnFailureError("tool-not-found", message, failure);
|
|
973
|
+
}
|
|
974
|
+
throw failure;
|
|
821
975
|
}
|
|
822
976
|
logSessionStart2(`lsp launch: command=${command} resolved=${spawnCommand} args=${JSON.stringify(args)} cwd=${cwd} shell=${needsShell ? "true" : "false"} pid=${proc.pid ?? 0}`);
|
|
823
977
|
const formatStartupStderr = (stderr) => {
|
|
@@ -850,7 +1004,13 @@ async function launchLSP(command, args = [], options = {}) {
|
|
|
850
1004
|
settled = true;
|
|
851
1005
|
const isWindowsCmd = isWindows && command.endsWith(".cmd");
|
|
852
1006
|
const errorMsg = isWindowsCmd && code === 1 ? `npm .cmd shim failed (underlying binary not installed). Run 'npm install' in this project or use a global installation.` : `The binary may be missing or corrupted.`;
|
|
853
|
-
|
|
1007
|
+
const message = `LSP server ${command} exited immediately with code ${code}. ${errorMsg}${formatStartupStderr(startupStderr)}`;
|
|
1008
|
+
const failure = new Error(message);
|
|
1009
|
+
if (code === 1 && isMissingWindowsStartupCommand(command, spawnCommand, cwd, env)) {
|
|
1010
|
+
reject(new SpawnFailureError("tool-not-found", message, failure));
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1013
|
+
reject(failure);
|
|
854
1014
|
}
|
|
855
1015
|
});
|
|
856
1016
|
const startupFailureWindowMs = (() => {
|
|
@@ -890,61 +1050,13 @@ async function launchLSP(command, args = [], options = {}) {
|
|
|
890
1050
|
};
|
|
891
1051
|
}
|
|
892
1052
|
|
|
893
|
-
// dist/clients/lsp/session-roots.js
|
|
894
|
-
import path3 from "node:path";
|
|
895
|
-
var SESSION_ROOT_CAP = 128;
|
|
896
|
-
var sessionRoots = new BoundedFifoMap(SESSION_ROOT_CAP);
|
|
897
|
-
function noteEvictedRoots(evicted) {
|
|
898
|
-
const roots = evicted.map(([root]) => root);
|
|
899
|
-
if (roots.length > 0) {
|
|
900
|
-
incrementDegradationCount({
|
|
901
|
-
kind: "lsp-session-root-evicted",
|
|
902
|
-
subject: `cap=${SESSION_ROOT_CAP}`,
|
|
903
|
-
reason: `session root registry at capacity; will load the dropped root again on the next session start or tool call naming it (dropped: ${roots[0]})`
|
|
904
|
-
});
|
|
905
|
-
}
|
|
906
|
-
return roots;
|
|
907
|
-
}
|
|
908
|
-
function registerSessionRoot(cwd) {
|
|
909
|
-
const root = path3.resolve(cwd);
|
|
910
|
-
if (sessionRoots.has(root))
|
|
911
|
-
return [];
|
|
912
|
-
return noteEvictedRoots(sessionRoots.set(root, void 0));
|
|
913
|
-
}
|
|
914
|
-
function setSessionRootConfig(cwd, config) {
|
|
915
|
-
return noteEvictedRoots(sessionRoots.set(path3.resolve(cwd), config));
|
|
916
|
-
}
|
|
917
|
-
function sessionRootConfigEntries() {
|
|
918
|
-
return sessionRoots;
|
|
919
|
-
}
|
|
920
|
-
function isSessionRootRegistered(cwd) {
|
|
921
|
-
return sessionRoots.has(path3.resolve(cwd));
|
|
922
|
-
}
|
|
923
|
-
function shouldInitializeSessionRoot(cwd, readyRoots) {
|
|
924
|
-
const normalized = path3.resolve(cwd);
|
|
925
|
-
return !readyRoots.has(normalized) || !isSessionRootRegistered(normalized);
|
|
926
|
-
}
|
|
927
|
-
function isOutsideAllSessionRoots(filePath) {
|
|
928
|
-
if (sessionRoots.size === 0)
|
|
929
|
-
return false;
|
|
930
|
-
const resolved = path3.resolve(filePath);
|
|
931
|
-
for (const root of sessionRoots.keys()) {
|
|
932
|
-
if (isSameOrWithin(root, resolved))
|
|
933
|
-
return false;
|
|
934
|
-
}
|
|
935
|
-
return true;
|
|
936
|
-
}
|
|
937
|
-
function getSessionRootsForTelemetry(limit = 4) {
|
|
938
|
-
return [...sessionRoots.keys()].sort((a, b) => Number(a > b) - Number(a < b)).slice(0, limit);
|
|
939
|
-
}
|
|
940
|
-
|
|
941
1053
|
// dist/clients/lsp/config.js
|
|
942
1054
|
function asRecord(value) {
|
|
943
1055
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
944
1056
|
}
|
|
945
1057
|
var CONFIG_RESOLVED_PHASE = "config_resolved";
|
|
946
1058
|
function configResolutionKey(cwd) {
|
|
947
|
-
return normalizeFilePath(
|
|
1059
|
+
return normalizeFilePath(path3.resolve(normalizeFilePath(cwd)));
|
|
948
1060
|
}
|
|
949
1061
|
function publishConfigResolutionPending(cwd) {
|
|
950
1062
|
logSessionStart(`session_start config_resolution_pending session=${currentSessionRecordId()} root=${configResolutionKey(cwd)}`);
|
|
@@ -1000,6 +1112,10 @@ async function loadLSPConfig(cwd, homeDir = os3.homedir(), options = {}) {
|
|
|
1000
1112
|
});
|
|
1001
1113
|
const coversProblems = newCoversClaimProblems();
|
|
1002
1114
|
const config = lspConfigOf(resolution.value, coversProblems);
|
|
1115
|
+
Object.defineProperty(config, "__provenance", {
|
|
1116
|
+
value: resolution.provenance,
|
|
1117
|
+
enumerable: false
|
|
1118
|
+
});
|
|
1003
1119
|
if (reporting) {
|
|
1004
1120
|
reportPiLensConfigRecords([
|
|
1005
1121
|
...resolution.records,
|
|
@@ -1097,7 +1213,7 @@ function customServerSpecsOf(value) {
|
|
|
1097
1213
|
const servers = asRecord(lspSectionOf(value).servers);
|
|
1098
1214
|
return servers ? coversValidatedServers(servers) : {};
|
|
1099
1215
|
}
|
|
1100
|
-
function lspConfigOf(value, problems) {
|
|
1216
|
+
function lspConfigOf(value, problems, provenance) {
|
|
1101
1217
|
const section = lspSectionOf(value);
|
|
1102
1218
|
const config = {};
|
|
1103
1219
|
const servers = asRecord(section.servers);
|
|
@@ -1113,6 +1229,12 @@ function lspConfigOf(value, problems) {
|
|
|
1113
1229
|
if (Array.isArray(section.warmFiles)) {
|
|
1114
1230
|
config.warmFiles = section.warmFiles;
|
|
1115
1231
|
}
|
|
1232
|
+
if (provenance) {
|
|
1233
|
+
Object.defineProperty(config, "__provenance", {
|
|
1234
|
+
value: provenance,
|
|
1235
|
+
enumerable: false
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1116
1238
|
return config;
|
|
1117
1239
|
}
|
|
1118
1240
|
function createCustomServer(config, id) {
|
|
@@ -1125,6 +1247,14 @@ function createCustomServer(config, id) {
|
|
|
1125
1247
|
// be probeable before the claim can defer a CLI runner.
|
|
1126
1248
|
command: config.command,
|
|
1127
1249
|
extensions: config.extensions,
|
|
1250
|
+
// A config-declared server is a language server. The public
|
|
1251
|
+
// `lsp.servers.<id>.role` field is validated and projected by
|
|
1252
|
+
// `ResolvedLspConfig` (clients/lsp/resolved-config.ts) but stays
|
|
1253
|
+
// RESERVED and inert here: honouring it would change which servers a
|
|
1254
|
+
// file selects as primary, and that is the catalog slice's call, not
|
|
1255
|
+
// this loader's (#2416 slice 1). The stated default is applied rather
|
|
1256
|
+
// than left absent (#1488).
|
|
1257
|
+
role: DEFAULT_LSP_SERVER_ROLE,
|
|
1128
1258
|
idleEviction: "unmeasured",
|
|
1129
1259
|
// The config-declared covers channel (#3968): the claim the loader
|
|
1130
1260
|
// validated (`lspConfigOf`'s projection drops unknown runner ids) rides
|
|
@@ -1140,26 +1270,74 @@ function createCustomServer(config, id) {
|
|
|
1140
1270
|
cwd: root,
|
|
1141
1271
|
env: config.env ? { ...process.env, ...config.env } : process.env
|
|
1142
1272
|
});
|
|
1143
|
-
return {
|
|
1273
|
+
return {
|
|
1274
|
+
process: proc,
|
|
1275
|
+
...config.initializationOptions ? { initialization: config.initializationOptions } : {}
|
|
1276
|
+
};
|
|
1144
1277
|
}
|
|
1145
1278
|
};
|
|
1146
1279
|
}
|
|
1147
1280
|
var EMPTY_CONFIG = {
|
|
1148
1281
|
customServers: [],
|
|
1282
|
+
// Avoid reading LSP_SERVERS during the config/server module cycle. The
|
|
1283
|
+
// selection helper falls back to the live builtin table after evaluation.
|
|
1284
|
+
registeredServers: [],
|
|
1149
1285
|
disabledServerIds: /* @__PURE__ */ new Set(),
|
|
1150
1286
|
serverOverrides: /* @__PURE__ */ new Map()
|
|
1151
1287
|
};
|
|
1152
1288
|
var configInFlight = /* @__PURE__ */ new Map();
|
|
1153
1289
|
function normalizeWorkspacePath(cwd) {
|
|
1154
|
-
return
|
|
1290
|
+
return path3.resolve(cwd);
|
|
1291
|
+
}
|
|
1292
|
+
var unknownTrustNoticeGeneration = -1;
|
|
1293
|
+
function sourceFor(provenance, key) {
|
|
1294
|
+
const direct = provenanceFor({ value: void 0, provenance }, key);
|
|
1295
|
+
if (direct)
|
|
1296
|
+
return direct;
|
|
1297
|
+
let fallback;
|
|
1298
|
+
for (const [candidate, entry] of provenance) {
|
|
1299
|
+
if (!candidate.startsWith(`${key}/`))
|
|
1300
|
+
continue;
|
|
1301
|
+
if (isRepoTier(entry.tier))
|
|
1302
|
+
return entry;
|
|
1303
|
+
fallback ??= entry;
|
|
1304
|
+
}
|
|
1305
|
+
return fallback;
|
|
1306
|
+
}
|
|
1307
|
+
function executableAllowed(provenance, trust) {
|
|
1308
|
+
return !provenance || !isRepoTier(provenance.tier) || trust === "trusted";
|
|
1309
|
+
}
|
|
1310
|
+
function registryDecision(id, field, provenance, trust, allowed) {
|
|
1311
|
+
if (allowed || !provenance || !isRepoTier(provenance.tier))
|
|
1312
|
+
return;
|
|
1313
|
+
const subject = `${id}:${field}:${provenance.tier}`;
|
|
1314
|
+
const reason = `project LSP ${field} refused for ${id}: pi project trust is ${trust}`;
|
|
1315
|
+
recordDegradationOnce({
|
|
1316
|
+
kind: "lsp-registry-decision",
|
|
1317
|
+
subject,
|
|
1318
|
+
reason,
|
|
1319
|
+
metadata: { serverId: id, field, tier: provenance.tier, trust }
|
|
1320
|
+
});
|
|
1321
|
+
if (trust === "unknown") {
|
|
1322
|
+
const generation = getDegradationLedgerGeneration();
|
|
1323
|
+
if (unknownTrustNoticeGeneration !== generation) {
|
|
1324
|
+
unknownTrustNoticeGeneration = generation;
|
|
1325
|
+
logExtension({
|
|
1326
|
+
subsystem: "lsp-registry",
|
|
1327
|
+
level: "warn",
|
|
1328
|
+
message: "project LSP executables refused: mark the project trusted in pi or upgrade pi",
|
|
1329
|
+
metadata: { serverId: id, field }
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1155
1333
|
}
|
|
1156
1334
|
function isSameOrChildPath(filePath, candidateRoot) {
|
|
1157
1335
|
if (filePath === candidateRoot)
|
|
1158
1336
|
return true;
|
|
1159
|
-
return filePath.startsWith(`${candidateRoot}${
|
|
1337
|
+
return filePath.startsWith(`${candidateRoot}${path3.sep}`);
|
|
1160
1338
|
}
|
|
1161
1339
|
function getConfigForFile(filePath) {
|
|
1162
|
-
const resolvedFilePath =
|
|
1340
|
+
const resolvedFilePath = path3.resolve(filePath);
|
|
1163
1341
|
let bestMatch;
|
|
1164
1342
|
for (const [root, config] of sessionRootConfigEntries()) {
|
|
1165
1343
|
if (config === void 0)
|
|
@@ -1173,13 +1351,33 @@ function getConfigForFile(filePath) {
|
|
|
1173
1351
|
return bestMatch?.config ?? EMPTY_CONFIG;
|
|
1174
1352
|
}
|
|
1175
1353
|
function registerLSPConfig(config) {
|
|
1354
|
+
return compileLspRegistry(config, config.__provenance);
|
|
1355
|
+
}
|
|
1356
|
+
function compileLspRegistry(config, provenance = /* @__PURE__ */ new Map()) {
|
|
1357
|
+
const trust = getProjectTrustState();
|
|
1176
1358
|
const customServers = [];
|
|
1177
1359
|
const disabledServerIds = new Set(config.disabledServers ?? []);
|
|
1178
1360
|
if (config.servers) {
|
|
1179
1361
|
for (const [id, serverConfig] of Object.entries(config.servers)) {
|
|
1362
|
+
const commandSource = sourceFor(provenance, `/lsp/servers/${id}/command`);
|
|
1363
|
+
const commandAllowed = executableAllowed(commandSource, trust);
|
|
1364
|
+
registryDecision(id, "command", commandSource, trust, commandAllowed);
|
|
1365
|
+
if (!commandAllowed)
|
|
1366
|
+
continue;
|
|
1367
|
+
const envSource = sourceFor(provenance, `/lsp/servers/${id}/env`);
|
|
1368
|
+
const initSource = sourceFor(provenance, `/lsp/servers/${id}/initializationOptions`);
|
|
1369
|
+
const envAllowed = executableAllowed(envSource, trust);
|
|
1370
|
+
const initAllowed = executableAllowed(initSource, trust);
|
|
1371
|
+
registryDecision(id, "env", envSource, trust, envAllowed);
|
|
1372
|
+
registryDecision(id, "initializationOptions", initSource, trust, initAllowed);
|
|
1373
|
+
const admitted = { ...serverConfig };
|
|
1374
|
+
if (!envAllowed)
|
|
1375
|
+
delete admitted.env;
|
|
1376
|
+
if (!initAllowed)
|
|
1377
|
+
delete admitted.initializationOptions;
|
|
1180
1378
|
try {
|
|
1181
|
-
const server = createCustomServer(
|
|
1182
|
-
customServers.push(server);
|
|
1379
|
+
const server = createCustomServer(admitted, id);
|
|
1380
|
+
customServers.push({ ...server, trustAllowed: true });
|
|
1183
1381
|
} catch {
|
|
1184
1382
|
}
|
|
1185
1383
|
}
|
|
@@ -1189,15 +1387,53 @@ function registerLSPConfig(config) {
|
|
|
1189
1387
|
for (const [id, entry] of Object.entries(config.serverOverrides)) {
|
|
1190
1388
|
if (entry && typeof entry === "object" && !Array.isArray(entry)) {
|
|
1191
1389
|
const initOpts = entry.initializationOptions;
|
|
1192
|
-
|
|
1390
|
+
const command = entry.command;
|
|
1391
|
+
const commandSource = sourceFor(provenance, `/lsp/serverOverrides/${id}/command`);
|
|
1392
|
+
const envSource = sourceFor(provenance, `/lsp/serverOverrides/${id}/env`);
|
|
1393
|
+
const initSource = sourceFor(provenance, `/lsp/serverOverrides/${id}/initializationOptions`);
|
|
1394
|
+
const commandAllowed = executableAllowed(commandSource, trust);
|
|
1395
|
+
const envAllowed = executableAllowed(envSource, trust);
|
|
1396
|
+
const overrideInitAllowed = executableAllowed(initSource, trust);
|
|
1397
|
+
registryDecision(id, "command override", commandSource, trust, commandAllowed);
|
|
1398
|
+
registryDecision(id, "env override", envSource, trust, envAllowed);
|
|
1399
|
+
registryDecision(id, "initializationOptions", initSource, trust, overrideInitAllowed);
|
|
1400
|
+
if (command !== void 0 || entry.env !== void 0 || initOpts !== void 0 && typeof initOpts === "object" && initOpts !== null && !Array.isArray(initOpts)) {
|
|
1193
1401
|
serverOverrides.set(id, {
|
|
1194
|
-
initializationOptions: initOpts
|
|
1402
|
+
...overrideInitAllowed && initOpts !== void 0 ? { initializationOptions: initOpts } : {},
|
|
1403
|
+
...commandAllowed && command !== void 0 ? { command } : {},
|
|
1404
|
+
...envAllowed && entry.env ? { env: entry.env } : {}
|
|
1195
1405
|
});
|
|
1196
1406
|
}
|
|
1197
1407
|
}
|
|
1198
1408
|
}
|
|
1199
1409
|
}
|
|
1200
|
-
|
|
1410
|
+
const overriddenBuiltins = LSP_SERVERS.map((server) => {
|
|
1411
|
+
const override = serverOverrides.get(server.id);
|
|
1412
|
+
if (!override?.command)
|
|
1413
|
+
return { ...server };
|
|
1414
|
+
const argv = Array.isArray(override.command) ? override.command : [override.command, "--stdio"];
|
|
1415
|
+
return {
|
|
1416
|
+
...server,
|
|
1417
|
+
trustAllowed: true,
|
|
1418
|
+
async spawn(root, options) {
|
|
1419
|
+
void options;
|
|
1420
|
+
const program = argv[0];
|
|
1421
|
+
if (!program)
|
|
1422
|
+
throw new Error(`empty command override for ${server.id}`);
|
|
1423
|
+
const proc = await launchLSP(program, argv.slice(1), {
|
|
1424
|
+
cwd: root,
|
|
1425
|
+
env: override.env ? { ...process.env, ...override.env } : process.env
|
|
1426
|
+
});
|
|
1427
|
+
return { process: proc };
|
|
1428
|
+
}
|
|
1429
|
+
};
|
|
1430
|
+
});
|
|
1431
|
+
return {
|
|
1432
|
+
customServers,
|
|
1433
|
+
registeredServers: overriddenBuiltins,
|
|
1434
|
+
disabledServerIds,
|
|
1435
|
+
serverOverrides
|
|
1436
|
+
};
|
|
1201
1437
|
}
|
|
1202
1438
|
function forgetConfigResolvedClaims(evictedRoots) {
|
|
1203
1439
|
for (const root of evictedRoots) {
|
|
@@ -1224,7 +1460,8 @@ async function initLSPConfig(cwd) {
|
|
|
1224
1460
|
}
|
|
1225
1461
|
}
|
|
1226
1462
|
function registeredServers(config) {
|
|
1227
|
-
|
|
1463
|
+
const builtins = config.registeredServers.length ? config.registeredServers : LSP_SERVERS;
|
|
1464
|
+
return [...builtins, ...config.customServers];
|
|
1228
1465
|
}
|
|
1229
1466
|
function selectionReason(server, config, filePath, ext, base) {
|
|
1230
1467
|
if (config.disabledServerIds.has(server.id))
|
|
@@ -1244,8 +1481,8 @@ function selectionReason(server, config, filePath, ext, base) {
|
|
|
1244
1481
|
return "selected";
|
|
1245
1482
|
}
|
|
1246
1483
|
function explainServersForFile(filePath, config = getConfigForFile(filePath)) {
|
|
1247
|
-
const ext =
|
|
1248
|
-
const base =
|
|
1484
|
+
const ext = path3.extname(filePath).toLowerCase();
|
|
1485
|
+
const base = path3.basename(filePath).toLowerCase();
|
|
1249
1486
|
return registeredServers(config).map((server) => {
|
|
1250
1487
|
const reason = selectionReason(server, config, filePath, ext, base);
|
|
1251
1488
|
return { server, selected: reason === "selected", reason };
|
|
@@ -1253,12 +1490,12 @@ function explainServersForFile(filePath, config = getConfigForFile(filePath)) {
|
|
|
1253
1490
|
}
|
|
1254
1491
|
function getServersForFileWithConfig(filePath) {
|
|
1255
1492
|
const config = getConfigForFile(filePath);
|
|
1256
|
-
const ext =
|
|
1257
|
-
const base =
|
|
1493
|
+
const ext = path3.extname(filePath).toLowerCase();
|
|
1494
|
+
const base = path3.basename(filePath).toLowerCase();
|
|
1258
1495
|
return registeredServers(config).filter((server) => selectionReason(server, config, filePath, ext, base) === "selected");
|
|
1259
1496
|
}
|
|
1260
1497
|
function primaryServerEntry(filePath) {
|
|
1261
|
-
return getServersForFileWithConfig(filePath).find((s) => s
|
|
1498
|
+
return getServersForFileWithConfig(filePath).find((s) => !isAuxiliary(s));
|
|
1262
1499
|
}
|
|
1263
1500
|
function primaryServerId(filePath) {
|
|
1264
1501
|
return primaryServerEntry(filePath)?.id;
|
|
@@ -1315,11 +1552,15 @@ function resolveAstGrepNativeExe(platform = process.platform, arch = process.arc
|
|
|
1315
1552
|
}
|
|
1316
1553
|
var SERVER_DIAGNOSTIC_STRATEGIES = {
|
|
1317
1554
|
typescript: {
|
|
1318
|
-
seedFirstPush:
|
|
1555
|
+
seedFirstPush: false,
|
|
1319
1556
|
pullRetryBudgetMs: 0,
|
|
1320
1557
|
debounceMs: 50,
|
|
1321
1558
|
aggregateWaitMs: 1e3,
|
|
1322
1559
|
expectSemanticSecondPush: false,
|
|
1560
|
+
// #3310 / nightly run 37930006227: the clean TypeScript fixture
|
|
1561
|
+
// published an empty pre-index result before its settled result.
|
|
1562
|
+
// Hold that first publish so it cannot resolve a push wait as clean.
|
|
1563
|
+
emptyFirstPublish: "indexing",
|
|
1323
1564
|
// Tier 3 (#458): typescript-language-server publishes nothing on a
|
|
1324
1565
|
// clean→clean edit (docs/lsp-capability-matrix.md, re-confirmed
|
|
1325
1566
|
// 2026-07-12). It's the lone core-set tier-3 server, which is exactly
|
|
@@ -1701,7 +1942,7 @@ function classifyServerWaitTier(serverId, snapshot) {
|
|
|
1701
1942
|
return "tier3-silent";
|
|
1702
1943
|
}
|
|
1703
1944
|
function resolvePrimaryServerForWaitPolicy(filePath, snapshots) {
|
|
1704
|
-
const servers = getServersForFileWithConfig(filePath).filter((s) => s
|
|
1945
|
+
const servers = getServersForFileWithConfig(filePath).filter((s) => !isAuxiliary(s));
|
|
1705
1946
|
const primary = servers[0];
|
|
1706
1947
|
if (!primary)
|
|
1707
1948
|
return void 0;
|
|
@@ -1721,14 +1962,14 @@ function classifyCascadeWaitTier(lspService, filePath, snapshots) {
|
|
|
1721
1962
|
// dist/clients/lsp/lombok.js
|
|
1722
1963
|
import * as fs4 from "node:fs";
|
|
1723
1964
|
import * as os4 from "node:os";
|
|
1724
|
-
import * as
|
|
1965
|
+
import * as path4 from "node:path";
|
|
1725
1966
|
var LOMBOK_ENV_KEYS = ["PI_LENS_LOMBOK_JAR", "LOMBOK_JAR"];
|
|
1726
1967
|
var LOMBOK_PROJECT_FILES = [
|
|
1727
1968
|
"lombok.config",
|
|
1728
1969
|
"pom.xml",
|
|
1729
1970
|
"build.gradle",
|
|
1730
1971
|
"build.gradle.kts",
|
|
1731
|
-
|
|
1972
|
+
path4.join("gradle", "libs.versions.toml")
|
|
1732
1973
|
];
|
|
1733
1974
|
function fileExists(filePath) {
|
|
1734
1975
|
if (!filePath)
|
|
@@ -1753,13 +1994,13 @@ function containsLombokDependency(text) {
|
|
|
1753
1994
|
return /\borg\.projectlombok\b/i.test(text) || /<artifactId>\s*lombok\s*<\/artifactId>/i.test(text) || /\b(annotationProcessor|compileOnly|testCompileOnly|testAnnotationProcessor)\b[^\n]*\blombok\b/i.test(text);
|
|
1754
1995
|
}
|
|
1755
1996
|
function hasLombokProject(root) {
|
|
1756
|
-
const lombokConfig =
|
|
1997
|
+
const lombokConfig = path4.join(root, "lombok.config");
|
|
1757
1998
|
if (fileExists(lombokConfig))
|
|
1758
1999
|
return true;
|
|
1759
2000
|
for (const name of LOMBOK_PROJECT_FILES) {
|
|
1760
2001
|
if (name === "lombok.config")
|
|
1761
2002
|
continue;
|
|
1762
|
-
const text = readTextIfSmall(
|
|
2003
|
+
const text = readTextIfSmall(path4.join(root, name));
|
|
1763
2004
|
if (text && containsLombokDependency(text))
|
|
1764
2005
|
return true;
|
|
1765
2006
|
}
|
|
@@ -1769,16 +2010,16 @@ function envJarCandidate(env) {
|
|
|
1769
2010
|
for (const key of LOMBOK_ENV_KEYS) {
|
|
1770
2011
|
const value = env[key]?.trim();
|
|
1771
2012
|
if (fileExists(value))
|
|
1772
|
-
return
|
|
2013
|
+
return path4.resolve(value);
|
|
1773
2014
|
}
|
|
1774
2015
|
return void 0;
|
|
1775
2016
|
}
|
|
1776
2017
|
function localJarCandidates(root) {
|
|
1777
2018
|
return [
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
2019
|
+
path4.join(root, "lombok.jar"),
|
|
2020
|
+
path4.join(root, ".lombok", "lombok.jar"),
|
|
2021
|
+
path4.join(root, "lib", "lombok.jar"),
|
|
2022
|
+
path4.join(root, "libs", "lombok.jar")
|
|
1782
2023
|
];
|
|
1783
2024
|
}
|
|
1784
2025
|
function newestExistingJar(candidates) {
|
|
@@ -1797,17 +2038,17 @@ function newestExistingJar(candidates) {
|
|
|
1797
2038
|
return best?.filePath;
|
|
1798
2039
|
}
|
|
1799
2040
|
function mavenLocalLombokJar(home = os4.homedir()) {
|
|
1800
|
-
const base =
|
|
2041
|
+
const base = path4.join(home, ".m2", "repository", "org", "projectlombok", "lombok");
|
|
1801
2042
|
let versions = [];
|
|
1802
2043
|
try {
|
|
1803
2044
|
versions = fs4.readdirSync(base);
|
|
1804
2045
|
} catch {
|
|
1805
2046
|
return void 0;
|
|
1806
2047
|
}
|
|
1807
|
-
return newestExistingJar(versions.map((version) =>
|
|
2048
|
+
return newestExistingJar(versions.map((version) => path4.join(base, version, `lombok-${version}.jar`)));
|
|
1808
2049
|
}
|
|
1809
2050
|
function gradleCacheLombokJar(home = os4.homedir()) {
|
|
1810
|
-
const base =
|
|
2051
|
+
const base = path4.join(home, ".gradle", "caches", "modules-2", "files-2.1", "org.projectlombok", "lombok");
|
|
1811
2052
|
const candidates = [];
|
|
1812
2053
|
let versions = [];
|
|
1813
2054
|
try {
|
|
@@ -1816,7 +2057,7 @@ function gradleCacheLombokJar(home = os4.homedir()) {
|
|
|
1816
2057
|
return void 0;
|
|
1817
2058
|
}
|
|
1818
2059
|
for (const version of versions) {
|
|
1819
|
-
const versionDir =
|
|
2060
|
+
const versionDir = path4.join(base, version);
|
|
1820
2061
|
let hashes = [];
|
|
1821
2062
|
try {
|
|
1822
2063
|
hashes = fs4.readdirSync(versionDir);
|
|
@@ -1824,7 +2065,7 @@ function gradleCacheLombokJar(home = os4.homedir()) {
|
|
|
1824
2065
|
continue;
|
|
1825
2066
|
}
|
|
1826
2067
|
for (const hash of hashes) {
|
|
1827
|
-
candidates.push(
|
|
2068
|
+
candidates.push(path4.join(versionDir, hash, `lombok-${version}.jar`));
|
|
1828
2069
|
}
|
|
1829
2070
|
}
|
|
1830
2071
|
return newestExistingJar(candidates);
|
|
@@ -1857,15 +2098,15 @@ function createLombokJdtlsArgs(root, baseEnv = process.env) {
|
|
|
1857
2098
|
// dist/clients/lsp/jvm-runtime.js
|
|
1858
2099
|
import { existsSync as existsSync2, readdirSync as readdirSync4 } from "node:fs";
|
|
1859
2100
|
import os5 from "node:os";
|
|
1860
|
-
import
|
|
2101
|
+
import path5 from "node:path";
|
|
1861
2102
|
var JAVA_EXE = process.platform === "win32" ? "java.exe" : "java";
|
|
1862
2103
|
var JAVA_PROBE_TIMEOUT_MS = 5e3;
|
|
1863
2104
|
var MIN_JAVA_MAJOR = 17;
|
|
1864
2105
|
function jdkHomeFrom(dir) {
|
|
1865
|
-
if (existsSync2(
|
|
2106
|
+
if (existsSync2(path5.join(dir, "bin", JAVA_EXE)))
|
|
1866
2107
|
return dir;
|
|
1867
|
-
const macHome =
|
|
1868
|
-
if (existsSync2(
|
|
2108
|
+
const macHome = path5.join(dir, "Contents", "Home");
|
|
2109
|
+
if (existsSync2(path5.join(macHome, "bin", JAVA_EXE)))
|
|
1869
2110
|
return macHome;
|
|
1870
2111
|
return void 0;
|
|
1871
2112
|
}
|
|
@@ -1878,7 +2119,7 @@ function parseMajorVersion(name) {
|
|
|
1878
2119
|
}
|
|
1879
2120
|
function childDirs(base) {
|
|
1880
2121
|
try {
|
|
1881
|
-
return readdirSync4(base, { withFileTypes: true }).filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) =>
|
|
2122
|
+
return readdirSync4(base, { withFileTypes: true }).filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) => path5.join(base, e.name));
|
|
1882
2123
|
} catch {
|
|
1883
2124
|
return [];
|
|
1884
2125
|
}
|
|
@@ -1886,26 +2127,26 @@ function childDirs(base) {
|
|
|
1886
2127
|
function candidateRoots() {
|
|
1887
2128
|
const home = os5.homedir();
|
|
1888
2129
|
const roots = [];
|
|
1889
|
-
roots.push(
|
|
1890
|
-
roots.push(
|
|
2130
|
+
roots.push(path5.join(home, ".jdks"));
|
|
2131
|
+
roots.push(path5.join(getGlobalPiLensDir(), "tools"));
|
|
1891
2132
|
if (process.platform === "win32") {
|
|
1892
2133
|
const progFiles = [
|
|
1893
2134
|
process.env.ProgramFiles,
|
|
1894
2135
|
process.env["ProgramFiles(x86)"],
|
|
1895
2136
|
process.env.ProgramW6432,
|
|
1896
|
-
|
|
2137
|
+
path5.join(process.env.LOCALAPPDATA ?? path5.join(home, "AppData", "Local"), "Programs")
|
|
1897
2138
|
].filter((p) => Boolean(p));
|
|
1898
2139
|
for (const base of progFiles) {
|
|
1899
|
-
roots.push(
|
|
1900
|
-
roots.push(
|
|
1901
|
-
roots.push(
|
|
1902
|
-
roots.push(
|
|
1903
|
-
roots.push(
|
|
1904
|
-
roots.push(
|
|
2140
|
+
roots.push(path5.join(base, "Eclipse Adoptium"));
|
|
2141
|
+
roots.push(path5.join(base, "Java"));
|
|
2142
|
+
roots.push(path5.join(base, "Microsoft"));
|
|
2143
|
+
roots.push(path5.join(base, "Zulu"));
|
|
2144
|
+
roots.push(path5.join(base, "Amazon Corretto"));
|
|
2145
|
+
roots.push(path5.join(base, "BellSoft"));
|
|
1905
2146
|
}
|
|
1906
2147
|
} else if (process.platform === "darwin") {
|
|
1907
2148
|
roots.push("/Library/Java/JavaVirtualMachines");
|
|
1908
|
-
roots.push(
|
|
2149
|
+
roots.push(path5.join(home, "Library", "Java", "JavaVirtualMachines"));
|
|
1909
2150
|
roots.push("/opt/homebrew/opt");
|
|
1910
2151
|
roots.push("/usr/local/opt");
|
|
1911
2152
|
} else {
|
|
@@ -1929,7 +2170,7 @@ function discoverJdkHome(roots = candidateRoots(), javaHome = process.env.JAVA_H
|
|
|
1929
2170
|
continue;
|
|
1930
2171
|
found.push({
|
|
1931
2172
|
home: resolved,
|
|
1932
|
-
major: parseMajorVersion(
|
|
2173
|
+
major: parseMajorVersion(path5.basename(dir))
|
|
1933
2174
|
});
|
|
1934
2175
|
}
|
|
1935
2176
|
}
|
|
@@ -2028,12 +2269,12 @@ async function resolveJavaRuntimeEnv() {
|
|
|
2028
2269
|
}
|
|
2029
2270
|
const home = discoverJdkHome();
|
|
2030
2271
|
if (home) {
|
|
2031
|
-
const binDir =
|
|
2272
|
+
const binDir = path5.join(home, "bin");
|
|
2032
2273
|
const currentPath = process.env.PATH ?? process.env.Path ?? "";
|
|
2033
2274
|
_cachedEnv = {
|
|
2034
2275
|
value: {
|
|
2035
2276
|
JAVA_HOME: home,
|
|
2036
|
-
PATH: binDir +
|
|
2277
|
+
PATH: binDir + path5.delimiter + currentPath
|
|
2037
2278
|
}
|
|
2038
2279
|
};
|
|
2039
2280
|
return _cachedEnv.value;
|
|
@@ -2089,7 +2330,7 @@ async function resolveLspServerCwd(server, filePath, sessionCwd, onRootFailure,
|
|
|
2089
2330
|
rootFailed = true;
|
|
2090
2331
|
onRootFailure?.(reason);
|
|
2091
2332
|
}
|
|
2092
|
-
const isFileDirFallback = serverRoot !== void 0 && rootMarkers?.length &&
|
|
2333
|
+
const isFileDirFallback = serverRoot !== void 0 && rootMarkers?.length && path6.resolve(serverRoot) === path6.resolve(path6.dirname(filePath));
|
|
2093
2334
|
if (!serverRoot || isFileDirFallback) {
|
|
2094
2335
|
const probedMarker = onRootFallback && !rootFailed && rootMarkers?.length ? resolveToolCwd("lsp", server.id, filePath, {
|
|
2095
2336
|
cwd: sessionCwd,
|
|
@@ -2098,7 +2339,7 @@ async function resolveLspServerCwd(server, filePath, sessionCwd, onRootFailure,
|
|
|
2098
2339
|
}).marker : void 0;
|
|
2099
2340
|
const refusedMarker = probedMarker !== void 0 && rootMarkers?.includes(probedMarker) ? probedMarker : void 0;
|
|
2100
2341
|
const fallbackCwd = rootMarkers?.length ? resolveToolCwd("lsp", server.id, filePath, {
|
|
2101
|
-
cwd:
|
|
2342
|
+
cwd: path6.dirname(path6.resolve(filePath)),
|
|
2102
2343
|
rootMarkers
|
|
2103
2344
|
}) : void 0;
|
|
2104
2345
|
if (!serverRoot) {
|
|
@@ -2168,17 +2409,17 @@ var PROJECT_BOUNDARY_MARKERS = [
|
|
|
2168
2409
|
var loggedRootCeilingClamps = /* @__PURE__ */ new Set();
|
|
2169
2410
|
var posixCaseInsensitiveByPath = /* @__PURE__ */ new Map();
|
|
2170
2411
|
function posixFilesystemIsCaseInsensitive(root) {
|
|
2171
|
-
const resolved =
|
|
2412
|
+
const resolved = path6.resolve(root);
|
|
2172
2413
|
const cached = posixCaseInsensitiveByPath.get(resolved);
|
|
2173
2414
|
if (cached !== void 0)
|
|
2174
2415
|
return cached;
|
|
2175
2416
|
if (!existsSync3(resolved)) {
|
|
2176
2417
|
return false;
|
|
2177
2418
|
}
|
|
2178
|
-
const name =
|
|
2419
|
+
const name = path6.basename(resolved);
|
|
2179
2420
|
const alternate = name.toLowerCase() === name ? name.toUpperCase() : name.toLowerCase();
|
|
2180
2421
|
let insensitive = false;
|
|
2181
|
-
const alternatePath =
|
|
2422
|
+
const alternatePath = path6.join(path6.dirname(resolved), alternate);
|
|
2182
2423
|
if (alternate !== name && existsSync3(alternatePath)) {
|
|
2183
2424
|
try {
|
|
2184
2425
|
const actual = statSync3(resolved);
|
|
@@ -2196,7 +2437,7 @@ function resetLSPCaseSensitivityState() {
|
|
|
2196
2437
|
}
|
|
2197
2438
|
function isSameOrWithin(ancestor, candidate, deps = {}) {
|
|
2198
2439
|
const windowsShaped = isWindowsPath(ancestor) || isWindowsPath(candidate);
|
|
2199
|
-
const pathApi = windowsShaped ?
|
|
2440
|
+
const pathApi = windowsShaped ? path6.win32 : path6;
|
|
2200
2441
|
const resolvedAncestor = pathApi.resolve(ancestor);
|
|
2201
2442
|
const resolvedCandidate = pathApi.resolve(candidate);
|
|
2202
2443
|
let caseInsensitive = false;
|
|
@@ -2216,7 +2457,7 @@ function isSameOrWithin(ancestor, candidate, deps = {}) {
|
|
|
2216
2457
|
}
|
|
2217
2458
|
function enforceLspRootCeiling(root, sessionCwd, filePath) {
|
|
2218
2459
|
const windowsShaped = isWindowsPath(root) || isWindowsPath(sessionCwd);
|
|
2219
|
-
const pathApi = windowsShaped ?
|
|
2460
|
+
const pathApi = windowsShaped ? path6.win32 : path6;
|
|
2220
2461
|
const resolvedRoot = pathApi.resolve(root);
|
|
2221
2462
|
const resolvedCwd = pathApi.resolve(sessionCwd);
|
|
2222
2463
|
if (filePath && !isSameOrWithin(resolvedCwd, pathApi.resolve(filePath))) {
|
|
@@ -2241,8 +2482,8 @@ async function hasProjectBoundaryMarker(dir) {
|
|
|
2241
2482
|
return false;
|
|
2242
2483
|
}
|
|
2243
2484
|
function pathSegments(dir) {
|
|
2244
|
-
const parsed =
|
|
2245
|
-
return
|
|
2485
|
+
const parsed = path6.parse(path6.resolve(dir));
|
|
2486
|
+
return path6.relative(parsed.root, path6.resolve(dir)).split(path6.sep).filter(Boolean).map((segment) => segment.toLowerCase());
|
|
2246
2487
|
}
|
|
2247
2488
|
function hasFixtureConvention(dir) {
|
|
2248
2489
|
const segments = pathSegments(dir);
|
|
@@ -2254,18 +2495,18 @@ function hasAtomicStageSegment(dir) {
|
|
|
2254
2495
|
return pathSegments(dir).some((segment) => STAGE_TMP_PATTERN.test(segment));
|
|
2255
2496
|
}
|
|
2256
2497
|
async function findGitBoundary(dir) {
|
|
2257
|
-
let current =
|
|
2258
|
-
const fsRoot =
|
|
2498
|
+
let current = path6.resolve(dir);
|
|
2499
|
+
const fsRoot = path6.parse(current).root;
|
|
2259
2500
|
while (true) {
|
|
2260
2501
|
if (await markerExists(current, ".git"))
|
|
2261
2502
|
return current;
|
|
2262
2503
|
if (current === fsRoot)
|
|
2263
2504
|
return void 0;
|
|
2264
|
-
current =
|
|
2505
|
+
current = path6.dirname(current);
|
|
2265
2506
|
}
|
|
2266
2507
|
}
|
|
2267
2508
|
async function isExcludedLspRoot(dir) {
|
|
2268
|
-
const candidate =
|
|
2509
|
+
const candidate = path6.resolve(dir);
|
|
2269
2510
|
if (hasFixtureConvention(candidate) || hasAtomicStageSegment(candidate))
|
|
2270
2511
|
return true;
|
|
2271
2512
|
const gitRoot = await findGitBoundary(candidate);
|
|
@@ -2277,9 +2518,9 @@ async function isExcludedLspRoot(dir) {
|
|
|
2277
2518
|
}
|
|
2278
2519
|
async function nearestNonExcludedFallbackRoot(candidate) {
|
|
2279
2520
|
if (!await isExcludedLspRoot(candidate))
|
|
2280
|
-
return
|
|
2281
|
-
let current =
|
|
2282
|
-
const fsRoot =
|
|
2521
|
+
return path6.resolve(candidate);
|
|
2522
|
+
let current = path6.dirname(path6.resolve(candidate));
|
|
2523
|
+
const fsRoot = path6.parse(current).root;
|
|
2283
2524
|
let nearestAllowed;
|
|
2284
2525
|
while (true) {
|
|
2285
2526
|
if (!await isExcludedLspRoot(current)) {
|
|
@@ -2291,7 +2532,7 @@ async function nearestNonExcludedFallbackRoot(candidate) {
|
|
|
2291
2532
|
}
|
|
2292
2533
|
if (current === fsRoot)
|
|
2293
2534
|
break;
|
|
2294
|
-
current =
|
|
2535
|
+
current = path6.dirname(current);
|
|
2295
2536
|
}
|
|
2296
2537
|
return nearestAllowed ?? fsRoot;
|
|
2297
2538
|
}
|
|
@@ -2332,7 +2573,7 @@ async function installEvidenceForLaunch(toolId, installed, attempt) {
|
|
|
2332
2573
|
const confirmedManagedPath = await findManagedToolBinary(toolId);
|
|
2333
2574
|
return {
|
|
2334
2575
|
...evidence,
|
|
2335
|
-
binary:
|
|
2576
|
+
binary: path6.basename(installed),
|
|
2336
2577
|
...confirmedManagedPath !== void 0 && pathsEqual(confirmedManagedPath, installed) && {
|
|
2337
2578
|
source: "managed-dir"
|
|
2338
2579
|
}
|
|
@@ -2385,7 +2626,7 @@ function markDirectLspCommandUnavailable(command) {
|
|
|
2385
2626
|
directLspCommandUnavailableUntil.set(command, Date.now() + DIRECT_LSP_NEGATIVE_TTL_MS);
|
|
2386
2627
|
directLspCommandSkipLoggedUntil.delete(command);
|
|
2387
2628
|
}
|
|
2388
|
-
var PI_LENS_BIN_DIR2 =
|
|
2629
|
+
var PI_LENS_BIN_DIR2 = path6.join(getGlobalPiLensDir(), "bin");
|
|
2389
2630
|
async function resolveAndLaunch(spec, allowInstall) {
|
|
2390
2631
|
const generation = lspLaunchAvailabilityGeneration.capture();
|
|
2391
2632
|
const toolLabel = spec.managedToolId ?? spec.candidates[spec.candidates.length - 1] ?? "unknown";
|
|
@@ -2450,7 +2691,7 @@ async function resolveAndLaunch(spec, allowInstall) {
|
|
|
2450
2691
|
producer: "lsp-launch",
|
|
2451
2692
|
classifiedBy: "probe",
|
|
2452
2693
|
evidence: {
|
|
2453
|
-
binary:
|
|
2694
|
+
binary: path6.basename(managedCandidate),
|
|
2454
2695
|
source: "managed-dir",
|
|
2455
2696
|
correctsLatchedRow: false
|
|
2456
2697
|
}
|
|
@@ -2743,7 +2984,7 @@ async function resolveAndLaunchTreeBinary(spec, allowInstall) {
|
|
|
2743
2984
|
return void 0;
|
|
2744
2985
|
}
|
|
2745
2986
|
const suffix = process.platform === "win32" ? ".exe" : "";
|
|
2746
|
-
const binPath =
|
|
2987
|
+
const binPath = path6.join(bundleDir, ...spec.binRelPath.split("/")) + suffix;
|
|
2747
2988
|
try {
|
|
2748
2989
|
const proc = await launchLSP(binPath, spec.args, {
|
|
2749
2990
|
cwd: spec.cwd,
|
|
@@ -2758,7 +2999,7 @@ async function resolveAndLaunchTreeBinary(spec, allowInstall) {
|
|
|
2758
2999
|
}
|
|
2759
3000
|
}
|
|
2760
3001
|
function nodeBinLocalCandidates(root, baseName) {
|
|
2761
|
-
const localBase =
|
|
3002
|
+
const localBase = path6.join(root, "node_modules", ".bin", baseName);
|
|
2762
3003
|
if (process.platform === "win32") {
|
|
2763
3004
|
return [`${localBase}.cmd`, `${localBase}.exe`];
|
|
2764
3005
|
}
|
|
@@ -2768,7 +3009,7 @@ function nodeBinCandidates(root, baseName) {
|
|
|
2768
3009
|
return [...nodeBinLocalCandidates(root, baseName), baseName];
|
|
2769
3010
|
}
|
|
2770
3011
|
function piAgentExtensionsRootKey(file) {
|
|
2771
|
-
const dirKey = normalizeEphemeralMapKey(
|
|
3012
|
+
const dirKey = normalizeEphemeralMapKey(path6.dirname(path6.resolve(file)));
|
|
2772
3013
|
const marker = "/.pi/agent/extensions";
|
|
2773
3014
|
const index = dirKey.indexOf(marker);
|
|
2774
3015
|
if (index === -1)
|
|
@@ -2776,12 +3017,12 @@ function piAgentExtensionsRootKey(file) {
|
|
|
2776
3017
|
return dirKey.slice(0, index + marker.length);
|
|
2777
3018
|
}
|
|
2778
3019
|
function IgnoreHomeRoot(primary) {
|
|
2779
|
-
const homeKey = normalizeEphemeralMapKey(
|
|
3020
|
+
const homeKey = normalizeEphemeralMapKey(path6.resolve(os6.homedir()));
|
|
2780
3021
|
return withRootMarkers(async (file) => {
|
|
2781
3022
|
const root = await primary(file);
|
|
2782
3023
|
if (!root)
|
|
2783
3024
|
return void 0;
|
|
2784
|
-
return normalizeEphemeralMapKey(
|
|
3025
|
+
return normalizeEphemeralMapKey(path6.resolve(root)) === homeKey ? void 0 : root;
|
|
2785
3026
|
}, primary.rootMarkers ?? []);
|
|
2786
3027
|
}
|
|
2787
3028
|
function rubyBinCandidates(baseName) {
|
|
@@ -2789,13 +3030,13 @@ function rubyBinCandidates(baseName) {
|
|
|
2789
3030
|
const home = os6.homedir();
|
|
2790
3031
|
const isWin = process.platform === "win32";
|
|
2791
3032
|
const ext = isWin ? ".bat" : "";
|
|
2792
|
-
candidates.push(
|
|
2793
|
-
candidates.push(
|
|
3033
|
+
candidates.push(path6.join(home, ".local", "share", "mise", "installs", "ruby", "bin", `${baseName}${ext}`));
|
|
3034
|
+
candidates.push(path6.join(home, ".asdf", "installs", "ruby", "bin", `${baseName}${ext}`));
|
|
2794
3035
|
if (isWin) {
|
|
2795
|
-
const driveRoot =
|
|
3036
|
+
const driveRoot = path6.parse(home).root;
|
|
2796
3037
|
for (const entry of getRubyVersionDirNamesSync(driveRoot)) {
|
|
2797
|
-
candidates.push(
|
|
2798
|
-
candidates.push(
|
|
3038
|
+
candidates.push(path6.join(driveRoot, entry, "bin", `${baseName}.bat`));
|
|
3039
|
+
candidates.push(path6.join(driveRoot, entry, "bin", baseName));
|
|
2799
3040
|
}
|
|
2800
3041
|
}
|
|
2801
3042
|
return candidates;
|
|
@@ -2806,10 +3047,16 @@ function createInteractiveServer(spec) {
|
|
|
2806
3047
|
name: spec.name,
|
|
2807
3048
|
extensions: spec.extensions,
|
|
2808
3049
|
idleEviction: "unmeasured",
|
|
3050
|
+
// `InteractiveServerSpec` declares no role, so the factory applies the
|
|
3051
|
+
// stated default rather than leaving `role` absent for each consumer to
|
|
3052
|
+
// read by negation (#1488). An auxiliary would declare its role on a
|
|
3053
|
+
// row of its own, the way the four scanner rows do.
|
|
3054
|
+
role: DEFAULT_LSP_SERVER_ROLE,
|
|
2809
3055
|
root: spec.root,
|
|
2810
3056
|
rootMarkers: spec.root.rootMarkers,
|
|
2811
3057
|
fallbackFor: spec.fallbackFor,
|
|
2812
3058
|
requiresProjectRoot: spec.requiresProjectRoot,
|
|
3059
|
+
executesProjectCode: spec.executesProjectCode,
|
|
2813
3060
|
availabilityKey: typeof spec.command === "string" && isSimpleCommand(spec.command) ? spec.command : void 0,
|
|
2814
3061
|
async spawn(root) {
|
|
2815
3062
|
const command = typeof spec.command === "function" ? spec.command(root) : spec.command;
|
|
@@ -2846,7 +3093,7 @@ function PriorityRoot(markerGroups, excludePatterns, stopDir) {
|
|
|
2846
3093
|
}, markerGroups.flat());
|
|
2847
3094
|
}
|
|
2848
3095
|
var FileDirRoot = async (file) => {
|
|
2849
|
-
const candidate =
|
|
3096
|
+
const candidate = path6.resolve(path6.dirname(file));
|
|
2850
3097
|
return nearestNonExcludedFallbackRoot(candidate);
|
|
2851
3098
|
};
|
|
2852
3099
|
function RootWithFallback(primary, fallback = FileDirRoot) {
|
|
@@ -2868,16 +3115,16 @@ function markerProbeDir(dir, pattern) {
|
|
|
2868
3115
|
const normalized = toPosix(pattern);
|
|
2869
3116
|
const slash = normalized.lastIndexOf("/");
|
|
2870
3117
|
const parentPattern = slash >= 0 ? normalized.slice(0, slash) : "";
|
|
2871
|
-
return parentPattern ?
|
|
3118
|
+
return parentPattern ? path6.join(dir, ...parentPattern.split("/").filter(Boolean)) : dir;
|
|
2872
3119
|
}
|
|
2873
3120
|
async function markerExists(dir, pattern) {
|
|
2874
3121
|
if (!pattern.includes("*")) {
|
|
2875
3122
|
try {
|
|
2876
|
-
await stat(
|
|
3123
|
+
await stat(path6.join(dir, pattern));
|
|
2877
3124
|
return true;
|
|
2878
3125
|
} catch (err) {
|
|
2879
3126
|
if (isPermissionFsError(err)) {
|
|
2880
|
-
logSessionStart(`lsp root marker skipped: permission error stat ${
|
|
3127
|
+
logSessionStart(`lsp root marker skipped: permission error stat ${path6.join(dir, pattern)}`);
|
|
2881
3128
|
}
|
|
2882
3129
|
return false;
|
|
2883
3130
|
}
|
|
@@ -2913,7 +3160,7 @@ function NearestRoot(includePatterns, excludePatterns, stopDir) {
|
|
|
2913
3160
|
subdirPatterns.push(pattern);
|
|
2914
3161
|
}
|
|
2915
3162
|
return withRootMarkers(async (file) => {
|
|
2916
|
-
const startDir =
|
|
3163
|
+
const startDir = path6.resolve(path6.dirname(file));
|
|
2917
3164
|
const dirKey = normalizeMapKey(startDir);
|
|
2918
3165
|
const cached = cache.get(dirKey);
|
|
2919
3166
|
if (cached !== void 0 && Date.now() - cached.walkedAt < FRESHNESS_CADENCE_MS && await bounded(dirMtimesStillFreshAsync(cached.probedDirs), rootMtimeBound("lsp-root-memo-freshness")) === true)
|
|
@@ -2925,10 +3172,10 @@ function NearestRoot(includePatterns, excludePatterns, stopDir) {
|
|
|
2925
3172
|
const walkedAt = Date.now();
|
|
2926
3173
|
const promise = (async () => {
|
|
2927
3174
|
let currentDir = startDir;
|
|
2928
|
-
const fsRoot =
|
|
2929
|
-
const stop = stopDir ?
|
|
3175
|
+
const fsRoot = path6.parse(currentDir).root;
|
|
3176
|
+
const stop = stopDir ? path6.resolve(stopDir) : fsRoot;
|
|
2930
3177
|
while (true) {
|
|
2931
|
-
if (stop !== fsRoot && currentDir.startsWith(stop +
|
|
3178
|
+
if (stop !== fsRoot && currentDir.startsWith(stop + path6.sep) === false && currentDir !== stop) {
|
|
2932
3179
|
break;
|
|
2933
3180
|
}
|
|
2934
3181
|
const stepDirs = [
|
|
@@ -2946,7 +3193,7 @@ function NearestRoot(includePatterns, excludePatterns, stopDir) {
|
|
|
2946
3193
|
}
|
|
2947
3194
|
}
|
|
2948
3195
|
if (excluded) {
|
|
2949
|
-
currentDir =
|
|
3196
|
+
currentDir = path6.dirname(currentDir);
|
|
2950
3197
|
continue;
|
|
2951
3198
|
}
|
|
2952
3199
|
}
|
|
@@ -2958,7 +3205,7 @@ function NearestRoot(includePatterns, excludePatterns, stopDir) {
|
|
|
2958
3205
|
if (currentDir === stop || currentDir === fsRoot) {
|
|
2959
3206
|
break;
|
|
2960
3207
|
}
|
|
2961
|
-
currentDir =
|
|
3208
|
+
currentDir = path6.dirname(currentDir);
|
|
2962
3209
|
}
|
|
2963
3210
|
return void 0;
|
|
2964
3211
|
})();
|
|
@@ -3000,17 +3247,17 @@ async function findAncestorFile(startDir, ...relativeSegments) {
|
|
|
3000
3247
|
}
|
|
3001
3248
|
async function findAncestorFileAmong(startDir, candidateSegmentLists) {
|
|
3002
3249
|
const fs5 = await import("node:fs/promises");
|
|
3003
|
-
let currentDir =
|
|
3250
|
+
let currentDir = path6.resolve(startDir);
|
|
3004
3251
|
while (!isAtOrAboveHomeDir(currentDir)) {
|
|
3005
3252
|
for (const segments of candidateSegmentLists) {
|
|
3006
|
-
const candidate =
|
|
3253
|
+
const candidate = path6.join(currentDir, ...segments);
|
|
3007
3254
|
try {
|
|
3008
3255
|
await fs5.access(candidate);
|
|
3009
3256
|
return candidate;
|
|
3010
3257
|
} catch {
|
|
3011
3258
|
}
|
|
3012
3259
|
}
|
|
3013
|
-
const parent =
|
|
3260
|
+
const parent = path6.dirname(currentDir);
|
|
3014
3261
|
if (parent === currentDir)
|
|
3015
3262
|
break;
|
|
3016
3263
|
currentDir = parent;
|
|
@@ -3026,19 +3273,19 @@ function resetClassicTsRepairGuard() {
|
|
|
3026
3273
|
classicTsRepairState().attempted = false;
|
|
3027
3274
|
}
|
|
3028
3275
|
function typescriptDirsForTsc(tscPath) {
|
|
3029
|
-
const binDir =
|
|
3276
|
+
const binDir = path6.dirname(tscPath);
|
|
3030
3277
|
return [
|
|
3031
|
-
|
|
3032
|
-
|
|
3278
|
+
path6.join(binDir, "..", "typescript"),
|
|
3279
|
+
path6.join(binDir, "..", "..", "typescript")
|
|
3033
3280
|
];
|
|
3034
3281
|
}
|
|
3035
3282
|
async function typescriptVersionForTsc(tscPath) {
|
|
3036
|
-
if (!
|
|
3283
|
+
if (!path6.isAbsolute(tscPath))
|
|
3037
3284
|
return void 0;
|
|
3038
3285
|
for (const dir of typescriptDirsForTsc(tscPath)) {
|
|
3039
3286
|
let manifest;
|
|
3040
3287
|
try {
|
|
3041
|
-
manifest = await readFile(
|
|
3288
|
+
manifest = await readFile(path6.join(dir, "package.json"), "utf8");
|
|
3042
3289
|
} catch {
|
|
3043
3290
|
continue;
|
|
3044
3291
|
}
|
|
@@ -3060,25 +3307,45 @@ async function typescriptVersionForTsc(tscPath) {
|
|
|
3060
3307
|
}
|
|
3061
3308
|
return void 0;
|
|
3062
3309
|
}
|
|
3063
|
-
async function findTsserverPath(root, allowInstall) {
|
|
3310
|
+
async function findTsserverPath(root, allowInstall, options) {
|
|
3064
3311
|
const fs5 = await import("node:fs/promises");
|
|
3312
|
+
const projectRoots = await Promise.all([root, options?.sessionRoot ?? process.cwd(), process.cwd()].map((dir) => fs5.realpath(dir).catch(() => path6.resolve(dir))));
|
|
3313
|
+
const admitCandidate = async (candidate, projectSupplied) => {
|
|
3314
|
+
try {
|
|
3315
|
+
const real = await fs5.realpath(candidate);
|
|
3316
|
+
if (path6.basename(real) !== "tsserver.js" || !(await fs5.stat(real)).isFile())
|
|
3317
|
+
return void 0;
|
|
3318
|
+
const manifest = JSON.parse(await fs5.readFile(path6.join(path6.dirname(real), "..", "package.json"), "utf8"));
|
|
3319
|
+
if (typeof manifest?.version !== "string" || !manifest.version)
|
|
3320
|
+
return void 0;
|
|
3321
|
+
return admitProjectSuppliedTsserver(real, options?.sessionRoot ?? process.cwd(), projectSupplied || projectRoots.some((dir) => isUnderDir(real, dir)), options?.projectCodeAllowed);
|
|
3322
|
+
} catch {
|
|
3323
|
+
return void 0;
|
|
3324
|
+
}
|
|
3325
|
+
};
|
|
3065
3326
|
const ancestorHit = await findAncestorFile(root, "node_modules", "typescript", "lib", "tsserver.js");
|
|
3066
|
-
if (ancestorHit)
|
|
3067
|
-
|
|
3068
|
-
|
|
3327
|
+
if (ancestorHit) {
|
|
3328
|
+
const admittedAncestor = await admitCandidate(ancestorHit, true);
|
|
3329
|
+
if (admittedAncestor)
|
|
3330
|
+
return admittedAncestor;
|
|
3331
|
+
}
|
|
3332
|
+
const cwdCandidate = path6.join(process.cwd(), "node_modules", "typescript", "lib", "tsserver.js");
|
|
3069
3333
|
try {
|
|
3070
3334
|
await fs5.access(cwdCandidate);
|
|
3071
|
-
|
|
3335
|
+
const admittedCwd = await admitCandidate(cwdCandidate, false);
|
|
3336
|
+
if (admittedCwd)
|
|
3337
|
+
return admittedCwd;
|
|
3072
3338
|
} catch {
|
|
3073
3339
|
}
|
|
3074
3340
|
const tsserverForTsc = async (tscPath) => {
|
|
3075
|
-
if (!tscPath)
|
|
3341
|
+
if (!tscPath || !path6.isAbsolute(tscPath))
|
|
3076
3342
|
return void 0;
|
|
3077
3343
|
for (const dir of typescriptDirsForTsc(tscPath)) {
|
|
3078
|
-
const candidate =
|
|
3344
|
+
const candidate = path6.join(dir, "lib", "tsserver.js");
|
|
3079
3345
|
try {
|
|
3080
|
-
await
|
|
3081
|
-
|
|
3346
|
+
const admitted = await admitCandidate(candidate, false);
|
|
3347
|
+
if (admitted)
|
|
3348
|
+
return admitted;
|
|
3082
3349
|
} catch {
|
|
3083
3350
|
}
|
|
3084
3351
|
}
|
|
@@ -3104,10 +3371,10 @@ async function findTsserverPath(root, allowInstall) {
|
|
|
3104
3371
|
return tsserverForTsc(repairedTsc);
|
|
3105
3372
|
}
|
|
3106
3373
|
async function findNativeTypeScriptLsp(root) {
|
|
3107
|
-
let currentDir =
|
|
3374
|
+
let currentDir = path6.resolve(root);
|
|
3108
3375
|
while (!isAtOrAboveHomeDir(currentDir)) {
|
|
3109
|
-
const typescriptDir =
|
|
3110
|
-
const packageJsonPath =
|
|
3376
|
+
const typescriptDir = path6.join(currentDir, "node_modules", "typescript");
|
|
3377
|
+
const packageJsonPath = path6.join(typescriptDir, "package.json");
|
|
3111
3378
|
let packageJsonText;
|
|
3112
3379
|
try {
|
|
3113
3380
|
packageJsonText = await readFile(packageJsonPath, "utf8");
|
|
@@ -3121,7 +3388,7 @@ async function findNativeTypeScriptLsp(root) {
|
|
|
3121
3388
|
return void 0;
|
|
3122
3389
|
} catch {
|
|
3123
3390
|
}
|
|
3124
|
-
const parent =
|
|
3391
|
+
const parent = path6.dirname(currentDir);
|
|
3125
3392
|
if (parent === currentDir)
|
|
3126
3393
|
return void 0;
|
|
3127
3394
|
currentDir = parent;
|
|
@@ -3141,7 +3408,7 @@ async function findNativeTypeScriptLsp(root) {
|
|
|
3141
3408
|
const major = /^\d+$/.test(majorText) ? Number(majorText) : Number.NaN;
|
|
3142
3409
|
if (!Number.isFinite(major) || major < 7)
|
|
3143
3410
|
return void 0;
|
|
3144
|
-
const localTsc =
|
|
3411
|
+
const localTsc = path6.join(currentDir, "node_modules", ".bin", "tsc");
|
|
3145
3412
|
const candidates = process.platform === "win32" ? [`${localTsc}.cmd`, `${localTsc}.exe`, localTsc] : [localTsc];
|
|
3146
3413
|
for (const command of candidates) {
|
|
3147
3414
|
try {
|
|
@@ -3157,23 +3424,23 @@ async function findNativeTypeScriptLsp(root) {
|
|
|
3157
3424
|
function dotnetToolCandidates(tool) {
|
|
3158
3425
|
const home = os6.homedir();
|
|
3159
3426
|
return [
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3427
|
+
path6.join(PI_LENS_BIN_DIR2, `${tool}.exe`),
|
|
3428
|
+
path6.join(PI_LENS_BIN_DIR2, tool),
|
|
3429
|
+
path6.join(home, ".dotnet", "tools", `${tool}.exe`),
|
|
3430
|
+
path6.join(home, ".dotnet", "tools", tool),
|
|
3164
3431
|
tool
|
|
3165
3432
|
].filter(Boolean);
|
|
3166
3433
|
}
|
|
3167
3434
|
function binExeVariants(dir, tool) {
|
|
3168
|
-
return process.platform === "win32" ? [
|
|
3435
|
+
return process.platform === "win32" ? [path6.join(dir, `${tool}.exe`), path6.join(dir, tool)] : [path6.join(dir, tool)];
|
|
3169
3436
|
}
|
|
3170
3437
|
function goBinCandidates(tool) {
|
|
3171
|
-
const gopath = process.env.GOPATH?.split(
|
|
3172
|
-
return [tool, ...binExeVariants(
|
|
3438
|
+
const gopath = process.env.GOPATH?.split(path6.delimiter)[0] || path6.join(os6.homedir(), "go");
|
|
3439
|
+
return [tool, ...binExeVariants(path6.join(gopath, "bin"), tool)];
|
|
3173
3440
|
}
|
|
3174
3441
|
function cargoBinCandidates(tool) {
|
|
3175
|
-
const cargoHome = process.env.CARGO_HOME ||
|
|
3176
|
-
return [tool, ...binExeVariants(
|
|
3442
|
+
const cargoHome = process.env.CARGO_HOME || path6.join(os6.homedir(), ".cargo");
|
|
3443
|
+
return [tool, ...binExeVariants(path6.join(cargoHome, "bin"), tool)];
|
|
3177
3444
|
}
|
|
3178
3445
|
async function tryGemInstall(gem) {
|
|
3179
3446
|
const { join: join3 } = await import("node:path");
|
|
@@ -3211,7 +3478,7 @@ var TS_TOOLING_MARKERS = [
|
|
|
3211
3478
|
];
|
|
3212
3479
|
var TS_FAMILY_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts"]);
|
|
3213
3480
|
function isTsFamilyFile(file) {
|
|
3214
|
-
return TS_FAMILY_EXTENSIONS.has(
|
|
3481
|
+
return TS_FAMILY_EXTENSIONS.has(path6.extname(file).toLowerCase());
|
|
3215
3482
|
}
|
|
3216
3483
|
function tsConfigMarkersForFile(file) {
|
|
3217
3484
|
return isTsFamilyFile(file) ? ["tsconfig.json"] : TS_CONFIG_MARKERS;
|
|
@@ -3232,40 +3499,40 @@ async function findTypeScriptProjectRoot(file) {
|
|
|
3232
3499
|
return isSameOrWithin(toolingRoot, configRoot) ? configRoot : toolingRoot;
|
|
3233
3500
|
}
|
|
3234
3501
|
async function findExtensionBoundedRoot(file, extensionRootKey) {
|
|
3235
|
-
const startDir =
|
|
3502
|
+
const startDir = path6.resolve(path6.dirname(file));
|
|
3236
3503
|
let currentDir = startDir;
|
|
3237
3504
|
const configMarkers = tsConfigMarkersForFile(file);
|
|
3238
3505
|
while (true) {
|
|
3239
3506
|
for (const pattern of configMarkers) {
|
|
3240
3507
|
try {
|
|
3241
|
-
await stat(
|
|
3508
|
+
await stat(path6.join(currentDir, pattern));
|
|
3242
3509
|
return currentDir;
|
|
3243
3510
|
} catch {
|
|
3244
3511
|
}
|
|
3245
3512
|
}
|
|
3246
3513
|
for (const pattern of TS_TOOLING_MARKERS) {
|
|
3247
3514
|
try {
|
|
3248
|
-
await stat(
|
|
3515
|
+
await stat(path6.join(currentDir, pattern));
|
|
3249
3516
|
return currentDir;
|
|
3250
3517
|
} catch {
|
|
3251
3518
|
}
|
|
3252
3519
|
}
|
|
3253
|
-
const currentKey = normalizeEphemeralMapKey(
|
|
3520
|
+
const currentKey = normalizeEphemeralMapKey(path6.resolve(currentDir));
|
|
3254
3521
|
if (currentKey === extensionRootKey)
|
|
3255
3522
|
return void 0;
|
|
3256
|
-
const parent =
|
|
3523
|
+
const parent = path6.dirname(currentDir);
|
|
3257
3524
|
if (parent === currentDir)
|
|
3258
3525
|
return void 0;
|
|
3259
3526
|
currentDir = parent;
|
|
3260
3527
|
}
|
|
3261
3528
|
}
|
|
3262
3529
|
async function hasAgentLevelProjectMarker(extensionRootKey) {
|
|
3263
|
-
const agentDir =
|
|
3530
|
+
const agentDir = path6.dirname(extensionRootKey);
|
|
3264
3531
|
if (!agentDir || agentDir === extensionRootKey)
|
|
3265
3532
|
return false;
|
|
3266
3533
|
for (const pattern of [...TS_CONFIG_MARKERS, ...TS_TOOLING_MARKERS]) {
|
|
3267
3534
|
try {
|
|
3268
|
-
await stat(
|
|
3535
|
+
await stat(path6.join(agentDir, pattern));
|
|
3269
3536
|
return true;
|
|
3270
3537
|
} catch {
|
|
3271
3538
|
}
|
|
@@ -3291,15 +3558,16 @@ var TypeScriptRoot = withRootMarkers(DenoExcludeRoot(async (file) => {
|
|
|
3291
3558
|
var TypeScriptServer = {
|
|
3292
3559
|
id: "typescript",
|
|
3293
3560
|
idleEviction: "transparent",
|
|
3561
|
+
role: "language",
|
|
3294
3562
|
name: "TypeScript Language Server",
|
|
3563
|
+
projectLocalCommand: "typescript-language-server",
|
|
3295
3564
|
extensions: JS_TS_LSP_EXTENSIONS,
|
|
3296
3565
|
autoPropagateDiagnostics: true,
|
|
3297
3566
|
root: TypeScriptRoot,
|
|
3298
3567
|
rootMarkers: TypeScriptRoot.rootMarkers,
|
|
3299
3568
|
async spawn(root, options) {
|
|
3300
|
-
const fs5 = await import("node:fs/promises");
|
|
3301
3569
|
const nativeLsp = await findNativeTypeScriptLsp(root);
|
|
3302
|
-
if (nativeLsp) {
|
|
3570
|
+
if (nativeLsp && admitProjectSuppliedTsserver(nativeLsp.command, root, true, options?.projectCodeAllowed)) {
|
|
3303
3571
|
const env2 = await getToolEnvironment();
|
|
3304
3572
|
logSessionStart(`lsp typescript-native: version=${nativeLsp.version} command=${nativeLsp.command}`);
|
|
3305
3573
|
const proc2 = await launchLSP(nativeLsp.command, ["--lsp", "--stdio"], {
|
|
@@ -3323,14 +3591,10 @@ var TypeScriptServer = {
|
|
|
3323
3591
|
return void 0;
|
|
3324
3592
|
}
|
|
3325
3593
|
}
|
|
3326
|
-
|
|
3594
|
+
const tsserverPath = await findTsserverPath(root, options?.allowInstall, options);
|
|
3327
3595
|
if (!tsserverPath) {
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
await fs5.access(localCandidate);
|
|
3331
|
-
tsserverPath = localCandidate;
|
|
3332
|
-
} catch {
|
|
3333
|
-
}
|
|
3596
|
+
admitProjectSuppliedTsserver(void 0, root, true, options?.projectCodeAllowed);
|
|
3597
|
+
return void 0;
|
|
3334
3598
|
}
|
|
3335
3599
|
if (tsserverPath)
|
|
3336
3600
|
source = "managed";
|
|
@@ -3353,6 +3617,7 @@ var TypeScriptServer = {
|
|
|
3353
3617
|
var DenoServer = {
|
|
3354
3618
|
id: "deno",
|
|
3355
3619
|
idleEviction: "transparent",
|
|
3620
|
+
role: "language",
|
|
3356
3621
|
name: "Deno Language Server",
|
|
3357
3622
|
fallbackFor: "typescript",
|
|
3358
3623
|
extensions: JS_TS_LSP_EXTENSIONS,
|
|
@@ -3370,6 +3635,7 @@ var DenoServer = {
|
|
|
3370
3635
|
var PythonServer = {
|
|
3371
3636
|
id: "python",
|
|
3372
3637
|
idleEviction: "transparent",
|
|
3638
|
+
role: "language",
|
|
3373
3639
|
name: "Pyright Language Server",
|
|
3374
3640
|
extensions: KIND_EXTENSIONS["python"],
|
|
3375
3641
|
root: RootWithFallback(createRootDetector([
|
|
@@ -3444,13 +3710,13 @@ var PythonServer = {
|
|
|
3444
3710
|
if (!pyrightPath)
|
|
3445
3711
|
return void 0;
|
|
3446
3712
|
source = "managed";
|
|
3447
|
-
const binDir =
|
|
3713
|
+
const binDir = path6.dirname(pyrightPath);
|
|
3448
3714
|
const isWindows2 = process.platform === "win32";
|
|
3449
3715
|
const managedCandidates = isWindows2 ? [
|
|
3450
|
-
|
|
3451
|
-
|
|
3716
|
+
path6.join(binDir, "pyright-langserver.cmd"),
|
|
3717
|
+
path6.join(binDir, "pyright-langserver"),
|
|
3452
3718
|
"pyright-langserver"
|
|
3453
|
-
] : [
|
|
3719
|
+
] : [path6.join(binDir, "pyright-langserver"), "pyright-langserver"];
|
|
3454
3720
|
const resolved = await resolveAndLaunch({ candidates: managedCandidates, args: ["--stdio"], cwd: root, env }, false);
|
|
3455
3721
|
if (!resolved)
|
|
3456
3722
|
return void 0;
|
|
@@ -3463,7 +3729,8 @@ var PythonServer = {
|
|
|
3463
3729
|
};
|
|
3464
3730
|
var PythonJediServer = {
|
|
3465
3731
|
id: "python-jedi",
|
|
3466
|
-
idleEviction: "
|
|
3732
|
+
idleEviction: "transparent",
|
|
3733
|
+
role: "language",
|
|
3467
3734
|
name: "Jedi Language Server",
|
|
3468
3735
|
fallbackFor: "python",
|
|
3469
3736
|
extensions: KIND_EXTENSIONS["python"],
|
|
@@ -3495,6 +3762,7 @@ var PythonJediServer = {
|
|
|
3495
3762
|
var GoServer = {
|
|
3496
3763
|
id: "go",
|
|
3497
3764
|
idleEviction: "unmeasured",
|
|
3765
|
+
role: "language",
|
|
3498
3766
|
name: "gopls",
|
|
3499
3767
|
extensions: KIND_EXTENSIONS["go"],
|
|
3500
3768
|
root: RootWithFallback(WorkspacePriorityRoot([["go.work"], ["go.mod", "go.sum"], [".git"]])),
|
|
@@ -3517,7 +3785,7 @@ var GoServer = {
|
|
|
3517
3785
|
}
|
|
3518
3786
|
};
|
|
3519
3787
|
function cargoWorkspaceDeclaresMember(workspaceContent, parentDir, childDir) {
|
|
3520
|
-
const relativePath =
|
|
3788
|
+
const relativePath = path6.relative(parentDir, childDir).split(path6.sep).join("/");
|
|
3521
3789
|
if (relativePath === "" || relativePath.startsWith(".."))
|
|
3522
3790
|
return false;
|
|
3523
3791
|
const matches = (pattern) => matchesWorkspaceMemberPattern(pattern, relativePath, CARGO_WORKSPACE_MEMBER_DIALECT, () => recordDegradationOnce({
|
|
@@ -3531,7 +3799,7 @@ function cargoWorkspaceDeclaresMember(workspaceContent, parentDir, childDir) {
|
|
|
3531
3799
|
return readCargoWorkspaceMembers(workspaceContent).some(matches);
|
|
3532
3800
|
}
|
|
3533
3801
|
function sessionHoistCeiling(sessionCwd, file) {
|
|
3534
|
-
return isSameOrWithin(
|
|
3802
|
+
return isSameOrWithin(path6.resolve(sessionCwd), path6.resolve(file)) ? path6.resolve(sessionCwd) : void 0;
|
|
3535
3803
|
}
|
|
3536
3804
|
function RustWorkspaceRoot() {
|
|
3537
3805
|
const crateRoot = createRootDetector(["Cargo.toml", "Cargo.lock"]);
|
|
@@ -3542,14 +3810,14 @@ function RustWorkspaceRoot() {
|
|
|
3542
3810
|
const sessionCwd = process.cwd();
|
|
3543
3811
|
const stop = sessionHoistCeiling(sessionCwd, file);
|
|
3544
3812
|
let current = root;
|
|
3545
|
-
const fsRoot =
|
|
3813
|
+
const fsRoot = path6.parse(current).root;
|
|
3546
3814
|
while (true) {
|
|
3547
3815
|
if (stop !== void 0 && current === stop)
|
|
3548
3816
|
break;
|
|
3549
|
-
const parent =
|
|
3817
|
+
const parent = path6.dirname(current);
|
|
3550
3818
|
if (parent === current || parent === fsRoot)
|
|
3551
3819
|
break;
|
|
3552
|
-
const parentCargoPath =
|
|
3820
|
+
const parentCargoPath = path6.join(parent, "Cargo.toml");
|
|
3553
3821
|
const parentCargoContent = await readTextFileOrUndefined(parentCargoPath);
|
|
3554
3822
|
if (parentCargoContent !== void 0 && hasCargoWorkspaceTable(parentCargoContent)) {
|
|
3555
3823
|
if (cargoWorkspaceDeclaresMember(parentCargoContent, parent, root)) {
|
|
@@ -3577,9 +3845,9 @@ async function declaresMavenModule(parentDir, parentPomPath, childDir) {
|
|
|
3577
3845
|
const modulesBlock = content.match(/<modules>([\s\S]*?)<\/modules>/);
|
|
3578
3846
|
if (!modulesBlock)
|
|
3579
3847
|
return false;
|
|
3580
|
-
const resolvedChild =
|
|
3848
|
+
const resolvedChild = path6.resolve(childDir);
|
|
3581
3849
|
for (const match of modulesBlock[1].matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)) {
|
|
3582
|
-
if (pathsEqual(
|
|
3850
|
+
if (pathsEqual(path6.resolve(parentDir, match[1]), resolvedChild))
|
|
3583
3851
|
return true;
|
|
3584
3852
|
}
|
|
3585
3853
|
return false;
|
|
@@ -3603,15 +3871,15 @@ function JavaWorkspaceRoot() {
|
|
|
3603
3871
|
const stop = sessionHoistCeiling(sessionCwd, file);
|
|
3604
3872
|
let current = root;
|
|
3605
3873
|
let lastHop = root;
|
|
3606
|
-
const fsRoot =
|
|
3874
|
+
const fsRoot = path6.parse(current).root;
|
|
3607
3875
|
while (true) {
|
|
3608
3876
|
if (stop !== void 0 && current === stop)
|
|
3609
3877
|
break;
|
|
3610
|
-
const parent =
|
|
3878
|
+
const parent = path6.dirname(current);
|
|
3611
3879
|
if (parent === current || parent === fsRoot)
|
|
3612
3880
|
break;
|
|
3613
3881
|
if (await markerExists(parent, "pom.xml")) {
|
|
3614
|
-
const parentPom =
|
|
3882
|
+
const parentPom = path6.join(parent, "pom.xml");
|
|
3615
3883
|
if (!await declaresMavenModule(parent, parentPom, lastHop))
|
|
3616
3884
|
break;
|
|
3617
3885
|
current = parent;
|
|
@@ -3626,9 +3894,11 @@ function JavaWorkspaceRoot() {
|
|
|
3626
3894
|
var RustServer = {
|
|
3627
3895
|
id: "rust",
|
|
3628
3896
|
idleEviction: "unmeasured",
|
|
3897
|
+
role: "language",
|
|
3629
3898
|
// Measured (#3750): rust-analyzer answers an empty result for a detached file.
|
|
3630
3899
|
requiresProjectRoot: true,
|
|
3631
3900
|
name: "rust-analyzer",
|
|
3901
|
+
executesProjectCode: true,
|
|
3632
3902
|
extensions: KIND_EXTENSIONS["rust"],
|
|
3633
3903
|
// No FileDirRoot fallback (#201): rust-analyzer is a heavy workspace server
|
|
3634
3904
|
// that is useless without a Cargo manifest. With the fallback, every .rs file
|
|
@@ -3660,7 +3930,9 @@ var RustServer = {
|
|
|
3660
3930
|
var RubyServer = {
|
|
3661
3931
|
id: "ruby",
|
|
3662
3932
|
idleEviction: "unmeasured",
|
|
3933
|
+
role: "language",
|
|
3663
3934
|
name: "Ruby LSP",
|
|
3935
|
+
executesProjectCode: true,
|
|
3664
3936
|
extensions: KIND_EXTENSIONS["ruby"],
|
|
3665
3937
|
root: RootWithFallback(PriorityRoot([["Gemfile", ".ruby-version"], [".git"]])),
|
|
3666
3938
|
// Ruby LSP may need extra time to finish composed-bundle setup before it can
|
|
@@ -3697,6 +3969,7 @@ var RubyServer = {
|
|
|
3697
3969
|
var PHPServer = {
|
|
3698
3970
|
id: "php",
|
|
3699
3971
|
idleEviction: "transparent",
|
|
3972
|
+
role: "language",
|
|
3700
3973
|
name: "Intelephense",
|
|
3701
3974
|
extensions: KIND_EXTENSIONS["php"],
|
|
3702
3975
|
root: RootWithFallback(createRootDetector(["composer.json", "composer.lock"])),
|
|
@@ -3712,17 +3985,17 @@ var PHPServer = {
|
|
|
3712
3985
|
return {
|
|
3713
3986
|
...result,
|
|
3714
3987
|
initialization: {
|
|
3715
|
-
storagePath:
|
|
3988
|
+
storagePath: path6.join(getGlobalPiLensDir(), "intelephense")
|
|
3716
3989
|
}
|
|
3717
3990
|
};
|
|
3718
3991
|
}
|
|
3719
3992
|
};
|
|
3720
3993
|
function buildPsesArgs(bundleDir) {
|
|
3721
|
-
const script =
|
|
3722
|
-
const sessionDir =
|
|
3994
|
+
const script = path6.join(bundleDir, "PowerShellEditorServices", "Start-EditorServices.ps1");
|
|
3995
|
+
const sessionDir = path6.join(getGlobalPiLensDir(), "pses", `${process.pid}-${Date.now()}`);
|
|
3723
3996
|
mkdirSync2(sessionDir, { recursive: true });
|
|
3724
|
-
const logPath =
|
|
3725
|
-
const sessionDetailsPath =
|
|
3997
|
+
const logPath = path6.join(sessionDir, "pses.log");
|
|
3998
|
+
const sessionDetailsPath = path6.join(sessionDir, "session.json");
|
|
3726
3999
|
return [
|
|
3727
4000
|
"-NoLogo",
|
|
3728
4001
|
"-NoProfile",
|
|
@@ -3754,7 +4027,9 @@ function buildPsesArgs(bundleDir) {
|
|
|
3754
4027
|
var PowerShellServer = {
|
|
3755
4028
|
id: "powershell",
|
|
3756
4029
|
idleEviction: "unmeasured",
|
|
4030
|
+
role: "language",
|
|
3757
4031
|
name: "PowerShell Editor Services",
|
|
4032
|
+
executesProjectCode: true,
|
|
3758
4033
|
extensions: KIND_EXTENSIONS["powershell"],
|
|
3759
4034
|
// Index at the workspace (script modules reference siblings); fall back to the
|
|
3760
4035
|
// file dir.
|
|
@@ -3771,9 +4046,11 @@ var PowerShellServer = {
|
|
|
3771
4046
|
var CSharpServer = {
|
|
3772
4047
|
id: "csharp",
|
|
3773
4048
|
idleEviction: "unmeasured",
|
|
4049
|
+
role: "language",
|
|
3774
4050
|
// Documented (#3750): csharp-ls needs a solution or project.
|
|
3775
4051
|
requiresProjectRoot: true,
|
|
3776
4052
|
name: "csharp-ls",
|
|
4053
|
+
executesProjectCode: true,
|
|
3777
4054
|
extensions: KIND_EXTENSIONS["csharp"],
|
|
3778
4055
|
// No FileDirRoot fallback (#201): csharp-ls is a workspace server and should
|
|
3779
4056
|
// not spawn once per source directory before a .sln/.csproj exists. Glob root
|
|
@@ -3797,6 +4074,7 @@ var CSharpServer = {
|
|
|
3797
4074
|
var OmniSharpServer = createInteractiveServer({
|
|
3798
4075
|
id: "omnisharp",
|
|
3799
4076
|
name: "OmniSharp",
|
|
4077
|
+
executesProjectCode: true,
|
|
3800
4078
|
// Documented (#3750): OmniSharp needs a solution or project.
|
|
3801
4079
|
requiresProjectRoot: true,
|
|
3802
4080
|
fallbackFor: "csharp",
|
|
@@ -3809,9 +4087,11 @@ var OmniSharpServer = createInteractiveServer({
|
|
|
3809
4087
|
var FSharpServer = {
|
|
3810
4088
|
id: "fsharp",
|
|
3811
4089
|
idleEviction: "unmeasured",
|
|
4090
|
+
role: "language",
|
|
3812
4091
|
// Documented (#3750): FSAutocomplete needs a project.
|
|
3813
4092
|
requiresProjectRoot: true,
|
|
3814
4093
|
name: "FSAutocomplete",
|
|
4094
|
+
executesProjectCode: true,
|
|
3815
4095
|
extensions: KIND_EXTENSIONS["fsharp"],
|
|
3816
4096
|
root: createRootDetector([...DOTNET_FSHARP_ROOT_MARKERS]),
|
|
3817
4097
|
async spawn(root, options) {
|
|
@@ -3831,6 +4111,7 @@ var FSharpServer = {
|
|
|
3831
4111
|
var JavaServer = createInteractiveServer({
|
|
3832
4112
|
id: "java",
|
|
3833
4113
|
name: "JDT Language Server",
|
|
4114
|
+
executesProjectCode: true,
|
|
3834
4115
|
extensions: KIND_EXTENSIONS["java"],
|
|
3835
4116
|
root: RootWithFallback(JavaWorkspaceRoot()),
|
|
3836
4117
|
language: "java",
|
|
@@ -3841,7 +4122,9 @@ var JavaServer = createInteractiveServer({
|
|
|
3841
4122
|
var KotlinServer = {
|
|
3842
4123
|
id: "kotlin",
|
|
3843
4124
|
idleEviction: "unmeasured",
|
|
4125
|
+
role: "language",
|
|
3844
4126
|
name: "Kotlin Language Server",
|
|
4127
|
+
executesProjectCode: true,
|
|
3845
4128
|
extensions: KIND_EXTENSIONS["kotlin"],
|
|
3846
4129
|
root: RootWithFallback(createRootDetector(["build.gradle.kts", "build.gradle", "pom.xml"])),
|
|
3847
4130
|
async spawn(root, options) {
|
|
@@ -3857,9 +4140,26 @@ var KotlinServer = {
|
|
|
3857
4140
|
}, options?.allowInstall);
|
|
3858
4141
|
}
|
|
3859
4142
|
};
|
|
4143
|
+
var LeanServer = createInteractiveServer({
|
|
4144
|
+
id: "lean",
|
|
4145
|
+
name: "Lean 4 Language Server",
|
|
4146
|
+
extensions: KIND_EXTENSIONS.lean,
|
|
4147
|
+
root: RootWithFallback(createRootDetector([...LEAN_ROOT_MARKERS])),
|
|
4148
|
+
language: "lean",
|
|
4149
|
+
// Documented (#3750): `lake serve` analyses a file only when a Lake project
|
|
4150
|
+
// roots it; a root-fallback empty answer is unconfirmed, not clean.
|
|
4151
|
+
requiresProjectRoot: true,
|
|
4152
|
+
// `lake serve` loads and interprets the project's `lakefile.lean` and its
|
|
4153
|
+
// imported build scripts, so it executes project-owned code: refuse it until
|
|
4154
|
+
// the host grants project trust (#4269).
|
|
4155
|
+
executesProjectCode: true,
|
|
4156
|
+
command: "lake",
|
|
4157
|
+
args: ["serve"]
|
|
4158
|
+
});
|
|
3860
4159
|
var SwiftServer = createInteractiveServer({
|
|
3861
4160
|
id: "swift",
|
|
3862
4161
|
name: "SourceKit-LSP",
|
|
4162
|
+
executesProjectCode: true,
|
|
3863
4163
|
extensions: KIND_EXTENSIONS["swift"],
|
|
3864
4164
|
root: createRootDetector(["Package.swift"]),
|
|
3865
4165
|
language: "swift",
|
|
@@ -3867,6 +4167,7 @@ var SwiftServer = createInteractiveServer({
|
|
|
3867
4167
|
});
|
|
3868
4168
|
var DartServer = createInteractiveServer({
|
|
3869
4169
|
id: "dart",
|
|
4170
|
+
executesProjectCode: true,
|
|
3870
4171
|
name: "Dart Analysis Server",
|
|
3871
4172
|
extensions: KIND_EXTENSIONS["dart"],
|
|
3872
4173
|
root: RootWithFallback(createRootDetector(["pubspec.yaml"])),
|
|
@@ -3880,6 +4181,9 @@ function createTreeBinaryServer(spec) {
|
|
|
3880
4181
|
name: spec.name,
|
|
3881
4182
|
extensions: spec.extensions,
|
|
3882
4183
|
idleEviction: spec.idleEviction ?? "unmeasured",
|
|
4184
|
+
// The spec declares no role, so the factory applies the stated default
|
|
4185
|
+
// (#1488) — see `createInteractiveServer`.
|
|
4186
|
+
role: DEFAULT_LSP_SERVER_ROLE,
|
|
3883
4187
|
root: spec.root,
|
|
3884
4188
|
spawn(root, options) {
|
|
3885
4189
|
return resolveAndLaunchTreeBinary({
|
|
@@ -3917,7 +4221,9 @@ var CppServer = createTreeBinaryServer({
|
|
|
3917
4221
|
});
|
|
3918
4222
|
var ZigServer = {
|
|
3919
4223
|
id: "zig",
|
|
4224
|
+
executesProjectCode: true,
|
|
3920
4225
|
idleEviction: "unmeasured",
|
|
4226
|
+
role: "language",
|
|
3921
4227
|
name: "ZLS",
|
|
3922
4228
|
extensions: KIND_EXTENSIONS["zig"],
|
|
3923
4229
|
root: RootWithFallback(createRootDetector(["build.zig"])),
|
|
@@ -3933,6 +4239,7 @@ var ZigServer = {
|
|
|
3933
4239
|
var HaskellServer = createInteractiveServer({
|
|
3934
4240
|
id: "haskell",
|
|
3935
4241
|
name: "Haskell Language Server",
|
|
4242
|
+
executesProjectCode: true,
|
|
3936
4243
|
extensions: KIND_EXTENSIONS["haskell"],
|
|
3937
4244
|
root: createRootDetector(["stack.yaml", "cabal.project", "*.cabal"]),
|
|
3938
4245
|
language: "haskell",
|
|
@@ -3942,6 +4249,7 @@ var HaskellServer = createInteractiveServer({
|
|
|
3942
4249
|
var ElixirServer = createInteractiveServer({
|
|
3943
4250
|
id: "elixir",
|
|
3944
4251
|
name: "ElixirLS",
|
|
4252
|
+
executesProjectCode: true,
|
|
3945
4253
|
extensions: KIND_EXTENSIONS["elixir"],
|
|
3946
4254
|
root: RootWithFallback(createRootDetector(["mix.exs"])),
|
|
3947
4255
|
language: "elixir",
|
|
@@ -3950,7 +4258,9 @@ var ElixirServer = createInteractiveServer({
|
|
|
3950
4258
|
var ElixirExpertServer = {
|
|
3951
4259
|
id: "expert",
|
|
3952
4260
|
idleEviction: "unmeasured",
|
|
4261
|
+
role: "language",
|
|
3953
4262
|
name: "Expert",
|
|
4263
|
+
executesProjectCode: true,
|
|
3954
4264
|
fallbackFor: "elixir",
|
|
3955
4265
|
extensions: KIND_EXTENSIONS["elixir"],
|
|
3956
4266
|
root: RootWithFallback(createRootDetector(["mix.exs"])),
|
|
@@ -3968,6 +4278,7 @@ var ElixirExpertServer = {
|
|
|
3968
4278
|
var GleamServer = {
|
|
3969
4279
|
id: "gleam",
|
|
3970
4280
|
idleEviction: "unmeasured",
|
|
4281
|
+
role: "language",
|
|
3971
4282
|
name: "Gleam LSP",
|
|
3972
4283
|
extensions: KIND_EXTENSIONS["gleam"],
|
|
3973
4284
|
root: RootWithFallback(createRootDetector(["gleam.toml"])),
|
|
@@ -3982,7 +4293,9 @@ var GleamServer = {
|
|
|
3982
4293
|
};
|
|
3983
4294
|
var TinymistServer = {
|
|
3984
4295
|
id: "tinymist",
|
|
4296
|
+
executesProjectCode: true,
|
|
3985
4297
|
idleEviction: "unmeasured",
|
|
4298
|
+
role: "language",
|
|
3986
4299
|
name: "Tinymist",
|
|
3987
4300
|
extensions: extensionsForLanguage("typst"),
|
|
3988
4301
|
root: RootWithFallback(createRootDetector(["typst.toml", ".git"])),
|
|
@@ -3999,6 +4312,7 @@ var TinymistServer = {
|
|
|
3999
4312
|
var MarksmanServer = {
|
|
4000
4313
|
id: "marksman",
|
|
4001
4314
|
idleEviction: "transparent",
|
|
4315
|
+
role: "language",
|
|
4002
4316
|
name: "Marksman",
|
|
4003
4317
|
extensions: KIND_EXTENSIONS["markdown"],
|
|
4004
4318
|
// Index at the workspace root so cross-file checks (broken intra-repo links,
|
|
@@ -4016,6 +4330,7 @@ var MarksmanServer = {
|
|
|
4016
4330
|
};
|
|
4017
4331
|
var OCamlServer = createInteractiveServer({
|
|
4018
4332
|
id: "ocaml",
|
|
4333
|
+
executesProjectCode: true,
|
|
4019
4334
|
name: "ocamllsp",
|
|
4020
4335
|
extensions: KIND_EXTENSIONS["ocaml"],
|
|
4021
4336
|
root: createRootDetector(["dune-project", "opam"]),
|
|
@@ -4024,7 +4339,9 @@ var OCamlServer = createInteractiveServer({
|
|
|
4024
4339
|
});
|
|
4025
4340
|
var ClojureServer = {
|
|
4026
4341
|
id: "clojure",
|
|
4342
|
+
executesProjectCode: true,
|
|
4027
4343
|
idleEviction: "transparent",
|
|
4344
|
+
role: "language",
|
|
4028
4345
|
name: "Clojure LSP",
|
|
4029
4346
|
extensions: KIND_EXTENSIONS["clojure"],
|
|
4030
4347
|
root: createRootDetector(["deps.edn", "project.clj"]),
|
|
@@ -4040,6 +4357,7 @@ var ClojureServer = {
|
|
|
4040
4357
|
var CueServer = {
|
|
4041
4358
|
id: "cue",
|
|
4042
4359
|
idleEviction: "unmeasured",
|
|
4360
|
+
role: "language",
|
|
4043
4361
|
name: "CUE Language Server",
|
|
4044
4362
|
extensions: KIND_EXTENSIONS["cue"],
|
|
4045
4363
|
root: RootWithFallback(createRootDetector(["cue.mod", ".git"])),
|
|
@@ -4054,7 +4372,9 @@ var CueServer = {
|
|
|
4054
4372
|
};
|
|
4055
4373
|
var TerraformServer = {
|
|
4056
4374
|
id: "terraform",
|
|
4375
|
+
executesProjectCode: true,
|
|
4057
4376
|
idleEviction: "unmeasured",
|
|
4377
|
+
role: "language",
|
|
4058
4378
|
name: "Terraform LSP",
|
|
4059
4379
|
extensions: KIND_EXTENSIONS["terraform"],
|
|
4060
4380
|
root: RootWithFallback(createRootDetector([".terraform.lock.hcl", ".terraform"])),
|
|
@@ -4069,6 +4389,7 @@ var TerraformServer = {
|
|
|
4069
4389
|
};
|
|
4070
4390
|
var NixServer = createInteractiveServer({
|
|
4071
4391
|
id: "nix",
|
|
4392
|
+
executesProjectCode: true,
|
|
4072
4393
|
name: "nixd",
|
|
4073
4394
|
extensions: KIND_EXTENSIONS["nix"],
|
|
4074
4395
|
root: createRootDetector(["flake.nix"]),
|
|
@@ -4078,6 +4399,7 @@ var NixServer = createInteractiveServer({
|
|
|
4078
4399
|
var BashServer = {
|
|
4079
4400
|
id: "bash",
|
|
4080
4401
|
idleEviction: "transparent",
|
|
4402
|
+
role: "language",
|
|
4081
4403
|
name: "Bash Language Server",
|
|
4082
4404
|
// #3968: narrowed from [".bash", ".sh", ".zsh"] — bash-language-server does
|
|
4083
4405
|
// not support zsh (its own analyzer refuses the dialect), and its ≥5.7.0
|
|
@@ -4121,6 +4443,7 @@ var ShuckServer = createInteractiveServer({
|
|
|
4121
4443
|
var FishServer = {
|
|
4122
4444
|
id: "fish",
|
|
4123
4445
|
idleEviction: "transparent",
|
|
4446
|
+
role: "language",
|
|
4124
4447
|
name: "Fish Language Server",
|
|
4125
4448
|
extensions: KIND_EXTENSIONS["fish"],
|
|
4126
4449
|
root: RootWithFallback(createRootDetector([".git"])),
|
|
@@ -4135,7 +4458,9 @@ var FishServer = {
|
|
|
4135
4458
|
};
|
|
4136
4459
|
var CMakeServer = {
|
|
4137
4460
|
id: "cmake",
|
|
4461
|
+
executesProjectCode: true,
|
|
4138
4462
|
idleEviction: "unmeasured",
|
|
4463
|
+
role: "language",
|
|
4139
4464
|
name: "CMake Language Server",
|
|
4140
4465
|
// CMake's canonical project file has no .cmake suffix. The configured-server
|
|
4141
4466
|
// matcher supports exact basenames as well as extensions.
|
|
@@ -4152,7 +4477,8 @@ var CMakeServer = {
|
|
|
4152
4477
|
};
|
|
4153
4478
|
var DockerServer = {
|
|
4154
4479
|
id: "docker",
|
|
4155
|
-
idleEviction: "
|
|
4480
|
+
idleEviction: "transparent",
|
|
4481
|
+
role: "language",
|
|
4156
4482
|
name: "Dockerfile Language Server",
|
|
4157
4483
|
extensions: [".dockerfile", "Dockerfile"],
|
|
4158
4484
|
root: RootWithFallback(PriorityRoot([
|
|
@@ -4176,6 +4502,7 @@ var DockerServer = {
|
|
|
4176
4502
|
var DockerOfficialServer = {
|
|
4177
4503
|
id: "docker-official",
|
|
4178
4504
|
idleEviction: "unmeasured",
|
|
4505
|
+
role: "language",
|
|
4179
4506
|
name: "Docker Language Server (official)",
|
|
4180
4507
|
fallbackFor: "docker",
|
|
4181
4508
|
extensions: [".dockerfile", "Dockerfile"],
|
|
@@ -4199,6 +4526,7 @@ var DockerOfficialServer = {
|
|
|
4199
4526
|
var YamlServer = {
|
|
4200
4527
|
id: "yaml",
|
|
4201
4528
|
idleEviction: "transparent",
|
|
4529
|
+
role: "language",
|
|
4202
4530
|
name: "YAML Language Server",
|
|
4203
4531
|
extensions: KIND_EXTENSIONS["yaml"],
|
|
4204
4532
|
root: RootWithFallback(PriorityRoot([
|
|
@@ -4216,7 +4544,8 @@ var YamlServer = {
|
|
|
4216
4544
|
};
|
|
4217
4545
|
var JsonServer = {
|
|
4218
4546
|
id: "json",
|
|
4219
|
-
idleEviction: "
|
|
4547
|
+
idleEviction: "transparent",
|
|
4548
|
+
role: "language",
|
|
4220
4549
|
name: "VSCode JSON Language Server",
|
|
4221
4550
|
extensions: KIND_EXTENSIONS["json"],
|
|
4222
4551
|
root: RootWithFallback(WorkspacePriorityRoot([
|
|
@@ -4242,6 +4571,7 @@ var JsonServer = {
|
|
|
4242
4571
|
var HtmlServer = {
|
|
4243
4572
|
id: "html",
|
|
4244
4573
|
idleEviction: "transparent",
|
|
4574
|
+
role: "language",
|
|
4245
4575
|
name: "VSCode HTML Language Server",
|
|
4246
4576
|
extensions: KIND_EXTENSIONS["html"],
|
|
4247
4577
|
root: RootWithFallback(IgnoreHomeRoot(PriorityRoot([["package.json", "index.html", "vite.config.ts"]]))),
|
|
@@ -4257,6 +4587,7 @@ var HtmlServer = {
|
|
|
4257
4587
|
var TomlServer = {
|
|
4258
4588
|
id: "toml",
|
|
4259
4589
|
idleEviction: "unmeasured",
|
|
4590
|
+
role: "language",
|
|
4260
4591
|
name: "Taplo",
|
|
4261
4592
|
extensions: KIND_EXTENSIONS["toml"],
|
|
4262
4593
|
root: RootWithFallback(PriorityRoot([["pyproject.toml", "Cargo.toml", "taplo.toml"], [".git"]])),
|
|
@@ -4272,6 +4603,7 @@ var TomlServer = {
|
|
|
4272
4603
|
var PrismaServer = {
|
|
4273
4604
|
id: "prisma",
|
|
4274
4605
|
idleEviction: "transparent",
|
|
4606
|
+
role: "language",
|
|
4275
4607
|
name: "Prisma Language Server",
|
|
4276
4608
|
extensions: KIND_EXTENSIONS["prisma"],
|
|
4277
4609
|
root: RootWithFallback(createRootDetector(["prisma/schema.prisma", "schema.prisma"])),
|
|
@@ -4297,7 +4629,9 @@ var PrismaServer = {
|
|
|
4297
4629
|
};
|
|
4298
4630
|
var VueServer = {
|
|
4299
4631
|
id: "vue",
|
|
4632
|
+
executesProjectCode: true,
|
|
4300
4633
|
idleEviction: "unmeasured",
|
|
4634
|
+
role: "language",
|
|
4301
4635
|
name: "Vue Language Server",
|
|
4302
4636
|
extensions: [".vue"],
|
|
4303
4637
|
root: RootWithFallback(IgnoreHomeRoot(createRootDetector([
|
|
@@ -4318,9 +4652,9 @@ var VueServer = {
|
|
|
4318
4652
|
clientWaitTimeoutMs: 3e4,
|
|
4319
4653
|
initializeTimeoutMs: 3e4,
|
|
4320
4654
|
async spawn(root, options) {
|
|
4321
|
-
const tsserverPath = await findTsserverPath(root, options?.allowInstall);
|
|
4322
|
-
const hasPackageJson = existsSync3(
|
|
4323
|
-
const hasNodeModules = existsSync3(
|
|
4655
|
+
const tsserverPath = await findTsserverPath(root, options?.allowInstall, options);
|
|
4656
|
+
const hasPackageJson = existsSync3(path6.join(root, "package.json"));
|
|
4657
|
+
const hasNodeModules = existsSync3(path6.join(root, "node_modules"));
|
|
4324
4658
|
if (hasPackageJson && !hasNodeModules) {
|
|
4325
4659
|
logSessionStart(`lsp vue: node_modules missing in ${root} \u2014 Vue navigation may be limited. Run: npm install (or pnpm/yarn install) in this project.`);
|
|
4326
4660
|
}
|
|
@@ -4335,13 +4669,15 @@ var VueServer = {
|
|
|
4335
4669
|
return {
|
|
4336
4670
|
process: proc.process,
|
|
4337
4671
|
source: proc.source,
|
|
4338
|
-
initialization: tsserverPath ? { typescript: { tsdk:
|
|
4672
|
+
initialization: tsserverPath ? { typescript: { tsdk: path6.dirname(tsserverPath) } } : void 0
|
|
4339
4673
|
};
|
|
4340
4674
|
}
|
|
4341
4675
|
};
|
|
4342
4676
|
var SvelteServer = {
|
|
4343
4677
|
id: "svelte",
|
|
4678
|
+
executesProjectCode: true,
|
|
4344
4679
|
idleEviction: "unmeasured",
|
|
4680
|
+
role: "language",
|
|
4345
4681
|
name: "Svelte Language Server",
|
|
4346
4682
|
extensions: [".svelte"],
|
|
4347
4683
|
root: RootWithFallback(IgnoreHomeRoot(createRootDetector([
|
|
@@ -4360,7 +4696,7 @@ var SvelteServer = {
|
|
|
4360
4696
|
clientWaitTimeoutMs: 2e4,
|
|
4361
4697
|
initializeTimeoutMs: 2e4,
|
|
4362
4698
|
async spawn(root, options) {
|
|
4363
|
-
const tsserverPath = await findTsserverPath(root, options?.allowInstall);
|
|
4699
|
+
const tsserverPath = await findTsserverPath(root, options?.allowInstall, options);
|
|
4364
4700
|
const proc = await resolveAndLaunch({
|
|
4365
4701
|
candidates: [
|
|
4366
4702
|
...nodeBinCandidates(root, "svelteserver"),
|
|
@@ -4375,13 +4711,14 @@ var SvelteServer = {
|
|
|
4375
4711
|
return {
|
|
4376
4712
|
process: proc.process,
|
|
4377
4713
|
source: proc.source,
|
|
4378
|
-
initialization: tsserverPath ? { typescript: { tsdk:
|
|
4714
|
+
initialization: tsserverPath ? { typescript: { tsdk: path6.dirname(tsserverPath) } } : void 0
|
|
4379
4715
|
};
|
|
4380
4716
|
}
|
|
4381
4717
|
};
|
|
4382
4718
|
var CssServer = {
|
|
4383
4719
|
id: "css",
|
|
4384
4720
|
idleEviction: "transparent",
|
|
4721
|
+
role: "language",
|
|
4385
4722
|
name: "CSS Language Server",
|
|
4386
4723
|
extensions: KIND_EXTENSIONS["css"],
|
|
4387
4724
|
root: RootWithFallback(IgnoreHomeRoot(PriorityRoot([
|
|
@@ -4439,8 +4776,8 @@ function opengrepInitialization(root) {
|
|
|
4439
4776
|
var OpengrepServer = {
|
|
4440
4777
|
id: "opengrep",
|
|
4441
4778
|
idleEviction: "transparent",
|
|
4442
|
-
name: "Opengrep Security Scanner",
|
|
4443
4779
|
role: "auxiliary",
|
|
4780
|
+
name: "Opengrep Security Scanner",
|
|
4444
4781
|
extensions: OPENGREP_EXTENSIONS,
|
|
4445
4782
|
// Stable per-repo root so ONE warm server serves the whole project (a
|
|
4446
4783
|
// per-directory root would spawn a fresh server — and re-pay rule load —
|
|
@@ -4489,8 +4826,8 @@ var AST_GREP_EXTENSIONS = Array.from(new Set(AST_GREP_KINDS.flatMap((k) => KIND_
|
|
|
4489
4826
|
var AstGrepServer = {
|
|
4490
4827
|
id: "ast-grep",
|
|
4491
4828
|
idleEviction: "unmeasured",
|
|
4492
|
-
name: "ast-grep structural linter",
|
|
4493
4829
|
role: "auxiliary",
|
|
4830
|
+
name: "ast-grep structural linter",
|
|
4494
4831
|
extensions: AST_GREP_EXTENSIONS,
|
|
4495
4832
|
// Attaches everywhere (#239 Phase 2): prefer a project `sgconfig.y[a]ml` root,
|
|
4496
4833
|
// else the repo root (.git) or cwd — like Opengrep. When there's no project
|
|
@@ -4506,6 +4843,13 @@ var AstGrepServer = {
|
|
|
4506
4843
|
// the whole file on every didOpen, so it absorbs a sweep more slowly than the
|
|
4507
4844
|
// other scanners — hold it to half the shared default.
|
|
4508
4845
|
notifyInflightLimit: 4,
|
|
4846
|
+
// #1722, measured against the real binary over 30 repository files rather
|
|
4847
|
+
// than assumed: ast-grep-lsp is tower-lsp-server and drains its message
|
|
4848
|
+
// stream in order on one task, so the notify barrier's round-trip proves
|
|
4849
|
+
// the backlog was scanned. Declared here because the barrier's soundness
|
|
4850
|
+
// rests on it (#1756 stage 1); the evidence table is on
|
|
4851
|
+
// `LspReplyOrdering`.
|
|
4852
|
+
replyOrdering: "single-task-ordered",
|
|
4509
4853
|
// First scan of a session compiles the rules.
|
|
4510
4854
|
initializeTimeoutMs: 15e3,
|
|
4511
4855
|
async spawn(root, options) {
|
|
@@ -4531,8 +4875,8 @@ var ZIZMOR_EXTENSIONS = KIND_EXTENSIONS["yaml"];
|
|
|
4531
4875
|
var ZizmorServer = {
|
|
4532
4876
|
id: "zizmor",
|
|
4533
4877
|
idleEviction: "unmeasured",
|
|
4534
|
-
name: "zizmor Actions Security Scanner",
|
|
4535
4878
|
role: "auxiliary",
|
|
4879
|
+
name: "zizmor Actions Security Scanner",
|
|
4536
4880
|
extensions: ZIZMOR_EXTENSIONS,
|
|
4537
4881
|
pathFilter: isZizmorAuditTarget,
|
|
4538
4882
|
// Stable per-repo root so ONE warm server serves the whole project (like
|
|
@@ -4579,8 +4923,8 @@ function typosInitialization(root) {
|
|
|
4579
4923
|
var TyposServer = {
|
|
4580
4924
|
id: "typos",
|
|
4581
4925
|
idleEviction: "unmeasured",
|
|
4582
|
-
name: "typos Spell Checker",
|
|
4583
4926
|
role: "auxiliary",
|
|
4927
|
+
name: "typos Spell Checker",
|
|
4584
4928
|
extensions: TYPOS_EXTENSIONS,
|
|
4585
4929
|
// Stable per-repo root so ONE warm server serves the whole project (like the
|
|
4586
4930
|
// other auxiliaries) — typos.toml discovery is repo-relative.
|
|
@@ -4618,6 +4962,7 @@ var LSP_SERVERS = [
|
|
|
4618
4962
|
FSharpServer,
|
|
4619
4963
|
JavaServer,
|
|
4620
4964
|
KotlinServer,
|
|
4965
|
+
LeanServer,
|
|
4621
4966
|
SwiftServer,
|
|
4622
4967
|
DartServer,
|
|
4623
4968
|
LuaServer,
|
|
@@ -4656,11 +5001,67 @@ var LSP_SERVERS = [
|
|
|
4656
5001
|
ZizmorServer,
|
|
4657
5002
|
TyposServer
|
|
4658
5003
|
];
|
|
5004
|
+
function getServerById(id) {
|
|
5005
|
+
return LSP_SERVERS.find((server) => server.id === id);
|
|
5006
|
+
}
|
|
5007
|
+
|
|
5008
|
+
// dist/clients/lsp/session-roots.js
|
|
5009
|
+
import path7 from "node:path";
|
|
5010
|
+
var SESSION_ROOT_CAP = 128;
|
|
5011
|
+
var sessionRoots = new BoundedFifoMap(SESSION_ROOT_CAP);
|
|
5012
|
+
function noteEvictedRoots(evicted) {
|
|
5013
|
+
const roots = evicted.map(([root]) => root);
|
|
5014
|
+
if (roots.length > 0) {
|
|
5015
|
+
incrementDegradationCount({
|
|
5016
|
+
kind: "lsp-session-root-evicted",
|
|
5017
|
+
subject: `cap=${SESSION_ROOT_CAP}`,
|
|
5018
|
+
reason: `session root registry at capacity; will load the dropped root again on the next session start or tool call naming it (dropped: ${roots[0]})`
|
|
5019
|
+
});
|
|
5020
|
+
}
|
|
5021
|
+
return roots;
|
|
5022
|
+
}
|
|
5023
|
+
function registerSessionRoot(cwd) {
|
|
5024
|
+
const root = path7.resolve(cwd);
|
|
5025
|
+
if (sessionRoots.has(root))
|
|
5026
|
+
return [];
|
|
5027
|
+
return noteEvictedRoots(sessionRoots.set(root, void 0));
|
|
5028
|
+
}
|
|
5029
|
+
function setSessionRootConfig(cwd, config) {
|
|
5030
|
+
return noteEvictedRoots(sessionRoots.set(path7.resolve(cwd), config));
|
|
5031
|
+
}
|
|
5032
|
+
function sessionRootConfigEntries() {
|
|
5033
|
+
return sessionRoots;
|
|
5034
|
+
}
|
|
5035
|
+
function isSessionRootRegistered(cwd) {
|
|
5036
|
+
return sessionRoots.has(path7.resolve(cwd));
|
|
5037
|
+
}
|
|
5038
|
+
function shouldInitializeSessionRoot(cwd, readyRoots) {
|
|
5039
|
+
const normalized = path7.resolve(cwd);
|
|
5040
|
+
return !readyRoots.has(normalized) || !isSessionRootRegistered(normalized);
|
|
5041
|
+
}
|
|
5042
|
+
function isOutsideAllSessionRoots(filePath) {
|
|
5043
|
+
if (sessionRoots.size === 0)
|
|
5044
|
+
return false;
|
|
5045
|
+
const resolved = path7.resolve(filePath);
|
|
5046
|
+
for (const root of sessionRoots.keys()) {
|
|
5047
|
+
if (isSameOrWithin(root, resolved))
|
|
5048
|
+
return false;
|
|
5049
|
+
}
|
|
5050
|
+
return true;
|
|
5051
|
+
}
|
|
5052
|
+
function getSessionRootsForTelemetry(limit = 4) {
|
|
5053
|
+
return [...sessionRoots.keys()].sort((a, b) => Number(a > b) - Number(a < b)).slice(0, limit);
|
|
5054
|
+
}
|
|
4659
5055
|
|
|
4660
5056
|
export {
|
|
4661
5057
|
findLocalTyposConfig,
|
|
4662
5058
|
getAstGrepRuleSources,
|
|
5059
|
+
getAstGrepRuleFingerprint,
|
|
5060
|
+
isAuxiliary,
|
|
5061
|
+
serverTraits,
|
|
4663
5062
|
registerRunnerId,
|
|
5063
|
+
withLspProjectCodePermission,
|
|
5064
|
+
refuseUntrustedLspExecution,
|
|
4664
5065
|
BUILTIN_SERVER_RUNNER_COVERS,
|
|
4665
5066
|
describeRootFallback,
|
|
4666
5067
|
resolveLspServerCwd,
|
|
@@ -4673,6 +5074,7 @@ export {
|
|
|
4673
5074
|
isDirectLspCommandTemporarilyUnavailable,
|
|
4674
5075
|
resetClassicTsRepairGuard,
|
|
4675
5076
|
LSP_SERVERS,
|
|
5077
|
+
getServerById,
|
|
4676
5078
|
shouldInitializeSessionRoot,
|
|
4677
5079
|
isOutsideAllSessionRoots,
|
|
4678
5080
|
getSessionRootsForTelemetry,
|