Skip to content

Commit 304821d

Browse files
committed
Track scopes for definition field
1 parent 32caaf6 commit 304821d

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

src/builder/builder.test.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
import { beforeEach, describe, it } from "jsr:@std/testing/bdd";
66
import { ScopeInfoBuilder } from "./builder.ts";
7-
import { assertEquals, assertStrictEquals } from "jsr:@std/assert";
7+
import {
8+
assertEquals,
9+
assertNotStrictEquals,
10+
assertStrictEquals,
11+
} from "jsr:@std/assert";
812

913
describe("ScopeInfoBuilder", () => {
1014
let builder: ScopeInfoBuilder;
@@ -126,4 +130,49 @@ describe("ScopeInfoBuilder", () => {
126130
builder.endRange(0, 20);
127131
});
128132
});
133+
134+
describe("currentScope", () => {
135+
it("returns 'null' when no scope is on the stack", () => {
136+
assertStrictEquals(builder.currentScope(), null);
137+
});
138+
139+
it("returns the currently open scope (top-level)", () => {
140+
builder.startScope(0, 0);
141+
142+
assertNotStrictEquals(builder.currentScope(), null);
143+
});
144+
145+
it("returns the currently open scope (nested)", () => {
146+
builder.startScope(0, 0).startScope(10, 0);
147+
148+
assertEquals(builder.currentScope()?.start, { line: 10, column: 0 });
149+
});
150+
});
151+
152+
describe("lastScope", () => {
153+
it("returns 'null' when no scope was closed yet", () => {
154+
assertStrictEquals(builder.lastScope(), null);
155+
});
156+
157+
it("returns the last closed scope (top-level)", () => {
158+
builder.startScope(0, 0).endScope(10, 0);
159+
160+
assertNotStrictEquals(builder.lastScope(), null);
161+
});
162+
163+
it("returns the last closed scope (nested)", () => {
164+
builder.startScope(0, 0).startScope(10, 0).endScope(20, 0);
165+
166+
assertEquals(builder.lastScope()?.start, { line: 10, column: 0 });
167+
});
168+
169+
it("returns the last closed scope after starting new ones", () => {
170+
builder.startScope(0, 0).startScope(10, 0).endScope(20, 0).startScope(
171+
30,
172+
0,
173+
);
174+
175+
assertEquals(builder.lastScope()?.start, { line: 10, column: 0 });
176+
});
177+
});
129178
});

src/builder/builder.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ export class ScopeInfoBuilder {
2121
#scopeStack: OriginalScope[] = [];
2222
#rangeStack: GeneratedRange[] = [];
2323

24+
#scopeCounter = 0;
25+
#scopeToCount = new Map<OriginalScope, number>();
26+
#lastScope: OriginalScope | null = null;
27+
2428
addNullScope(): this {
2529
this.#scopes.push(null);
2630
return this;
@@ -46,6 +50,7 @@ export class ScopeInfoBuilder {
4650
scope.parent = this.#scopeStack.at(-1);
4751
}
4852
this.#scopeStack.push(scope);
53+
this.#scopeToCount.set(scope, this.#scopeCounter++);
4954

5055
return this;
5156
}
@@ -79,10 +84,25 @@ export class ScopeInfoBuilder {
7984
} else {
8085
this.#scopeStack.at(-1)!.children.push(scope);
8186
}
87+
this.#lastScope = scope;
8288

8389
return this;
8490
}
8591

92+
/**
93+
* @returns The OriginalScope opened with the most recent `startScope` call, but not yet closed.
94+
*/
95+
currentScope(): OriginalScope | null {
96+
return this.#scopeStack.at(-1) ?? null;
97+
}
98+
99+
/**
100+
* @returns The most recent OriginalScope closed with `endScope`.
101+
*/
102+
lastScope(): OriginalScope | null {
103+
return this.#lastScope;
104+
}
105+
86106
startRange(line: number, column: number): this {
87107
const range: GeneratedRange = {
88108
start: { line, column },
@@ -122,6 +142,7 @@ export class ScopeInfoBuilder {
122142

123143
this.#scopes = [];
124144
this.#ranges = [];
145+
this.#scopeToCount.clear();
125146

126147
return info;
127148
}

0 commit comments

Comments
 (0)