All root-finding tests

This commit is contained in:
James Yu 2024-06-11 12:47:29 +01:00
parent 6a0d3761a4
commit 75dd78702a
12 changed files with 217 additions and 18 deletions

View File

@ -27,8 +27,7 @@ export const root = {
findFromMagic,
findFromActive,
findFromRoot,
findInWorkspace,
findSubfiles
findInWorkspace
}
}
@ -264,19 +263,16 @@ function findFromActive(): string | undefined {
* if not found.
*/
function findSubfiles(content: string): string | undefined {
if (!vscode.window.activeTextEditor) {
return
}
const regex = /(?:\\documentclass\[(.*)\]{subfiles})/s
const result = content.match(regex)
if (result) {
const filePath = utils.resolveFile([path.dirname(vscode.window.activeTextEditor.document.fileName)], result[1])
if (filePath) {
logger.log(`Found subfile root ${filePath} from active.`)
}
return filePath
if (!result) {
return
}
return
const filePath = utils.resolveFile([path.dirname(vscode.window.activeTextEditor!.document.fileName)], result[1])
if (filePath) {
logger.log(`Found subfile root ${filePath} from active.`)
}
return filePath
}
/**

View File

@ -0,0 +1 @@
\input{../main}

View File

@ -0,0 +1 @@
% \documentclass{article}

View File

@ -0,0 +1 @@
INPUT another.tex

View File

@ -0,0 +1 @@
\documentclass{article}

View File

@ -0,0 +1,2 @@
\documentclass{article}
\input{another.tex}

View File

@ -828,6 +828,7 @@ describe(path.basename(__filename).split('.')[0] + ':', () => {
it('should return a list of de-duplicated .tex files', async () => {
const toParse = get.path(fixture, 'included_tex', 'duplicate_1.tex')
await lw.cache.refreshCache(toParse)
await lw.cache.wait(get.path(fixture, 'included_tex', 'another.tex'))
assert.listStrictEqual(lw.cache.getIncludedTeX(toParse), [
get.path(fixture, 'included_tex', 'duplicate_1.tex'),
get.path(fixture, 'included_tex', 'duplicate_2.tex'),

View File

@ -229,4 +229,200 @@ describe(path.basename(__filename).split('.')[0] + ':', () => {
assert.strictEqual(root, rootPath)
})
})
describe('lw.root.findFromRoot', () => {
it('should return undefined if there is no active editor', () => {
const stub = sinon.stub(vscode.window, 'activeTextEditor').value(undefined)
const root = lw.root._test.findFromRoot()
stub.restore()
assert.strictEqual(root, undefined)
})
it('should return undefined if there is no root', () => {
const texPath = get.path(fixture, 'main.tex')
const stub = mock.activeTextEditor(texPath, '')
const root = lw.root._test.findFromRoot()
stub.restore()
assert.strictEqual(root, undefined)
})
it('should return undefined if active editor is not a file', () => {
const texPath = get.path(fixture, 'main.tex')
set.root(texPath)
const stub = mock.activeTextEditor('https://google.com', '', { scheme: 'https' })
const root = lw.root._test.findFromRoot()
stub.restore()
assert.strictEqual(root, undefined)
})
it('should find root if active file is in the root tex tree', async () => {
const texPath = get.path(fixture, 'main.tex')
const toParse = get.path(fixture, 'find_root', 'root.tex')
set.root(toParse)
await lw.cache.refreshCache(toParse)
const stub = mock.activeTextEditor(texPath, '')
const root = lw.root._test.findFromRoot()
stub.restore()
assert.strictEqual(root, toParse)
})
it('should return undefined if active file is not in the root tex tree', async () => {
const texPath = get.path(fixture, 'main.tex')
const toParse = get.path(fixture, 'find_root', 'root_no_input.tex')
set.root(toParse)
await lw.cache.refreshCache(toParse)
const stub = mock.activeTextEditor(texPath, '')
const root = lw.root._test.findFromRoot()
stub.restore()
assert.strictEqual(root, undefined)
})
})
describe('lw.root.findFromActive', () => {
beforeEach(async () => {
await set.config('latex.rootFile.indicator', '\\documentclass[]{}')
})
it('should return undefined if there is no active editor', () => {
const stub = sinon.stub(vscode.window, 'activeTextEditor').value(undefined)
const root = lw.root._test.findFromActive()
stub.restore()
assert.strictEqual(root, undefined)
})
it('should return undefined if active editor is not a file', () => {
const texPath = get.path(fixture, 'main.tex')
set.root(texPath)
const stub = mock.activeTextEditor('https://google.com', '', { scheme: 'https' })
const root = lw.root._test.findFromActive()
stub.restore()
assert.strictEqual(root, undefined)
})
it('should find root if active file has root file indicator', () => {
const texPath = get.path(fixture, 'main.tex')
const stub = mock.activeTextEditor(texPath, '\\documentclass{article}\n')
const root = lw.root._test.findFromActive()
stub.restore()
assert.strictEqual(root, texPath)
})
it('should ignore root file indicators in comments', () => {
const texPath = get.path(fixture, 'main.tex')
const stub = mock.activeTextEditor(texPath, '% \\documentclass{article}\n')
const root = lw.root._test.findFromActive()
stub.restore()
assert.strictEqual(root, undefined)
})
it('should find subfile root if active file is a subfile', () => {
const texPath = get.path(fixture, 'main.tex')
const stub = mock.activeTextEditor(texPath, '\\documentclass[find_active/main.tex]{subfiles}\n')
const root = lw.root._test.findFromActive()
stub.restore()
assert.strictEqual(root, get.path(fixture, 'find_active', 'main.tex'))
})
it('should find root if active file is a subfile but points to non-existing file', () => {
const texPath = get.path(fixture, 'main.tex')
const stub = mock.activeTextEditor(texPath, '\\documentclass[find_active/nothing.tex]{subfiles}\n')
const root = lw.root._test.findFromActive()
stub.restore()
assert.strictEqual(root, texPath)
})
})
describe('lw.root.findInWorkspace', () => {
beforeEach(async () => {
await set.config('latex.rootFile.indicator', '\\documentclass[]{}')
})
it('should follow `latex.search.rootFiles.include` config', async () => {
await set.config('latex.search.rootFiles.include', [ 'absolutely-nothing.tex' ])
const root = await lw.root._test.findInWorkspace()
assert.strictEqual(root, undefined)
})
it('should follow `latex.search.rootFiles.exclude` config', async () => {
await set.config('latex.search.rootFiles.exclude', [ '**/*' ])
const root = await lw.root._test.findInWorkspace()
assert.strictEqual(root, undefined)
})
it('should find the correct root from workspace', async () => {
const texPath = get.path(fixture, 'find_workspace', 'main.tex')
await set.config('latex.search.rootFiles.include', [ `${fixture}/find_workspace/**/*.tex` ])
await set.config('latex.search.rootFiles.exclude', [ `${fixture}/find_workspace/**/parent.tex` ])
const root = await lw.root._test.findInWorkspace()
assert.strictEqual(root, texPath)
})
it('should ignore root file indicators in comments', async () => {
await set.config('latex.search.rootFiles.include', [ `${fixture}/find_workspace/**/comment.tex` ])
const root = await lw.root._test.findInWorkspace()
assert.strictEqual(root, undefined)
})
it('should find the correct root if the .fls of root includes active editor', async () => {
const texPath = get.path(fixture, 'find_workspace', 'main.tex')
const texPathAnother = get.path(fixture, 'find_workspace', 'another.tex')
await set.config('latex.search.rootFiles.include', [ `${fixture}/find_workspace/**/*.tex` ])
const stub = mock.activeTextEditor(texPathAnother, '\\documentclass{article}\n')
const root = await lw.root._test.findInWorkspace()
stub.restore()
assert.strictEqual(root, texPath)
})
it('should find the correct root if the children of root includes active editor', async () => {
const texPath = get.path(fixture, 'find_workspace', 'parent.tex')
const texPathAnother = get.path(fixture, 'find_workspace', 'another.tex')
await set.config('latex.search.rootFiles.include', [ `${fixture}/find_workspace/**/*.tex` ])
await lw.cache.refreshCache(texPath)
const stub = mock.activeTextEditor(texPathAnother, '\\documentclass{article}\n')
const root = await lw.root._test.findInWorkspace()
stub.restore()
assert.strictEqual(root, texPath)
})
it('should find the correct root if current root is in the candidates', async () => {
const texPath = get.path(fixture, 'find_workspace', 'main.tex')
await set.config('latex.search.rootFiles.include', [ `${fixture}/find_workspace/**/*.tex` ])
set.root(fixture, 'find_workspace', 'main.tex')
const stub = mock.activeTextEditor(texPath, '\\documentclass{article}\n')
const root = await lw.root._test.findInWorkspace()
stub.restore()
assert.strictEqual(root, texPath)
})
})
})

View File

@ -103,10 +103,10 @@ export const mock = {
}
})
},
textDocument: (filePath: string, content: string, params: { languageId?: string, isDirty?: boolean, isClosed?: boolean } = {}) => {
textDocument: (filePath: string, content: string, params: { languageId?: string, isDirty?: boolean, isClosed?: boolean, scheme?: string } = {}) => {
return sinon.stub(vscode.workspace, 'textDocuments').value([ new TextDocument(filePath, content, params) ])
},
activeTextEditor: (filePath: string, content: string, params: { languageId?: string, isDirty?: boolean, isClosed?: boolean } = {}) => {
activeTextEditor: (filePath: string, content: string, params: { languageId?: string, isDirty?: boolean, isClosed?: boolean, scheme?: string } = {}) => {
return sinon.stub(vscode.window, 'activeTextEditor').value(new TextEditor(filePath, content, params))
}
}
@ -135,10 +135,10 @@ class TextDocument implements vscode.TextDocument {
eol: vscode.EndOfLine = vscode.EndOfLine.LF
lineCount: number
constructor(filePath: string, content: string, { languageId = 'latex', isDirty = false, isClosed = false }: { languageId?: string, isDirty?: boolean, isClosed?: boolean }) {
constructor(filePath: string, content: string, { languageId = 'latex', isDirty = false, isClosed = false, scheme = 'file' }: { languageId?: string, isDirty?: boolean, isClosed?: boolean, scheme?: string }) {
this.content = content
this.lines = content.split('\n')
this.uri = vscode.Uri.file(filePath)
this.uri = scheme === 'file' ? vscode.Uri.file(filePath) : vscode.Uri.from({ scheme, path: filePath })
this.fileName = filePath
this.languageId = languageId
this.isDirty = isDirty
@ -163,8 +163,8 @@ class TextEditor implements vscode.TextEditor {
options: vscode.TextEditorOptions = {}
viewColumn: vscode.ViewColumn | undefined = vscode.ViewColumn.Active
constructor(filePath: string, content: string, { languageId = 'latex', isDirty = false, isClosed = false }: { languageId?: string, isDirty?: boolean, isClosed?: boolean }) {
this.document = new TextDocument(filePath, content, { languageId, isDirty, isClosed })
constructor(filePath: string, content: string, { languageId = 'latex', isDirty = false, isClosed = false, scheme = 'file' }: { languageId?: string, isDirty?: boolean, isClosed?: boolean, scheme?: string }) {
this.document = new TextDocument(filePath, content, { languageId, isDirty, isClosed, scheme })
}
edit(_: (_: vscode.TextEditorEdit) => void): Thenable<boolean> { throw new Error('Not implemented.') }