import * as vscode from 'vscode' import * as path from 'path' import { WINGED_DIRS } from '../consts' import { Completion } from './Completion' import { fm } from '../helpers/FileManage' import { FileWatcher } from '../helpers/FileWatcher' import { tc } from '../helpers/TsComplier' export class SubviewNameCompletion extends Completion { public completionArr!: vscode.CompletionItem[] private preveFilePath = '' private completionArrCache!: vscode.CompletionItem[] constructor() { super() this.init() } private init() { const rootPath = fm.getRootPath() if (rootPath) { const compsDir = path.join(rootPath, WINGED_DIRS.TPL_COMP) const fw = new FileWatcher(compsDir) this.completionArr = [] fw.onFileAdd(this.add.bind(this)) fw.onFileDlete(this.delete.bind(this)) } else { throw new Error('无法识别 workspace') } } public add(filePath: string) { if (this.pathMatcher.test(filePath) && this.completionArr) { const label = fm.getCompNameByPath(filePath) const isExist = this.completionArr.some((item) => item.label === label) if (isExist) { vscode.window.showErrorMessage( `组件(Component)名称重复"${label}",请确保「所有」文件夹中的组件名称都不重复!${filePath}` ) } else { this.completionArr.push(this.getCompletionItem(label)) // 新增completion后filterWithCache重新计算缓存 this.preveFilePath = '' } } } public delete(filePath: string) { if (this.pathMatcher.test(filePath) && this.completionArr) { const label = fm.getCompNameByPath(filePath) let isExist = false this.completionArr = this.completionArr.filter((item) => { const compare = item.label === label if (compare) { isExist = true } return !compare }) if (isExist) { // 删除completion后filterWithCache重新计算缓存 this.preveFilePath = '' } else { vscode.window.showErrorMessage(`删除或更新失败,组件(Component)不存在"${label}",请检查路径${filePath}`) } } } /** * 根据路径过滤掉当前文件中不需要的提示 * 例如在example-item 文件中不需要 ExampleItem 提示 * @param uri 触发completion的路径 */ public filter(uri: string): vscode.CompletionItem[] { if (this.pathMatcher.test(uri)) { const label = fm.getCompNameByPath(uri) return this.completionArr.filter((item) => item.label !== label) } return [] } /** * 优化 filter的性能,加入缓存的逻辑,不会因为每次提示触发都过滤一遍数组 * @param uri 触发completion的路径 */ public filterWithCache(uri: string): vscode.CompletionItem[] { if (this.preveFilePath === uri && this.completionArrCache) { return this.completionArrCache } else { this.preveFilePath = uri this.completionArrCache = this.filter(uri) return this.completionArrCache } } public validateContext(document: vscode.TextDocument, position: vscode.Position) { console.log(document.lineCount, '~~~~~~~~~~~~~~~~~~') const res = tc.validateTagRange(document, position) if (res && res.type === 'other') { return true } return false } protected getCompletionItem(label: string): vscode.CompletionItem { const compleItem = new vscode.CompletionItem(label) compleItem.kind = vscode.CompletionItemKind.Function compleItem.documentation = `winged子视图${label}` compleItem.insertText = new vscode.SnippetString(`<${label} \${1}>\${2}`) return compleItem } public getCompletinArrWithRange( range: | { inserting: vscode.Range replacing: vscode.Range } | vscode.Range, uri: string ) { const cachArr = this.filterWithCache(uri) const temp = cachArr.map((item) => { const tempItem: vscode.CompletionItem = { label: item.label, kind: item.kind, documentation: item.documentation, insertText: item.insertText, range, } return tempItem }) return temp } }