API Stability Notice
Macroforge is under active development. The API is not yet stable and may change between versions. Some documentation sections may be outdated.
PositionMapper
Maps positions between original source code and macro-expanded code. Essential for accurate error reporting and debugging.
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(): booleanoriginalToExpanded()
Map a position from original to expanded code:
TypeScript
originalToExpanded(pos: number): numberexpandedToOriginal()
Map a position from expanded to original code:
TypeScript
expandedToOriginal(pos: number): number | nullReturns null if the position is in generated code.
isInGenerated()
Check if a position is in macro-generated code:
TypeScript
isInGenerated(pos: number): booleangeneratedBy()
Get the name of the macro that generated code at a position:
TypeScript
generatedBy(pos: number): string | nullmapSpanToOriginal()
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): SpanResultExample: 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