diff --git a/vscode/src/codeReader/rules/contractOnly.test.ts b/vscode/src/codeReader/rules/contractOnly.test.ts index 40e5657..69d71b8 100644 --- a/vscode/src/codeReader/rules/contractOnly.test.ts +++ b/vscode/src/codeReader/rules/contractOnly.test.ts @@ -12,7 +12,7 @@ describe('库规则只经 contract 拿信息', () => { const files = readdirSync(__dirname).filter(file => file.endsWith('.ts') && !file.endsWith('.test.ts')) it('目录里有规则', () => { - expect(files).toEqual(expect.arrayContaining(['sqlalchemy.ts', 'celery.ts', 'enum.ts', 'dataclass.ts', 'fastapi.ts'])) + expect(files).toEqual(expect.arrayContaining(['sqlalchemy.ts', 'celery.ts', 'enum.ts', 'dataclass.ts', 'pydantic.ts', 'fastapi.ts'])) }) it.each(files)('%s 不 import 语言插件、翻译插件和宿主', (file) => { diff --git a/vscode/src/codeReader/rules/pydantic.ts b/vscode/src/codeReader/rules/pydantic.ts index 9f9ff59..3a408c3 100644 --- a/vscode/src/codeReader/rules/pydantic.ts +++ b/vscode/src/codeReader/rules/pydantic.ts @@ -1,6 +1,5 @@ import type { Access, ClassBlock, CodeBlock, ImportFacts, IndexEntry, Inline, KindIconName, LibraryRule, Node, PropertyItem, PropertyRow, RuleCard, RuleContext, ThemeColor, WorkspaceIndex } from '../contract' import type { Call, LibraryNames } from './pythonTree' -import { fromLibrary } from '../libraryRules' import { annotatedAssignments, memberDocs, withLeadingComments } from './children' import { aliasesOf, callOf, canonicalName, genericOf, libraryName, libraryNames, stringValue, syntaxChildren, unwrapType } from './pythonTree' import { hint, joined, name, plain, range, word } from './segments' @@ -98,11 +97,16 @@ interface Field { value?: Node } +/** 模块名是 pydantic,或是它的子模块(`pydantic.main`)。 */ +function fromPydantic(module: string): boolean { + return module === LIBRARY || module.startsWith(`${LIBRARY}.`) || module.startsWith(`${LIBRARY}/`) +} + /** pydantic 以及它的子模块(`pydantic.main`)里导入的名字。 */ function pydanticNames(imports: readonly ImportFacts[]): LibraryNames { const names = libraryNames(imports, LIBRARY) for (const facts of imports) { - if (!facts.sources.some(source => fromLibrary(source.text, LIBRARY) && source.text !== LIBRARY)) + if (!facts.sources.some(source => fromPydantic(source.text) && source.text !== LIBRARY)) continue for (const item of facts.items) { if (item.kind === 'named') @@ -159,14 +163,14 @@ function namesInSource(root: Node): LibraryNames { for (const item of statement.childrenForFieldName('name')) { const original = item.type === 'aliased_import' ? item.childForFieldName('name') : item const alias = item.type === 'aliased_import' ? item.childForFieldName('alias') : null - if (original && fromLibrary(original.text, LIBRARY)) + if (original && fromPydantic(original.text)) names.modules.add(alias?.text ?? original.text) } } if (statement.type !== 'import_from_statement') continue const module = statement.childForFieldName('module_name') - if (!module || !fromLibrary(module.text, LIBRARY)) + if (!module || !fromPydantic(module.text)) continue for (const item of statement.childrenForFieldName('name')) { const original = item.type === 'aliased_import' ? item.childForFieldName('name') : item