291 lines
11 KiB
TypeScript
291 lines
11 KiB
TypeScript
import { Neovim } from '@chemzqm/neovim'
|
|
import fs from 'fs'
|
|
import os from 'os'
|
|
import path from 'path'
|
|
import { Disposable, WorkspaceFoldersChangeEvent } from 'vscode-languageserver-protocol'
|
|
import { URI } from 'vscode-uri'
|
|
import Configurations from '../../configuration/index'
|
|
import WorkspaceFolderController from '../../core/workspaceFolder'
|
|
import { PatternType } from '../../types'
|
|
import { disposeAll } from '../../util'
|
|
import workspace from '../../workspace'
|
|
import helper from '../helper'
|
|
|
|
let workspaceFolder: WorkspaceFolderController
|
|
let configurations: Configurations
|
|
let disposables: Disposable[] = []
|
|
let nvim: Neovim
|
|
|
|
function updateConfiguration(key: string, value: any, defaults: any): void {
|
|
configurations.updateUserConfig({ [key]: value })
|
|
disposables.push({
|
|
dispose: () => {
|
|
configurations.updateUserConfig({ [key]: defaults })
|
|
}
|
|
})
|
|
}
|
|
|
|
beforeAll(async () => {
|
|
await helper.setup()
|
|
nvim = helper.nvim
|
|
let userConfigFile = path.join(process.env.COC_VIMCONFIG, 'coc-settings.json')
|
|
configurations = new Configurations(userConfigFile, {
|
|
$removeConfigurationOption: () => {},
|
|
$updateConfigurationOption: () => {}
|
|
})
|
|
workspaceFolder = new WorkspaceFolderController(configurations)
|
|
})
|
|
|
|
afterEach(async () => {
|
|
await helper.reset()
|
|
disposeAll(disposables)
|
|
workspaceFolder.reset()
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await helper.shutdown()
|
|
})
|
|
|
|
describe('WorkspaceFolderController', () => {
|
|
describe('asRelativePath()', () => {
|
|
function assertAsRelativePath(input: string, expected: string, includeWorkspace?: boolean) {
|
|
const actual = workspaceFolder.getRelativePath(input, includeWorkspace)
|
|
expect(actual).toBe(expected)
|
|
}
|
|
|
|
it('should get relative path', async () => {
|
|
workspaceFolder.addWorkspaceFolder(`/Coding/Applications/NewsWoWBot`, false)
|
|
assertAsRelativePath('/Coding/Applications/NewsWoWBot/bernd/das/brot', 'bernd/das/brot')
|
|
assertAsRelativePath('/Apps/DartPubCache/hosted/pub.dartlang.org/convert-2.0.1/lib/src/hex.dart',
|
|
'/Apps/DartPubCache/hosted/pub.dartlang.org/convert-2.0.1/lib/src/hex.dart')
|
|
assertAsRelativePath('', '')
|
|
assertAsRelativePath('/foo/bar', '/foo/bar')
|
|
assertAsRelativePath('in/out', 'in/out')
|
|
})
|
|
|
|
it('should asRelativePath, same paths, #11402', async () => {
|
|
const root = '/home/aeschli/workspaces/samples/docker'
|
|
const input = '/home/aeschli/workspaces/samples/docker'
|
|
workspaceFolder.addWorkspaceFolder(root, false)
|
|
assertAsRelativePath(input, input)
|
|
const input2 = '/home/aeschli/workspaces/samples/docker/a.file'
|
|
assertAsRelativePath(input2, 'a.file')
|
|
})
|
|
|
|
it('should asRelativePath, not workspaceFolder', async () => {
|
|
expect(workspace.getRelativePath('')).toBe('')
|
|
assertAsRelativePath('/foo/bar', '/foo/bar')
|
|
})
|
|
|
|
it('should asRelativePath, multiple folders', () => {
|
|
workspaceFolder.addWorkspaceFolder(`/Coding/One`, false)
|
|
workspaceFolder.addWorkspaceFolder(`/Coding/Two`, false)
|
|
assertAsRelativePath('/Coding/One/file.txt', 'One/file.txt')
|
|
assertAsRelativePath('/Coding/Two/files/out.txt', 'Two/files/out.txt')
|
|
assertAsRelativePath('/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt')
|
|
})
|
|
|
|
it('should slightly inconsistent behaviour of asRelativePath and getWorkspaceFolder, #31553', async () => {
|
|
workspaceFolder.addWorkspaceFolder(`/Coding/One`, false)
|
|
workspaceFolder.addWorkspaceFolder(`/Coding/Two`, false)
|
|
|
|
assertAsRelativePath('/Coding/One/file.txt', 'One/file.txt')
|
|
assertAsRelativePath('/Coding/One/file.txt', 'One/file.txt', true)
|
|
assertAsRelativePath('/Coding/One/file.txt', 'file.txt', false)
|
|
assertAsRelativePath('/Coding/Two/files/out.txt', 'Two/files/out.txt')
|
|
assertAsRelativePath('/Coding/Two/files/out.txt', 'Two/files/out.txt', true)
|
|
assertAsRelativePath('/Coding/Two/files/out.txt', 'files/out.txt', false)
|
|
assertAsRelativePath('/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt')
|
|
assertAsRelativePath('/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt', true)
|
|
assertAsRelativePath('/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt', false)
|
|
})
|
|
})
|
|
|
|
describe('setWorkspaceFolders()', () => {
|
|
it('should set valid folders', async () => {
|
|
workspaceFolder.setWorkspaceFolders([os.tmpdir(), '/a/not_exists'])
|
|
let folders = workspaceFolder.workspaceFolders
|
|
expect(folders.length).toBe(2)
|
|
})
|
|
})
|
|
|
|
describe('getWorkspaceFolder()', () => {
|
|
it('should get workspaceFolder by uri', async () => {
|
|
let res = workspaceFolder.getWorkspaceFolder(URI.parse('untitled://1'))
|
|
expect(res).toBeUndefined()
|
|
res = workspaceFolder.getWorkspaceFolder(URI.file('/a/b'))
|
|
expect(res).toBeUndefined()
|
|
let filepath = path.join(process.cwd(), 'a/b')
|
|
workspaceFolder.setWorkspaceFolders([process.cwd()])
|
|
res = workspaceFolder.getWorkspaceFolder(URI.file(filepath))
|
|
expect(URI.parse(res.uri).fsPath).toBe(process.cwd())
|
|
})
|
|
})
|
|
|
|
describe('getRootPatterns()', () => {
|
|
it('should get patterns from b:coc_root_patterns', async () => {
|
|
await nvim.command('edit t.vim | let b:coc_root_patterns=["foo"]')
|
|
await nvim.command('setf vim')
|
|
let doc = await workspace.document
|
|
let res = workspaceFolder.getRootPatterns(doc, PatternType.Buffer)
|
|
expect(res).toEqual(['foo'])
|
|
})
|
|
|
|
it('should get patterns from languageserver', async () => {
|
|
updateConfiguration('languageserver', {
|
|
test: {
|
|
filetypes: ['vim'],
|
|
rootPatterns: ['bar']
|
|
}
|
|
}, {})
|
|
workspaceFolder.addRootPattern('vim', ['foo'])
|
|
await nvim.command('edit t.vim')
|
|
await nvim.command('setf vim')
|
|
let doc = await workspace.document
|
|
let res = workspaceFolder.getRootPatterns(doc, PatternType.LanguageServer)
|
|
expect(res).toEqual(['bar', 'foo'])
|
|
})
|
|
|
|
it('should get patterns from user configuration', async () => {
|
|
let doc = await workspace.document
|
|
let res = workspaceFolder.getRootPatterns(doc, PatternType.Global)
|
|
expect(res.includes('.git')).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('resolveRoot()', () => {
|
|
const cwd = process.cwd()
|
|
const expand = (input: string) => {
|
|
return workspace.expand(input)
|
|
}
|
|
|
|
it('should resolve to cwd for file in cwd', async () => {
|
|
updateConfiguration('coc.preferences.rootPatterns', [], ['.git', '.hg', '.projections.json'])
|
|
let file = path.join(os.tmpdir(), 'foo')
|
|
await nvim.command(`edit ${file}`)
|
|
let doc = await workspace.document
|
|
let res = workspaceFolder.resolveRoot(doc, os.tmpdir(), false, expand)
|
|
expect(res).toBe(os.tmpdir())
|
|
})
|
|
|
|
it('should not fallback to cwd as workspace folder', async () => {
|
|
updateConfiguration('coc.preferences.rootPatterns', [], ['.git', '.hg', '.projections.json'])
|
|
updateConfiguration('workspace.workspaceFolderFallbackCwd', false, true)
|
|
let file = path.join(os.tmpdir(), 'foo')
|
|
await nvim.command(`edit ${file}`)
|
|
let doc = await workspace.document
|
|
let res = workspaceFolder.resolveRoot(doc, os.tmpdir(), false, expand)
|
|
expect(res).toBe(null)
|
|
})
|
|
|
|
it('should return null for untitled buffer', async () => {
|
|
await nvim.command('enew')
|
|
let doc = await workspace.document
|
|
let res = workspaceFolder.resolveRoot(doc, cwd, false, expand)
|
|
expect(res).toBe(null)
|
|
})
|
|
|
|
it('should respect ignored filetypes', async () => {
|
|
updateConfiguration('workspace.ignoredFiletypes', ['vim'], [])
|
|
await nvim.command('edit t.vim')
|
|
await nvim.command('setf vim')
|
|
let doc = await workspace.document
|
|
let res = workspaceFolder.resolveRoot(doc, cwd, false, expand)
|
|
expect(res).toBe(null)
|
|
})
|
|
|
|
it('should respect workspaceFolderCheckCwd', async () => {
|
|
let called = 0
|
|
disposables.push(workspaceFolder.onDidChangeWorkspaceFolders(() => {
|
|
called++
|
|
}))
|
|
workspaceFolder.addRootPattern('vim', ['.vim'])
|
|
await nvim.command('edit a/.vim/t.vim')
|
|
await nvim.command('setf vim')
|
|
let doc = await workspace.document
|
|
let res = workspaceFolder.resolveRoot(doc, cwd, true, expand)
|
|
expect(res).toBe(process.cwd())
|
|
await nvim.command('edit a/foo')
|
|
doc = await workspace.document
|
|
res = workspaceFolder.resolveRoot(doc, cwd, true, expand)
|
|
expect(res).toBe(process.cwd())
|
|
expect(called).toBe(1)
|
|
})
|
|
|
|
it('should respect ignored folders', async () => {
|
|
updateConfiguration('workspace.ignoredFolders', ['$HOME/foo', '$HOME'], [])
|
|
let file = path.join(os.homedir(), '.vim/bar')
|
|
workspaceFolder.addRootPattern('vim', ['.vim'])
|
|
await nvim.command(`edit ${file}`)
|
|
await nvim.command('setf vim')
|
|
let doc = await workspace.document
|
|
let res = workspaceFolder.resolveRoot(doc, path.join(os.homedir(), 'foo'), true, expand)
|
|
expect(res).toBe(null)
|
|
})
|
|
|
|
describe('bottomUpFileTypes', () => {
|
|
it('should respect specific filetype', async () => {
|
|
updateConfiguration('coc.preferences.rootPatterns', ['.vim'], ['.git', '.hg', '.projections.json'])
|
|
updateConfiguration('workspace.bottomUpFiletypes', ['vim'], [])
|
|
let root = path.join(os.tmpdir(), 'a')
|
|
let dir = path.join(root, '.vim')
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true })
|
|
}
|
|
let file = path.join(dir, 'foo')
|
|
await nvim.command(`edit ${file}`)
|
|
await nvim.command('setf vim')
|
|
let doc = await workspace.document
|
|
let res = workspaceFolder.resolveRoot(doc, file, true, expand)
|
|
expect(res).toBe(root)
|
|
})
|
|
|
|
it('should respect wildcard', async () => {
|
|
updateConfiguration('coc.preferences.rootPatterns', ['.vim'], ['.git', '.hg', '.projections.json'])
|
|
updateConfiguration('workspace.bottomUpFiletypes', ['*'], [])
|
|
let root = path.join(os.tmpdir(), 'a')
|
|
let dir = path.join(root, '.vim')
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true })
|
|
await helper.wait(30)
|
|
}
|
|
let file = path.join(dir, 'foo')
|
|
await nvim.command(`edit ${file}`)
|
|
let doc = await workspace.document
|
|
let res = workspaceFolder.resolveRoot(doc, file, true, expand)
|
|
expect(res).toBe(root)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('renameWorkspaceFolder()', () => {
|
|
it('should rename workspaceFolder', async () => {
|
|
let e: WorkspaceFoldersChangeEvent
|
|
disposables.push(workspaceFolder.onDidChangeWorkspaceFolders(ev => {
|
|
e = ev
|
|
}))
|
|
let cwd = process.cwd()
|
|
workspaceFolder.addWorkspaceFolder(cwd, false)
|
|
workspaceFolder.addWorkspaceFolder(cwd, false)
|
|
workspaceFolder.renameWorkspaceFolder(cwd, path.join(cwd, '.vim'))
|
|
expect(e.removed.length).toBe(1)
|
|
expect(e.added.length).toBe(1)
|
|
})
|
|
})
|
|
|
|
describe('removeWorkspaceFolder()', () => {
|
|
it('should remote workspaceFolder', async () => {
|
|
let e: WorkspaceFoldersChangeEvent
|
|
disposables.push(workspaceFolder.onDidChangeWorkspaceFolders(ev => {
|
|
e = ev
|
|
}))
|
|
let cwd = process.cwd()
|
|
workspaceFolder.addWorkspaceFolder(cwd, false)
|
|
workspaceFolder.removeWorkspaceFolder(cwd)
|
|
workspaceFolder.removeWorkspaceFolder('/a/b')
|
|
expect(e.removed.length).toBe(1)
|
|
expect(e.added.length).toBe(0)
|
|
})
|
|
})
|
|
})
|