-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support liquid doc inner tags completion + hover (#789)
- Loading branch information
Showing
13 changed files
with
312 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--- | ||
'@shopify/theme-language-server-common': minor | ||
'@shopify/liquid-html-parser': minor | ||
--- | ||
|
||
Support liquid doc inner tags completion + hover | ||
|
||
- `@param`, `@description`, `@example` will support code completion | ||
whenever being typed inside of `doc` tag | ||
- `@param`, `@description`, `@example` can be hovered to show their | ||
help doc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
...e-language-server-common/src/completions/providers/LiquidDocTagCompletionProvider.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { describe, beforeEach, it, expect } from 'vitest'; | ||
import { CompletionsProvider } from '../CompletionsProvider'; | ||
import { DocumentManager } from '../../documents'; | ||
import { MetafieldDefinitionMap } from '@shopify/theme-check-common'; | ||
|
||
describe('Module: LiquidDocTagCompletionProvider', async () => { | ||
let provider: CompletionsProvider; | ||
|
||
beforeEach(async () => { | ||
provider = new CompletionsProvider({ | ||
documentManager: new DocumentManager(), | ||
themeDocset: { | ||
filters: async () => [], | ||
objects: async () => [], | ||
tags: async () => [], | ||
systemTranslations: async () => ({}), | ||
}, | ||
getMetafieldDefinitions: async (_rootUri: string) => ({} as MetafieldDefinitionMap), | ||
}); | ||
}); | ||
|
||
it('offers completions within liquid doc tag', async () => { | ||
await expect(provider).to.complete(`{% doc %} @█`, ['param', 'example', 'description']); | ||
await expect(provider).to.complete(`{% doc %} @par█`, ['param']); | ||
}); | ||
|
||
it("does not offer completion if it doesn't start with @", async () => { | ||
await expect(provider).to.complete(`{% doc %} █`, []); | ||
}); | ||
|
||
it('does not offer completion if it is not within a doc tag', async () => { | ||
await expect(provider).to.complete(`{% notdoc %} @█`, []); | ||
}); | ||
}); |
51 changes: 51 additions & 0 deletions
51
.../theme-language-server-common/src/completions/providers/LiquidDocTagCompletionProvider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { NodeTypes } from '@shopify/liquid-html-parser'; | ||
import { | ||
CompletionItem, | ||
CompletionItemKind, | ||
InsertTextFormat, | ||
MarkupKind, | ||
Range, | ||
TextEdit, | ||
} from 'vscode-languageserver'; | ||
import { LiquidCompletionParams } from '../params'; | ||
import { Provider } from './common'; | ||
import { formatLiquidDocTagHandle, SUPPORTED_LIQUID_DOC_TAG_HANDLES } from '../../utils/liquidDoc'; | ||
|
||
export class LiquidDocTagCompletionProvider implements Provider { | ||
constructor() {} | ||
|
||
async completions(params: LiquidCompletionParams): Promise<CompletionItem[]> { | ||
if (!params.completionContext) return []; | ||
|
||
const { node, ancestors } = params.completionContext; | ||
const parentNode = ancestors.at(-1); | ||
|
||
if ( | ||
!node || | ||
!parentNode || | ||
node.type !== NodeTypes.TextNode || | ||
parentNode.type !== NodeTypes.LiquidRawTag || | ||
parentNode.name !== 'doc' || | ||
!node.value.startsWith('@') | ||
) { | ||
return []; | ||
} | ||
|
||
// Need to offset the '@' symbol by 1 | ||
let start = params.document.textDocument.positionAt(node.position.start + 1); | ||
let end = params.document.textDocument.positionAt(node.position.end); | ||
|
||
return Object.entries(SUPPORTED_LIQUID_DOC_TAG_HANDLES) | ||
.filter(([label]) => label.startsWith(node.value.slice(1))) | ||
.map(([label, { description, example, template }]) => ({ | ||
label, | ||
kind: CompletionItemKind.EnumMember, | ||
documentation: { | ||
kind: MarkupKind.Markdown, | ||
value: formatLiquidDocTagHandle(label, description, example), | ||
}, | ||
textEdit: TextEdit.replace(Range.create(start, end), template), | ||
insertTextFormat: InsertTextFormat.Snippet, | ||
})); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
packages/theme-language-server-common/src/hover/providers/LiquidDocTagHoverProvider.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { describe, beforeEach, it, expect } from 'vitest'; | ||
import { DocumentManager } from '../../documents'; | ||
import { HoverProvider } from '../HoverProvider'; | ||
import { MetafieldDefinitionMap } from '@shopify/theme-check-common'; | ||
import '../../../../theme-check-common/src/test/test-setup'; | ||
import { formatLiquidDocTagHandle, SUPPORTED_LIQUID_DOC_TAG_HANDLES } from '../../utils/liquidDoc'; | ||
|
||
describe('Module: RenderSnippetParameterHoverProvider', async () => { | ||
let provider: HoverProvider; | ||
|
||
beforeEach(() => { | ||
provider = new HoverProvider( | ||
new DocumentManager(), | ||
{ | ||
filters: async () => [], | ||
objects: async () => [], | ||
tags: async () => [], | ||
systemTranslations: async () => ({}), | ||
}, | ||
async (_rootUri: string) => ({} as MetafieldDefinitionMap), | ||
); | ||
}); | ||
|
||
it('should show the param help doc when hovering over the tag itself', async () => { | ||
await expect(provider).to.hover( | ||
`{% doc %} @para█m {string} name - your name {% enddoc %}`, | ||
formatLiquidDocTagHandle( | ||
'param', | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['param'].description, | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['param'].example, | ||
), | ||
); | ||
await expect(provider).to.hover( | ||
`{% doc %} @exampl█e my example {% enddoc %}`, | ||
formatLiquidDocTagHandle( | ||
'example', | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['example'].description, | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['example'].example, | ||
), | ||
); | ||
await expect(provider).to.hover( | ||
`{% doc %} @descrip█tion cool text is cool {% enddoc %}`, | ||
formatLiquidDocTagHandle( | ||
'description', | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['description'].description, | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['description'].example, | ||
), | ||
); | ||
}); | ||
|
||
it('should show the param help doc when hovering over the text', async () => { | ||
await expect(provider).to.hover( | ||
`{% doc %} @param {string} name - █your name {% enddoc %}`, | ||
formatLiquidDocTagHandle( | ||
'param', | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['param'].description, | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['param'].example, | ||
), | ||
); | ||
await expect(provider).to.hover( | ||
`{% doc %} @example my █example {% enddoc %}`, | ||
formatLiquidDocTagHandle( | ||
'example', | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['example'].description, | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['example'].example, | ||
), | ||
); | ||
await expect(provider).to.hover( | ||
`{% doc %} @description cool text█ is cool {% enddoc %}`, | ||
formatLiquidDocTagHandle( | ||
'description', | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['description'].description, | ||
SUPPORTED_LIQUID_DOC_TAG_HANDLES['description'].example, | ||
), | ||
); | ||
}); | ||
}); |
55 changes: 55 additions & 0 deletions
55
packages/theme-language-server-common/src/hover/providers/LiquidDocTagHoverProvider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { NodeTypes } from '@shopify/liquid-html-parser'; | ||
import { LiquidHtmlNode } from '@shopify/theme-check-common'; | ||
import { Hover, MarkupKind } from 'vscode-languageserver'; | ||
import { BaseHoverProvider } from '../BaseHoverProvider'; | ||
import { formatLiquidDocTagHandle, SUPPORTED_LIQUID_DOC_TAG_HANDLES } from '../../utils/liquidDoc'; | ||
|
||
export class LiquidDocTagHoverProvider implements BaseHoverProvider { | ||
constructor() {} | ||
|
||
async hover(currentNode: LiquidHtmlNode, ancestors: LiquidHtmlNode[]): Promise<Hover | null> { | ||
const parentNode = ancestors.at(-1); | ||
|
||
let docTagNode; | ||
|
||
// We could be hovering on the liquidDoc tag itself | ||
if ( | ||
currentNode.type === NodeTypes.LiquidDocParamNode || | ||
currentNode.type === NodeTypes.LiquidDocDescriptionNode || | ||
currentNode.type === NodeTypes.LiquidDocExampleNode | ||
) { | ||
docTagNode = currentNode; | ||
} | ||
|
||
// or we could be hovering on the liquidDoc tag's text | ||
if ( | ||
(parentNode?.type === NodeTypes.LiquidDocParamNode || | ||
parentNode?.type === NodeTypes.LiquidDocDescriptionNode || | ||
parentNode?.type === NodeTypes.LiquidDocExampleNode) && | ||
currentNode.type === NodeTypes.TextNode | ||
) { | ||
docTagNode = parentNode; | ||
} | ||
|
||
if (!docTagNode) { | ||
return null; | ||
} | ||
|
||
const docTagData = SUPPORTED_LIQUID_DOC_TAG_HANDLES[docTagNode.name]; | ||
|
||
if (!docTagData) { | ||
return null; | ||
} | ||
|
||
return { | ||
contents: { | ||
kind: MarkupKind.Markdown, | ||
value: formatLiquidDocTagHandle( | ||
docTagNode.name, | ||
docTagData.description, | ||
docTagData.example, | ||
), | ||
}, | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters