@abco20/btxml-checker 0.1.3 → 0.1.5
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/dist/cli.js +42 -29
- package/dist/editor-node.js +21 -21
- package/dist/editor.js +19 -19
- package/dist/index.d.ts +30 -0
- package/dist/index.js +7 -7
- package/dist/rules.d.ts +9 -3
- package/dist/rules.js +4 -4
- package/dist/server.cjs +323 -95
- package/dist/server.cjs.map +1 -1
- package/package.json +1 -1
- package/schemas/btxml.config.schema.json +2 -0
package/dist/server.cjs
CHANGED
|
@@ -34993,6 +34993,7 @@ var RuleCodes = {
|
|
|
34993
34993
|
ConflictingModelKind: "BT120_CONFLICTING_MODEL_KIND",
|
|
34994
34994
|
UnusedModelDefinition: "BT121_UNUSED_MODEL_DEFINITION",
|
|
34995
34995
|
DuplicateModelDefinition: "BT122_DUPLICATE_MODEL_DEFINITION",
|
|
34996
|
+
MissingLocalModelDefinition: "BT123_MISSING_LOCAL_MODEL_DEFINITION",
|
|
34996
34997
|
ExternalModelFileNotFound: "BT321_EXTERNAL_MODEL_FILE_NOT_FOUND",
|
|
34997
34998
|
AugmentationFileNotFound: "BT324_AUGMENTATION_FILE_NOT_FOUND",
|
|
34998
34999
|
MissingTreeNodesModel: "BT322_MISSING_TREENODESMODEL",
|
|
@@ -35213,8 +35214,8 @@ var RULES = {
|
|
|
35213
35214
|
},
|
|
35214
35215
|
"model/require-output-port-remap": {
|
|
35215
35216
|
code: RuleCodes.OutputPortRequiresRemap,
|
|
35216
|
-
defaultSeverity: "
|
|
35217
|
-
description: "Resolved output ports must
|
|
35217
|
+
defaultSeverity: "error",
|
|
35218
|
+
description: "Resolved output ports must be explicitly or default-remapped to a blackboard entry."
|
|
35218
35219
|
},
|
|
35219
35220
|
"model/no-childless-control-shape-mismatch": {
|
|
35220
35221
|
code: RuleCodes.ChildCapableNodeSelfClosing,
|
|
@@ -35246,6 +35247,11 @@ var RULES = {
|
|
|
35246
35247
|
defaultSeverity: "error",
|
|
35247
35248
|
description: "Inline model definitions should be used in the same BT XML file."
|
|
35248
35249
|
},
|
|
35250
|
+
"model/require-local-definition": {
|
|
35251
|
+
code: RuleCodes.MissingLocalModelDefinition,
|
|
35252
|
+
defaultSeverity: "error",
|
|
35253
|
+
description: "When models.convention is used-only, normal node usages should have a local TreeNodesModel definition in the same file."
|
|
35254
|
+
},
|
|
35249
35255
|
"model/no-duplicate-definition": {
|
|
35250
35256
|
code: RuleCodes.DuplicateModelDefinition,
|
|
35251
35257
|
defaultSeverity: "error",
|
|
@@ -39197,6 +39203,8 @@ async function resolveIncludeGraph(input) {
|
|
|
39197
39203
|
var RULE_CONFLICTING_KIND = "model/no-conflicting-kind-for-id";
|
|
39198
39204
|
var RULE_UNUSED_DEFINITION = "model/no-unused-definition";
|
|
39199
39205
|
var RULE_DUPLICATE_DEFINITION = "model/no-duplicate-definition";
|
|
39206
|
+
var RULE_REQUIRE_LOCAL_DEFINITION = "model/require-local-definition";
|
|
39207
|
+
var NORMAL_MODEL_KINDS = /* @__PURE__ */ new Set(["Action", "Condition", "Decorator", "Control"]);
|
|
39200
39208
|
function createConventionDiagnostic(input) {
|
|
39201
39209
|
const diagnostic = createDiagnostic(
|
|
39202
39210
|
input.code,
|
|
@@ -39223,6 +39231,9 @@ function resolveConventionSeverity(config2, rule) {
|
|
|
39223
39231
|
function definitionRange(definition) {
|
|
39224
39232
|
return definition.model.idRange ?? definition.range;
|
|
39225
39233
|
}
|
|
39234
|
+
function definitionDeleteRange(definition) {
|
|
39235
|
+
return definition.range;
|
|
39236
|
+
}
|
|
39226
39237
|
function definitionInfo(definition) {
|
|
39227
39238
|
return {
|
|
39228
39239
|
uri: definition.uri,
|
|
@@ -39231,6 +39242,30 @@ function definitionInfo(definition) {
|
|
|
39231
39242
|
range: definition.range
|
|
39232
39243
|
};
|
|
39233
39244
|
}
|
|
39245
|
+
function isNormalModelKind(kind) {
|
|
39246
|
+
return NORMAL_MODEL_KINDS.has(kind);
|
|
39247
|
+
}
|
|
39248
|
+
function toFixableModel(index, id) {
|
|
39249
|
+
const resolved = getNodeModel(index, id);
|
|
39250
|
+
if (!resolved) return void 0;
|
|
39251
|
+
if (!isNormalModelKind(resolved.kind)) return void 0;
|
|
39252
|
+
const hasConflict = getModelConflicts(index).some(
|
|
39253
|
+
(conflict) => conflict.id === id && (conflict.code === "BT012_CONFLICTING_NODE_MODEL" || conflict.code === "BT107_CONFLICTING_PORT_DEFAULT")
|
|
39254
|
+
);
|
|
39255
|
+
if (hasConflict) return void 0;
|
|
39256
|
+
return {
|
|
39257
|
+
id: resolved.id,
|
|
39258
|
+
kind: resolved.kind,
|
|
39259
|
+
ports: resolved.ports.map((port) => ({
|
|
39260
|
+
direction: port.direction,
|
|
39261
|
+
name: port.name,
|
|
39262
|
+
type: port.type,
|
|
39263
|
+
defaultValue: port.defaultValue,
|
|
39264
|
+
description: port.description,
|
|
39265
|
+
enum: port.enum
|
|
39266
|
+
}))
|
|
39267
|
+
};
|
|
39268
|
+
}
|
|
39234
39269
|
function validateConflictingKinds(input) {
|
|
39235
39270
|
const severity = resolveConventionSeverity(input.config, RULE_CONFLICTING_KIND);
|
|
39236
39271
|
if (!severity) return [];
|
|
@@ -39274,17 +39309,75 @@ function validateConflictingKinds(input) {
|
|
|
39274
39309
|
function validateUsedOnly(input) {
|
|
39275
39310
|
if (input.config.models.convention !== "used-only") return [];
|
|
39276
39311
|
const severity = resolveConventionSeverity(input.config, RULE_UNUSED_DEFINITION);
|
|
39277
|
-
|
|
39312
|
+
const missingSeverity = resolveConventionSeverity(input.config, RULE_REQUIRE_LOCAL_DEFINITION);
|
|
39313
|
+
if (!severity && !missingSeverity) return [];
|
|
39278
39314
|
const diagnostics = [];
|
|
39279
39315
|
const usagesByUri = getNodeUsagesByUri(input.index);
|
|
39280
|
-
|
|
39281
|
-
|
|
39316
|
+
const allInlineByUri = buildAllInlineDefinitionsByUri(input.facts);
|
|
39317
|
+
const localNormalByUri = buildLocalNormalDefinitionsByUri(input.facts);
|
|
39318
|
+
const relevantUris = /* @__PURE__ */ new Set([
|
|
39319
|
+
...usagesByUri.keys(),
|
|
39320
|
+
...localNormalByUri.keys(),
|
|
39321
|
+
...allInlineByUri.keys()
|
|
39322
|
+
]);
|
|
39323
|
+
for (const uri of relevantUris) {
|
|
39324
|
+
const sameFileNodeUsages = usagesByUri.get(uri) ?? [];
|
|
39325
|
+
const usedNodeIds = getUsedNodeIds(sameFileNodeUsages);
|
|
39326
|
+
const localNormalDefinitions = localNormalByUri.get(uri) ?? [];
|
|
39327
|
+
const localNormalIds = new Set(localNormalDefinitions.map((definition) => definition.id));
|
|
39328
|
+
const localAnyIds = new Set((allInlineByUri.get(uri) ?? []).map((definition) => definition.id));
|
|
39329
|
+
if (severity) {
|
|
39330
|
+
diagnostics.push(
|
|
39331
|
+
...createUnusedDefinitionDiagnostics(localNormalDefinitions, usedNodeIds, severity)
|
|
39332
|
+
);
|
|
39333
|
+
}
|
|
39334
|
+
if (missingSeverity) {
|
|
39335
|
+
diagnostics.push(
|
|
39336
|
+
...createMissingLocalDefinitionDiagnostics({
|
|
39337
|
+
index: input.index,
|
|
39338
|
+
uri,
|
|
39339
|
+
usedNodeIds,
|
|
39340
|
+
localNormalIds,
|
|
39341
|
+
localAnyIds,
|
|
39342
|
+
sameFileNodeUsages,
|
|
39343
|
+
severity: missingSeverity
|
|
39344
|
+
})
|
|
39345
|
+
);
|
|
39346
|
+
}
|
|
39347
|
+
}
|
|
39348
|
+
return diagnostics;
|
|
39349
|
+
}
|
|
39350
|
+
function buildAllInlineDefinitionsByUri(facts) {
|
|
39351
|
+
const allInlineByUri = /* @__PURE__ */ new Map();
|
|
39352
|
+
for (const definition of facts) {
|
|
39282
39353
|
if (definition.sourceKind !== "inline-tree-nodes-model") continue;
|
|
39283
|
-
if (definition.
|
|
39284
|
-
const
|
|
39285
|
-
|
|
39286
|
-
|
|
39287
|
-
|
|
39354
|
+
if (!definition.uri) continue;
|
|
39355
|
+
const allInline = allInlineByUri.get(definition.uri) ?? [];
|
|
39356
|
+
allInline.push(definition);
|
|
39357
|
+
allInlineByUri.set(definition.uri, allInline);
|
|
39358
|
+
}
|
|
39359
|
+
return allInlineByUri;
|
|
39360
|
+
}
|
|
39361
|
+
function buildLocalNormalDefinitionsByUri(facts) {
|
|
39362
|
+
const localNormalByUri = /* @__PURE__ */ new Map();
|
|
39363
|
+
for (const definition of facts) {
|
|
39364
|
+
if (definition.sourceKind !== "inline-tree-nodes-model") continue;
|
|
39365
|
+
if (!definition.uri) continue;
|
|
39366
|
+
if (!isNormalModelKind(definition.kind)) continue;
|
|
39367
|
+
const localNormal = localNormalByUri.get(definition.uri) ?? [];
|
|
39368
|
+
localNormal.push(definition);
|
|
39369
|
+
localNormalByUri.set(definition.uri, localNormal);
|
|
39370
|
+
}
|
|
39371
|
+
return localNormalByUri;
|
|
39372
|
+
}
|
|
39373
|
+
function getUsedNodeIds(sameFileNodeUsages) {
|
|
39374
|
+
return new Set(
|
|
39375
|
+
sameFileNodeUsages.filter((usage) => usage.kind === "node").map((usage) => usage.id)
|
|
39376
|
+
);
|
|
39377
|
+
}
|
|
39378
|
+
function createUnusedDefinitionDiagnostics(localNormalDefinitions, usedNodeIds, severity) {
|
|
39379
|
+
const diagnostics = [];
|
|
39380
|
+
for (const definition of localNormalDefinitions) {
|
|
39288
39381
|
if (usedNodeIds.has(definition.id)) continue;
|
|
39289
39382
|
diagnostics.push(
|
|
39290
39383
|
createConventionDiagnostic({
|
|
@@ -39299,10 +39392,47 @@ function validateUsedOnly(input) {
|
|
|
39299
39392
|
nodeId: definition.id,
|
|
39300
39393
|
modelKind: definition.kind,
|
|
39301
39394
|
sourceKind: "inline-tree-nodes-model",
|
|
39302
|
-
fix: definition.uri &&
|
|
39395
|
+
fix: definition.uri && definitionDeleteRange(definition) && definition.editable ? {
|
|
39303
39396
|
kind: "delete-definition",
|
|
39304
39397
|
uri: definition.uri,
|
|
39305
|
-
range:
|
|
39398
|
+
range: definitionDeleteRange(definition)
|
|
39399
|
+
} : void 0
|
|
39400
|
+
}
|
|
39401
|
+
})
|
|
39402
|
+
);
|
|
39403
|
+
}
|
|
39404
|
+
return diagnostics;
|
|
39405
|
+
}
|
|
39406
|
+
function createMissingLocalDefinitionDiagnostics(input) {
|
|
39407
|
+
const diagnostics = [];
|
|
39408
|
+
for (const nodeId of input.usedNodeIds) {
|
|
39409
|
+
if (input.localNormalIds.has(nodeId)) continue;
|
|
39410
|
+
const hasNormalModel = getNodeModelDefinitions(input.index, nodeId).some(
|
|
39411
|
+
(definition) => isNormalModelKind(definition.kind)
|
|
39412
|
+
);
|
|
39413
|
+
if (!hasNormalModel) continue;
|
|
39414
|
+
const hasNonNormalLocalDefinition = input.localAnyIds.has(nodeId);
|
|
39415
|
+
const firstUsage = input.sameFileNodeUsages.find(
|
|
39416
|
+
(usage) => usage.kind === "node" && usage.id === nodeId
|
|
39417
|
+
);
|
|
39418
|
+
const fixableModel = hasNonNormalLocalDefinition ? void 0 : toFixableModel(input.index, nodeId);
|
|
39419
|
+
diagnostics.push(
|
|
39420
|
+
createConventionDiagnostic({
|
|
39421
|
+
code: "BT123_MISSING_LOCAL_MODEL_DEFINITION",
|
|
39422
|
+
message: `missing local model definition \`${nodeId}\` in this file`,
|
|
39423
|
+
uri: input.uri,
|
|
39424
|
+
range: firstUsage?.elementRange ?? firstUsage?.range,
|
|
39425
|
+
rule: RULE_REQUIRE_LOCAL_DEFINITION,
|
|
39426
|
+
severity: input.severity,
|
|
39427
|
+
data: {
|
|
39428
|
+
kind: "missing-local-model-definition",
|
|
39429
|
+
nodeId,
|
|
39430
|
+
sourceKind: "inline-tree-nodes-model",
|
|
39431
|
+
fix: fixableModel && input.uri ? {
|
|
39432
|
+
kind: "add-local-definition",
|
|
39433
|
+
uri: input.uri,
|
|
39434
|
+
nodeId,
|
|
39435
|
+
model: fixableModel
|
|
39306
39436
|
} : void 0
|
|
39307
39437
|
}
|
|
39308
39438
|
})
|
|
@@ -39317,7 +39447,7 @@ function duplicateFix(definitions) {
|
|
|
39317
39447
|
if (!keep?.uri) return void 0;
|
|
39318
39448
|
const deleteTargets = definitions.filter((definition) => definition !== keep);
|
|
39319
39449
|
if (deleteTargets.some(
|
|
39320
|
-
(definition) => !definition.uri || !
|
|
39450
|
+
(definition) => !definition.uri || !definitionDeleteRange(definition) || !definition.editable
|
|
39321
39451
|
)) {
|
|
39322
39452
|
return void 0;
|
|
39323
39453
|
}
|
|
@@ -39329,7 +39459,7 @@ function duplicateFix(definitions) {
|
|
|
39329
39459
|
},
|
|
39330
39460
|
delete: deleteTargets.map((definition) => ({
|
|
39331
39461
|
uri: definition.uri,
|
|
39332
|
-
range:
|
|
39462
|
+
range: definitionDeleteRange(definition)
|
|
39333
39463
|
}))
|
|
39334
39464
|
};
|
|
39335
39465
|
}
|
|
@@ -40256,7 +40386,9 @@ var modelRules = [
|
|
|
40256
40386
|
}),
|
|
40257
40387
|
makeRuleModule({
|
|
40258
40388
|
name: "model/valid-port-name",
|
|
40259
|
-
meta: {
|
|
40389
|
+
meta: {
|
|
40390
|
+
description: "Port names must be valid XML attribute names for BT nodes."
|
|
40391
|
+
},
|
|
40260
40392
|
create(context) {
|
|
40261
40393
|
return {
|
|
40262
40394
|
TreeNodeModel(node) {
|
|
@@ -40301,7 +40433,9 @@ var modelRules = [
|
|
|
40301
40433
|
}),
|
|
40302
40434
|
makeRuleModule({
|
|
40303
40435
|
name: "model/valid-port-default-value",
|
|
40304
|
-
meta: {
|
|
40436
|
+
meta: {
|
|
40437
|
+
description: "TreeNodesModel port defaults must match the declared type."
|
|
40438
|
+
},
|
|
40305
40439
|
create(context) {
|
|
40306
40440
|
return {
|
|
40307
40441
|
Element(element) {
|
|
@@ -40411,7 +40545,7 @@ var modelRules = [
|
|
|
40411
40545
|
makeRuleModule({
|
|
40412
40546
|
name: "model/require-output-port-remap",
|
|
40413
40547
|
meta: {
|
|
40414
|
-
description: "Resolved output ports must
|
|
40548
|
+
description: "Resolved output ports must be explicitly or default-remapped to a blackboard entry."
|
|
40415
40549
|
},
|
|
40416
40550
|
create(context) {
|
|
40417
40551
|
return {
|
|
@@ -40419,19 +40553,34 @@ var modelRules = [
|
|
|
40419
40553
|
if (isStructuralElement2(element)) return;
|
|
40420
40554
|
const usage = context.getNodeUsage(element);
|
|
40421
40555
|
if (usage.model.status !== "resolved" && usage.tagForm !== "subtree") return;
|
|
40422
|
-
for (const
|
|
40423
|
-
|
|
40424
|
-
|
|
40425
|
-
|
|
40426
|
-
|
|
40556
|
+
for (const port of usage.ports) {
|
|
40557
|
+
if (port.direction !== "output") continue;
|
|
40558
|
+
const binding = usage.portUsages.find(
|
|
40559
|
+
(candidate) => candidate.name === port.name && candidate.status === "resolved"
|
|
40560
|
+
);
|
|
40561
|
+
if (binding) {
|
|
40562
|
+
if (getExactBlackboardReference(port.name, binding.value) !== void 0) continue;
|
|
40563
|
+
context.report({
|
|
40564
|
+
code: RuleCodes.OutputPortRequiresRemap,
|
|
40565
|
+
message: `output port \`${port.name}\` must be remapped to a blackboard entry`,
|
|
40566
|
+
range: binding.attribute.range,
|
|
40567
|
+
details: {
|
|
40568
|
+
primaryLabel: `output port \`${port.name}\` requires a blackboard remap`,
|
|
40569
|
+
help: `use \`${port.name}="{${port.name}}"\` or \`${port.name}="{some_key}"\``
|
|
40570
|
+
}
|
|
40571
|
+
});
|
|
40572
|
+
continue;
|
|
40573
|
+
}
|
|
40574
|
+
if (port.defaultValue !== void 0 && getExactBlackboardReference(port.name, port.defaultValue) !== void 0) {
|
|
40427
40575
|
continue;
|
|
40576
|
+
}
|
|
40428
40577
|
context.report({
|
|
40429
40578
|
code: RuleCodes.OutputPortRequiresRemap,
|
|
40430
|
-
message: `output port \`${
|
|
40431
|
-
range:
|
|
40579
|
+
message: `output port \`${port.name}\` must be remapped to a blackboard entry`,
|
|
40580
|
+
range: element.range,
|
|
40432
40581
|
details: {
|
|
40433
|
-
primaryLabel: `output port \`${
|
|
40434
|
-
help: `use \`${
|
|
40582
|
+
primaryLabel: `output port \`${port.name}\` requires a blackboard remap`,
|
|
40583
|
+
help: `use \`${port.name}="{${port.name}}"\` or \`${port.name}="{some_key}"\``
|
|
40435
40584
|
}
|
|
40436
40585
|
});
|
|
40437
40586
|
}
|
|
@@ -44002,12 +44151,15 @@ function removeAttributeEdit(document, attribute) {
|
|
|
44002
44151
|
return { range, newText: "" };
|
|
44003
44152
|
}
|
|
44004
44153
|
function addAttributeEdit(document, element, name) {
|
|
44154
|
+
return addAttributeWithValueEdit(document, element, name, "");
|
|
44155
|
+
}
|
|
44156
|
+
function addAttributeWithValueEdit(document, element, name, value) {
|
|
44005
44157
|
const closeOffset = Math.max(
|
|
44006
44158
|
element.openTagRange.end.offset - (element.selfClosing ? 2 : 1),
|
|
44007
44159
|
element.openTagRange.start.offset
|
|
44008
44160
|
);
|
|
44009
44161
|
const pos = document.positionAt(closeOffset);
|
|
44010
|
-
return { range: sourceRange(pos, pos), newText: ` ${name}=""` };
|
|
44162
|
+
return { range: sourceRange(pos, pos), newText: ` ${name}="${value}"` };
|
|
44011
44163
|
}
|
|
44012
44164
|
|
|
44013
44165
|
// ../language-service/src/ranges.ts
|
|
@@ -44028,84 +44180,160 @@ function getCodeActions(context, input) {
|
|
|
44028
44180
|
});
|
|
44029
44181
|
}
|
|
44030
44182
|
for (const diag of diagnostics) {
|
|
44031
|
-
if (!diag
|
|
44183
|
+
if (!hasRange(diag)) continue;
|
|
44032
44184
|
const inspect = inspectXmlCursor({
|
|
44033
44185
|
document: input.document,
|
|
44034
44186
|
parsed: context.parsed,
|
|
44035
44187
|
position: diag.range.start
|
|
44036
44188
|
});
|
|
44037
|
-
|
|
44038
|
-
|
|
44039
|
-
|
|
44040
|
-
|
|
44041
|
-
|
|
44042
|
-
|
|
44043
|
-
|
|
44044
|
-
|
|
44045
|
-
|
|
44046
|
-
|
|
44047
|
-
|
|
44048
|
-
|
|
44049
|
-
|
|
44050
|
-
|
|
44051
|
-
|
|
44052
|
-
|
|
44053
|
-
|
|
44054
|
-
|
|
44055
|
-
|
|
44056
|
-
|
|
44057
|
-
|
|
44058
|
-
|
|
44059
|
-
|
|
44060
|
-
|
|
44061
|
-
|
|
44062
|
-
|
|
44063
|
-
|
|
44064
|
-
|
|
44065
|
-
|
|
44066
|
-
|
|
44067
|
-
|
|
44068
|
-
|
|
44069
|
-
|
|
44070
|
-
|
|
44071
|
-
|
|
44072
|
-
|
|
44073
|
-
|
|
44074
|
-
|
|
44075
|
-
|
|
44076
|
-
|
|
44077
|
-
|
|
44078
|
-
|
|
44079
|
-
|
|
44080
|
-
|
|
44081
|
-
|
|
44082
|
-
}
|
|
44083
|
-
|
|
44084
|
-
|
|
44085
|
-
|
|
44086
|
-
|
|
44189
|
+
const target = resolveTargetElement(context, input, diag, inspect);
|
|
44190
|
+
addMissingRequiredPortAction(actions, context, input, diag.code, diag, target);
|
|
44191
|
+
addOutputRemapAction(actions, context, input, diag.code, diag, inspect, target);
|
|
44192
|
+
addUnknownPortAction(actions, context, input, diag.code, diag, inspect);
|
|
44193
|
+
addMissingBtcppFormatAction(actions, context, input, diag.code, diag);
|
|
44194
|
+
addSuppressionAction(actions, input, diag);
|
|
44195
|
+
}
|
|
44196
|
+
return { actions };
|
|
44197
|
+
}
|
|
44198
|
+
function hasRange(diag) {
|
|
44199
|
+
return !!diag.range;
|
|
44200
|
+
}
|
|
44201
|
+
function isResolvedPortUsage(binding) {
|
|
44202
|
+
return binding.status === "resolved";
|
|
44203
|
+
}
|
|
44204
|
+
function resolveUsage(context, input, element) {
|
|
44205
|
+
return resolveNodeUsage(context.semantic, {
|
|
44206
|
+
element,
|
|
44207
|
+
documentRoot: context.parsed?.root,
|
|
44208
|
+
uri: input.document.uri,
|
|
44209
|
+
config: context.config,
|
|
44210
|
+
policy: context.nodeUsagePolicy
|
|
44211
|
+
});
|
|
44212
|
+
}
|
|
44213
|
+
function inspectElement(inspect) {
|
|
44214
|
+
return "element" in inspect ? inspect.element : void 0;
|
|
44215
|
+
}
|
|
44216
|
+
function resolveTargetElement(context, input, diag, inspect) {
|
|
44217
|
+
const fallback = inspectElement(inspect);
|
|
44218
|
+
const root = context.parsed?.root;
|
|
44219
|
+
if (!root || !diag.range) return fallback;
|
|
44220
|
+
const targetOffset = Math.min(diag.range.start.offset + 1, diag.range.end.offset);
|
|
44221
|
+
return findElementAt(root, targetOffset) ?? fallback;
|
|
44222
|
+
}
|
|
44223
|
+
function addMissingRequiredPortAction(actions, context, input, code, diag, target) {
|
|
44224
|
+
if (code !== "BT101_MISSING_REQUIRED_PORT") return;
|
|
44225
|
+
if (!target) return;
|
|
44226
|
+
const usage = resolveUsage(context, input, target);
|
|
44227
|
+
const missing = usage.ports.find(
|
|
44228
|
+
(port) => port.required && !usage.portUsages.some(
|
|
44229
|
+
(binding) => binding.status === "resolved" && binding.name === port.name
|
|
44230
|
+
)
|
|
44231
|
+
);
|
|
44232
|
+
if (!missing) return;
|
|
44233
|
+
actions.push({
|
|
44234
|
+
title: `Add missing port ${missing.name}`,
|
|
44235
|
+
kind: "quickfix",
|
|
44236
|
+
diagnostics: [diag],
|
|
44237
|
+
edits: [addAttributeEdit(input.document, target, missing.name)]
|
|
44238
|
+
});
|
|
44239
|
+
}
|
|
44240
|
+
function addOutputRemapAction(actions, context, input, code, diag, inspect, target) {
|
|
44241
|
+
if (code !== "BT115_OUTPUT_PORT_REQUIRES_REMAP") return;
|
|
44242
|
+
if (!target) return;
|
|
44243
|
+
const outputPortName = /`([^`]+)`/.exec(diag.message)?.[1];
|
|
44244
|
+
const usage = resolveUsage(context, input, target);
|
|
44245
|
+
const attribute = "attribute" in inspect ? inspect.attribute : void 0;
|
|
44246
|
+
if (attribute) {
|
|
44247
|
+
const binding = usage.portUsages.find(
|
|
44248
|
+
(candidate) => isResolvedPortUsage(candidate) && candidate.port.direction === "output" && candidate.attribute === attribute && (!outputPortName || candidate.port.name === outputPortName)
|
|
44249
|
+
);
|
|
44250
|
+
if (binding) {
|
|
44087
44251
|
actions.push({
|
|
44088
|
-
title:
|
|
44252
|
+
title: `Remap output port ${binding.port.name}`,
|
|
44089
44253
|
kind: "quickfix",
|
|
44090
44254
|
diagnostics: [diag],
|
|
44091
|
-
edits: [
|
|
44255
|
+
edits: [
|
|
44256
|
+
{
|
|
44257
|
+
range: attribute.valueContentRange ?? attribute.valueRange,
|
|
44258
|
+
newText: `{${binding.port.name}}`
|
|
44259
|
+
}
|
|
44260
|
+
]
|
|
44092
44261
|
});
|
|
44262
|
+
return;
|
|
44093
44263
|
}
|
|
44094
|
-
actions.push({
|
|
44095
|
-
title: `Suppress ${diag.code} for next line`,
|
|
44096
|
-
kind: "quickfix",
|
|
44097
|
-
diagnostics: [diag],
|
|
44098
|
-
edits: [
|
|
44099
|
-
insertAtLineStart(
|
|
44100
|
-
input.document,
|
|
44101
|
-
diag.range.start.line,
|
|
44102
|
-
`<!-- btxml-disable-next-line ${diag.code} reason: TODO -->
|
|
44103
|
-
`
|
|
44104
|
-
)
|
|
44105
|
-
]
|
|
44106
|
-
});
|
|
44107
44264
|
}
|
|
44108
|
-
|
|
44265
|
+
const missingOutputPort = usage.ports.find(
|
|
44266
|
+
(port) => port.direction === "output" && (!outputPortName || port.name === outputPortName) && !usage.portUsages.some(
|
|
44267
|
+
(binding) => binding.status === "resolved" && binding.name === port.name
|
|
44268
|
+
)
|
|
44269
|
+
);
|
|
44270
|
+
if (!missingOutputPort) return;
|
|
44271
|
+
actions.push({
|
|
44272
|
+
title: `Remap output port ${missingOutputPort.name}`,
|
|
44273
|
+
kind: "quickfix",
|
|
44274
|
+
diagnostics: [diag],
|
|
44275
|
+
edits: [
|
|
44276
|
+
addAttributeWithValueEdit(
|
|
44277
|
+
input.document,
|
|
44278
|
+
target,
|
|
44279
|
+
missingOutputPort.name,
|
|
44280
|
+
`{${missingOutputPort.name}}`
|
|
44281
|
+
)
|
|
44282
|
+
]
|
|
44283
|
+
});
|
|
44284
|
+
}
|
|
44285
|
+
function addUnknownPortAction(actions, context, input, code, diag, inspect) {
|
|
44286
|
+
if (code !== "BT102_UNKNOWN_PORT") return;
|
|
44287
|
+
if (!("attribute" in inspect && inspect.attribute)) return;
|
|
44288
|
+
const element = inspectElement(inspect);
|
|
44289
|
+
if (!element) return;
|
|
44290
|
+
const usage = resolveUsage(context, input, element);
|
|
44291
|
+
const unknown2 = usage.portUsages.find(
|
|
44292
|
+
(candidate) => candidate.status === "undeclared" && candidate.attribute === inspect.attribute
|
|
44293
|
+
);
|
|
44294
|
+
if (!unknown2) return;
|
|
44295
|
+
const edit = removeAttributeEdit(input.document, inspect.attribute);
|
|
44296
|
+
if (!edit) return;
|
|
44297
|
+
actions.push({
|
|
44298
|
+
title: `Remove unknown port ${inspect.attribute.name}`,
|
|
44299
|
+
kind: "quickfix",
|
|
44300
|
+
diagnostics: [diag],
|
|
44301
|
+
edits: [edit]
|
|
44302
|
+
});
|
|
44303
|
+
}
|
|
44304
|
+
function addMissingBtcppFormatAction(actions, context, input, code, diag) {
|
|
44305
|
+
if (code !== "BT002_MISSING_BTCPP_FORMAT") return;
|
|
44306
|
+
if (!context.parsed?.root) return;
|
|
44307
|
+
const insertPos = input.document.positionAt(
|
|
44308
|
+
context.parsed.root.nameRange?.end.offset || context.parsed.root.openTagRange.end.offset - 1
|
|
44309
|
+
);
|
|
44310
|
+
actions.push({
|
|
44311
|
+
title: 'Add BTCPP_format="4" to <root>',
|
|
44312
|
+
kind: "quickfix",
|
|
44313
|
+
diagnostics: [diag],
|
|
44314
|
+
edits: [
|
|
44315
|
+
{
|
|
44316
|
+
range: sourceRange(insertPos, insertPos),
|
|
44317
|
+
newText: ' BTCPP_format="4"'
|
|
44318
|
+
}
|
|
44319
|
+
]
|
|
44320
|
+
});
|
|
44321
|
+
}
|
|
44322
|
+
function addSuppressionAction(actions, input, diag) {
|
|
44323
|
+
if (!diag.range) return;
|
|
44324
|
+
actions.push({
|
|
44325
|
+
title: `Suppress ${diag.code} for next line`,
|
|
44326
|
+
kind: "quickfix",
|
|
44327
|
+
diagnostics: [diag],
|
|
44328
|
+
edits: [
|
|
44329
|
+
insertAtLineStart(
|
|
44330
|
+
input.document,
|
|
44331
|
+
diag.range.start.line,
|
|
44332
|
+
`<!-- btxml-disable-next-line ${diag.code} reason: TODO -->
|
|
44333
|
+
`
|
|
44334
|
+
)
|
|
44335
|
+
]
|
|
44336
|
+
});
|
|
44109
44337
|
}
|
|
44110
44338
|
|
|
44111
44339
|
// ../language-service/src/completions.ts
|
|
@@ -46852,7 +47080,7 @@ function handleGetChildCapability(workspace, params) {
|
|
|
46852
47080
|
}
|
|
46853
47081
|
|
|
46854
47082
|
// src/server.ts
|
|
46855
|
-
var SERVER_VERSION = true ? "0.1.
|
|
47083
|
+
var SERVER_VERSION = true ? "0.1.5" : "unknown";
|
|
46856
47084
|
var connection = (0, import_node4.createConnection)(import_node4.ProposedFeatures.all);
|
|
46857
47085
|
var documents = new import_node4.TextDocuments(TextDocument);
|
|
46858
47086
|
var openUris = /* @__PURE__ */ new Set();
|