@valbuild/language-server 0.123.3 → 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 +115 -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
|
@@ -170,22 +170,71 @@ function negotiateProtocolVersion(client, server = SUPPORTED_PROTOCOL_VERSIONS)
|
|
|
170
170
|
};
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
var packageJson = {
|
|
174
|
+
name: "@valbuild/language-server",
|
|
175
|
+
"private": false,
|
|
176
|
+
description: "Val - editor language server (LSP)",
|
|
177
|
+
repository: {
|
|
178
|
+
type: "git",
|
|
179
|
+
url: "git+https://github.com/valbuild/val.git"
|
|
180
|
+
},
|
|
181
|
+
keywords: [
|
|
182
|
+
"CMS",
|
|
183
|
+
"lsp",
|
|
184
|
+
"language-server"
|
|
185
|
+
],
|
|
186
|
+
version: "0.125.0",
|
|
187
|
+
bin: {
|
|
188
|
+
"val-language-server": "./bin.js"
|
|
189
|
+
},
|
|
190
|
+
main: "dist/valbuild-language-server.cjs.js",
|
|
191
|
+
module: "dist/valbuild-language-server.esm.js",
|
|
192
|
+
exports: {
|
|
193
|
+
".": {
|
|
194
|
+
module: "./dist/valbuild-language-server.esm.js",
|
|
195
|
+
"default": "./dist/valbuild-language-server.cjs.js"
|
|
196
|
+
},
|
|
197
|
+
"./package.json": "./package.json"
|
|
198
|
+
},
|
|
199
|
+
types: "dist/valbuild-language-server.cjs.d.ts",
|
|
200
|
+
scripts: {
|
|
201
|
+
typecheck: "tsc --noEmit",
|
|
202
|
+
test: "jest",
|
|
203
|
+
"test:watch": "jest --watch",
|
|
204
|
+
bench: "node scripts/evalLatency.bench.js"
|
|
205
|
+
},
|
|
206
|
+
dependencies: {
|
|
207
|
+
"@valbuild/core": "workspace:*",
|
|
208
|
+
"@valbuild/server": "workspace:*",
|
|
209
|
+
"@valbuild/shared": "workspace:*",
|
|
210
|
+
typescript: "^6.0.3",
|
|
211
|
+
"vscode-languageserver": "^10.1.0",
|
|
212
|
+
"vscode-languageserver-textdocument": "^1.0.14"
|
|
213
|
+
},
|
|
214
|
+
devDependencies: {
|
|
215
|
+
"@types/jest": "^30.0.0",
|
|
216
|
+
"vscode-jsonrpc": "^9.0.2"
|
|
217
|
+
},
|
|
218
|
+
engines: {
|
|
219
|
+
node: "^20.19.0 || >=22"
|
|
220
|
+
},
|
|
221
|
+
files: [
|
|
222
|
+
"CHANGELOG.md",
|
|
223
|
+
"dist",
|
|
224
|
+
"bin.js",
|
|
225
|
+
"README.md"
|
|
226
|
+
]
|
|
227
|
+
};
|
|
228
|
+
|
|
173
229
|
/**
|
|
174
|
-
*
|
|
230
|
+
* This package's version, inlined at build time.
|
|
175
231
|
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
* `null` rather than throwing if the file cannot be read — the version is only
|
|
180
|
-
* ever used for display, never for behaviour.
|
|
232
|
+
* See `packages/core/src/index.ts` for why this is a static JSON import rather
|
|
233
|
+
* than `require("../package.json")`. The version is only ever displayed here,
|
|
234
|
+
* but the two should not drift apart in how they read it.
|
|
181
235
|
*/
|
|
182
236
|
function getLanguageServerVersion() {
|
|
183
|
-
|
|
184
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
185
|
-
return require("../package.json").version;
|
|
186
|
-
} catch {
|
|
187
|
-
return null;
|
|
188
|
-
}
|
|
237
|
+
return packageJson.version ;
|
|
189
238
|
}
|
|
190
239
|
|
|
191
240
|
/**
|
|
@@ -858,19 +907,28 @@ function traverseObjectLiteral(node, sourceFile) {
|
|
|
858
907
|
}
|
|
859
908
|
|
|
860
909
|
/**
|
|
861
|
-
* Adjudicating the media
|
|
910
|
+
* Adjudicating the media placeholders core emits unconditionally.
|
|
911
|
+
*
|
|
912
|
+
* A media schema cannot answer two of its own questions, because both need
|
|
913
|
+
* something core has no access to -- the bytes on disk, or the bytes on the
|
|
914
|
+
* content host. So it defers, by reporting an error that only means "nobody
|
|
915
|
+
* has looked yet":
|
|
862
916
|
*
|
|
863
|
-
* `
|
|
864
|
-
*
|
|
865
|
-
* `s.
|
|
866
|
-
*
|
|
867
|
-
* `s.
|
|
917
|
+
* - **Metadata.** Any `s.image()` carrying metadata gets an
|
|
918
|
+
* `image:check-metadata` error whether or not anything is wrong
|
|
919
|
+
* (`packages/core/src/schema/image.ts`), and `s.file()` does the same with
|
|
920
|
+
* `file:check-metadata`.
|
|
921
|
+
* - **Remote refs.** Every `s.image().remote()` / `s.file().remote()` value
|
|
922
|
+
* whose path is a remote ref gets `Remote image was not checked.` with
|
|
923
|
+
* `image:check-remote` -- unconditionally, for every remote image in the
|
|
924
|
+
* project.
|
|
868
925
|
*
|
|
869
|
-
* `val validate` resolves
|
|
870
|
-
* `createFixPatch` in report mode, which
|
|
871
|
-
* and
|
|
872
|
-
*
|
|
873
|
-
* (`partitionValidationErrors` in
|
|
926
|
+
* `val validate` resolves both by running the fix handler and then
|
|
927
|
+
* `createFixPatch` in report mode, which returns one error per real problem
|
|
928
|
+
* and nothing at all when there is none. The Studio cannot do that -- a
|
|
929
|
+
* browser has neither the filesystem nor the project's remote credentials --
|
|
930
|
+
* so it drops them wholesale (`partitionValidationErrors` in
|
|
931
|
+
* `@valbuild/shared`).
|
|
874
932
|
*
|
|
875
933
|
* An editor is in the CLI's position, not the browser's, and publishing the
|
|
876
934
|
* placeholders raw put a permanent warning on every image in the project. So
|
|
@@ -886,15 +944,42 @@ function traverseObjectLiteral(node, sourceFile) {
|
|
|
886
944
|
*/
|
|
887
945
|
const METADATA_CHECK_FIXES = ["image:check-metadata", "file:check-metadata"];
|
|
888
946
|
|
|
889
|
-
/**
|
|
947
|
+
/**
|
|
948
|
+
* The fixes that carry an unconditional remote-ref placeholder.
|
|
949
|
+
*
|
|
950
|
+
* The plural `images:check-remote` / `files:check-remote` are deliberately
|
|
951
|
+
* absent. `RecordSchema.validateMediaKey` emits those only for a key that is
|
|
952
|
+
* already wrong -- an unparseable remote URL, or one outside the gallery's
|
|
953
|
+
* directory -- and their messages say so. They are findings, not deferrals,
|
|
954
|
+
* and `createFixPatch` has no branch for them at all, so adjudicating one
|
|
955
|
+
* would come back empty and silently drop a real error.
|
|
956
|
+
*/
|
|
957
|
+
const REMOTE_CHECK_FIXES = ["image:check-remote", "file:check-remote"];
|
|
958
|
+
|
|
959
|
+
/** One thing about a media value that a real check found to be wrong. */
|
|
890
960
|
|
|
891
961
|
/**
|
|
892
|
-
* The verdict on one placeholder. Empty means the
|
|
893
|
-
* file and nothing should be
|
|
962
|
+
* The verdict on one placeholder. Empty means the check passed -- the metadata
|
|
963
|
+
* agrees with the file, or the remote ref is sound -- and nothing should be
|
|
964
|
+
* published.
|
|
965
|
+
*/
|
|
966
|
+
|
|
967
|
+
/**
|
|
968
|
+
* Whether this error is the unconditional remote-ref deferral.
|
|
969
|
+
*
|
|
970
|
+
* Unlike the metadata deferral this needs no re-derivation: `image:check-remote`
|
|
971
|
+
* is attached to exactly one error in `ImageSchema.executeValidate`, the
|
|
972
|
+
* fall-through for a remote schema with a remote path, and `FileSchema` mirrors
|
|
973
|
+
* it. Everything else a remote media field can be wrong about carries a
|
|
974
|
+
* different fix (`image:upload-remote`, `image:download-remote`) or none.
|
|
894
975
|
*/
|
|
976
|
+
function isDeferredRemoteCheck(error) {
|
|
977
|
+
return (error.fixes ?? []).some(fix => REMOTE_CHECK_FIXES.includes(fix));
|
|
978
|
+
}
|
|
895
979
|
|
|
896
980
|
/**
|
|
897
|
-
* Whether this error is the unconditional deferral rather than a real
|
|
981
|
+
* Whether this error is the unconditional METADATA deferral rather than a real
|
|
982
|
+
* finding.
|
|
898
983
|
*
|
|
899
984
|
* This is the whole difficulty of the change. `image:check-metadata` is
|
|
900
985
|
* attached to FIVE different image errors, and only the last is a placeholder:
|
|
@@ -913,7 +998,7 @@ const METADATA_CHECK_FIXES = ["image:check-metadata", "file:check-metadata"];
|
|
|
913
998
|
* There is no flag on `ValidationError` saying which is which, so the four
|
|
914
999
|
* conditions are re-derived here from the same inputs core used. They are
|
|
915
1000
|
* transcribed from `ImageSchema.executeValidate`, in its order, and
|
|
916
|
-
* `
|
|
1001
|
+
* `mediaChecks.test.ts` drives real core through all five cases to
|
|
917
1002
|
* check that this agrees with it. If core grows a sixth condition, that test is
|
|
918
1003
|
* what catches it.
|
|
919
1004
|
*
|
|
@@ -958,33 +1043,33 @@ function isDeferredMediaMetadataCheck({
|
|
|
958
1043
|
}
|
|
959
1044
|
|
|
960
1045
|
/**
|
|
961
|
-
*
|
|
962
|
-
*
|
|
1046
|
+
* Whether an error in a module is either deferral, resolving the schema the
|
|
1047
|
+
* metadata classification needs.
|
|
963
1048
|
*
|
|
964
1049
|
* Both the adjudicator and `createValDiagnostics` have to make the same call,
|
|
965
1050
|
* on the same inputs -- one to decide what to adjudicate, the other to decide
|
|
966
1051
|
* what to publish -- so it lives here rather than being written out twice.
|
|
967
1052
|
*/
|
|
968
|
-
function
|
|
1053
|
+
function isDeferredMediaCheckAt({
|
|
969
1054
|
sourcePath,
|
|
970
1055
|
error,
|
|
971
1056
|
content
|
|
972
1057
|
}) {
|
|
973
|
-
return isDeferredMediaMetadataCheck({
|
|
1058
|
+
return isDeferredRemoteCheck(error) || isDeferredMediaMetadataCheck({
|
|
974
1059
|
error,
|
|
975
1060
|
schema: resolveSchemaAt$1(sourcePath, content)
|
|
976
1061
|
});
|
|
977
1062
|
}
|
|
978
1063
|
|
|
979
1064
|
/**
|
|
980
|
-
* Adjudicate every deferred
|
|
1065
|
+
* Adjudicate every deferred media placeholder in `validation`.
|
|
981
1066
|
*
|
|
982
1067
|
* Async, and therefore separate from `createValDiagnostics`, which stays
|
|
983
1068
|
* synchronous so it can be tested without a project -- the same split
|
|
984
1069
|
* `resolveGalleryChecks` uses. The caller runs this first and passes the
|
|
985
1070
|
* result in.
|
|
986
1071
|
*/
|
|
987
|
-
async function
|
|
1072
|
+
async function resolveMediaChecks({
|
|
988
1073
|
validation,
|
|
989
1074
|
content,
|
|
990
1075
|
valRoot,
|
|
@@ -993,14 +1078,14 @@ async function resolveMediaMetadataChecks({
|
|
|
993
1078
|
const verdicts = new Map();
|
|
994
1079
|
for (const [sourcePath, errors] of Object.entries(validation)) {
|
|
995
1080
|
for (const error of errors) {
|
|
996
|
-
if (!
|
|
1081
|
+
if (!isDeferredMediaCheckAt({
|
|
997
1082
|
sourcePath,
|
|
998
1083
|
error,
|
|
999
1084
|
content
|
|
1000
1085
|
})) {
|
|
1001
1086
|
continue;
|
|
1002
1087
|
}
|
|
1003
|
-
const key =
|
|
1088
|
+
const key = mediaCheckKey(sourcePath, error);
|
|
1004
1089
|
try {
|
|
1005
1090
|
verdicts.set(key, await adjudicate({
|
|
1006
1091
|
sourcePath,
|
|
@@ -1012,7 +1097,7 @@ async function resolveMediaMetadataChecks({
|
|
|
1012
1097
|
} catch {
|
|
1013
1098
|
// This runs inside `validate`, which publishes NOTHING if it throws --
|
|
1014
1099
|
// one bad image would silently clear every Val diagnostic in the file.
|
|
1015
|
-
// Keep the placeholder rather than claiming the
|
|
1100
|
+
// Keep the placeholder rather than claiming the check passed.
|
|
1016
1101
|
verdicts.set(key, keep(error));
|
|
1017
1102
|
}
|
|
1018
1103
|
}
|
|
@@ -1024,7 +1109,7 @@ async function resolveMediaMetadataChecks({
|
|
|
1024
1109
|
* Key for one placeholder. A value can in principle carry more than one, so
|
|
1025
1110
|
* the fix names are part of the key -- as they are for the gallery checks.
|
|
1026
1111
|
*/
|
|
1027
|
-
function
|
|
1112
|
+
function mediaCheckKey(sourcePath, error) {
|
|
1028
1113
|
return `${sourcePath}|${(error.fixes ?? []).join(",")}`;
|
|
1029
1114
|
}
|
|
1030
1115
|
|
|
@@ -1044,6 +1129,17 @@ function keep(error) {
|
|
|
1044
1129
|
/**
|
|
1045
1130
|
* What `createFixPatch` says about one placeholder, in report mode.
|
|
1046
1131
|
*
|
|
1132
|
+
* Which placeholder decides only what has to be true before asking; the asking
|
|
1133
|
+
* is the same call either way, and `reportFixPatch` is it.
|
|
1134
|
+
*/
|
|
1135
|
+
async function adjudicate(args) {
|
|
1136
|
+
return isDeferredRemoteCheck(args.error) ? adjudicateRemote(args) : adjudicateMetadata(args);
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
/**
|
|
1140
|
+
* The metadata placeholder: does the stored width/height/mimeType match the
|
|
1141
|
+
* bytes?
|
|
1142
|
+
*
|
|
1047
1143
|
* `val validate` runs the fix handler first and then `createFixPatch`, but for
|
|
1048
1144
|
* these four fixes the handler is `handleFileMetadata`, whose whole job is the
|
|
1049
1145
|
* precondition "the ref resolves and the file is on disk". That precondition is
|
|
@@ -1065,7 +1161,7 @@ function keep(error) {
|
|
|
1065
1161
|
* `createFixPatch` reads and decodes the image itself, so this is one file read
|
|
1066
1162
|
* per media field per validation pass, and nothing here should add another.
|
|
1067
1163
|
*/
|
|
1068
|
-
async function
|
|
1164
|
+
async function adjudicateMetadata({
|
|
1069
1165
|
sourcePath,
|
|
1070
1166
|
error,
|
|
1071
1167
|
content,
|
|
@@ -1086,19 +1182,17 @@ async function adjudicate({
|
|
|
1086
1182
|
// means this verdict never has the last word on a file that is not there.
|
|
1087
1183
|
return keep(error);
|
|
1088
1184
|
}
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
false, sourcePath, error, {}, content.source, content.schema);
|
|
1098
|
-
} catch {
|
|
1185
|
+
const reported = await reportFixPatch({
|
|
1186
|
+
sourcePath,
|
|
1187
|
+
error,
|
|
1188
|
+
content,
|
|
1189
|
+
valRoot,
|
|
1190
|
+
remoteHost
|
|
1191
|
+
});
|
|
1192
|
+
if (reported === undefined) {
|
|
1099
1193
|
return keep(error);
|
|
1100
1194
|
}
|
|
1101
|
-
return
|
|
1195
|
+
return reported.map(remaining => ({
|
|
1102
1196
|
message: remaining.message,
|
|
1103
1197
|
// `createFixPatch` clears `fixes` on the per-field errors it reports, but
|
|
1104
1198
|
// the fix is still available and still the remedy -- it is what the
|
|
@@ -1114,6 +1208,77 @@ async function adjudicate({
|
|
|
1114
1208
|
}));
|
|
1115
1209
|
}
|
|
1116
1210
|
|
|
1211
|
+
/**
|
|
1212
|
+
* The remote-ref placeholder: is the ref this value carries still the ref the
|
|
1213
|
+
* bytes behind it produce?
|
|
1214
|
+
*
|
|
1215
|
+
* `handleRemoteFileCheck` is a no-op that asks for the patch, so unlike the
|
|
1216
|
+
* metadata case there is no precondition of its own to stand in for -- the
|
|
1217
|
+
* whole check is `checkRemoteRef` inside `createFixPatch`. It recomputes the
|
|
1218
|
+
* validation hash from the schema, the file extension, the metadata on the
|
|
1219
|
+
* value and the file hash in the ref; when that agrees with the ref, nothing is
|
|
1220
|
+
* downloaded and nothing is reported. Only a ref that no longer adds up costs a
|
|
1221
|
+
* download, and that is cached under `.val/remote-file-cache`.
|
|
1222
|
+
*
|
|
1223
|
+
* The findings deliberately carry no `fixes`. `createFixPatch` clears them
|
|
1224
|
+
* (`Remote ref: ... is not valid. Use the --fix flag to fix this issue.`
|
|
1225
|
+
* arrives with `fixes: undefined`), no quick fix is registered for
|
|
1226
|
+
* `image:check-remote` -- rewriting the ref needs the bytes off the content
|
|
1227
|
+
* host, so it is `val validate --fix`'s job, not a lightbulb's -- and dropping
|
|
1228
|
+
* them is what makes this an Error rather than a Warning, matching the `✘` the
|
|
1229
|
+
* CLI prints for the same finding.
|
|
1230
|
+
*/
|
|
1231
|
+
async function adjudicateRemote({
|
|
1232
|
+
sourcePath,
|
|
1233
|
+
error,
|
|
1234
|
+
content,
|
|
1235
|
+
valRoot,
|
|
1236
|
+
remoteHost
|
|
1237
|
+
}) {
|
|
1238
|
+
const reported = await reportFixPatch({
|
|
1239
|
+
sourcePath,
|
|
1240
|
+
error,
|
|
1241
|
+
content,
|
|
1242
|
+
valRoot,
|
|
1243
|
+
remoteHost
|
|
1244
|
+
});
|
|
1245
|
+
if (reported === undefined) {
|
|
1246
|
+
return keep(error);
|
|
1247
|
+
}
|
|
1248
|
+
return reported.map(remaining => ({
|
|
1249
|
+
message: remaining.message,
|
|
1250
|
+
...(error.value !== undefined ? {
|
|
1251
|
+
value: error.value
|
|
1252
|
+
} : {})
|
|
1253
|
+
}));
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
/**
|
|
1257
|
+
* `createFixPatch` in report mode, or `undefined` if it could not answer.
|
|
1258
|
+
*
|
|
1259
|
+
* `false` is the load-bearing argument: this is a question, not a fix. Asking
|
|
1260
|
+
* for the patch would have `createFixPatch` read and rewrite files behind the
|
|
1261
|
+
* editor's back -- and, for a remote ref, re-derive one from bytes it had to
|
|
1262
|
+
* download first.
|
|
1263
|
+
*/
|
|
1264
|
+
async function reportFixPatch({
|
|
1265
|
+
sourcePath,
|
|
1266
|
+
error,
|
|
1267
|
+
content,
|
|
1268
|
+
valRoot,
|
|
1269
|
+
remoteHost
|
|
1270
|
+
}) {
|
|
1271
|
+
try {
|
|
1272
|
+
const fixed = await server.createFixPatch({
|
|
1273
|
+
projectRoot: valRoot,
|
|
1274
|
+
remoteHost
|
|
1275
|
+
}, false, sourcePath, error, {}, content.source, content.schema);
|
|
1276
|
+
return fixed?.remainingErrors ?? [];
|
|
1277
|
+
} catch {
|
|
1278
|
+
return undefined;
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1117
1282
|
/**
|
|
1118
1283
|
* The `accept` a media schema declares, if any.
|
|
1119
1284
|
*
|
|
@@ -1238,8 +1403,18 @@ const FALLBACK_RANGE = {
|
|
|
1238
1403
|
}
|
|
1239
1404
|
};
|
|
1240
1405
|
|
|
1241
|
-
/**
|
|
1242
|
-
|
|
1406
|
+
/**
|
|
1407
|
+
* Fixes that operate on a LOCAL file or image reference.
|
|
1408
|
+
*
|
|
1409
|
+
* `*:check-remote` is deliberately absent. A remote value's bytes are on the
|
|
1410
|
+
* content host by design, so "is it on disk" is never its question -- and for
|
|
1411
|
+
* a path that is neither under `/public` nor a parseable remote ref, this
|
|
1412
|
+
* check answered "File <root>/... does not exist" and pre-empted the remote
|
|
1413
|
+
* adjudication, which has the real answer ("Invalid remote ref: ..."). The
|
|
1414
|
+
* upload/download fixes stay: `*:upload-remote` is reported on a local path
|
|
1415
|
+
* and a missing file really is its problem.
|
|
1416
|
+
*/
|
|
1417
|
+
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"];
|
|
1243
1418
|
function build(range, message, data) {
|
|
1244
1419
|
return {
|
|
1245
1420
|
range,
|
|
@@ -1257,7 +1432,7 @@ function createValDiagnostics({
|
|
|
1257
1432
|
valRoot,
|
|
1258
1433
|
snapshot,
|
|
1259
1434
|
galleryChecks,
|
|
1260
|
-
|
|
1435
|
+
mediaChecks
|
|
1261
1436
|
}) {
|
|
1262
1437
|
if (content.errors === false) {
|
|
1263
1438
|
return [];
|
|
@@ -1329,18 +1504,20 @@ function createValDiagnostics({
|
|
|
1329
1504
|
continue;
|
|
1330
1505
|
}
|
|
1331
1506
|
|
|
1332
|
-
// An unconditional media
|
|
1333
|
-
// `image:check-metadata` on every `s.image()` carrying metadata
|
|
1334
|
-
// or not it disagrees with the file
|
|
1335
|
-
//
|
|
1336
|
-
// the
|
|
1337
|
-
//
|
|
1338
|
-
|
|
1507
|
+
// An unconditional media placeholder: core reports
|
|
1508
|
+
// `image:check-metadata` on every `s.image()` carrying metadata whether
|
|
1509
|
+
// or not it disagrees with the file, and `Remote image was not checked.`
|
|
1510
|
+
// on every remote image whether or not its ref is stale. Show only what
|
|
1511
|
+
// the adjudication actually found, and nothing when it found nothing.
|
|
1512
|
+
// Deliberately after the missing-file branch above, so a deleted file is
|
|
1513
|
+
// still reported as `val/file-not-found` rather than as a metadata
|
|
1514
|
+
// mismatch.
|
|
1515
|
+
if (isDeferredMediaCheckAt({
|
|
1339
1516
|
sourcePath,
|
|
1340
1517
|
error,
|
|
1341
1518
|
content
|
|
1342
1519
|
})) {
|
|
1343
|
-
const verdict =
|
|
1520
|
+
const verdict = mediaChecks?.get(mediaCheckKey(sourcePath, error));
|
|
1344
1521
|
for (const finding of verdict ?? []) {
|
|
1345
1522
|
diagnostics.push(build(rangeOf(sourcePath, modulePathMap), finding.message, {
|
|
1346
1523
|
code: "val/validation",
|
|
@@ -4069,9 +4246,11 @@ function createValLanguageServer(connection) {
|
|
|
4069
4246
|
})
|
|
4070
4247
|
}) : undefined;
|
|
4071
4248
|
// Core also defers "does this image's stored metadata match its file",
|
|
4072
|
-
// reporting it on every `s.image()` that carries any metadata
|
|
4073
|
-
//
|
|
4074
|
-
|
|
4249
|
+
// reporting it on every `s.image()` that carries any metadata, and
|
|
4250
|
+
// "is this remote ref still valid", reporting it on every remote image.
|
|
4251
|
+
// Same treatment: adjudicate with the fix machinery before showing
|
|
4252
|
+
// anything.
|
|
4253
|
+
const mediaChecks = result.content.errors !== false && result.content.errors.validation ? await resolveMediaChecks({
|
|
4075
4254
|
validation: result.content.errors.validation,
|
|
4076
4255
|
content: result.content,
|
|
4077
4256
|
valRoot: activeProject.valRoot
|
|
@@ -4087,8 +4266,8 @@ function createValLanguageServer(connection) {
|
|
|
4087
4266
|
...(galleryChecks ? {
|
|
4088
4267
|
galleryChecks
|
|
4089
4268
|
} : {}),
|
|
4090
|
-
...(
|
|
4091
|
-
|
|
4269
|
+
...(mediaChecks ? {
|
|
4270
|
+
mediaChecks
|
|
4092
4271
|
} : {})
|
|
4093
4272
|
});
|
|
4094
4273
|
const unregistered = findMissingModuleDiagnostic(project.valRoot, moduleFilePath, readOpenDocument);
|