# PositionMapper
macroforge v0.1.43
Bidirectional position mapper for translating between original and expanded source positions. This mapper enables IDE features like error reporting, go-to-definition, and hover to work correctly with macro-expanded code by translating positions between the original source (what the user wrote) and the expanded source (what the compiler sees).
## Getting a Mapper
TypeScript
```
import { NativePlugin, PositionMapper } from "macroforge";
const plugin = new NativePlugin();
const result = plugin.processFile("user.ts", code, { version: "1" });
// Get the mapper for this file
const mapper = plugin.getMapper("user.ts");
if (mapper) {
// Use the mapper...
}
```
## Methods
### isEmpty()
Check if the mapper has any mappings:
TypeScript
```
isEmpty(): boolean
```
### originalToExpanded()
Map a position from original to expanded code:
TypeScript
```
originalToExpanded(pos: number): number
```
### expandedToOriginal()
Map a position from expanded to original code:
TypeScript
```
expandedToOriginal(pos: number): number | null
```
Returns `null` if the position is in generated code.
### isInGenerated()
Check if a position is in macro-generated code:
TypeScript
```
isInGenerated(pos: number): boolean
```
### generatedBy()
Get the name of the macro that generated code at a position:
TypeScript
```
generatedBy(pos: number): string | null
```
### mapSpanToOriginal()
Map a span (range) from expanded to original code:
TypeScript
```
mapSpanToOriginal(start: number, length: number): SpanResult | null
interface SpanResult {
start: number;
length: number;
}
```
### mapSpanToExpanded()
Map a span from original to expanded code:
TypeScript
```
mapSpanToExpanded(start: number, length: number): SpanResult
```
## Example: Error Position Mapping
TypeScript
```
import { NativePlugin } from "macroforge";
const plugin = new NativePlugin();
function mapError(filepath: string, expandedPos: number, message: string) {
const mapper = plugin.getMapper(filepath);
if (!mapper) return null;
// Check if the error is in generated code
if (mapper.isInGenerated(expandedPos)) {
const macroName = mapper.generatedBy(expandedPos);
return {
message: `Error in code generated by @derive(${macroName}): ${message}`,
// Find the @derive decorator position
position: findDecoratorPosition(filepath)
};
}
// Map to original position
const originalPos = mapper.expandedToOriginal(expandedPos);
if (originalPos !== null) {
return {
message,
position: originalPos
};
}
return null;
}
```
## Performance
Position mapping uses binary search with O(log n) complexity:
* Fast lookups even for large files
* Minimal memory overhead
* Thread-safe access