Skip to content

Commit

Permalink
Fix Attributes defined in another file which is included (asciidoctor…
Browse files Browse the repository at this point in the history
…#734)

Fix attributes completion defined in another file which is included

resolves asciidoctor#727

Signed-off-by: Aurélien Pupier <[email protected]>
Co-authored-by: Guillaume Grossetie <[email protected]>
  • Loading branch information
apupier and ggrossetie authored Jun 28, 2023
1 parent 45302b5 commit 6a03eeb
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Bug fixes

- folding of several single line comments is not working for more than 2 lines (#722)
- attribute coming from include files are missing in completion with 3.0.x (#727)

## 3.0.5 "pre-release" (2023-06-03)

Expand Down
3 changes: 1 addition & 2 deletions src/asciidocEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ export class AsciidocEngine {
}

public static load (textDocument: SkinnyTextDocument): Asciidoctor.Document {
const { document } = AsciidocParser.load(textDocument)
return document
return AsciidocParser.load(textDocument)
}
}
44 changes: 25 additions & 19 deletions src/asciidocParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,13 @@ export class AsciidocParser {
highlightjsBuiltInSyntaxHighlighter.$register_for('highlight.js', 'highlightjs')
const baseDir = AsciidocTextDocument.fromTextDocument(textDocument).getBaseDir()
const templateDirs = this.getTemplateDirs()
const options: { [key: string]: any } = {
attributes: {
'env-vscode': '',
env: 'vscode',
...asciidoctorAttributes,
},
backend,
extension_registry: registry,
header_footer: true,
safe: 'unsafe',
...(baseDir && { base_dir: baseDir }),
const options: { [key: string]: any } = AsciidocParser.getDefaultAsciidoctorOptions(baseDir)
options.extension_registry = registry
options.header_footer = true
options.attributes = {
'env-vscode': '',
env: 'vscode',
...asciidoctorAttributes,
}
if (templateDirs.length !== 0) {
options.template_dirs = templateDirs
Expand All @@ -110,27 +106,37 @@ export class AsciidocParser {

// Load

public static load (textDocument: SkinnyTextDocument): { document: Asciidoctor.Document, baseDocumentIncludeItems: IncludeItems } {
public static getBaseDocumentIncludeItems (textDocument: SkinnyTextDocument): IncludeItems {
const memoryLogger = processor.MemoryLogger.create()
processor.LoggerManager.setLogger(memoryLogger)
const registry = processor.Extensions.create()
asciidoctorFindIncludeProcessor.register(registry)
asciidoctorFindIncludeProcessor.resetIncludes()
const baseDir = AsciidocTextDocument.fromTextDocument(textDocument).getBaseDir()
const document = processor.load(textDocument.getText(), {
const options = this.getDefaultAsciidoctorOptions(baseDir)
options.extension_registry = registry
processor.load(textDocument.getText(), options)
// QUESTION: should we report error?
return asciidoctorFindIncludeProcessor.getBaseDocIncludes()
}

public static load (textDocument: SkinnyTextDocument): Asciidoctor.Document {
const memoryLogger = processor.MemoryLogger.create()
processor.LoggerManager.setLogger(memoryLogger)
const baseDir = AsciidocTextDocument.fromTextDocument(textDocument).getBaseDir()
return processor.load(textDocument.getText(), AsciidocParser.getDefaultAsciidoctorOptions(baseDir))
}

private static getDefaultAsciidoctorOptions (baseDir: string): any {
return {
attributes: {
'env-vscode': '',
env: 'vscode',
},
extension_registry: registry,
sourcemap: true,
safe: 'unsafe',
parse: true,
...(baseDir && { base_dir: baseDir }),
})
// QUESTION: should we report error?
return {
document,
baseDocumentIncludeItems: asciidoctorFindIncludeProcessor.getBaseDocIncludes(),
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/features/attributeReferenceProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AsciidocParser } from '../asciidocParser'

export class AttributeReferenceProvider {
provideCompletionItems (textDocument: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
const { document } = AsciidocParser.load(textDocument)
const document = AsciidocParser.load(textDocument)
const attributes = document.getAttributes()
const lineText = textDocument.lineAt(position).text
const prefix = lineText.substring(position.character - 1, position.character)
Expand Down
8 changes: 5 additions & 3 deletions src/features/documentLinkProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,22 @@ function normalizeLink (

export default class LinkProvider implements vscode.DocumentLinkProvider {
public provideDocumentLinks (textDocument: vscode.TextDocument, _token: vscode.CancellationToken): vscode.DocumentLink[] {
const { document, baseDocumentIncludeItems } = AsciidocParser.load(textDocument)
const baseDocumentIncludeItems = AsciidocParser.getBaseDocumentIncludeItems(textDocument)

// includes from the reader are resolved correctly but the line numbers may be offset and not exactly match the document
let baseDocumentProcessorIncludes = baseDocumentIncludeItems
const includeDirective = /^(\\)?include::([^[][^[]*)\[([^\n]+)?\]$/
// get includes from document text. These may be inside ifeval or ifdef but the line numbers are correct.
const baseDocumentRegexIncludes = new Map()
document.getSourceLines().forEach((line, index) => {
const splittedLines = textDocument.getText().split('\n')
for (let index = 0; index < splittedLines.length; index++) {
const line = splittedLines[index]
const match = includeDirective.exec(line)
if (match) {
// match[2] is the include reference
baseDocumentRegexIncludes.set(index, match[2].length)
}
})
}

// find a corrected mapping for line numbers
const betterIncludeMatching = similarArrayMatch(
Expand Down
2 changes: 1 addition & 1 deletion src/image-paste.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ export namespace Import {
return dir
}

const { document } = AsciidocParser.load(textDocument)
const document = AsciidocParser.load(textDocument)
return document.getAttribute('imagesdir', '')
}

Expand Down
32 changes: 29 additions & 3 deletions src/test/attributeRefCompletionProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ suite('Attribute ref CompletionsProvider', () => {
createdFiles = []
})
test('Should return attribute key defined in same file', async () => {
const fileToAutoComplete = vscode.Uri.file(`${root}/fileToAutoComplete-attributeRef.adoc`)
const fileToAutoComplete = vscode.Uri.file(`${root}/fileToAutoComplete-attributeRef-samefile.adoc`)
await vscode.workspace.fs.writeFile(fileToAutoComplete, Buffer.from(`:my-attribute-to-find-in-completion: dummy value
`))
createdFiles.push(fileToAutoComplete)
Expand Down Expand Up @@ -49,8 +49,8 @@ dumm`))
assert.deepStrictEqual((completionItem.label as vscode.CompletionItemLabel).description, 'dummy value')
assert.deepStrictEqual(completionItem.insertText, '{my-attribute-to-find-in-completion}')
})
test('Should return no completion when nothign corresponds', async () => {
const fileToAutoComplete = vscode.Uri.file(`${root}/fileToAutoComplete-attributeRef.adoc`)
test('Should return no completion when nothing corresponds', async () => {
const fileToAutoComplete = vscode.Uri.file(`${root}/fileToAutoComplete-attributeRef-samefile-basedOnValue.adoc`)
await vscode.workspace.fs.writeFile(fileToAutoComplete, Buffer.from(`:my-attribute-to-find-in-completion: dummy value
somethingVeryDifferent`))
createdFiles.push(fileToAutoComplete)
Expand All @@ -59,4 +59,30 @@ somethingVeryDifferent`))
const completionsItems = new AttributeReferenceProvider().provideCompletionItems(file, new Position(1, 22))
assert.notStrictEqual(completionsItems.length, 0, 'There are Completion provided although none are expected.')
})
test('Should return attribute key defined in another file', async () => {
const fileToAutoComplete = vscode.Uri.file(`${root}/fileToAutoComplete-attributeRef-differentFile.adoc`)
await vscode.workspace.fs.writeFile(fileToAutoComplete, Buffer.from(`= test
include::file-referenced-with-an-attribute.adoc[]
`))
createdFiles.push(fileToAutoComplete)

const fileReferencedWithAnAttribute = vscode.Uri.file(`${root}/file-referenced-with-an-attribute.adoc`)
await vscode.workspace.fs.writeFile(fileReferencedWithAnAttribute, Buffer.from(':my-attribute-to-find-in-completion: dummy value'))
createdFiles.push(fileReferencedWithAnAttribute)

const file = await vscode.workspace.openTextDocument(fileToAutoComplete)
const completionsItems = new AttributeReferenceProvider().provideCompletionItems(file, new Position(3, 0))
const filteredCompletionItems = completionsItems.filter((completionItem) => {
if ((completionItem.label as vscode.CompletionItemLabel)) {
return (completionItem.label as vscode.CompletionItemLabel).label === 'my-attribute-to-find-in-completion'
} else {
return false
}
})
const completionItem = filteredCompletionItems[0]
assert.deepStrictEqual((completionItem.label as vscode.CompletionItemLabel).description, 'dummy value')
assert.deepStrictEqual(completionItem.insertText, '{my-attribute-to-find-in-completion}')
})
})

0 comments on commit 6a03eeb

Please sign in to comment.