# PositionMapper

macroforge v0.1.48

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
