fix(adminui): tag-path completion replaces the whole dotted path, not just the last segment
v2-ci / build (push) Failing after 43s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped

Monaco's word definition splits on '.', so accepting a full tag path while a
partial path was typed (e.g. "X.Protected") duplicated the prefix
(-> "X.X.ProtectedValue"). Tag-path items now replace the whole literal
content from the opening quote to the caret.
This commit is contained in:
Joseph Doherty
2026-06-09 17:06:55 -04:00
parent da80195599
commit 688a003d1d
@@ -36,17 +36,30 @@
if (!resp.ok) return { suggestions: [] };
const data = await resp.json();
const word = model.getWordUntilPosition(position);
const range = {
const wordRange = {
startLineNumber: position.lineNumber, endLineNumber: position.lineNumber,
startColumn: word.startColumn, endColumn: word.endColumn
};
// Tag-path items (detail "tag path") are full dotted paths inside a string literal.
// Monaco's word definition splits on '.', so the word range would cover only the last
// segment and accepting the full path would duplicate the prefix
// (e.g. "X.Protected" + insert "X.ProtectedValue" -> "X.X.ProtectedValue").
// Replace the whole partial path instead: from just after the opening quote to the caret.
const lineText = model.getLineContent(position.lineNumber);
const beforeCaret = lineText.substring(0, position.column - 1);
const quoteIdx = Math.max(beforeCaret.lastIndexOf('"'), beforeCaret.lastIndexOf("'"));
const literalRange = {
startLineNumber: position.lineNumber, endLineNumber: position.lineNumber,
startColumn: quoteIdx >= 0 ? quoteIdx + 2 : position.column,
endColumn: position.column
};
return {
suggestions: (data.items || []).map(function (it) {
return {
label: it.label, insertText: it.insertText, detail: it.detail,
kind: KIND_MAP[it.kind] != null ? KIND_MAP[it.kind] : 18,
insertTextRules: it.insertTextRules || 0,
range: range
range: it.detail === "tag path" ? literalRange : wordRange
};
})
};