✨ feat(vscode): 代码阅读支持库规则,内置 SQLAlchemy 模型类显示成数据表卡片

This commit is contained in:
cruldra committed 2026-09-26 18:29:40 +08:00
1 parent 32be7d54b6
commit 5ece24cef9
26 files changed
+1768 -81

No files matched your search

+12 -2
View File
@@ -1,5 +1,5 @@
import type { Disposable, Event, Memento } from 'vscode'
import type { CodeReaderApi, LanguageAdapter, Translator } from './contract'
import type { CodeReaderApi, LanguageAdapter, LibraryRule, Translator } from './contract'
/** globalState 里按 languageId 记选中的翻译插件 id:Record<languageId, translatorId>。 */
export const TRANSLATOR_CHOICE_KEY = 'superpowers.codeReader.translatorByLanguage'
@@ -7,12 +7,13 @@ export const TRANSLATOR_CHOICE_KEY = 'superpowers.codeReader.translatorByLanguag
interface Entry<T> { value: T }
/**
* 语言插件、翻译插件的注册表。内置实现和其他扩展都通过它注册(它本身就是对外的 CodeReaderApi)。
* 语言插件、翻译插件、库规则的注册表。内置实现和其他扩展都通过它注册(它本身就是对外的 CodeReaderApi)。
* 不依赖 vscode 运行时:Disposable 和事件都是结构兼容的普通对象,便于单元测试。
*/
export class CodeReaderRegistry implements CodeReaderApi {
private readonly adapters: Entry<LanguageAdapter>[] = []
private readonly translators: Entry<Translator>[] = []
private readonly rules: Entry<LibraryRule>[] = []
private readonly listeners = new Set<() => void>()
constructor(private readonly state: Pick<Memento, 'get' | 'update'>) {}
@@ -36,6 +37,10 @@ export class CodeReaderRegistry implements CodeReaderApi {
return this.add(this.translators, translator)
}
registerLibraryRule(rule: LibraryRule): Disposable {
return this.add(this.rules, rule)
}
/** 当前语言插件覆盖的全部 languageId(去重、排序),给 when 子句用。 */
languageIds(): string[] {
return [...new Set(this.adapters.flatMap(entry => entry.value.languageIds))].sort()
@@ -51,6 +56,11 @@ export class CodeReaderRegistry implements CodeReaderApi {
return this.translators.map(entry => entry.value).filter(translator => translator.languageIds.includes(languageId))
}
/** 某 languageId 的库规则,按注册顺序:几个规则都认同一块时先注册的算。 */
rulesFor(languageId: string): LibraryRule[] {
return this.rules.map(entry => entry.value).filter(rule => rule.languageIds.includes(languageId))
}
/** 选中的翻译:globalState 里记的那个还注册着就用它,否则用第一个。 */
selectedTranslator(languageId: string): Translator | undefined {
const candidates = this.translatorsFor(languageId)