@valbuild/language-server 0.124.0 → 0.125.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/CHANGELOG.md +106 -0
- package/dist/declarations/src/diagnostics.d.ts +9 -9
- package/dist/declarations/src/{mediaMetadataChecks.d.ts → mediaChecks.d.ts} +46 -25
- package/dist/declarations/src/version.d.ts +0 -9
- package/dist/valbuild-language-server.cjs.dev.js +245 -66
- package/dist/valbuild-language-server.cjs.prod.js +245 -66
- package/dist/valbuild-language-server.esm.js +245 -66
- package/package.json +4 -4
|
@@ -159,22 +159,71 @@ function negotiateProtocolVersion(client, server = SUPPORTED_PROTOCOL_VERSIONS)
|
|
|
159
159
|
};
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
var packageJson = {
|
|
163
|
+
name: "@valbuild/language-server",
|
|
164
|
+
"private": false,
|
|
165
|
+
description: "Val - editor language server (LSP)",
|
|
166
|
+
repository: {
|
|
167
|
+
type: "git",
|
|
168
|
+
url: "git+https://github.com/valbuild/val.git"
|
|
169
|
+
},
|
|
170
|
+
keywords: [
|
|
171
|
+
"CMS",
|
|
172
|
+
"lsp",
|
|
173
|
+
"language-server"
|
|
174
|
+
],
|
|
175
|
+
version: "0.125.0",
|
|
176
|
+
bin: {
|
|
177
|
+
"val-language-server": "./bin.js"
|
|
178
|
+
},
|
|
179
|
+
main: "dist/valbuild-language-server.cjs.js",
|
|
180
|
+
module: "dist/valbuild-language-server.esm.js",
|
|
181
|
+
exports: {
|
|
182
|
+
".": {
|
|
183
|
+
module: "./dist/valbuild-language-server.esm.js",
|
|
184
|
+
"default": "./dist/valbuild-language-server.cjs.js"
|
|
185
|
+
},
|
|
186
|
+
"./package.json": "./package.json"
|
|
187
|
+
},
|
|
188
|
+
types: "dist/valbuild-language-server.cjs.d.ts",
|
|
189
|
+
scripts: {
|
|
190
|
+
typecheck: "tsc --noEmit",
|
|
191
|
+
test: "jest",
|
|
192
|
+
"test:watch": "jest --watch",
|
|
193
|
+
bench: "node scripts/evalLatency.bench.js"
|
|
194
|
+
},
|
|
195
|
+
dependencies: {
|
|
196
|
+
"@valbuild/core": "workspace:*",
|
|
197
|
+
"@valbuild/server": "workspace:*",
|
|
198
|
+
"@valbuild/shared": "workspace:*",
|
|
199
|
+
typescript: "^6.0.3",
|
|
200
|
+
"vscode-languageserver": "^10.1.0",
|
|
201
|
+
"vscode-languageserver-textdocument": "^1.0.14"
|
|
202
|
+
},
|
|
203
|
+
devDependencies: {
|
|
204
|
+
"@types/jest": "^30.0.0",
|
|
205
|
+
"vscode-jsonrpc": "^9.0.2"
|
|
206
|
+
},
|
|
207
|
+
engines: {
|
|
208
|
+
node: "^20.19.0 || >=22"
|
|
209
|
+
},
|
|
210
|
+
files: [
|
|
211
|
+
"CHANGELOG.md",
|
|
212
|
+
"dist",
|
|
213
|
+
"bin.js",
|
|
214
|
+
"README.md"
|
|
215
|
+
]
|
|
216
|
+
};
|
|
217
|
+
|
|
162
218
|
/**
|
|
163
|
-
*
|
|
219
|
+
* This package's version, inlined at build time.
|
|
164
220
|
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* `null` rather than throwing if the file cannot be read — the version is only
|
|
169
|
-
* ever used for display, never for behaviour.
|
|
221
|
+
* See `packages/core/src/index.ts` for why this is a static JSON import rather
|
|
222
|
+
* than `require("../package.json")`. The version is only ever displayed here,
|
|
223
|
+
* but the two should not drift apart in how they read it.
|
|
170
224
|
*/
|
|
171
225
|
function getLanguageServerVersion() {
|
|
172
|
-
|
|
173
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
174
|
-
return require("../package.json").version;
|
|
175
|
-
} catch {
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
226
|
+
return packageJson.version ;
|
|
178
227
|
}
|
|
179
228
|
|
|
180
229
|
/**
|
|
@@ -847,19 +896,28 @@ function traverseObjectLiteral(node, sourceFile) {
|
|
|
847
896
|
}
|
|
848
897
|
|
|
849
898
|
/**
|
|
850
|
-
* Adjudicating the media
|
|
899
|
+
* Adjudicating the media placeholders core emits unconditionally.
|
|
900
|
+
*
|
|
901
|
+
* A media schema cannot answer two of its own questions, because both need
|
|
902
|
+
* something core has no access to -- the bytes on disk, or the bytes on the
|
|
903
|
+
* content host. So it defers, by reporting an error that only means "nobody
|
|
904
|
+
* has looked yet":
|
|
851
905
|
*
|
|
852
|
-
* `
|
|
853
|
-
*
|
|
854
|
-
* `s.
|
|
855
|
-
*
|
|
856
|
-
* `s.
|
|
906
|
+
* - **Metadata.** Any `s.image()` carrying metadata gets an
|
|
907
|
+
* `image:check-metadata` error whether or not anything is wrong
|
|
908
|
+
* (`packages/core/src/schema/image.ts`), and `s.file()` does the same with
|
|
909
|
+
* `file:check-metadata`.
|
|
910
|
+
* - **Remote refs.** Every `s.image().remote()` / `s.file().remote()` value
|
|
911
|
+
* whose path is a remote ref gets `Remote image was not checked.` with
|
|
912
|
+
* `image:check-remote` -- unconditionally, for every remote image in the
|
|
913
|
+
* project.
|
|
857
914
|
*
|
|
858
|
-
* `val validate` resolves
|
|
859
|
-
* `createFixPatch` in report mode, which
|
|
860
|
-
* and
|
|
861
|
-
*
|
|
862
|
-
* (`partitionValidationErrors` in
|
|
915
|
+
* `val validate` resolves both by running the fix handler and then
|
|
916
|
+
* `createFixPatch` in report mode, which returns one error per real problem
|
|
917
|
+
* and nothing at all when there is none. The Studio cannot do that -- a
|
|
918
|
+
* browser has neither the filesystem nor the project's remote credentials --
|
|
919
|
+
* so it drops them wholesale (`partitionValidationErrors` in
|
|
920
|
+
* `@valbuild/shared`).
|
|
863
921
|
*
|
|
864
922
|
* An editor is in the CLI's position, not the browser's, and publishing the
|
|
865
923
|
* placeholders raw put a permanent warning on every image in the project. So
|
|
@@ -875,15 +933,42 @@ function traverseObjectLiteral(node, sourceFile) {
|
|
|
875
933
|
*/
|
|
876
934
|
const METADATA_CHECK_FIXES = ["image:check-metadata", "file:check-metadata"];
|
|
877
935
|
|
|
878
|
-
/**
|
|
936
|
+
/**
|
|
937
|
+
* The fixes that carry an unconditional remote-ref placeholder.
|
|
938
|
+
*
|
|
939
|
+
* The plural `images:check-remote` / `files:check-remote` are deliberately
|
|
940
|
+
* absent. `RecordSchema.validateMediaKey` emits those only for a key that is
|
|
941
|
+
* already wrong -- an unparseable remote URL, or one outside the gallery's
|
|
942
|
+
* directory -- and their messages say so. They are findings, not deferrals,
|
|
943
|
+
* and `createFixPatch` has no branch for them at all, so adjudicating one
|
|
944
|
+
* would come back empty and silently drop a real error.
|
|
945
|
+
*/
|
|
946
|
+
const REMOTE_CHECK_FIXES = ["image:check-remote", "file:check-remote"];
|
|
947
|
+
|
|
948
|
+
/** One thing about a media value that a real check found to be wrong. */
|
|
879
949
|
|
|
880
950
|
/**
|
|
881
|
-
* The verdict on one placeholder. Empty means the
|
|
882
|
-
* file and nothing should be
|
|
951
|
+
* The verdict on one placeholder. Empty means the check passed -- the metadata
|
|
952
|
+
* agrees with the file, or the remote ref is sound -- and nothing should be
|
|
953
|
+
* published.
|
|
954
|
+
*/
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* Whether this error is the unconditional remote-ref deferral.
|
|
958
|
+
*
|
|
959
|
+
* Unlike the metadata deferral this needs no re-derivation: `image:check-remote`
|
|
960
|
+
* is attached to exactly one error in `ImageSchema.executeValidate`, the
|
|
961
|
+
* fall-through for a remote schema with a remote path, and `FileSchema` mirrors
|
|
962
|
+
* it. Everything else a remote media field can be wrong about carries a
|
|
963
|
+
* different fix (`image:upload-remote`, `image:download-remote`) or none.
|
|
883
964
|
*/
|
|
965
|
+
function isDeferredRemoteCheck(error) {
|
|
966
|
+
return (error.fixes ?? []).some(fix => REMOTE_CHECK_FIXES.includes(fix));
|
|
967
|
+
}
|
|
884
968
|
|
|
885
969
|
/**
|
|
886
|
-
* Whether this error is the unconditional deferral rather than a real
|
|
970
|
+
* Whether this error is the unconditional METADATA deferral rather than a real
|
|
971
|
+
* finding.
|
|
887
972
|
*
|
|
888
973
|
* This is the whole difficulty of the change. `image:check-metadata` is
|
|
889
974
|
* attached to FIVE different image errors, and only the last is a placeholder:
|
|
@@ -902,7 +987,7 @@ const METADATA_CHECK_FIXES = ["image:check-metadata", "file:check-metadata"];
|
|
|
902
987
|
* There is no flag on `ValidationError` saying which is which, so the four
|
|
903
988
|
* conditions are re-derived here from the same inputs core used. They are
|
|
904
989
|
* transcribed from `ImageSchema.executeValidate`, in its order, and
|
|
905
|
-
* `
|
|
990
|
+
* `mediaChecks.test.ts` drives real core through all five cases to
|
|
906
991
|
* check that this agrees with it. If core grows a sixth condition, that test is
|
|
907
992
|
* what catches it.
|
|
908
993
|
*
|
|
@@ -947,33 +1032,33 @@ function isDeferredMediaMetadataCheck({
|
|
|
947
1032
|
}
|
|
948
1033
|
|
|
949
1034
|
/**
|
|
950
|
-
*
|
|
951
|
-
*
|
|
1035
|
+
* Whether an error in a module is either deferral, resolving the schema the
|
|
1036
|
+
* metadata classification needs.
|
|
952
1037
|
*
|
|
953
1038
|
* Both the adjudicator and `createValDiagnostics` have to make the same call,
|
|
954
1039
|
* on the same inputs -- one to decide what to adjudicate, the other to decide
|
|
955
1040
|
* what to publish -- so it lives here rather than being written out twice.
|
|
956
1041
|
*/
|
|
957
|
-
function
|
|
1042
|
+
function isDeferredMediaCheckAt({
|
|
958
1043
|
sourcePath,
|
|
959
1044
|
error,
|
|
960
1045
|
content
|
|
961
1046
|
}) {
|
|
962
|
-
return isDeferredMediaMetadataCheck({
|
|
1047
|
+
return isDeferredRemoteCheck(error) || isDeferredMediaMetadataCheck({
|
|
963
1048
|
error,
|
|
964
1049
|
schema: resolveSchemaAt$1(sourcePath, content)
|
|
965
1050
|
});
|
|
966
1051
|
}
|
|
967
1052
|
|
|
968
1053
|
/**
|
|
969
|
-
* Adjudicate every deferred
|
|
1054
|
+
* Adjudicate every deferred media placeholder in `validation`.
|
|
970
1055
|
*
|
|
971
1056
|
* Async, and therefore separate from `createValDiagnostics`, which stays
|
|
972
1057
|
* synchronous so it can be tested without a project -- the same split
|
|
973
1058
|
* `resolveGalleryChecks` uses. The caller runs this first and passes the
|
|
974
1059
|
* result in.
|
|
975
1060
|
*/
|
|
976
|
-
async function
|
|
1061
|
+
async function resolveMediaChecks({
|
|
977
1062
|
validation,
|
|
978
1063
|
content,
|
|
979
1064
|
valRoot,
|
|
@@ -982,14 +1067,14 @@ async function resolveMediaMetadataChecks({
|
|
|
982
1067
|
const verdicts = new Map();
|
|
983
1068
|
for (const [sourcePath, errors] of Object.entries(validation)) {
|
|
984
1069
|
for (const error of errors) {
|
|
985
|
-
if (!
|
|
1070
|
+
if (!isDeferredMediaCheckAt({
|
|
986
1071
|
sourcePath,
|
|
987
1072
|
error,
|
|
988
1073
|
content
|
|
989
1074
|
})) {
|
|
990
1075
|
continue;
|
|
991
1076
|
}
|
|
992
|
-
const key =
|
|
1077
|
+
const key = mediaCheckKey(sourcePath, error);
|
|
993
1078
|
try {
|
|
994
1079
|
verdicts.set(key, await adjudicate({
|
|
995
1080
|
sourcePath,
|
|
@@ -1001,7 +1086,7 @@ async function resolveMediaMetadataChecks({
|
|
|
1001
1086
|
} catch {
|
|
1002
1087
|
// This runs inside `validate`, which publishes NOTHING if it throws --
|
|
1003
1088
|
// one bad image would silently clear every Val diagnostic in the file.
|
|
1004
|
-
// Keep the placeholder rather than claiming the
|
|
1089
|
+
// Keep the placeholder rather than claiming the check passed.
|
|
1005
1090
|
verdicts.set(key, keep(error));
|
|
1006
1091
|
}
|
|
1007
1092
|
}
|
|
@@ -1013,7 +1098,7 @@ async function resolveMediaMetadataChecks({
|
|
|
1013
1098
|
* Key for one placeholder. A value can in principle carry more than one, so
|
|
1014
1099
|
* the fix names are part of the key -- as they are for the gallery checks.
|
|
1015
1100
|
*/
|
|
1016
|
-
function
|
|
1101
|
+
function mediaCheckKey(sourcePath, error) {
|
|
1017
1102
|
return `${sourcePath}|${(error.fixes ?? []).join(",")}`;
|
|
1018
1103
|
}
|
|
1019
1104
|
|
|
@@ -1033,6 +1118,17 @@ function keep(error) {
|
|
|
1033
1118
|
/**
|
|
1034
1119
|
* What `createFixPatch` says about one placeholder, in report mode.
|
|
1035
1120
|
*
|
|
1121
|
+
* Which placeholder decides only what has to be true before asking; the asking
|
|
1122
|
+
* is the same call either way, and `reportFixPatch` is it.
|
|
1123
|
+
*/
|
|
1124
|
+
async function adjudicate(args) {
|
|
1125
|
+
return isDeferredRemoteCheck(args.error) ? adjudicateRemote(args) : adjudicateMetadata(args);
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
/**
|
|
1129
|
+
* The metadata placeholder: does the stored width/height/mimeType match the
|
|
1130
|
+
* bytes?
|
|
1131
|
+
*
|
|
1036
1132
|
* `val validate` runs the fix handler first and then `createFixPatch`, but for
|
|
1037
1133
|
* these four fixes the handler is `handleFileMetadata`, whose whole job is the
|
|
1038
1134
|
* precondition "the ref resolves and the file is on disk". That precondition is
|
|
@@ -1054,7 +1150,7 @@ function keep(error) {
|
|
|
1054
1150
|
* `createFixPatch` reads and decodes the image itself, so this is one file read
|
|
1055
1151
|
* per media field per validation pass, and nothing here should add another.
|
|
1056
1152
|
*/
|
|
1057
|
-
async function
|
|
1153
|
+
async function adjudicateMetadata({
|
|
1058
1154
|
sourcePath,
|
|
1059
1155
|
error,
|
|
1060
1156
|
content,
|
|
@@ -1075,19 +1171,17 @@ async function adjudicate({
|
|
|
1075
1171
|
// means this verdict never has the last word on a file that is not there.
|
|
1076
1172
|
return keep(error);
|
|
1077
1173
|
}
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
false, sourcePath, error, {}, content.source, content.schema);
|
|
1087
|
-
} catch {
|
|
1174
|
+
const reported = await reportFixPatch({
|
|
1175
|
+
sourcePath,
|
|
1176
|
+
error,
|
|
1177
|
+
content,
|
|
1178
|
+
valRoot,
|
|
1179
|
+
remoteHost
|
|
1180
|
+
});
|
|
1181
|
+
if (reported === undefined) {
|
|
1088
1182
|
return keep(error);
|
|
1089
1183
|
}
|
|
1090
|
-
return
|
|
1184
|
+
return reported.map(remaining => ({
|
|
1091
1185
|
message: remaining.message,
|
|
1092
1186
|
// `createFixPatch` clears `fixes` on the per-field errors it reports, but
|
|
1093
1187
|
// the fix is still available and still the remedy -- it is what the
|
|
@@ -1103,6 +1197,77 @@ async function adjudicate({
|
|
|
1103
1197
|
}));
|
|
1104
1198
|
}
|
|
1105
1199
|
|
|
1200
|
+
/**
|
|
1201
|
+
* The remote-ref placeholder: is the ref this value carries still the ref the
|
|
1202
|
+
* bytes behind it produce?
|
|
1203
|
+
*
|
|
1204
|
+
* `handleRemoteFileCheck` is a no-op that asks for the patch, so unlike the
|
|
1205
|
+
* metadata case there is no precondition of its own to stand in for -- the
|
|
1206
|
+
* whole check is `checkRemoteRef` inside `createFixPatch`. It recomputes the
|
|
1207
|
+
* validation hash from the schema, the file extension, the metadata on the
|
|
1208
|
+
* value and the file hash in the ref; when that agrees with the ref, nothing is
|
|
1209
|
+
* downloaded and nothing is reported. Only a ref that no longer adds up costs a
|
|
1210
|
+
* download, and that is cached under `.val/remote-file-cache`.
|
|
1211
|
+
*
|
|
1212
|
+
* The findings deliberately carry no `fixes`. `createFixPatch` clears them
|
|
1213
|
+
* (`Remote ref: ... is not valid. Use the --fix flag to fix this issue.`
|
|
1214
|
+
* arrives with `fixes: undefined`), no quick fix is registered for
|
|
1215
|
+
* `image:check-remote` -- rewriting the ref needs the bytes off the content
|
|
1216
|
+
* host, so it is `val validate --fix`'s job, not a lightbulb's -- and dropping
|
|
1217
|
+
* them is what makes this an Error rather than a Warning, matching the `✘` the
|
|
1218
|
+
* CLI prints for the same finding.
|
|
1219
|
+
*/
|
|
1220
|
+
async function adjudicateRemote({
|
|
1221
|
+
sourcePath,
|
|
1222
|
+
error,
|
|
1223
|
+
content,
|
|
1224
|
+
valRoot,
|
|
1225
|
+
remoteHost
|
|
1226
|
+
}) {
|
|
1227
|
+
const reported = await reportFixPatch({
|
|
1228
|
+
sourcePath,
|
|
1229
|
+
error,
|
|
1230
|
+
content,
|
|
1231
|
+
valRoot,
|
|
1232
|
+
remoteHost
|
|
1233
|
+
});
|
|
1234
|
+
if (reported === undefined) {
|
|
1235
|
+
return keep(error);
|
|
1236
|
+
}
|
|
1237
|
+
return reported.map(remaining => ({
|
|
1238
|
+
message: remaining.message,
|
|
1239
|
+
...(error.value !== undefined ? {
|
|
1240
|
+
value: error.value
|
|
1241
|
+
} : {})
|
|
1242
|
+
}));
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
/**
|
|
1246
|
+
* `createFixPatch` in report mode, or `undefined` if it could not answer.
|
|
1247
|
+
*
|
|
1248
|
+
* `false` is the load-bearing argument: this is a question, not a fix. Asking
|
|
1249
|
+
* for the patch would have `createFixPatch` read and rewrite files behind the
|
|
1250
|
+
* editor's back -- and, for a remote ref, re-derive one from bytes it had to
|
|
1251
|
+
* download first.
|
|
1252
|
+
*/
|
|
1253
|
+
async function reportFixPatch({
|
|
1254
|
+
sourcePath,
|
|
1255
|
+
error,
|
|
1256
|
+
content,
|
|
1257
|
+
valRoot,
|
|
1258
|
+
remoteHost
|
|
1259
|
+
}) {
|
|
1260
|
+
try {
|
|
1261
|
+
const fixed = await createFixPatch({
|
|
1262
|
+
projectRoot: valRoot,
|
|
1263
|
+
remoteHost
|
|
1264
|
+
}, false, sourcePath, error, {}, content.source, content.schema);
|
|
1265
|
+
return fixed?.remainingErrors ?? [];
|
|
1266
|
+
} catch {
|
|
1267
|
+
return undefined;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1106
1271
|
/**
|
|
1107
1272
|
* The `accept` a media schema declares, if any.
|
|
1108
1273
|
*
|
|
@@ -1227,8 +1392,18 @@ const FALLBACK_RANGE = {
|
|
|
1227
1392
|
}
|
|
1228
1393
|
};
|
|
1229
1394
|
|
|
1230
|
-
/**
|
|
1231
|
-
|
|
1395
|
+
/**
|
|
1396
|
+
* Fixes that operate on a LOCAL file or image reference.
|
|
1397
|
+
*
|
|
1398
|
+
* `*:check-remote` is deliberately absent. A remote value's bytes are on the
|
|
1399
|
+
* content host by design, so "is it on disk" is never its question -- and for
|
|
1400
|
+
* a path that is neither under `/public` nor a parseable remote ref, this
|
|
1401
|
+
* check answered "File <root>/... does not exist" and pre-empted the remote
|
|
1402
|
+
* adjudication, which has the real answer ("Invalid remote ref: ..."). The
|
|
1403
|
+
* upload/download fixes stay: `*:upload-remote` is reported on a local path
|
|
1404
|
+
* and a missing file really is its problem.
|
|
1405
|
+
*/
|
|
1406
|
+
const FILE_FIXES = ["image:add-metadata", "image:check-metadata", "image:upload-remote", "image:download-remote", "file:add-metadata", "file:check-metadata", "file:upload-remote", "file:download-remote"];
|
|
1232
1407
|
function build(range, message, data) {
|
|
1233
1408
|
return {
|
|
1234
1409
|
range,
|
|
@@ -1246,7 +1421,7 @@ function createValDiagnostics({
|
|
|
1246
1421
|
valRoot,
|
|
1247
1422
|
snapshot,
|
|
1248
1423
|
galleryChecks,
|
|
1249
|
-
|
|
1424
|
+
mediaChecks
|
|
1250
1425
|
}) {
|
|
1251
1426
|
if (content.errors === false) {
|
|
1252
1427
|
return [];
|
|
@@ -1318,18 +1493,20 @@ function createValDiagnostics({
|
|
|
1318
1493
|
continue;
|
|
1319
1494
|
}
|
|
1320
1495
|
|
|
1321
|
-
// An unconditional media
|
|
1322
|
-
// `image:check-metadata` on every `s.image()` carrying metadata
|
|
1323
|
-
// or not it disagrees with the file
|
|
1324
|
-
//
|
|
1325
|
-
// the
|
|
1326
|
-
//
|
|
1327
|
-
|
|
1496
|
+
// An unconditional media placeholder: core reports
|
|
1497
|
+
// `image:check-metadata` on every `s.image()` carrying metadata whether
|
|
1498
|
+
// or not it disagrees with the file, and `Remote image was not checked.`
|
|
1499
|
+
// on every remote image whether or not its ref is stale. Show only what
|
|
1500
|
+
// the adjudication actually found, and nothing when it found nothing.
|
|
1501
|
+
// Deliberately after the missing-file branch above, so a deleted file is
|
|
1502
|
+
// still reported as `val/file-not-found` rather than as a metadata
|
|
1503
|
+
// mismatch.
|
|
1504
|
+
if (isDeferredMediaCheckAt({
|
|
1328
1505
|
sourcePath,
|
|
1329
1506
|
error,
|
|
1330
1507
|
content
|
|
1331
1508
|
})) {
|
|
1332
|
-
const verdict =
|
|
1509
|
+
const verdict = mediaChecks?.get(mediaCheckKey(sourcePath, error));
|
|
1333
1510
|
for (const finding of verdict ?? []) {
|
|
1334
1511
|
diagnostics.push(build(rangeOf(sourcePath, modulePathMap), finding.message, {
|
|
1335
1512
|
code: "val/validation",
|
|
@@ -4058,9 +4235,11 @@ function createValLanguageServer(connection) {
|
|
|
4058
4235
|
})
|
|
4059
4236
|
}) : undefined;
|
|
4060
4237
|
// Core also defers "does this image's stored metadata match its file",
|
|
4061
|
-
// reporting it on every `s.image()` that carries any metadata
|
|
4062
|
-
//
|
|
4063
|
-
|
|
4238
|
+
// reporting it on every `s.image()` that carries any metadata, and
|
|
4239
|
+
// "is this remote ref still valid", reporting it on every remote image.
|
|
4240
|
+
// Same treatment: adjudicate with the fix machinery before showing
|
|
4241
|
+
// anything.
|
|
4242
|
+
const mediaChecks = result.content.errors !== false && result.content.errors.validation ? await resolveMediaChecks({
|
|
4064
4243
|
validation: result.content.errors.validation,
|
|
4065
4244
|
content: result.content,
|
|
4066
4245
|
valRoot: activeProject.valRoot
|
|
@@ -4076,8 +4255,8 @@ function createValLanguageServer(connection) {
|
|
|
4076
4255
|
...(galleryChecks ? {
|
|
4077
4256
|
galleryChecks
|
|
4078
4257
|
} : {}),
|
|
4079
|
-
...(
|
|
4080
|
-
|
|
4258
|
+
...(mediaChecks ? {
|
|
4259
|
+
mediaChecks
|
|
4081
4260
|
} : {})
|
|
4082
4261
|
});
|
|
4083
4262
|
const unregistered = findMissingModuleDiagnostic(project.valRoot, moduleFilePath, readOpenDocument);
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"lsp",
|
|
12
12
|
"language-server"
|
|
13
13
|
],
|
|
14
|
-
"version": "0.
|
|
14
|
+
"version": "0.125.0",
|
|
15
15
|
"bin": {
|
|
16
16
|
"val-language-server": "./bin.js"
|
|
17
17
|
},
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"typescript": "^6.0.3",
|
|
30
30
|
"vscode-languageserver": "^10.1.0",
|
|
31
31
|
"vscode-languageserver-textdocument": "^1.0.14",
|
|
32
|
-
"@valbuild/core": "0.
|
|
33
|
-
"@valbuild/server": "0.
|
|
34
|
-
"@valbuild/shared": "0.
|
|
32
|
+
"@valbuild/core": "0.125.0",
|
|
33
|
+
"@valbuild/server": "0.125.0",
|
|
34
|
+
"@valbuild/shared": "0.125.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/jest": "^30.0.0",
|