From d7e9c762355710bcff3af94a0b81131f4c36ad08 Mon Sep 17 00:00:00 2001 From: Bhsd <55071315+bhsd-harry@users.noreply.github.com> Date: Tue, 3 Dec 2024 20:07:32 +0800 Subject: [PATCH] feat(folding): sticky scroll --- CHANGELOG.md | 1 + server/src/folding.ts | 33 ++- server/src/links.ts | 3 +- server/src/test/folding.ts | 28 +-- server/src/test/hover.ts | 56 +++++ server/src/test/links.ts | 110 +++++++++ server/src/test/reference.ts | 454 +++++++++++++++++++++++++++++++++++ server/src/test/signature.ts | 121 ++++++++++ 8 files changed, 783 insertions(+), 23 deletions(-) create mode 100644 server/src/test/hover.ts create mode 100644 server/src/test/links.ts create mode 100644 server/src/test/reference.ts create mode 100644 server/src/test/signature.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 69d63c6..1152ee0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ **Added** - New parser function signatures +- Sticky scroll by sections **Fixed** diff --git a/server/src/folding.ts b/server/src/folding.ts index 0a12199..a2f8c59 100644 --- a/server/src/folding.ts +++ b/server/src/folding.ts @@ -1,5 +1,6 @@ import {FoldingRangeKind, Range as TextRange, SymbolKind} from 'vscode-languageserver/node'; import {parse, docs} from './tasks'; +import {getText} from './util'; import type {FoldingRangeParams, FoldingRange, DocumentSymbol} from 'vscode-languageserver/node'; import type {Token, HeadingToken} from 'wikilint'; @@ -19,28 +20,38 @@ async function provide( sections = new Array(6), tokens = root.querySelectorAll(symbol ? 'heading-title' : 'heading-title,table,template,magic-word'); for (const token of tokens) { - const {top, height} = token.getBoundingClientRect(); + const {top, left, height, width} = token.getBoundingClientRect(); if (token.type === 'heading-title') { const {level} = token.parentNode as HeadingToken; if (symbol) { + for (let i = level - 1; i < 6; i++) { + if (sections[i]) { + const {end} = sections[i]!.range; + end.line = top - 1; + end.character = getText(doc, top - 1, 0, top, 0).length - 1; + } + sections[i] = undefined; + } const section = token.text().trim() || ' ', name = names.has(section) ? new Array(names.size).fill('').map((_, i) => `${section.trim()}_${i + 2}`) .find(s => !names.has(s))! : section, container = sections.slice(0, level - 1).findLast(Boolean), - range = TextRange.create(top, 0, top + height, 0), + range = TextRange.create( + top, + left - level, + top + height - 1, + (height === 1 ? left : 0) + width + level, + ), info: DocumentSymbol = { name, kind: SymbolKind.String, range, - selectionRange: range, + selectionRange: structuredClone(range), }; names.add(name); sections[level - 1] = info; - for (let i = level; i < 6; i++) { - sections[i] = undefined; - } if (container) { container.children ??= []; container.children.push(info); @@ -69,7 +80,15 @@ async function provide( }); } } - if (!symbol) { + if (symbol) { + for (const section of sections) { + if (section) { + const {end} = section.range; + end.line = lineCount - 1; + end.character = getText(doc, lineCount - 1, 0, lineCount, 0).length; + } + } + } else { for (const line of levels) { if (line !== undefined && line < lineCount) { ranges.push({ diff --git a/server/src/links.ts b/server/src/links.ts index 9ffb8a4..31fde98 100644 --- a/server/src/links.ts +++ b/server/src/links.ts @@ -54,8 +54,7 @@ export const provideLinks = async ({uri}: TextDocumentIdentifier, path: string): if (target.startsWith('//')) { target = `https:${target}`; } - new URL(target); // eslint-disable-line no-new - return [{range: createNodeRange(root, token), target}]; + return [{range: createNodeRange(root, token), target: new URL(target).href}]; } catch { return []; } diff --git a/server/src/test/folding.ts b/server/src/test/folding.ts index 7310cdd..67ca0ff 100644 --- a/server/src/test/folding.ts +++ b/server/src/test/folding.ts @@ -50,26 +50,26 @@ y }} z { name: '1', kind: SymbolKind.String, - range: {start: {line: 3, character: 0}, end: {line: 4, character: 0}}, - selectionRange: {start: {line: 3, character: 0}, end: {line: 4, character: 0}}, + range: {start: {line: 3, character: 3}, end: {line: 22, character: 0}}, + selectionRange: {start: {line: 3, character: 3}, end: {line: 3, character: 8}}, children: [ { name: '2', kind: SymbolKind.String, - range: {start: {line: 7, character: 0}, end: {line: 8, character: 0}}, - selectionRange: {start: {line: 7, character: 0}, end: {line: 8, character: 0}}, + range: {start: {line: 7, character: 8}, end: {line: 19, character: 0}}, + selectionRange: {start: {line: 7, character: 8}, end: {line: 7, character: 15}}, children: [ { name: '3', kind: SymbolKind.String, - range: {start: {line: 11, character: 0}, end: {line: 12, character: 0}}, - selectionRange: {start: {line: 11, character: 0}, end: {line: 12, character: 0}}, + range: {start: {line: 11, character: 0}, end: {line: 19, character: 0}}, + selectionRange: {start: {line: 11, character: 0}, end: {line: 11, character: 13}}, children: [ { name: '4_2', kind: SymbolKind.String, - range: {start: {line: 16, character: 0}, end: {line: 18, character: 0}}, - selectionRange: {start: {line: 16, character: 0}, end: {line: 18, character: 0}}, + range: {start: {line: 16, character: 0}, end: {line: 19, character: 0}}, + selectionRange: {start: {line: 16, character: 0}, end: {line: 17, character: 11}}, }, ], }, @@ -78,22 +78,22 @@ y }} z { name: '4', kind: SymbolKind.String, - range: {start: {line: 20, character: 0}, end: {line: 21, character: 0}}, - selectionRange: {start: {line: 20, character: 0}, end: {line: 21, character: 0}}, + range: {start: {line: 20, character: 0}, end: {line: 22, character: 0}}, + selectionRange: {start: {line: 20, character: 0}, end: {line: 20, character: 7}}, }, ], }, { name: '4_3', kind: SymbolKind.String, - range: {start: {line: 23, character: 0}, end: {line: 24, character: 0}}, - selectionRange: {start: {line: 23, character: 0}, end: {line: 24, character: 0}}, + range: {start: {line: 23, character: 0}, end: {line: 30, character: 0}}, + selectionRange: {start: {line: 23, character: 0}, end: {line: 23, character: 5}}, children: [ { name: '4_4', kind: SymbolKind.String, - range: {start: {line: 27, character: 0}, end: {line: 28, character: 0}}, - selectionRange: {start: {line: 27, character: 0}, end: {line: 28, character: 0}}, + range: {start: {line: 27, character: 0}, end: {line: 30, character: 0}}, + selectionRange: {start: {line: 27, character: 0}, end: {line: 27, character: 9}}, }, ], }, diff --git a/server/src/test/hover.ts b/server/src/test/hover.ts new file mode 100644 index 0000000..ef5bb78 --- /dev/null +++ b/server/src/test/hover.ts @@ -0,0 +1,56 @@ +import * as assert from 'assert'; +import {getPositionParams} from './util'; +import {provideHover} from '../hover'; + +const wikitext = ` +__NOTOC__ +{{ #LEN: }} +{{ PAGESIZE }} +`; + +describe('hoverProvider', () => { + it('behavior switch', async () => { + assert.deepStrictEqual(await provideHover(getPositionParams(__filename, wikitext, 1, 0)), { + contents: { + kind: 'markdown', + value: 'Hides the table of contents (TOC).', + }, + range: { + start: {line: 1, character: 0}, + end: {line: 1, character: 9}, + }, + }); + }); + it('parser function', async () => { + assert.deepStrictEqual(await provideHover(getPositionParams(__filename, wikitext, 2, 7)), { + contents: { + kind: 'markdown', + value: +`- **{{ #LEN:** *string* **}}** + +The #len function returns the length of the given string.`, + }, + range: { + start: {line: 2, character: 2}, + end: {line: 2, character: 7}, + }, + }); + }); + it('variable', async () => { + assert.deepStrictEqual(await provideHover(getPositionParams(__filename, wikitext, 3, 4)), { + contents: { + kind: 'markdown', + value: +`- **{{ PAGESIZE** **}}** +- **{{ PAGESIZE:** *page name* **}}** +- **{{ PAGESIZE:** *page name* **|** R **}}** + +**[Expensive]** Returns the byte size of the specified page.`, + }, + range: { + start: {line: 3, character: 2}, + end: {line: 3, character: 12}, + }, + }); + }); +}); diff --git a/server/src/test/links.ts b/server/src/test/links.ts new file mode 100644 index 0000000..7dbfd47 --- /dev/null +++ b/server/src/test/links.ts @@ -0,0 +1,110 @@ +import * as assert from 'assert'; +import {getParams} from './util'; +import {provideLinks} from '../links'; +import type {DocumentLink} from 'vscode-languageserver/node'; + +const wikitext = ` +[[ : help : a ]] +{{ b }} +{{ #invoke: c | c }} +RFC 1 +PMID 1 +ISBN 1-2-3-4-5-6-7-8-9-0 +[//d d] +News:e + + +`, + results: DocumentLink[] = [ + { + range: { + start: {line: 1, character: 2}, + end: {line: 1, character: 14}, + }, + target: 'https://mediawiki.org/wiki/Help%3AA', + }, + { + range: { + start: {line: 2, character: 2}, + end: {line: 2, character: 5}, + }, + target: 'https://mediawiki.org/wiki/Template%3AB', + }, + { + range: { + start: {line: 3, character: 11}, + end: {line: 3, character: 14}, + }, + target: 'https://mediawiki.org/wiki/Module%3AC', + }, + { + range: { + start: {line: 4, character: 0}, + end: {line: 4, character: 5}, + }, + target: 'https://tools.ietf.org/html/rfc1', + }, + { + range: { + start: {line: 5, character: 0}, + end: {line: 5, character: 6}, + }, + target: 'https://pubmed.ncbi.nlm.nih.gov/1', + }, + { + range: { + start: {line: 6, character: 0}, + end: {line: 6, character: 24}, + }, + target: 'https://mediawiki.org/wiki/Special%3ABooksources%2F1234567890', + }, + { + range: { + start: {line: 7, character: 1}, + end: {line: 7, character: 4}, + }, + target: 'https://d/', + }, + { + range: { + start: {line: 8, character: 0}, + end: {line: 8, character: 6}, + }, + target: 'news:e', + }, + { + range: { + start: {line: 9, character: 22}, + end: {line: 9, character: 23}, + }, + target: 'https://mediawiki.org/wiki/Template%3AF', + }, + { + range: { + start: {line: 10, character: 11}, + end: {line: 10, character: 22}, + }, + target: 'https://g/G', + }, + ]; + +describe('documentLinkProvider', () => { + it('https://mediawiki.org/wiki/$1', async () => { + assert.deepStrictEqual( + await provideLinks(getParams(__filename, wikitext).textDocument, 'https://mediawiki.org/wiki/$1'), + results, + ); + }); + it('https://mediawiki.org/wiki/', async () => { + assert.deepStrictEqual( + await provideLinks(getParams(__filename, wikitext).textDocument, 'https://mediawiki.org/wiki/'), + results, + ); + }); + it('https://mediawiki.org/wiki', async () => { + assert.deepStrictEqual( + await provideLinks(getParams(__filename, wikitext).textDocument, 'https://mediawiki.org/wiki'), + results, + ); + }); +}); diff --git a/server/src/test/reference.ts b/server/src/test/reference.ts new file mode 100644 index 0000000..acb2640 --- /dev/null +++ b/server/src/test/reference.ts @@ -0,0 +1,454 @@ +import * as assert from 'assert'; +import {getPositionParams} from './util'; +import {provideReferences, provideDefinition, prepareRename, provideRename} from '../reference'; + +const wikitext = ` +{{{ a }}} +{{{a|}}} +{{ b }} +{{ : template : b |b=}} +{{ PAGENAME }} +{{PAGENAME:c}} +[[ file : d | thumb ]] +[[ :file:d ]] +{{ e | e = }} +{{Template:E|e=}} + + + + +[[file:g|thumbnail]] +== h == +== i == +`; + +describe('referencesProvider', () => { + it('arg-name', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 1, 4)), + [ + { + range: {start: {line: 1, character: 3}, end: {line: 1, character: 6}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 2, character: 3}, end: {line: 2, character: 4}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('template-name', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 3, 4)), + [ + { + range: {start: {line: 3, character: 2}, end: {line: 3, character: 5}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 4, character: 2}, end: {line: 4, character: 18}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('magic-word-name', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 5, 4)), + [ + { + range: {start: {line: 5, character: 2}, end: {line: 5, character: 12}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 6, character: 2}, end: {line: 6, character: 10}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('link-target', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 7, 4)), + [ + { + range: {start: {line: 7, character: 2}, end: {line: 7, character: 12}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 8, character: 2}, end: {line: 8, character: 11}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('parameter-key', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 9, 8)), + [ + { + range: {start: {line: 9, character: 6}, end: {line: 9, character: 11}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 10, character: 13}, end: {line: 10, character: 15}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('ext', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 11, 2)), + [ + { + range: {start: {line: 11, character: 0}, end: {line: 11, character: 32}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 12, character: 0}, end: {line: 12, character: 37}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('html', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 13, 2)), + [ + { + range: {start: {line: 13, character: 0}, end: {line: 13, character: 3}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 13, character: 3}, end: {line: 13, character: 7}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('attr-key', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 11, 6)), + [ + { + range: {start: {line: 11, character: 5}, end: {line: 11, character: 10}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 12, character: 5}, end: {line: 12, character: 10}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 14, character: 12}, end: {line: 14, character: 17}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('image-parameter', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 15, 10)), + [ + { + range: {start: {line: 7, character: 13}, end: {line: 7, character: 20}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 15, character: 9}, end: {line: 15, character: 18}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('heading-title', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 16, 4)), + [ + { + range: {start: {line: 16, character: 0}, end: {line: 16, character: 7}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 17, character: 0}, end: {line: 17, character: 7}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('heading', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 16, 1)), + [ + { + range: {start: {line: 16, character: 0}, end: {line: 16, character: 7}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 17, character: 0}, end: {line: 17, character: 7}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('attr-value#name', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 11, 23)), + [ + { + range: {start: {line: 11, character: 22}, end: {line: 11, character: 23}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 12, character: 30}, end: {line: 12, character: 33}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); + it('attr-value#group', async () => { + assert.deepStrictEqual( + await provideReferences(getPositionParams(__filename, wikitext, 11, 14)), + [ + { + range: {start: {line: 11, character: 13}, end: {line: 11, character: 14}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 12, character: 14}, end: {line: 12, character: 17}}, + uri: __filename, + kind: 1, + }, + { + range: {start: {line: 14, character: 20}, end: {line: 14, character: 21}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); +}); + +describe('definitionProvider', () => { + it('ref name', async () => { + assert.deepStrictEqual( + await provideDefinition(getPositionParams(__filename, wikitext, 12, 32)), + [ + { + range: {start: {line: 11, character: 22}, end: {line: 11, character: 23}}, + uri: __filename, + kind: 1, + }, + ], + ); + }); +}); + +describe('renameProvider', () => { + it('prepare: arg-name', async () => { + assert.deepStrictEqual( + await prepareRename(getPositionParams(__filename, wikitext, 1, 4)), + {start: {line: 1, character: 3}, end: {line: 1, character: 6}}, + ); + }); + it('rename: arg-name', async () => { + assert.deepStrictEqual( + await provideRename({...getPositionParams(__filename, wikitext, 1, 4), newName: 'x'}), + { + changes: { + [__filename]: [ + { + range: {start: {line: 1, character: 3}, end: {line: 1, character: 6}}, + newText: 'x', + }, + { + range: {start: {line: 2, character: 3}, end: {line: 2, character: 4}}, + newText: 'x', + }, + ], + }, + }, + ); + }); + it('prepare: template-name', async () => { + assert.deepStrictEqual( + await prepareRename(getPositionParams(__filename, wikitext, 3, 4)), + {start: {line: 3, character: 2}, end: {line: 3, character: 5}}, + ); + }); + it('rename: template-name', async () => { + assert.deepStrictEqual( + await provideRename({...getPositionParams(__filename, wikitext, 3, 4), newName: 'x'}), + { + changes: { + [__filename]: [ + { + range: {start: {line: 3, character: 2}, end: {line: 3, character: 5}}, + newText: 'x', + }, + { + range: {start: {line: 4, character: 2}, end: {line: 4, character: 18}}, + newText: 'x', + }, + ], + }, + }, + ); + }); + it('prepare: magic-word-name', async () => { + assert.deepStrictEqual( + await prepareRename(getPositionParams(__filename, wikitext, 5, 4)), + {start: {line: 5, character: 2}, end: {line: 5, character: 12}}, + ); + }); + it('rename: magic-word-name', async () => { + assert.deepStrictEqual( + await provideRename({...getPositionParams(__filename, wikitext, 5, 4), newName: 'PAGENAMEE'}), + { + changes: { + [__filename]: [ + { + range: {start: {line: 5, character: 2}, end: {line: 5, character: 12}}, + newText: 'PAGENAMEE', + }, + { + range: {start: {line: 6, character: 2}, end: {line: 6, character: 10}}, + newText: 'PAGENAMEE', + }, + ], + }, + }, + ); + }); + it('prepare: link-target', async () => { + assert.deepStrictEqual( + await prepareRename(getPositionParams(__filename, wikitext, 7, 4)), + {start: {line: 7, character: 2}, end: {line: 7, character: 12}}, + ); + }); + it('rename: link-target', async () => { + assert.deepStrictEqual( + await provideRename({...getPositionParams(__filename, wikitext, 7, 4), newName: 'x'}), + { + changes: { + [__filename]: [ + { + range: {start: {line: 7, character: 2}, end: {line: 7, character: 12}}, + newText: 'x', + }, + { + range: {start: {line: 8, character: 2}, end: {line: 8, character: 11}}, + newText: 'x', + }, + ], + }, + }, + ); + }); + it('prepare: parameter-key', async () => { + assert.deepStrictEqual( + await prepareRename(getPositionParams(__filename, wikitext, 9, 8)), + {start: {line: 9, character: 6}, end: {line: 9, character: 9}}, + ); + }); + it('rename: parameter-key', async () => { + assert.deepStrictEqual( + await provideRename({...getPositionParams(__filename, wikitext, 9, 8), newName: 'x'}), + { + changes: { + [__filename]: [ + { + range: {start: {line: 9, character: 6}, end: {line: 9, character: 11}}, + newText: 'x', + }, + { + range: {start: {line: 10, character: 13}, end: {line: 10, character: 15}}, + newText: 'x', + }, + ], + }, + }, + ); + }); + it('prepare: attr-value#name', async () => { + assert.deepStrictEqual( + await prepareRename(getPositionParams(__filename, wikitext, 11, 23)), + {start: {line: 11, character: 22}, end: {line: 11, character: 23}}, + ); + }); + it('rename: attr-value#name', async () => { + assert.deepStrictEqual( + await provideRename({...getPositionParams(__filename, wikitext, 11, 23), newName: 'x'}), + { + changes: { + [__filename]: [ + { + range: {start: {line: 11, character: 22}, end: {line: 11, character: 23}}, + newText: 'x', + }, + { + range: {start: {line: 12, character: 30}, end: {line: 12, character: 33}}, + newText: 'x', + }, + ], + }, + }, + ); + }); + it('prepare: attr-value#group', async () => { + assert.deepStrictEqual( + await prepareRename(getPositionParams(__filename, wikitext, 11, 14)), + {start: {line: 11, character: 13}, end: {line: 11, character: 14}}, + ); + }); + it('rename: attr-value#group', async () => { + assert.deepStrictEqual( + await provideRename({...getPositionParams(__filename, wikitext, 11, 14), newName: 'x'}), + { + changes: { + [__filename]: [ + { + range: {start: {line: 11, character: 13}, end: {line: 11, character: 14}}, + newText: 'x', + }, + { + range: {start: {line: 12, character: 14}, end: {line: 12, character: 17}}, + newText: 'x', + }, + { + range: {start: {line: 14, character: 20}, end: {line: 14, character: 21}}, + newText: 'x', + }, + ], + }, + }, + ); + }); +}); diff --git a/server/src/test/signature.ts b/server/src/test/signature.ts new file mode 100644 index 0000000..7f06c1a --- /dev/null +++ b/server/src/test/signature.ts @@ -0,0 +1,121 @@ +import * as assert from 'assert'; +import {getPositionParams} from './util'; +import {provideSignatureHelp} from '../signature'; + +const wikitext = ` +{{ #invoke: a | b | c | d }} +{{ PAGENAME }} +{{ PAGESIZE: a | R }} +`; + +describe('signatureHelpProvider', () => { + it('#invoke-1', async () => { + assert.deepStrictEqual( + await provideSignatureHelp(getPositionParams(__filename, wikitext, 1, 12, true)), + { + signatures: [ + { + label: '{{#invoke:module name|function name|args}}', + parameters: [ + {label: 'module name'}, + {label: 'function name'}, + {label: 'args'}, + ], + activeParameter: 0, + }, + ], + activeParameter: 0, + }, + ); + }); + it('#invoke-2', async () => { + assert.deepStrictEqual( + await provideSignatureHelp(getPositionParams(__filename, wikitext, 1, 16, true)), + { + signatures: [ + { + label: '{{#invoke:module name|function name|args}}', + parameters: [ + {label: 'module name'}, + {label: 'function name'}, + {label: 'args'}, + ], + activeParameter: 1, + }, + ], + activeParameter: 1, + }, + ); + }); + it('#invoke-4', async () => { + assert.deepStrictEqual( + await provideSignatureHelp(getPositionParams(__filename, wikitext, 1, 25, true)), + { + signatures: [ + { + label: '{{#invoke:module name|function name|args}}', + parameters: [ + {label: 'module name'}, + {label: 'function name'}, + {label: 'args'}, + ], + activeParameter: 2, + }, + ], + activeParameter: 3, + }, + ); + }); + it('PAGENAME-1', async () => { + assert.deepStrictEqual( + await provideSignatureHelp(getPositionParams(__filename, wikitext, 2, 11, true)), + { + signatures: [ + { + label: '{{PAGENAME}}', + parameters: [], + }, + { + label: '{{PAGENAME:page name}}', + parameters: [{label: 'page name'}], + }, + ], + activeParameter: -1, + }, + ); + }); + it('PAGESIZE-1', async () => { + assert.deepStrictEqual( + await provideSignatureHelp(getPositionParams(__filename, wikitext, 3, 13, true)), + { + signatures: [ + { + label: '{{PAGESIZE:page name|R}}', + parameters: [ + {label: 'page name'}, + {label: 'R', documentation: 'Predefined parameter'}, + ], + }, + ], + activeParameter: 0, + }, + ); + }); + it('PAGESIZE-2', async () => { + assert.deepStrictEqual( + await provideSignatureHelp(getPositionParams(__filename, wikitext, 3, 17, true)), + { + signatures: [ + { + label: '{{PAGESIZE:page name|R}}', + parameters: [ + {label: 'page name'}, + {label: 'R', documentation: 'Predefined parameter'}, + ], + }, + ], + activeParameter: 1, + }, + ); + }); +});