@mrclrchtr/supi-lsp 11.3.0 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -17
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +3 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/src/declaration-level.ts +34 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +64 -28
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/semver/classes/range.js +2 -2
- package/node_modules/semver/internal/constants.js +30 -0
- package/node_modules/semver/internal/trim-comparator-whitespace.js +438 -0
- package/node_modules/semver/package.json +1 -1
- package/package.json +3 -3
- package/src/api.ts +2 -2
- package/src/client/client-diagnostic-capabilities.ts +13 -3
- package/src/client/client-diagnostics.ts +25 -9
- package/src/client/client-document-sync.ts +7 -5
- package/src/client/client-edit-capture.ts +258 -0
- package/src/client/client.ts +64 -11
- package/src/config/capabilities.ts +8 -0
- package/src/config/operation-support.ts +48 -79
- package/src/config/tsconfig-scope.ts +10 -0
- package/src/manager/manager-typescript-coverage.ts +118 -0
- package/src/manager/manager.ts +67 -3
- package/src/manager/typescript-file-local.ts +87 -0
- package/src/provider/lsp-refactor-provider.ts +21 -35
- package/src/provider/refactor-command-capture.ts +139 -0
- package/src/provider/refactor-planning.ts +202 -47
- package/src/provider/semantic-symbol-mapper.ts +22 -17
- package/src/session/route-boundary.ts +26 -0
- package/src/session/runtime-registry.ts +106 -16
- package/src/session/runtime-rename.ts +3 -0
- package/src/session/workspace-lsp-runtime.ts +22 -1
package/README.md
CHANGED
|
@@ -59,8 +59,8 @@ A configured route is not a ready server. Features depend on the active server,
|
|
|
59
59
|
| Hover, definitions, references, implementations, document/workspace symbols | Supported through the server's corresponding LSP methods; availability and coverage differ by server. |
|
|
60
60
|
| Diagnostics | Native pull, the eligible TypeScript request adapter, or ambient push. Push observation alone cannot confirm that a file is clean. See the diagnostic policy below. |
|
|
61
61
|
| `rename_symbol` | Requires server rename support and validated text edits; uses `prepareRename` when advertised. |
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
62
|
+
| `code_action` | Requires a code action of the requested `refactor*` kind for the range that produces validated text edits, directly or by capturing the one edit its command pushes. Names generated by the server appear unchanged in the plan. |
|
|
63
|
+
| `source_action` | Requires a code action of the requested `source*` kind for the whole document that produces validated text edits, directly or (for `source.organizeImports` and `source.fixAll`) by capturing the one edit its command pushes. |
|
|
64
64
|
|
|
65
65
|
The [operation-support model](src/config/operation-support.ts) separates server advertisement from SuPi planning limits. A server can advertise an action that SuPi cannot safely turn into a plan.
|
|
66
66
|
|
|
@@ -100,13 +100,13 @@ For example, select a compiler installed as `my-ts6` without changing the TLS co
|
|
|
100
100
|
- `code_health` and `/supi-ci-status` show the `native` or `tsserver` backend and resolved compiler version when known, separately from wrapper version. Manual/legacy-fallback launches have no inferred compiler identity. Missing versions remain unknown. Selection failures identify the package/root and a corrective action.
|
|
101
101
|
- Topmost-root collapsing remains unchanged. Mixed nested backends, Windows live qualification, dependency watchers, performance benchmarking, and full TLS/native feature parity are outside this change. Existing legacy TLS support is not deliberately removed.
|
|
102
102
|
|
|
103
|
-
Focused qualification
|
|
103
|
+
Focused qualification uses the native TypeScript 7 alias (`@typescript/native`), TLS, ordinary TypeScript 6, and `@typescript/typescript6` backed by `@typescript/old` → TypeScript 6. Exact versions come from the root `package.json` and lockfile; the wrapper's dependency range does not fix its compiler version, so the lockfile does. SuPi retains TS6 for its compiler-API dependency and legacy-server tests. Workspace typechecking and declaration builds use the native TS7 launcher directly to avoid ambiguity between the installed `tsc` binaries.
|
|
104
104
|
|
|
105
105
|
The required [Linux/macOS CI matrix](../../.github/workflows/ci.yml) keeps [selection/layout tests](__tests__/unit/typescript-launch.test.ts), [real native lifecycle tests](__tests__/integration/workspace-runtime.integration.typescript-native.test.ts), and [wrapper lifecycle tests](__tests__/integration/workspace-runtime.integration.typescript-launch.test.ts) separate from the [public TS/JS semantic matrix](../supi-code-intelligence/__tests__/acceptance/language-baseline-harness.ts). Required missing/unavailable behavior fails rather than skips. The matrix covers hover, definitions, references, meaningful implementations, document/workspace symbols, confirmed error → clean diagnostics, refresh, cross-file invalidation, Unicode-safe rename plan/apply and stale-plan rejection, and precise organize-imports. The TypeScript public matrix also checks unused-import removal, unchanged source during planning, stale-plan rejection, and preservation of unrelated text; native support is imports-only. Native TSX/JSX and module suffixes receive routing/synchronization checks rather than duplicate matrices. Existing stale-result and edit-safety suites remain in place.
|
|
106
106
|
|
|
107
107
|
[Bounded config comparisons](__tests__/integration/typescript-config-coverage.test.ts) compare TS6 and native TS7 `--showConfig` root-file coverage for TS/JS defaults, include/exclude, `allowJs`/`checkJs`, inherited patterns (including late-created files), and separate referenced projects. These cases found no false exclusion; filtering is unchanged. **Config coverage state is not TypeScript program membership**: imports may bring excluded files into a program, and references do not merge root-file lists.
|
|
108
108
|
|
|
109
|
-
Native
|
|
109
|
+
Native TypeScript 7 offers `source.removeUnusedImports` through the same safe plan/apply workflow ([#554](https://github.com/mrclrchtr/supi/issues/554)); it removes unused imports only, not arbitrary unused declarations. Native TypeScript 7 advertises no `refactor*` kinds, so `code_action` extraction is unavailable there; no TLS/native feature-parity claim is made. Only the pinned combinations are tested, not every stable TS7 release. Focused qualification passed on macOS arm64 (Node 24.22.1) and Linux arm64 (Debian container, Node 24.22.0), including the native/TS6 public TS/JS matrix. The unused-import follow-up has local macOS arm64 verification only; its Linux verification remains pending. The pinned Linux/macOS CI jobs remain pending until they run; this is not a qualification claim for the complete multi-language baseline.
|
|
110
110
|
|
|
111
111
|
### Java startup and project JDKs
|
|
112
112
|
|
|
@@ -320,21 +320,26 @@ Disable one language with `lsp.servers.<language>.enabled: false`. Use `/supi-ci
|
|
|
320
320
|
- explicit ready, pending, inactive, disabled, and unavailable registry states
|
|
321
321
|
- a `SemanticProvider` adapter for `supi-code-runtime`
|
|
322
322
|
- precise rename and code-action edit conversion
|
|
323
|
-
-
|
|
323
|
+
- code-action kind-prefix filters, exact-title selection, and standard lazy edit resolution
|
|
324
324
|
- negotiated operation support in project-server status
|
|
325
325
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
326
|
+
Code- and source-action planners request exactly the caller's kind with `only` and
|
|
327
|
+
match the returned `CodeAction.kind` or its dotted descendants, never the title.
|
|
328
|
+
Entries outside `only` are dropped before validation. Disabled actions never match;
|
|
329
|
+
an optional exact title narrows the matches. Edit-only actions are validated before
|
|
330
|
+
planning. One eligible command-only action (`refactor*`, `source.organizeImports*`,
|
|
331
|
+
`source.fixAll*`; a command the server lists when it lists any) runs once: SuPi
|
|
332
|
+
advertises `workspace.applyEdit`, refuses every pushed edit with `applied: false`,
|
|
333
|
+
and plans the single edit captured while the command runs or shortly after it
|
|
334
|
+
answers, even when the server then reports the command as failed because the
|
|
335
|
+
edit was refused (clangd does). A timed-out or cancelled command keeps refusing late edits until it
|
|
336
|
+
settles. Touched open documents are re-sent as full text under a new version.
|
|
337
|
+
Running a command may still change server-side state. Resource operations,
|
|
338
|
+
snippets, annotations, malformed actions, and stale responses stay unavailable. Distinct matching plans return an
|
|
339
|
+
ambiguous result with each candidate's kind and title instead of selecting the first
|
|
340
|
+
action. Rename uses `prepareRename` when the server advertises it and otherwise uses
|
|
341
|
+
direct standard rename. Code actions choose generated names; plans preview them as
|
|
342
|
+
the server returns them.
|
|
338
343
|
|
|
339
344
|
Rename responses that need additional document state can trigger one bounded discovery/enrollment retry. SuPi validates edit shape and canonical mutation paths, enrolls at most 64 affected files on the same route, and requests fresh edits. The first response is not a plan. Numeric versions must still match. A null version for an open document requires verified synchronized-content evidence; the plan retains the request fingerprint and client version. Missing snapshots, changed inputs, a larger follow-up edit set, and unsafe edits remain unavailable. Planning and apply revalidate these preconditions; no version is discarded to make an edit fit.
|
|
340
345
|
|
|
@@ -14,6 +14,7 @@ export type {
|
|
|
14
14
|
StructuralProvider,
|
|
15
15
|
StructuralResult,
|
|
16
16
|
} from "./capability/types.ts";
|
|
17
|
+
export { childDeclarationLevel } from "./declaration-level.ts";
|
|
17
18
|
export type {
|
|
18
19
|
CFamilyExtension,
|
|
19
20
|
CFamilyFileAssociationResolver,
|
|
@@ -50,7 +51,7 @@ export type {
|
|
|
50
51
|
CodeResult,
|
|
51
52
|
CodeSymbol,
|
|
52
53
|
ConfidenceMode,
|
|
53
|
-
|
|
54
|
+
DeclarationLevel,
|
|
54
55
|
DisambiguationCandidate,
|
|
55
56
|
DocumentCodeSymbol,
|
|
56
57
|
DocumentEditPrecondition,
|
|
@@ -59,6 +60,7 @@ export type {
|
|
|
59
60
|
ImportData,
|
|
60
61
|
NodeAtData,
|
|
61
62
|
OutlineData,
|
|
63
|
+
RefactorActionIdentity,
|
|
62
64
|
RefactorOperation,
|
|
63
65
|
RefactorRequest,
|
|
64
66
|
RefactorResult,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { DeclarationLevel } from "./types.ts";
|
|
2
|
+
|
|
3
|
+
/** Declarations whose body holds statements, so nested declarations are local to it. */
|
|
4
|
+
const FUNCTION_LIKE_KINDS = new Set(["function", "method", "constructor"]);
|
|
5
|
+
/** Bindings whose value may be a function (locals) or an object literal (members). */
|
|
6
|
+
const VALUE_BINDING_KINDS = new Set(["variable", "constant", "property", "field"]);
|
|
7
|
+
/** Kinds that name an entry of an object, type, or enum rather than a statement-level binding. */
|
|
8
|
+
const MEMBER_ENTRY_KINDS = new Set(["property", "field", "method", "enummember", "key", "event"]);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Level of a declaration reported directly inside `parent`.
|
|
12
|
+
*
|
|
13
|
+
* Inside a local declaration everything stays local. A function, method, or
|
|
14
|
+
* constructor makes its nested declarations local. A variable, constant,
|
|
15
|
+
* property, or field holds either a function body (nested bindings are local)
|
|
16
|
+
* or an object literal (nested properties and methods are members). Every
|
|
17
|
+
* other container — class, interface, enum, struct, namespace, module, or a
|
|
18
|
+
* document section — makes its nested declarations members.
|
|
19
|
+
*
|
|
20
|
+
* Kinds compare case-insensitively, so LSP SymbolKind names and Tree-sitter
|
|
21
|
+
* outline kinds share one rule.
|
|
22
|
+
*/
|
|
23
|
+
export function childDeclarationLevel(
|
|
24
|
+
parent: { readonly kind: string | null; readonly level: DeclarationLevel },
|
|
25
|
+
childKind: string | null,
|
|
26
|
+
): Exclude<DeclarationLevel, "top-level" | "unknown"> {
|
|
27
|
+
if (parent.level === "local") return "local";
|
|
28
|
+
const parentKind = parent.kind?.toLowerCase() ?? "";
|
|
29
|
+
if (FUNCTION_LIKE_KINDS.has(parentKind)) return "local";
|
|
30
|
+
if (VALUE_BINDING_KINDS.has(parentKind)) {
|
|
31
|
+
return MEMBER_ENTRY_KINDS.has(childKind?.toLowerCase() ?? "") ? "member" : "local";
|
|
32
|
+
}
|
|
33
|
+
return "member";
|
|
34
|
+
}
|
|
@@ -34,8 +34,16 @@ export interface SymbolAnchor {
|
|
|
34
34
|
character: number;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
/**
|
|
38
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Where a declaration sits within its file, as reported by a provider.
|
|
39
|
+
*
|
|
40
|
+
* - `top-level`: directly in the file, not inside another declaration.
|
|
41
|
+
* - `member`: directly inside a class, interface, enum, struct, namespace,
|
|
42
|
+
* module, or object literal (methods, fields, properties, enum members).
|
|
43
|
+
* - `local`: inside the body of a function, method, or constructor.
|
|
44
|
+
* - `unknown`: the provider reported a flat symbol list without hierarchy.
|
|
45
|
+
*/
|
|
46
|
+
export type DeclarationLevel = "top-level" | "member" | "local" | "unknown";
|
|
39
47
|
|
|
40
48
|
/**
|
|
41
49
|
* A discovered symbol / declaration.
|
|
@@ -54,7 +62,7 @@ export interface CodeSymbol {
|
|
|
54
62
|
file: string;
|
|
55
63
|
declarationAnchor: SymbolAnchor;
|
|
56
64
|
nameAnchor?: SymbolAnchor;
|
|
57
|
-
/** Named
|
|
65
|
+
/** Named enclosing declaration when reported; absence does not prove a top-level declaration. */
|
|
58
66
|
container?: string | null;
|
|
59
67
|
}
|
|
60
68
|
|
|
@@ -63,10 +71,10 @@ export interface CodeSymbol {
|
|
|
63
71
|
*
|
|
64
72
|
* `unknown` means the provider returned a flat observation without an actual
|
|
65
73
|
* hierarchy. A reported container name remains metadata and does not promote
|
|
66
|
-
* a flat observation to known
|
|
74
|
+
* a flat observation to a known level.
|
|
67
75
|
*/
|
|
68
76
|
export interface DocumentCodeSymbol extends CodeSymbol {
|
|
69
|
-
|
|
77
|
+
level: DeclarationLevel;
|
|
70
78
|
}
|
|
71
79
|
|
|
72
80
|
// ── Result types ───────────────────────────────────────────────────────
|
|
@@ -185,31 +193,53 @@ export interface WorkspaceEdit {
|
|
|
185
193
|
}
|
|
186
194
|
|
|
187
195
|
/**
|
|
188
|
-
*
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
| "rename_file"
|
|
195
|
-
| "move_file"
|
|
196
|
-
| "update_imports"
|
|
197
|
-
| "delete_dead_code";
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Operation-aware refactor planning request.
|
|
196
|
+
* Operation-aware refactor planning request. Each operation carries only the
|
|
197
|
+
* scope it needs:
|
|
198
|
+
*
|
|
199
|
+
* - `rename_symbol`: one symbol position and the new name.
|
|
200
|
+
* - `code_action`: one file range and a CodeActionKind prefix under `refactor`.
|
|
201
|
+
* - `source_action`: one whole file and a CodeActionKind prefix under `source`.
|
|
201
202
|
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* explicitly and honestly until shared workspace-edit resource ops exist.
|
|
203
|
+
* `kind` matches the requested kind and its dotted sub-kinds. `title`, when
|
|
204
|
+
* present, selects one action by its exact title.
|
|
205
205
|
*/
|
|
206
|
-
export
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
206
|
+
export type RefactorRequest =
|
|
207
|
+
| {
|
|
208
|
+
operation: "rename_symbol";
|
|
209
|
+
file: string;
|
|
210
|
+
position: CodePosition;
|
|
211
|
+
newName: string;
|
|
212
|
+
}
|
|
213
|
+
| {
|
|
214
|
+
operation: "code_action";
|
|
215
|
+
file: string;
|
|
216
|
+
range: SourceRange;
|
|
217
|
+
kind: string;
|
|
218
|
+
title?: string;
|
|
219
|
+
}
|
|
220
|
+
| {
|
|
221
|
+
operation: "source_action";
|
|
222
|
+
file: string;
|
|
223
|
+
kind: string;
|
|
224
|
+
title?: string;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/** Supported refactor operation names. */
|
|
228
|
+
export type RefactorOperation = RefactorRequest["operation"];
|
|
229
|
+
|
|
230
|
+
/** The code action selected for a precise code- or source-action plan. */
|
|
231
|
+
export interface RefactorActionIdentity {
|
|
232
|
+
/** Server-reported CodeActionKind. */
|
|
233
|
+
kind: string;
|
|
234
|
+
/** Server-reported action title. */
|
|
235
|
+
title: string;
|
|
236
|
+
/**
|
|
237
|
+
* How the edits were obtained: `edit` from the action itself (after
|
|
238
|
+
* `codeAction/resolve` when needed), or `captured-command` from the single
|
|
239
|
+
* `workspace/applyEdit` the server pushed while running the action's command.
|
|
240
|
+
* Captured edits were refused, never applied.
|
|
241
|
+
*/
|
|
242
|
+
provenance?: "edit" | "captured-command";
|
|
213
243
|
}
|
|
214
244
|
|
|
215
245
|
/**
|
|
@@ -220,6 +250,10 @@ export interface DisambiguationCandidate {
|
|
|
220
250
|
file?: string;
|
|
221
251
|
line?: number;
|
|
222
252
|
character?: number;
|
|
253
|
+
/** Server-reported CodeActionKind, for code-action candidates. */
|
|
254
|
+
kind?: string;
|
|
255
|
+
/** Exact action title to pass back as `title`, for code-action candidates. */
|
|
256
|
+
title?: string;
|
|
223
257
|
}
|
|
224
258
|
|
|
225
259
|
/**
|
|
@@ -233,6 +267,8 @@ export type RefactorResult =
|
|
|
233
267
|
| {
|
|
234
268
|
kind: "precise";
|
|
235
269
|
edits: WorkspaceEdit;
|
|
270
|
+
/** The selected code action, for code- and source-action plans. */
|
|
271
|
+
action?: RefactorActionIdentity;
|
|
236
272
|
/** Provider roots authorized by the semantic route. Consumers canonicalize before storage. */
|
|
237
273
|
authorizedMutationRoots: string[];
|
|
238
274
|
}
|
|
@@ -119,7 +119,7 @@ class Range {
|
|
|
119
119
|
debug('hyphen replace', range)
|
|
120
120
|
|
|
121
121
|
// `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
|
|
122
|
-
range = range
|
|
122
|
+
range = trimComparatorWhitespace(range)
|
|
123
123
|
debug('comparator trim', range)
|
|
124
124
|
|
|
125
125
|
// `~ 1.2.3` => `~1.2.3`
|
|
@@ -224,11 +224,11 @@ const parseOptions = require('../internal/parse-options')
|
|
|
224
224
|
const Comparator = require('./comparator')
|
|
225
225
|
const debug = require('../internal/debug')
|
|
226
226
|
const SemVer = require('./semver')
|
|
227
|
+
const trimComparatorWhitespace = require('../internal/trim-comparator-whitespace')
|
|
227
228
|
const {
|
|
228
229
|
safeRe: re,
|
|
229
230
|
src,
|
|
230
231
|
t,
|
|
231
|
-
comparatorTrimReplace,
|
|
232
232
|
tildeTrimReplace,
|
|
233
233
|
caretTrimReplace,
|
|
234
234
|
} = require('../internal/re')
|
|
@@ -15,6 +15,35 @@ const MAX_SAFE_COMPONENT_LENGTH = 16
|
|
|
15
15
|
// the shortest version with a build 0.0.0+BUILD.
|
|
16
16
|
const MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6
|
|
17
17
|
|
|
18
|
+
// ECMAScript whitespace and line terminators matched by \s.
|
|
19
|
+
const WHITESPACE_CHARACTERS = [
|
|
20
|
+
'\t',
|
|
21
|
+
'\n',
|
|
22
|
+
'\v',
|
|
23
|
+
'\f',
|
|
24
|
+
'\r',
|
|
25
|
+
' ',
|
|
26
|
+
'\u00a0',
|
|
27
|
+
'\u1680',
|
|
28
|
+
'\u2000',
|
|
29
|
+
'\u2001',
|
|
30
|
+
'\u2002',
|
|
31
|
+
'\u2003',
|
|
32
|
+
'\u2004',
|
|
33
|
+
'\u2005',
|
|
34
|
+
'\u2006',
|
|
35
|
+
'\u2007',
|
|
36
|
+
'\u2008',
|
|
37
|
+
'\u2009',
|
|
38
|
+
'\u200a',
|
|
39
|
+
'\u2028',
|
|
40
|
+
'\u2029',
|
|
41
|
+
'\u202f',
|
|
42
|
+
'\u205f',
|
|
43
|
+
'\u3000',
|
|
44
|
+
'\ufeff',
|
|
45
|
+
]
|
|
46
|
+
|
|
18
47
|
const RELEASE_TYPES = [
|
|
19
48
|
'major',
|
|
20
49
|
'premajor',
|
|
@@ -30,6 +59,7 @@ module.exports = {
|
|
|
30
59
|
MAX_SAFE_COMPONENT_LENGTH,
|
|
31
60
|
MAX_SAFE_BUILD_LENGTH,
|
|
32
61
|
MAX_SAFE_INTEGER,
|
|
62
|
+
WHITESPACE_CHARACTERS,
|
|
33
63
|
RELEASE_TYPES,
|
|
34
64
|
SEMVER_SPEC_VERSION,
|
|
35
65
|
FLAG_INCLUDE_PRERELEASE: 0b001,
|