Skip to content

Commit 58c250b

Browse files
authored
fix: relative path in custom tag hover (#556)
The "Custom Marko tag discovered from:" hover built its path with path.relative(importer, ...), using the importing file's full path as the base instead of its directory, so a sibling counter.marko rendered as ../counter.marko. It now uses the file's directory and reads counter.marko.
1 parent 3132297 commit 58c250b

3 files changed

Lines changed: 84 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@marko/language-server": patch
3+
---
4+
5+
Fix the path in a custom tag's "discovered from" hover, which was computed against the importing file instead of its directory. A sibling `counter.marko` showed as `../counter.marko`; it now reads `counter.marko`.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import assert from "node:assert/strict";
2+
3+
import { Project } from "@marko/language-tools";
4+
import path from "path";
5+
import { CancellationToken } from "vscode-languageserver";
6+
import { TextDocument } from "vscode-languageserver-textdocument";
7+
import { URI } from "vscode-uri";
8+
9+
import { documents } from "../service";
10+
import MarkoPlugin from "../service/marko";
11+
12+
Project.setDefaultTypePaths({
13+
internalTypesFile:
14+
require.resolve("@marko/language-tools/marko.internal.d.ts"),
15+
markoTypesFile: require.resolve("marko/index.d.ts"),
16+
});
17+
18+
// Reuses a fixture that ships a discoverable `components/TestTagA.marko`; the
19+
// consumer is an in-memory file in the fixture root.
20+
const FIXTURE_DIR = path.join(
21+
__dirname,
22+
"fixtures",
23+
"script",
24+
"prefer-local-identifier-tag-name",
25+
);
26+
27+
// Hovers the tag name in `<TestTagA/>` and returns the markdown documentation.
28+
let runId = 0;
29+
async function hoverTagDoc() {
30+
const uri = URI.file(
31+
path.join(FIXTURE_DIR, `__hover-${runId++}.marko`),
32+
).toString();
33+
const text = "<TestTagA/>\n";
34+
documents.doOpen({
35+
textDocument: { uri, languageId: "marko", version: 1, text },
36+
});
37+
const doc = documents.get(uri) as TextDocument;
38+
try {
39+
const hover = await MarkoPlugin.doHover!(
40+
doc,
41+
{
42+
textDocument: { uri },
43+
position: doc.positionAt(text.indexOf("TestTagA") + 1),
44+
},
45+
CancellationToken.None,
46+
);
47+
const contents = hover?.contents;
48+
return contents &&
49+
typeof contents === "object" &&
50+
"value" in contents &&
51+
typeof contents.value === "string"
52+
? contents.value
53+
: "";
54+
} finally {
55+
documents.doClose({ textDocument: { uri } });
56+
}
57+
}
58+
59+
describe("custom tag hover 'discovered from' path", () => {
60+
it("is relative to the importing file's directory, not the file itself", async () => {
61+
const doc = await hoverTagDoc();
62+
assert.match(doc, /discovered from/, "expected the discovered-from hover");
63+
assert.match(
64+
doc,
65+
/components\/TestTagA\.marko/,
66+
"should link the discovered tag file",
67+
);
68+
// The importer's full path (not its directory) was previously used as the
69+
// base of `path.relative`, prefixing a spurious `../`.
70+
assert.doesNotMatch(
71+
doc,
72+
/\.\.\/components\/TestTagA\.marko/,
73+
"should not prefix a spurious `../`",
74+
);
75+
});
76+
});

packages/language-server/src/service/marko/util/get-tag-name-completion.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ export default function getTagNameCompletion({
4747
: nodeModuleName
4848
? `Custom Marko tag discovered from the ["${nodeModuleName}"](${fileURIForTag}) npm package.`
4949
: `Custom Marko tag discovered from:\n\n[${
50-
importer ? path.relative(importer, fileForTag) : fileForTag
50+
importer
51+
? path.relative(path.dirname(importer), fileForTag)
52+
: fileForTag
5153
}](${fileURIForTag})`,
5254
};
5355

0 commit comments

Comments
 (0)