Skip to content

Commit 082959b

Browse files
Even more cleanup
1 parent 138190d commit 082959b

1 file changed

Lines changed: 70 additions & 65 deletions

File tree

src/core/extractors.ts

Lines changed: 70 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,9 @@ export function decoratorExtractor(node: Node): RouteInfo | null {
170170

171171
/** Extracts tags from a list node like ["users", "admin"] */
172172
function extractTags(listNode: Node): string[] {
173-
const tags: string[] = []
174-
for (const elem of listNode.namedChildren) {
175-
const tagValue = extractStringValue(elem)
176-
if (tagValue !== null) {
177-
tags.push(tagValue)
178-
}
179-
}
180-
return tags
173+
return listNode.namedChildren
174+
.map((elem) => extractStringValue(elem))
175+
.filter((v): v is string => v !== null)
181176
}
182177

183178
export function routerExtractor(node: Node): RouterInfo | null {
@@ -192,14 +187,12 @@ export function routerExtractor(node: Node): RouterInfo | null {
192187
}
193188

194189
const funcName = valueNode.childForFieldName("function")?.text
195-
const type: RouterType =
196-
funcName === "APIRouter" || funcName === "fastapi.APIRouter"
197-
? "APIRouter"
198-
: funcName === "FastAPI" || funcName === "fastapi.FastAPI"
199-
? "FastAPI"
200-
: "Unknown"
201-
202-
if (type === "Unknown") {
190+
let type: RouterType
191+
if (funcName === "APIRouter" || funcName === "fastapi.APIRouter") {
192+
type = "APIRouter"
193+
} else if (funcName === "FastAPI" || funcName === "fastapi.FastAPI") {
194+
type = "FastAPI"
195+
} else {
203196
return null
204197
}
205198

@@ -230,6 +223,35 @@ export function routerExtractor(node: Node): RouterInfo | null {
230223
}
231224
}
232225

226+
/** Checks if a node is inside an ancestor of a given type */
227+
function hasAncestor(node: Node, ancestorType: string): boolean {
228+
let parent = node.parent
229+
while (parent) {
230+
if (parent.type === ancestorType) {
231+
return true
232+
}
233+
parent = parent.parent
234+
}
235+
return false
236+
}
237+
238+
/** Parses a module path, extracting relative dots if present */
239+
function parseModulePath(rawPath: string): {
240+
modulePath: string
241+
isRelative: boolean
242+
relativeDots: number
243+
} {
244+
const matches = rawPath.match(/^(\.+)(.*)/)
245+
if (matches) {
246+
return {
247+
modulePath: matches[2],
248+
isRelative: true,
249+
relativeDots: matches[1].length,
250+
}
251+
}
252+
return { modulePath: rawPath, isRelative: false, relativeDots: 0 }
253+
}
254+
233255
export function importExtractor(node: Node): ImportInfo | null {
234256
if (
235257
node.type !== "import_statement" &&
@@ -238,67 +260,50 @@ export function importExtractor(node: Node): ImportInfo | null {
238260
return null
239261
}
240262

241-
let modulePath = ""
242263
const names: string[] = []
243264
const namedImports: ImportedName[] = []
244-
let isRelative = false
245-
let relativeDots = 0
246265

247266
if (node.type === "import_statement") {
248267
const nameNodes = findNodesByType(node, "dotted_name")
249268
for (const nameNode of nameNodes) {
250-
modulePath = nameNode.text
251-
const asNames = nameNode.text.split(".")
252-
names.push(asNames[0])
253-
namedImports.push({ name: asNames[0], alias: null })
269+
const firstName = nameNode.text.split(".")[0]
270+
names.push(firstName)
271+
namedImports.push({ name: firstName, alias: null })
254272
}
255-
} else if (node.type === "import_from_statement") {
256-
const moduleNode = node.childForFieldName("module_name")
257-
if (moduleNode) {
258-
const rawPath = moduleNode.text
259-
const matches = rawPath.match(/^(\.+)(.*)/)
260-
if (matches) {
261-
isRelative = true
262-
relativeDots = matches[1].length
263-
modulePath = matches[2]
264-
} else {
265-
modulePath = rawPath
266-
}
273+
const modulePath = nameNodes[0]?.text ?? ""
274+
return {
275+
modulePath,
276+
names,
277+
namedImports,
278+
isRelative: false,
279+
relativeDots: 0,
267280
}
281+
}
268282

269-
// Look for aliased_import nodes (e.g., "router as users_router")
270-
const aliasedImports = findNodesByType(node, "aliased_import")
271-
for (const aliased of aliasedImports) {
272-
const nameNode = aliased.childForFieldName("name")
273-
const aliasNode = aliased.childForFieldName("alias")
274-
if (nameNode) {
275-
const originalName = nameNode.text
276-
const aliasName = aliasNode?.text ?? null
277-
names.push(aliasName ?? originalName)
278-
namedImports.push({ name: originalName, alias: aliasName })
279-
}
283+
// import_from_statement
284+
const moduleNode = node.childForFieldName("module_name")
285+
const { modulePath, isRelative, relativeDots } = parseModulePath(
286+
moduleNode?.text ?? "",
287+
)
288+
289+
// Aliased imports (e.g., "router as users_router")
290+
for (const aliased of findNodesByType(node, "aliased_import")) {
291+
const nameNode = aliased.childForFieldName("name")
292+
const aliasNode = aliased.childForFieldName("alias")
293+
if (nameNode) {
294+
const alias = aliasNode?.text ?? null
295+
names.push(alias ?? nameNode.text)
296+
namedImports.push({ name: nameNode.text, alias })
280297
}
281298
}
282299

283-
// Get non-aliased imports (dotted_name nodes not inside aliased_import)
284-
if (node.type === "import_from_statement") {
285-
const nameNodes = findNodesByType(node, "dotted_name")
286-
for (let i = 1; i < nameNodes.length; i++) {
287-
const nameNode = nameNodes[i]
288-
// Check if this node is inside an aliased_import
289-
let parent = nameNode.parent
290-
let isAliased = false
291-
while (parent) {
292-
if (parent.type === "aliased_import") {
293-
isAliased = true
294-
break
295-
}
296-
parent = parent.parent
297-
}
298-
if (!isAliased) {
299-
names.push(nameNode.text)
300-
namedImports.push({ name: nameNode.text, alias: null })
301-
}
300+
// Non-aliased imports (skip first dotted_name which is the module path)
301+
const nameNodes = findNodesByType(node, "dotted_name")
302+
for (let i = 1; i < nameNodes.length; i++) {
303+
const nameNode = nameNodes[i]
304+
if (!hasAncestor(nameNode, "aliased_import")) {
305+
names.push(nameNode.text)
306+
namedImports.push({ name: nameNode.text, alias: null })
302307
}
303308
}
304309

0 commit comments

Comments
 (0)