(rootNode: TSNode, code: string)
| 15 | * Parse all import statements from the AST |
| 16 | */ |
| 17 | export function parseImports(rootNode: TSNode, code: string): Map<string, ImportInfo> { |
| 18 | const imports = new Map<string, ImportInfo>(); |
| 19 | |
| 20 | // Handle "import xxx [as yyy]" statements (module imports) |
| 21 | const importNodes = queryNodes(rootNode, 'import_statement'); |
| 22 | for (const importNode of importNodes) { |
| 23 | for (const child of importNode.namedChildren) { |
| 24 | if (!child) {continue;} |
| 25 | if (child.type === 'aliased_import') { |
| 26 | const nameNode = child.childForFieldName('name'); |
| 27 | const aliasNode = child.childForFieldName('alias'); |
| 28 | if (!nameNode || !aliasNode) {continue;} |
| 29 | const modulePath = getNodeText(nameNode, code); |
| 30 | const alias = getNodeText(aliasNode, code); |
| 31 | imports.set(alias, { modulePath, className: '', alias, isModule: true }); |
| 32 | } else if (child.type === 'dotted_name') { |
| 33 | const modulePath = getNodeText(child, code); |
| 34 | // Only store non-dotted imports (e.g., "import masfactory") to avoid alias ambiguity. |
| 35 | if (!modulePath.includes('.')) { |
| 36 | imports.set(modulePath, { modulePath, className: '', alias: modulePath, isModule: true }); |
| 37 | } |
| 38 | } |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | // Find all import_from_statement nodes |
| 43 | // e.g., "from masfactory.components.compound_graph import InstructorAssistantGraph" |
| 44 | const importFromNodes = queryNodes(rootNode, 'import_from_statement'); |
| 45 | |
| 46 | for (const importNode of importFromNodes) { |
| 47 | const moduleNameNode = importNode.childForFieldName('module_name'); |
| 48 | if (!moduleNameNode) {continue;} |
| 49 | |
| 50 | const modulePath = getNodeText(moduleNameNode, code); |
| 51 | |
| 52 | // Get imported names |
| 53 | for (const child of importNode.namedChildren) { |
| 54 | if (!child) {continue;} |
| 55 | if (child.type === 'aliased_import') { |
| 56 | // from xxx import YYY as ZZZ |
| 57 | const nameNode = child.childForFieldName('name'); |
| 58 | const aliasNode = child.childForFieldName('alias'); |
| 59 | if (nameNode) { |
| 60 | const className = getNodeText(nameNode, code); |
| 61 | const alias = aliasNode ? getNodeText(aliasNode, code) : undefined; |
| 62 | const key = alias || className; |
| 63 | imports.set(key, { modulePath, className, alias, isModule: false }); |
| 64 | } |
| 65 | } else if (child.type === 'import_list') { |
| 66 | // from xxx import (YYY, ZZZ as AAA) |
| 67 | for (const item of child.namedChildren) { |
| 68 | if (!item) {continue;} |
| 69 | if (item.type === 'aliased_import') { |
| 70 | const nameNode = item.childForFieldName('name'); |
| 71 | const aliasNode = item.childForFieldName('alias'); |
| 72 | if (!nameNode) {continue;} |
| 73 | const className = getNodeText(nameNode, code); |
| 74 | const alias = aliasNode ? getNodeText(aliasNode, code) : undefined; |
no test coverage detected