diff --git a/src/providers/xref.provider.ts b/src/providers/xref.provider.ts index 949452d9..6ebbda91 100644 --- a/src/providers/xref.provider.ts +++ b/src/providers/xref.provider.ts @@ -30,18 +30,41 @@ function shouldProvide (context: Context): boolean { } async function getLabels (): Promise { + const files = await vscode.workspace.findFiles('**/*.adoc') + const contentOfFilesConcatenated = files + .map((uri) => readFileSync(uri.path).toString('utf-8')) + .join('\n') + const labelsFromLegacyBlock = await getLabelsFromLegacyBlock(contentOfFilesConcatenated) + const labelsFromShorthandNotation = await getLabelsFromShorthandNotation(contentOfFilesConcatenated) + const labelsFromLonghandNotation = await getLabelsFromLonghandNotation(contentOfFilesConcatenated) + return labelsFromLegacyBlock.concat(labelsFromShorthandNotation, labelsFromLonghandNotation) +} + +async function getLabelsFromLonghandNotation (content: string): Promise { + const regex = /\[id=(\w+)\]/g + const matched = content.match(regex) + if (matched) { + return matched.map((result) => result.replace('[id=', '').replace(']', '')) + } + return [] +} + +async function getLabelsFromShorthandNotation (content: string): Promise { + const regex = /\[#(\w+)\]/g + const matched = content.match(regex) + if (matched) { + return matched.map((result) => result.replace('[#', '').replace(']', '')) + } + return [] +} + +async function getLabelsFromLegacyBlock (content: string): Promise { const regex = /\[\[(\w+)\]\]/g - const labels = await vscode.workspace.findFiles('**/*.adoc').then((files) => { - const contentOfFilesConcatenated = files - .map((uri) => readFileSync(uri.path).toString('utf-8')) - .join('\n') - const matched = contentOfFilesConcatenated.match(regex) - if (matched) { - return matched.map((result) => result.replace('[[', '').replace(']]', '')) - } - return [] - }) - return labels + const matched = content.match(regex) + if (matched) { + return matched.map((result) => result.replace('[[', '').replace(']]', '')) + } + return [] } /** diff --git a/src/test/xrefCompletionProvider.test.ts b/src/test/xrefCompletionProvider.test.ts index 2f92aa43..5ea973b9 100644 --- a/src/test/xrefCompletionProvider.test.ts +++ b/src/test/xrefCompletionProvider.test.ts @@ -7,7 +7,7 @@ import { Position } from 'vscode' let root suite('Xref CompletionsProvider', () => { - const createdFiles: vscode.Uri[] = [] + let createdFiles: vscode.Uri[] = [] setup(() => { root = vscode.workspace.workspaceFolders[0].uri.fsPath }) @@ -15,6 +15,7 @@ suite('Xref CompletionsProvider', () => { for (const createdFile of createdFiles) { await vscode.workspace.fs.delete(createdFile) } + createdFiles = [] }) test('Should return other ids from old style double-brackets as completion after "xref:"', async () => { const fileToAutoComplete = vscode.Uri.file(`${root}/fileToAutoComplete.adoc`) @@ -33,4 +34,53 @@ suite('Xref CompletionsProvider', () => { label: 'anOldStyleID[]', }) }) + test('Should return ids declared using the shorthand syntax as completion after "xref:"', async () => { + const fileToAutoComplete = vscode.Uri.file(`${root}/fileToAutoComplete.adoc`) + await vscode.workspace.fs.writeFile(fileToAutoComplete, Buffer.from('xref:')) + createdFiles.push(fileToAutoComplete) + + const fileThatShouldAppearInAutoComplete = vscode.Uri.file(`${root}/fileToAppearInAutoComplete.adoc`) + await vscode.workspace.fs.writeFile(fileThatShouldAppearInAutoComplete, Buffer.from('[#aShortHandID]')) + createdFiles.push(fileThatShouldAppearInAutoComplete) + + const file = await vscode.workspace.openTextDocument(fileToAutoComplete) + const completionsItems = await xrefProvider.provideCompletionItems(file, new Position(0, 5)) + const filteredCompletionItems = completionsItems.filter((completionItem) => completionItem.label === 'aShortHandID[]') + assert.deepStrictEqual(filteredCompletionItems[0], { + kind: vscode.CompletionItemKind.Reference, + label: 'aShortHandID[]', + }) + }) + test('Should return ids declared using the longhand syntax as completion after "xref:"', async () => { + const fileToAutoComplete = vscode.Uri.file(`${root}/fileToAutoComplete.adoc`) + await vscode.workspace.fs.writeFile(fileToAutoComplete, Buffer.from('xref:')) + createdFiles.push(fileToAutoComplete) + + const fileThatShouldAppearInAutoComplete = vscode.Uri.file(`${root}/fileToAppearInAutoComplete.adoc`) + await vscode.workspace.fs.writeFile(fileThatShouldAppearInAutoComplete, Buffer.from('[id=longHandID]')) + createdFiles.push(fileThatShouldAppearInAutoComplete) + + const file = await vscode.workspace.openTextDocument(fileToAutoComplete) + const completionsItems = await xrefProvider.provideCompletionItems(file, new Position(0, 5)) + const filteredCompletionItems = completionsItems.filter((completionItem) => completionItem.label === 'longHandID[]') + assert.deepStrictEqual(filteredCompletionItems[0], { + kind: vscode.CompletionItemKind.Reference, + label: 'longHandID[]', + }) + }) + test('Should return id for inlined anchor', async () => { + const fileToAutoComplete = vscode.Uri.file(`${root}/fileToTestXrefAutoComplete.adoc`) + await vscode.workspace.fs.writeFile(fileToAutoComplete, Buffer.from(`* [id=anInlinedAnchor]demo + +xref:`)) + createdFiles.push(fileToAutoComplete) + + const file = await vscode.workspace.openTextDocument(fileToAutoComplete) + const completionsItems = await xrefProvider.provideCompletionItems(file, new Position(2, 5)) + const filteredCompletionItems = completionsItems.filter((completionItem) => completionItem.label === 'anInlinedAnchor[]') + assert.deepStrictEqual(filteredCompletionItems[0], { + kind: vscode.CompletionItemKind.Reference, + label: 'anInlinedAnchor[]', + }) + }) })