import { Completion } from './Completion' import * as vscode from 'vscode' import { fm } from '../helpers/FileManage' import { Dict, CompletionMap } from '../type' import { tc } from '../helpers/TsComplier' import { completionRefreshDelay } from '../readConfig' import { utils } from '../utils' export class PropsCompletion extends Completion { public completionArr!: vscode.CompletionItem[] // props关联补全map private completionMap: CompletionMap = {} private timerCache: number = 0 public validateContext(document: vscode.TextDocument, position: vscode.Position): boolean { const linePrefix = utils.getLinePrefix(document, position) if (linePrefix.includes('props.')) { return true } return false } /** * props 补全格式 * @param label 触发字段名 * @param desp 字段描述 */ protected getCompletionItem(label: string, desp: string): vscode.CompletionItem { const compleItem = new vscode.CompletionItem(label) compleItem.kind = vscode.CompletionItemKind.Field compleItem.detail = desp compleItem.documentation = `propsType.${label}` compleItem.insertText = label return compleItem } /** * 获取props相关联的字段补全 * 解析规则为 根据filePath 找到对应 ts文件的 propsInterface 并用 ts提供的 API 解析 AST 获取关联字段 * @param filePath 当前键入props.的html文件路径 * @param linePrefix 拿到当前行 */ public async getPropsRelateCompletion(filePath: string, linePrefix: string) { if (!this.pathMatcher.test(filePath)) return [] const now = Date.now() // 节流处理,节省获取 props 的开销 if (now - this.timerCache > completionRefreshDelay) { const compName = fm.getCompNameByPath(filePath) const desp = await tc.getPropsDespByCompName(compName) if (desp) { this.timerCache = now this.completionMap = {} this.generateCompletionMap('props.', desp) return this.parseCompletionMap(linePrefix) } } return this.parseCompletionMap(linePrefix) } /** * 解析propsDescribe生成completionMap,键为触发的上下文,值为提示数组 * @param context 触发上下文 * @param propsDescribe props的描述信息 */ private generateCompletionMap(context: string, propsDescribe: Dict) { const completion: vscode.CompletionItem[] = [] Object.keys(propsDescribe).forEach((key) => { const value = propsDescribe[key] key = utils.initLabel(key) if (typeof value === 'object') { completion.push(this.getCompletionItem(key, utils.marshalIndent(value))) this.generateCompletionMap(context + key + '.', value) } else { completion.push(this.getCompletionItem(key, value)) } }) this.completionMap[context] = completion } /** * 根据linePrefix返回对应的代码提示数组 */ private parseCompletionMap(linePrefix: string) { const map = this.completionMap const keys = Object.keys(map) for (const key of keys) { if (linePrefix.endsWith(key)) { return map[key] } } return [] } }