Skip to content

Commit 3c3b126

Browse files
authored
docs: Guide for ExternalModule (#28)
# Motivation <!-- Why is this change necessary? --> # Content <!-- Please include a summary of the change --> # Testing <!-- How was the change tested? --> # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed - [ ] I have read and agree to the [Contributor License Agreement](../CLA.md)
1 parent 6445462 commit 3c3b126

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
---
2+
title: "External Modules"
3+
sidebarTitle: "External Modules"
4+
icon: "box-archive"
5+
iconType: "solid"
6+
---
7+
8+
Codegen provides a way to handle imports from external packages and modules through the [ExternalModule](/api-reference/core/ExternalModule) class.
9+
10+
```python
11+
# Python examples
12+
import datetime
13+
from requests import get
14+
15+
# TypeScript/JavaScript examples
16+
import React from 'react'
17+
import { useState, useEffect } from 'react'
18+
import type { ReactNode } from 'react'
19+
import axios from 'axios'
20+
```
21+
22+
## What are External Modules?
23+
24+
When writing code, you often import from packages that aren't part of your project - like `datetime` and `requests` in Python, or `react` and `axios` in TypeScript. In Codegen, these are represented as [ExternalModule](/api-reference/core/ExternalModule) instances.
25+
26+
```python
27+
for imp in codebase.imports:
28+
if isinstance(imp.symbol, ExternalModule):
29+
print(f"Importing from external package: {imp.resolved_symbol.source}")
30+
```
31+
32+
<Note>
33+
External modules are read-only - you can analyze them but can't modify their
34+
implementation. This makes sense since they live in your project's
35+
dependencies!
36+
</Note>
37+
38+
## Working with External Modules
39+
40+
The most common use case is handling external modules differently from your project's code:
41+
42+
### Identifying Function Calls as External Modules
43+
44+
For [FunctionCall](/api-reference/core/FunctionCall) instances, you can check if the function definition is an [ExternalModule](/api-reference/core/ExternalModule) via the [FunctionCall.function_definition](/api-reference/core/FunctionCall#function-definition) property:
45+
46+
```python
47+
for fcall in file.function_calls:
48+
definition = fcall.function_definition
49+
if isinstance(definition, ExternalModule):
50+
# Skip external functions
51+
print(f'External function: {definition.name}')
52+
else:
53+
# Process local functions...
54+
print(f'Local function: {definition.name}')
55+
```
56+
57+
### Import Resolution
58+
59+
Similarly, when working with imports, you can determine if they resolve to external modules by checking the [Import.resolved_symbol](/api-reference/core/Import#resolved-symbol) property:
60+
61+
```python
62+
for imp in file.imports:
63+
resolved = imp.resolved_symbol
64+
if isinstance(resolved, ExternalModule):
65+
print(f"Import from external package: from {imp.module} import {imp.name}")
66+
```
67+
68+
<Tip>
69+
Use `isinstance(symbol, ExternalModule)` to reliably identify external
70+
modules. This works better than checking names or paths since it handles all
71+
edge cases.
72+
</Tip>
73+
74+
## Properties and Methods
75+
76+
External modules provide several useful properties:
77+
78+
```python
79+
# Get the module name
80+
module_name = external_module.name # e.g. "datetime" or "useState"
81+
82+
# Check if it's from node_modules (TypeScript/JavaScript)
83+
if external_module.filepath == "":
84+
print("This is an external package from node_modules")
85+
```
86+
87+
## Common Patterns
88+
89+
Here are some typical ways you might work with external modules:
90+
91+
### Skip External Processing:
92+
93+
When modifying function calls or imports, skip external modules since they can't be changed:
94+
95+
```python
96+
# Example from a codemod that adds type hints
97+
def add_type_hints(function):
98+
if isinstance(function.definition, ExternalModule):
99+
return # Can't add type hints to external modules like React.FC
100+
# Add type hints to local functions...
101+
```
102+
103+
### Analyze Dependencies
104+
105+
Track which external packages your code uses:
106+
107+
```python
108+
# Find all external package dependencies
109+
external_deps = set()
110+
for imp in codebase.imports:
111+
if isinstance(imp.resolved_symbol, ExternalModule):
112+
external_deps.add(imp.resolved_symbol.source)
113+
# Will find things like 'react', 'lodash', 'datetime', etc.
114+
```
115+
116+
<Note>
117+
When working with imports, always handle external modules as a special case.
118+
This ensures your codemods work correctly with both local and external code.
119+
</Note>

docs/mint.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
"building-with-codegen/variable-assignments",
103103
"building-with-codegen/local-variables",
104104
"building-with-codegen/comments-and-docstrings",
105+
"building-with-codegen/external-modules",
105106
"building-with-codegen/moving-symbols",
106107
"building-with-codegen/collections",
107108
"building-with-codegen/traversing-the-call-graph",

0 commit comments

Comments
 (0)