Skip to content

Commit e89192e

Browse files
committed
Added hover support for named arguments for inline snippets
1 parent 26c0bd4 commit e89192e

File tree

3 files changed

+92
-8
lines changed

3 files changed

+92
-8
lines changed

.changeset/moody-mice-learn.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@shopify/theme-language-server-common': minor
3+
'@shopify/theme-check-common': minor
4+
---
5+
6+
Added hover support for `render` handle and named arguments for inline snippets

packages/theme-language-server-common/src/hover/providers/RenderSnippetParameterHoverProvider.spec.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,67 @@ describe('Module: RenderSnippetParameterHoverProvider', async () => {
4646
);
4747
});
4848
});
49+
50+
describe('hover on inline snippet parameters', () => {
51+
it('should return parameter info for inline snippet', async () => {
52+
provider = createProvider(async () => undefined); // No file-based snippets
53+
54+
const source = `
55+
{% snippet product_card %}
56+
{% doc %}
57+
@param {string} title - The title of the product
58+
@param {number} price - The price of the product
59+
{% enddoc %}
60+
<div>{{ title }}: {{ price }}</div>
61+
{% endsnippet %}
62+
63+
{% render product_card, ti█tle: 'My Product', price: 99 %}
64+
`;
65+
66+
await expect(provider).to.hover(source, '### `title`: string\n\nThe title of the product');
67+
});
68+
69+
it('should return null if parameter not found in inline snippet doc', async () => {
70+
provider = createProvider(async () => undefined);
71+
72+
const source = `
73+
{% snippet product_card %}
74+
{% doc %}
75+
@param {string} title - The title of the product
76+
{% enddoc %}
77+
<div>{{ title }}</div>
78+
{% endsnippet %}
79+
80+
{% render product_card, unknown_para█m: 'value' %}
81+
`;
82+
83+
await expect(provider).to.hover(source, null);
84+
});
85+
86+
it('should handle multiple inline snippets correctly', async () => {
87+
provider = createProvider(async () => undefined);
88+
89+
const source = `
90+
{% snippet first_snippet %}
91+
{% doc %}
92+
@param {string} first_param - First parameter
93+
{% enddoc %}
94+
<div>{{ first_param }}</div>
95+
{% endsnippet %}
96+
97+
{% snippet second_snippet %}
98+
{% doc %}
99+
@param {number} second_param - Second parameter
100+
{% enddoc %}
101+
<div>{{ second_param }}</div>
102+
{% endsnippet %}
103+
104+
{% render second_snippet, second_para█m: 42 %}
105+
`;
106+
107+
await expect(provider).to.hover(source, '### `second_param`: number\n\nSecond parameter');
108+
});
109+
});
49110
});
50111

51112
const createProvider = (getSnippetDefinition: GetDocDefinitionForURI) => {

packages/theme-language-server-common/src/hover/providers/RenderSnippetParameterHoverProvider.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { NodeTypes } from '@shopify/liquid-html-parser';
2-
import { LiquidHtmlNode, GetDocDefinitionForURI } from '@shopify/theme-check-common';
2+
import {
3+
LiquidHtmlNode,
4+
GetDocDefinitionForURI,
5+
findInlineSnippet,
6+
extractDocDefinition,
7+
} from '@shopify/theme-check-common';
38
import { Hover, HoverParams } from 'vscode-languageserver';
49
import { BaseHoverProvider } from '../BaseHoverProvider';
510
import { formatLiquidDocParameter } from '../../utils/liquidDoc';
@@ -13,20 +18,32 @@ export class RenderSnippetParameterHoverProvider implements BaseHoverProvider {
1318
params: HoverParams,
1419
): Promise<Hover | null> {
1520
const parentNode = ancestors.at(-1);
21+
1622
if (
1723
currentNode.type !== NodeTypes.NamedArgument ||
1824
!parentNode ||
19-
parentNode.type !== NodeTypes.RenderMarkup ||
20-
parentNode.snippet.type !== NodeTypes.String
25+
parentNode.type !== NodeTypes.RenderMarkup
2126
) {
2227
return null;
2328
}
2429

25-
const docDefinition = await this.getDocDefinitionForURI(
26-
params.textDocument.uri,
27-
'snippets',
28-
parentNode.snippet.value,
29-
);
30+
let docDefinition;
31+
32+
if (parentNode.snippet.type === NodeTypes.String) {
33+
docDefinition = await this.getDocDefinitionForURI(
34+
params.textDocument.uri,
35+
'snippets',
36+
parentNode.snippet.value,
37+
);
38+
}
39+
else if (parentNode.snippet.type === NodeTypes.VariableLookup) {
40+
const snippetName = parentNode.snippet.name || '';
41+
const rootNode = ancestors[0];
42+
const snippetNode = findInlineSnippet(rootNode, snippetName);
43+
if (snippetNode) {
44+
docDefinition = extractDocDefinition(params.textDocument.uri, snippetNode);
45+
}
46+
}
3047

3148
const paramName = currentNode.name;
3249
const hoveredParameter = docDefinition?.liquidDoc?.parameters?.find(

0 commit comments

Comments
 (0)