@valbuild/language-server 0.102.0 → 0.103.1
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 +367 -0
- package/dist/declarations/src/ValProject.d.ts +39 -2
- package/dist/declarations/src/codeActions.d.ts +57 -8
- package/dist/declarations/src/commands.d.ts +63 -0
- package/dist/declarations/src/completionContext.d.ts +25 -40
- package/dist/declarations/src/completions.d.ts +12 -8
- package/dist/declarations/src/diagnostics.d.ts +107 -3
- package/dist/declarations/src/galleryFixes.d.ts +46 -0
- package/dist/declarations/src/index.d.ts +7 -3
- package/dist/declarations/src/textEdit.d.ts +10 -0
- package/dist/declarations/src/valModulesRegistry.d.ts +35 -0
- package/dist/valbuild-language-server.cjs.dev.js +1780 -513
- package/dist/valbuild-language-server.cjs.prod.js +1780 -513
- package/dist/valbuild-language-server.esm.js +1761 -517
- package/package.json +6 -5
|
@@ -6,26 +6,30 @@ import type { PublicValFiles } from "./publicValFiles.js";
|
|
|
6
6
|
* Completions for file and image references.
|
|
7
7
|
*
|
|
8
8
|
* Offers the files that actually exist under the project's files directory, and
|
|
9
|
-
* — when the item is accepted — fills in the metadata
|
|
9
|
+
* — when the item is accepted — fills in the metadata siblings by reading the
|
|
10
10
|
* chosen file. Getting width/height/mimeType right by hand is tedious and a
|
|
11
11
|
* frequent source of the very validation errors this server reports.
|
|
12
12
|
*/
|
|
13
13
|
/** Stashed on the item so `resolve` can do the expensive work lazily. */
|
|
14
14
|
export type ValCompletionItemData = {
|
|
15
|
-
kind: "
|
|
15
|
+
kind: "media-path";
|
|
16
16
|
uri: string;
|
|
17
17
|
/** Val-style ref of the chosen file. */
|
|
18
18
|
ref: string;
|
|
19
19
|
/** Absolute path of the chosen file. */
|
|
20
20
|
filePath: string;
|
|
21
|
-
|
|
22
|
-
/** Where a metadata argument goes, or what it replaces. */
|
|
21
|
+
mediaType: "image" | "file";
|
|
23
22
|
/**
|
|
24
|
-
*
|
|
23
|
+
* True when the field is backed by a gallery, in which case the dimensions
|
|
24
|
+
* and mime type live there and must not be written here too.
|
|
25
|
+
*/
|
|
26
|
+
gallery: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Start offset of the `path` value, used to re-find its object at resolve
|
|
25
29
|
* time. Offsets captured now cannot be replayed later: see
|
|
26
|
-
* {@link
|
|
30
|
+
* {@link findMediaPathObject}.
|
|
27
31
|
*/
|
|
28
|
-
|
|
32
|
+
pathValueStart: number;
|
|
29
33
|
};
|
|
30
34
|
export declare function createValCompletions({ document, offset, files, moduleFilePath, snapshot, }: {
|
|
31
35
|
document: TextDocument;
|
|
@@ -37,7 +41,7 @@ export declare function createValCompletions({ document, offset, files, moduleFi
|
|
|
37
41
|
snapshot?: SchemaSourceSnapshot;
|
|
38
42
|
}): CompletionItem[];
|
|
39
43
|
/**
|
|
40
|
-
* Fill in the metadata
|
|
44
|
+
* Fill in the metadata siblings for an accepted media path.
|
|
41
45
|
*
|
|
42
46
|
* Done at resolve time because it reads the file from disk, and an editor
|
|
43
47
|
* requests completions far more often than it accepts one.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ModuleFilePath, type ValidationFix } from "@valbuild/core";
|
|
1
|
+
import { type ModuleFilePath, type SourcePath, type ValidationError, type ValidationFix } from "@valbuild/core";
|
|
2
2
|
import { type SchemaSourceSnapshot } from "@valbuild/shared/internal";
|
|
3
3
|
import { Diagnostic, DiagnosticSeverity } from "vscode-languageserver";
|
|
4
4
|
import type { ValModuleContent } from "./ValProject.js";
|
|
@@ -17,7 +17,7 @@ export declare const VAL_DIAGNOSTIC_SOURCE = "val";
|
|
|
17
17
|
* vocabulary. A diagnostic says what is wrong; a fix says what can be done
|
|
18
18
|
* about it, and travels in {@link ValDiagnosticData.fixes}.
|
|
19
19
|
*/
|
|
20
|
-
export declare const VAL_DIAGNOSTIC_CODES: readonly ["val/validation", "val/schema", "val/fatal", "val/file-not-found", "val/missing-module"];
|
|
20
|
+
export declare const VAL_DIAGNOSTIC_CODES: readonly ["val/validation", "val/schema", "val/fatal", "val/file-not-found", "val/missing-module", "val/gallery-membership"];
|
|
21
21
|
export type ValDiagnosticCode = (typeof VAL_DIAGNOSTIC_CODES)[number];
|
|
22
22
|
/**
|
|
23
23
|
* Structured payload attached to every Val diagnostic.
|
|
@@ -41,6 +41,20 @@ export type ValDiagnosticData = {
|
|
|
41
41
|
value?: unknown;
|
|
42
42
|
/** Absolute path of the missing file, for `val/file-not-found`. */
|
|
43
43
|
filePath?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Where the gallery is and what the field points at, for `val/gallery-membership`.
|
|
46
|
+
* Carried here so a code action does not have to re-resolve the schema, and so
|
|
47
|
+
* a client could show it.
|
|
48
|
+
*/
|
|
49
|
+
gallery?: GalleryMembership;
|
|
50
|
+
/**
|
|
51
|
+
* The path to hand `createFixPatch`, when it differs from
|
|
52
|
+
* {@link ValDiagnosticData.sourcePath}.
|
|
53
|
+
*
|
|
54
|
+
* Only the gallery checks use this: they are reported on the entry that is
|
|
55
|
+
* wrong but fixed against the record that contains it.
|
|
56
|
+
*/
|
|
57
|
+
fixSourcePath?: string;
|
|
44
58
|
};
|
|
45
59
|
/**
|
|
46
60
|
* Severity policy, in one place.
|
|
@@ -59,7 +73,7 @@ export declare function severityFor({ code, fixes, }: {
|
|
|
59
73
|
code: ValDiagnosticCode;
|
|
60
74
|
fixes?: ValidationFix[];
|
|
61
75
|
}): DiagnosticSeverity;
|
|
62
|
-
export declare function createValDiagnostics({ moduleFilePath, content, text, valRoot, snapshot, }: {
|
|
76
|
+
export declare function createValDiagnostics({ moduleFilePath, content, text, valRoot, snapshot, galleryChecks, }: {
|
|
63
77
|
moduleFilePath: ModuleFilePath;
|
|
64
78
|
content: ValModuleContent;
|
|
65
79
|
/** Current text of the module, as the editor sees it. */
|
|
@@ -80,6 +94,13 @@ export declare function createValDiagnostics({ moduleFilePath, content, text, va
|
|
|
80
94
|
* unactionable noise on correct code.
|
|
81
95
|
*/
|
|
82
96
|
snapshot?: SchemaSourceSnapshot;
|
|
97
|
+
/**
|
|
98
|
+
* Verdicts for the gallery placeholders core emits unconditionally, from
|
|
99
|
+
* {@link resolveGalleryChecks}. Without it the placeholders are dropped: two
|
|
100
|
+
* permanent warnings on every gallery module is worse than a missed one, and
|
|
101
|
+
* the caller that can adjudicate them is the one that has a `Service`.
|
|
102
|
+
*/
|
|
103
|
+
galleryChecks?: ReadonlyMap<string, GalleryCheckVerdict>;
|
|
83
104
|
}): Diagnostic[];
|
|
84
105
|
/**
|
|
85
106
|
* Diagnostic for a project that could not be evaluated at all.
|
|
@@ -103,3 +124,86 @@ export declare function createProjectErrorDiagnostic({ moduleFilePath, message,
|
|
|
103
124
|
export declare function createMissingModuleDiagnostic({ moduleFilePath, }: {
|
|
104
125
|
moduleFilePath: ModuleFilePath;
|
|
105
126
|
}): Diagnostic;
|
|
127
|
+
export declare function isGalleryCheckFix(fix: string): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* One real problem found behind a gallery placeholder.
|
|
130
|
+
*
|
|
131
|
+
* A single placeholder can expand into several of these, each pointing at its
|
|
132
|
+
* own entry: `handleCheckAllFiles` reporting `shouldApplyPatch` means "no
|
|
133
|
+
* membership problem, now check the metadata", and `createFixPatch` then returns
|
|
134
|
+
* one error per entry whose stored metadata disagrees with its file. This is why
|
|
135
|
+
* the verdict is a list rather than a message, and why each carries its own
|
|
136
|
+
* source path.
|
|
137
|
+
*/
|
|
138
|
+
export type GalleryCheckFinding = {
|
|
139
|
+
/** Where to show it: the entry the problem is about. */
|
|
140
|
+
sourcePath: string;
|
|
141
|
+
message: string;
|
|
142
|
+
fixes?: ValidationFix[];
|
|
143
|
+
/**
|
|
144
|
+
* Where to *fix* it, when that is not where it is shown.
|
|
145
|
+
*
|
|
146
|
+
* The gallery fix is expressed against the record as a whole — it walks every
|
|
147
|
+
* entry — so `createFixPatch` must be given the record's path and the
|
|
148
|
+
* placeholder's value, while the diagnostic itself belongs on the offending
|
|
149
|
+
* entry. Splitting the two is what lets the message be precise without
|
|
150
|
+
* breaking the fix.
|
|
151
|
+
*/
|
|
152
|
+
fixSourcePath?: string;
|
|
153
|
+
/** The placeholder's `value`, which the fix reads. */
|
|
154
|
+
value?: unknown;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* The verdict on one gallery check. Empty means nothing is wrong and the
|
|
158
|
+
* placeholder is dropped.
|
|
159
|
+
*/
|
|
160
|
+
export type GalleryCheckVerdict = GalleryCheckFinding[];
|
|
161
|
+
/**
|
|
162
|
+
* Adjudicate every gallery placeholder in `validation`, by running the same fix
|
|
163
|
+
* handler `val validate` runs.
|
|
164
|
+
*
|
|
165
|
+
* Async and therefore separate from {@link createValDiagnostics}, which stays
|
|
166
|
+
* synchronous so it can be tested without a project. The caller runs this first
|
|
167
|
+
* and passes the result in.
|
|
168
|
+
*/
|
|
169
|
+
export declare function resolveGalleryChecks({ validation, runHandler, }: {
|
|
170
|
+
validation: Record<SourcePath, ValidationError[]>;
|
|
171
|
+
/**
|
|
172
|
+
* Runs the fix handler for one error and reports what it found. Injected so
|
|
173
|
+
* that this module needs no `Service`, and so tests can drive both outcomes.
|
|
174
|
+
*/
|
|
175
|
+
runHandler: (sourcePath: SourcePath, error: ValidationError) => Promise<GalleryCheckVerdict>;
|
|
176
|
+
}): Promise<Map<string, GalleryCheckVerdict>>;
|
|
177
|
+
/**
|
|
178
|
+
* Key for one placeholder. A gallery module carries several, all at the same
|
|
179
|
+
* source path, so the fix names have to be part of the key.
|
|
180
|
+
*/
|
|
181
|
+
export declare function galleryCheckKey(sourcePath: string, error: ValidationError): string;
|
|
182
|
+
/**
|
|
183
|
+
* A gallery-backed field pointing at something the gallery does not have.
|
|
184
|
+
*
|
|
185
|
+
* `ImageSchema.validate` reports this (`packages/core/src/schema/image.ts`:
|
|
186
|
+
* "The gallery does not have an image at '…'") but attaches no `ValidationFix`,
|
|
187
|
+
* because the remedy is not a change to this module: either the gallery gains an
|
|
188
|
+
* entry, or the file moves into the gallery's directory. Both are edits to
|
|
189
|
+
* somewhere else, which is not what a `ValidationFix` describes.
|
|
190
|
+
*
|
|
191
|
+
* So the fix is built in the editor instead, and this is what it needs. Derived
|
|
192
|
+
* from the **schema**, not from the message: matching on message text would break
|
|
193
|
+
* the moment the wording changed, silently.
|
|
194
|
+
*/
|
|
195
|
+
export type GalleryMembership = {
|
|
196
|
+
/** Module path of the gallery this field points at. */
|
|
197
|
+
referencedModule: string;
|
|
198
|
+
/** The gallery's directory, when it declares one. */
|
|
199
|
+
directory?: string;
|
|
200
|
+
/** The path the field currently holds. */
|
|
201
|
+
path: string;
|
|
202
|
+
/** `image` or `file`, for wording and for which metadata to read. */
|
|
203
|
+
mediaType: "image" | "file";
|
|
204
|
+
};
|
|
205
|
+
export declare function galleryMembershipAt({ sourcePath, content, snapshot, }: {
|
|
206
|
+
sourcePath: string;
|
|
207
|
+
content: ValModuleContent;
|
|
208
|
+
snapshot?: SchemaSourceSnapshot;
|
|
209
|
+
}): GalleryMembership | undefined;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two remedies for a gallery-backed field pointing at something its gallery
|
|
3
|
+
* does not have.
|
|
4
|
+
*
|
|
5
|
+
* Core reports the problem (`packages/core/src/schema/image.ts`) and offers no
|
|
6
|
+
* `ValidationFix`, because neither remedy is a change to the module holding the
|
|
7
|
+
* field:
|
|
8
|
+
*
|
|
9
|
+
* - **register it** — add an entry to the *gallery* module, keyed by the path,
|
|
10
|
+
* carrying the metadata read from the file. An edit to another document.
|
|
11
|
+
* - **move the file** — when the file is on disk but outside the gallery's
|
|
12
|
+
* directory, move it there and update the path. A file rename plus an edit.
|
|
13
|
+
*
|
|
14
|
+
* Both used to be VS Code commands in the extension, driven by diagnostics the
|
|
15
|
+
* extension computed itself. They are here so that every editor gets them, and
|
|
16
|
+
* so that a change to how galleries work has one place to be reflected.
|
|
17
|
+
*/
|
|
18
|
+
import ts from "typescript";
|
|
19
|
+
import { CodeAction } from "vscode-languageserver";
|
|
20
|
+
import type { TextDocument } from "vscode-languageserver-textdocument";
|
|
21
|
+
import type { GalleryMembership } from "./diagnostics.js";
|
|
22
|
+
/**
|
|
23
|
+
* Whether the client will honour a file rename inside a `WorkspaceEdit`.
|
|
24
|
+
*
|
|
25
|
+
* A `RenameFile` sent to a client that did not announce `resourceOperations`
|
|
26
|
+
* is silently dropped, which would leave the path rewritten and the file where it
|
|
27
|
+
* was — worse than not offering the fix.
|
|
28
|
+
*/
|
|
29
|
+
export declare function canRenameFiles(capabilities: unknown): boolean;
|
|
30
|
+
export declare function createGalleryMembershipActions({ document, gallery, valRoot, read, allowRename, }: {
|
|
31
|
+
document: TextDocument;
|
|
32
|
+
gallery: GalleryMembership;
|
|
33
|
+
valRoot: string;
|
|
34
|
+
/** The editor's view of a file, falling back to disk. */
|
|
35
|
+
read: (fsPath: string) => string | undefined;
|
|
36
|
+
allowRename: boolean;
|
|
37
|
+
}): Promise<CodeAction[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Where to insert into the record that is a gallery module's content -- the third
|
|
40
|
+
* argument of its `c.define(...)`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function findRecordInsertion(sourceFile: ts.SourceFile): {
|
|
43
|
+
insertOffset: number;
|
|
44
|
+
indentation: string;
|
|
45
|
+
hasProperties: boolean;
|
|
46
|
+
} | null;
|
|
@@ -2,11 +2,15 @@ export { main, createValLanguageServer, type ValSession } from "./server.js";
|
|
|
2
2
|
export { getLanguageServerVersion } from "./version.js";
|
|
3
3
|
export { createEditorFsHost, mapOpenDocuments, type OpenDocuments, } from "./EditorFsHost.js";
|
|
4
4
|
export { createValProject, defaultCoreResolver, type CoreResolver, type ValProject, type ValProjectInitError, type ValModuleContent, } from "./ValProject.js";
|
|
5
|
-
export { createValDiagnostics, createMissingModuleDiagnostic, createProjectErrorDiagnostic, severityFor, VAL_DIAGNOSTIC_SOURCE, VAL_DIAGNOSTIC_CODES, type ValDiagnosticCode, type ValDiagnosticData, } from "./diagnostics.js";
|
|
5
|
+
export { createValDiagnostics, createMissingModuleDiagnostic, createProjectErrorDiagnostic, severityFor, VAL_DIAGNOSTIC_SOURCE, VAL_DIAGNOSTIC_CODES, type ValDiagnosticCode, type ValDiagnosticData, resolveGalleryChecks, isGalleryCheckFix, galleryCheckKey, type GalleryCheckFinding, type GalleryCheckVerdict, galleryMembershipAt, type GalleryMembership, } from "./diagnostics.js";
|
|
6
6
|
export { findRegisteredModuleSpecifiers, isModuleRegistered, } from "./valModulesRegistry.js";
|
|
7
|
-
export { createValCodeActions,
|
|
7
|
+
export { createValCodeActions, createMissingModuleCodeAction, adjudicateGalleryCheck, isLocalFix, } from "./codeActions.js";
|
|
8
|
+
export { minimalTextEdit } from "./textEdit.js";
|
|
9
|
+
export { createValCommands, isRemoteFix, valCommandNames, readPersonalAccessToken, REMOTE_FIX_COMMANDS, REMOTE_FIX_TITLES, VAL_LOGIN_COMMAND, VAL_UPLOAD_REMOTE_COMMAND, VAL_DOWNLOAD_REMOTE_COMMAND, type RemoteFixCommandArgs, } from "./commands.js";
|
|
10
|
+
export { findValModulesInsertion, valModuleSpecifier, valModulesEntryText, } from "./valModulesRegistry.js";
|
|
11
|
+
export { canRenameFiles, createGalleryMembershipActions, findRecordInsertion, } from "./galleryFixes.js";
|
|
8
12
|
export { createValCompletions, resolveValCompletion, type ValCompletionItemData, } from "./completions.js";
|
|
9
|
-
export { getValCompletionContext, type
|
|
13
|
+
export { getValCompletionContext, findMediaPathObject, MEDIA_METADATA_KEYS, type MediaMetadataKey, type MediaPathObject, type ValCompletionContext, type ValStringValueContext, } from "./completionContext.js";
|
|
10
14
|
export { createPublicValFiles, DEFAULT_FILES_DIRECTORY, type PublicValFile, type PublicValFiles, } from "./publicValFiles.js";
|
|
11
15
|
export { createModulePathMap, findModulePathAtPosition, getModulePathRange, type ModulePathMap, type ModulePathRange, type ModulePosition, } from "./modulePathMap.js";
|
|
12
16
|
export { isValModuleUri, pathToUri, toModuleFilePath, uriToPath } from "./uri.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TextEdit } from "vscode-languageserver";
|
|
2
|
+
import type { TextDocument } from "vscode-languageserver-textdocument";
|
|
3
|
+
/**
|
|
4
|
+
* Narrow an edit down to the region that actually changed.
|
|
5
|
+
*
|
|
6
|
+
* A whole-document replacement would work, but it moves the cursor and shows up
|
|
7
|
+
* as a full-file change in review. Trimming the common prefix and suffix keeps
|
|
8
|
+
* the edit tight without needing a real diff algorithm.
|
|
9
|
+
*/
|
|
10
|
+
export declare function minimalTextEdit(before: string, after: string, document: TextDocument): TextEdit | undefined;
|
|
@@ -30,3 +30,38 @@ export declare function isModuleRegistered({ sourceFile, valModulesDir, moduleFi
|
|
|
30
30
|
valModulesDir: string;
|
|
31
31
|
moduleFilePath: ModuleFilePath;
|
|
32
32
|
}): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Where to insert a new entry in a `val.modules` file, and how to indent it.
|
|
35
|
+
*
|
|
36
|
+
* Only `modules(config, [ … ])` is matched, because that is the shape Val
|
|
37
|
+
* actually accepts and the shape `examples/next/val.modules.ts` uses. The
|
|
38
|
+
* over-reporting rule in {@link findRegisteredModuleSpecifiers} is right for
|
|
39
|
+
* *reading* a file someone else wrote; writing into one has to commit to a
|
|
40
|
+
* shape, and guessing wrong produces a file that no longer compiles.
|
|
41
|
+
*
|
|
42
|
+
* Returns `null` when the array cannot be found — the caller then offers no fix
|
|
43
|
+
* rather than inserting somewhere arbitrary.
|
|
44
|
+
*/
|
|
45
|
+
export declare function findValModulesInsertion(sourceFile: ts.SourceFile): {
|
|
46
|
+
insertOffset: number;
|
|
47
|
+
indentation: string;
|
|
48
|
+
hasElements: boolean;
|
|
49
|
+
} | null;
|
|
50
|
+
/**
|
|
51
|
+
* The specifier to write for `moduleFilePath`, relative to the `val.modules`
|
|
52
|
+
* file that will hold it.
|
|
53
|
+
*
|
|
54
|
+
* Both paths are Val-style (root-relative, leading slash). POSIX separators
|
|
55
|
+
* always: the string ends up in an `import()` in source, where a backslash is an
|
|
56
|
+
* escape rather than a separator.
|
|
57
|
+
*/
|
|
58
|
+
export declare function valModuleSpecifier({ valModulesFilePath, moduleFilePath, }: {
|
|
59
|
+
valModulesFilePath: string;
|
|
60
|
+
moduleFilePath: ModuleFilePath;
|
|
61
|
+
}): string;
|
|
62
|
+
/** The text to insert for one new entry, including its separator. */
|
|
63
|
+
export declare function valModulesEntryText({ specifier, indentation, hasElements, }: {
|
|
64
|
+
specifier: string;
|
|
65
|
+
indentation: string;
|
|
66
|
+
hasElements: boolean;
|
|
67
|
+
}): string;
|