Skip to content

Commit 5891cc5

Browse files
♻️ Simplify checks
1 parent beb9b54 commit 5891cc5

2 files changed

Lines changed: 65 additions & 68 deletions

File tree

src/core/extractors.ts

Lines changed: 65 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -48,67 +48,6 @@ function stripDocstring(raw: string): string {
4848
const dedented = lines.map((l, i) => (i === 0 ? l : l.slice(minIndent)))
4949
return dedented.join("\n").trim()
5050
}
51-
/*
52-
* Extracts recognized FastAPI and APIRouter names from imports and class definitions
53-
* This allows the rest of the extractors to handle user-defined aliases and subclasses.
54-
*
55-
* For example, if the code has:
56-
* from fastapi import FastAPI as MyApp
57-
* from fastapi import APIRouter as MyRouter
58-
* class CustomRouter(MyRouter): ...
59-
*
60-
* Then this function will return:
61-
* fastAPINames = Set { "FastAPI", "fastapi.FastAPI", "MyApp" }
62-
* apiRouterNames = Set { "APIRouter", "fastapi.APIRouter", "MyRouter", "CustomRouter" }
63-
*
64-
* This allows decoratorExtractor and routerExtractor to recognize routes and routers
65-
* defined using these aliases and subclasses without needing complex logic in those functions.
66-
*/
67-
export function collectRecognizedNames(rootNode: Node): {
68-
fastAPINames: Set<string>
69-
apiRouterNames: Set<string>
70-
} {
71-
const fastAPINames = new Set<string>(["FastAPI", "fastapi.FastAPI"])
72-
const apiRouterNames = new Set<string>(["APIRouter", "fastapi.APIRouter"])
73-
74-
// Add aliases from "from fastapi import X as Y" imports
75-
for (const node of findNodesByType(rootNode, "import_from_statement")) {
76-
const info = importExtractor(node)
77-
if (!info || info.modulePath !== "fastapi") continue
78-
for (const named of info.namedImports) {
79-
if (named.alias === null) continue
80-
if (named.name === "FastAPI") fastAPINames.add(named.alias)
81-
else if (named.name === "APIRouter") apiRouterNames.add(named.alias)
82-
}
83-
}
84-
85-
// Add module aliases from "import fastapi as f" → recognizes f.FastAPI, f.APIRouter
86-
for (const node of findNodesByType(rootNode, "import_statement")) {
87-
const info = importExtractor(node)
88-
if (!info) continue
89-
for (const named of info.namedImports) {
90-
if (named.alias === null) continue
91-
if (named.name === "fastapi") {
92-
fastAPINames.add(`${named.alias}.FastAPI`)
93-
apiRouterNames.add(`${named.alias}.APIRouter`)
94-
}
95-
}
96-
}
97-
98-
// Add subclasses, checking against the already-accumulated alias sets so
99-
// "class MyRouter(AR)" works when AR is an alias for APIRouter
100-
for (const cls of findNodesByType(rootNode, "class_definition")) {
101-
const nameNode = cls.childForFieldName("name")
102-
const superclassesNode = cls.childForFieldName("superclasses")
103-
if (!nameNode || !superclassesNode) continue
104-
for (const parent of superclassesNode.namedChildren) {
105-
if (apiRouterNames.has(parent.text)) apiRouterNames.add(nameNode.text)
106-
else if (fastAPINames.has(parent.text)) fastAPINames.add(nameNode.text)
107-
}
108-
}
109-
110-
return { fastAPINames, apiRouterNames }
111-
}
11251

11352
function collectNodesByType(node: Node, type: string, results: Node[]): void {
11453
if (node.type === type) {
@@ -316,15 +255,15 @@ export function routerExtractor(
316255
const funcName = valueNode.childForFieldName("function")?.text
317256
let type: RouterType
318257
if (
319-
funcName === "APIRouter" ||
320-
funcName === "fastapi.APIRouter" ||
321-
(funcName !== undefined && apiRouterNames?.has(funcName))
258+
funcName !== undefined &&
259+
(apiRouterNames?.has(funcName) ??
260+
(funcName === "APIRouter" || funcName === "fastapi.APIRouter"))
322261
) {
323262
type = "APIRouter"
324263
} else if (
325-
funcName === "FastAPI" ||
326-
funcName === "fastapi.FastAPI" ||
327-
(funcName !== undefined && fastAPINames?.has(funcName))
264+
funcName !== undefined &&
265+
(fastAPINames?.has(funcName) ??
266+
(funcName === "FastAPI" || funcName === "fastapi.FastAPI"))
328267
) {
329268
type = "FastAPI"
330269
} else {
@@ -460,6 +399,65 @@ export function importExtractor(node: Node): ImportInfo | null {
460399
return { modulePath, names, namedImports, isRelative, relativeDots }
461400
}
462401

402+
/**
403+
* Extracts recognized FastAPI and APIRouter names from imports and class definitions.
404+
* This allows routerExtractor to handle user-defined aliases and subclasses.
405+
*
406+
* For example, if the code has:
407+
* from fastapi import FastAPI as MyApp
408+
* from fastapi import APIRouter as MyRouter
409+
* class CustomRouter(MyRouter): ...
410+
*
411+
* Then this function will return:
412+
* fastAPINames = Set { "FastAPI", "fastapi.FastAPI", "MyApp" }
413+
* apiRouterNames = Set { "APIRouter", "fastapi.APIRouter", "MyRouter", "CustomRouter" }
414+
*/
415+
export function collectRecognizedNames(rootNode: Node): {
416+
fastAPINames: Set<string>
417+
apiRouterNames: Set<string>
418+
} {
419+
const fastAPINames = new Set<string>(["FastAPI", "fastapi.FastAPI"])
420+
const apiRouterNames = new Set<string>(["APIRouter", "fastapi.APIRouter"])
421+
422+
// Add aliases from "from fastapi import X as Y" imports
423+
for (const node of findNodesByType(rootNode, "import_from_statement")) {
424+
const info = importExtractor(node)
425+
if (!info || info.modulePath !== "fastapi") continue
426+
for (const named of info.namedImports) {
427+
if (named.alias === null) continue
428+
if (named.name === "FastAPI") fastAPINames.add(named.alias)
429+
else if (named.name === "APIRouter") apiRouterNames.add(named.alias)
430+
}
431+
}
432+
433+
// Add module aliases from "import fastapi as f" → recognizes f.FastAPI, f.APIRouter
434+
for (const node of findNodesByType(rootNode, "import_statement")) {
435+
const info = importExtractor(node)
436+
if (!info) continue
437+
for (const named of info.namedImports) {
438+
if (named.alias === null) continue
439+
if (named.name === "fastapi") {
440+
fastAPINames.add(`${named.alias}.FastAPI`)
441+
apiRouterNames.add(`${named.alias}.APIRouter`)
442+
}
443+
}
444+
}
445+
446+
// Add subclasses, checking against the already-accumulated alias sets so
447+
// "class MyRouter(AR)" works when AR is an alias for APIRouter
448+
for (const cls of findNodesByType(rootNode, "class_definition")) {
449+
const nameNode = cls.childForFieldName("name")
450+
const superclassesNode = cls.childForFieldName("superclasses")
451+
if (!nameNode || !superclassesNode) continue
452+
for (const parent of superclassesNode.namedChildren) {
453+
if (apiRouterNames.has(parent.text)) apiRouterNames.add(nameNode.text)
454+
else if (fastAPINames.has(parent.text)) fastAPINames.add(nameNode.text)
455+
}
456+
}
457+
458+
return { fastAPINames, apiRouterNames }
459+
}
460+
463461
/**
464462
* Resolves a function argument value node by positional index or keyword name.
465463
*

src/vscode/testCodeLensProvider.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ export class TestCodeLensProvider implements CodeLensProvider {
143143
if (!pathArg) {
144144
continue
145145
}
146-
// extractPathFromNode always returns a non-empty string for valid AST nodes
147146
const path = extractPathFromNode(pathArg)
148147

149148
calls.push({

0 commit comments

Comments
 (0)