Skip to content

Commit 45a71b3

Browse files
committed
feat(semantic): build semantic for .d.ts files
1 parent 94796a0 commit 45a71b3

File tree

5 files changed

+383
-161
lines changed

5 files changed

+383
-161
lines changed

crates/oxc_semantic/src/builder.rs

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -214,51 +214,47 @@ impl<'a> SemanticBuilder<'a> {
214214
if self.build_jsdoc {
215215
self.jsdoc = JSDocBuilder::new(self.source_text, &program.comments);
216216
}
217-
if self.source_type.is_typescript_definition() {
218-
let scope_id = self.scoping.add_scope(None, NodeId::DUMMY, ScopeFlags::Top);
219-
program.scope_id.set(Some(scope_id));
217+
218+
// Use counts of nodes, scopes, symbols, and references to pre-allocate sufficient capacity
219+
// in `AstNodes`, `ScopeTree` and `SymbolTable`.
220+
//
221+
// This means that as we traverse the AST and fill up these structures with data,
222+
// they never need to grow and reallocate - which is an expensive operation as it
223+
// involves copying all the memory from the old allocation to the new one.
224+
// For large source files, these structures are very large, so growth is very costly
225+
// as it involves copying massive chunks of memory.
226+
// Avoiding this growth produces up to 30% perf boost on our benchmarks.
227+
//
228+
// If user did not provide existing `Stats`, calculate them by visiting AST.
229+
#[cfg_attr(not(debug_assertions), expect(unused_variables))]
230+
let (stats, check_stats) = if let Some(stats) = self.stats {
231+
(stats, None)
220232
} else {
221-
// Use counts of nodes, scopes, symbols, and references to pre-allocate sufficient capacity
222-
// in `AstNodes`, `ScopeTree` and `SymbolTable`.
223-
//
224-
// This means that as we traverse the AST and fill up these structures with data,
225-
// they never need to grow and reallocate - which is an expensive operation as it
226-
// involves copying all the memory from the old allocation to the new one.
227-
// For large source files, these structures are very large, so growth is very costly
228-
// as it involves copying massive chunks of memory.
229-
// Avoiding this growth produces up to 30% perf boost on our benchmarks.
230-
//
231-
// If user did not provide existing `Stats`, calculate them by visiting AST.
232-
#[cfg_attr(not(debug_assertions), expect(unused_variables))]
233-
let (stats, check_stats) = if let Some(stats) = self.stats {
234-
(stats, None)
235-
} else {
236-
let stats = Stats::count(program);
237-
let stats_with_excess = stats.increase_by(self.excess_capacity);
238-
(stats_with_excess, Some(stats))
239-
};
240-
self.nodes.reserve(stats.nodes as usize);
241-
self.scoping.reserve(
242-
stats.symbols as usize,
243-
stats.references as usize,
244-
stats.scopes as usize,
245-
);
233+
let stats = Stats::count(program);
234+
let stats_with_excess = stats.increase_by(self.excess_capacity);
235+
(stats_with_excess, Some(stats))
236+
};
237+
self.nodes.reserve(stats.nodes as usize);
238+
self.scoping.reserve(
239+
stats.symbols as usize,
240+
stats.references as usize,
241+
stats.scopes as usize,
242+
);
246243

247-
// Visit AST to generate scopes tree etc
248-
self.visit_program(program);
249-
250-
// Check that estimated counts accurately (unless in release mode)
251-
#[cfg(debug_assertions)]
252-
if let Some(stats) = check_stats {
253-
#[expect(clippy::cast_possible_truncation)]
254-
let actual_stats = Stats::new(
255-
self.nodes.len() as u32,
256-
self.scoping.scopes_len() as u32,
257-
self.scoping.symbols_len() as u32,
258-
self.scoping.references.len() as u32,
259-
);
260-
stats.assert_accurate(actual_stats);
261-
}
244+
// Visit AST to generate scopes tree etc
245+
self.visit_program(program);
246+
247+
// Check that estimated counts accurately (unless in release mode)
248+
#[cfg(debug_assertions)]
249+
if let Some(stats) = check_stats {
250+
#[expect(clippy::cast_possible_truncation)]
251+
let actual_stats = Stats::new(
252+
self.nodes.len() as u32,
253+
self.scoping.scopes_len() as u32,
254+
self.scoping.symbols_len() as u32,
255+
self.scoping.references.len() as u32,
256+
);
257+
stats.assert_accurate(actual_stats);
262258
}
263259

264260
let comments = self.alloc(&program.comments);

tasks/coverage/snapshots/parser_babel.snap

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ commit: 1d4546bc
22

33
parser_babel Summary:
44
AST Parsed : 2351/2362 (99.53%)
5-
Positive Passed: 2330/2362 (98.65%)
5+
Positive Passed: 2328/2362 (98.56%)
66
Negative Passed: 1600/1698 (94.23%)
77
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-startindex-and-startline-specified-without-startcolumn/input.js
88

@@ -628,6 +628,74 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
628628
10 │
629629
╰────
630630

631+
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts
632+
633+
× Cannot assign to 'eval' in strict mode
634+
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts:4:25]
635+
3 │ export namespace ns {
636+
4 │ export function eval(): void;
637+
· ────
638+
5 │ export function arguments(): void;
639+
╰────
640+
641+
× Cannot assign to 'arguments' in strict mode
642+
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts:5:25]
643+
4 │ export function eval(): void;
644+
5 │ export function arguments(): void;
645+
· ─────────
646+
6 │ }
647+
╰────
648+
649+
× Cannot assign to 'eval' in strict mode
650+
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts:9:18]
651+
8 │
652+
9 │ declare function eval(): void;
653+
· ────
654+
10 │ declare function arguments(): void;
655+
╰────
656+
657+
× Cannot assign to 'arguments' in strict mode
658+
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts:10:18]
659+
9 │ declare function eval(): void;
660+
10 │ declare function arguments(): void;
661+
· ─────────
662+
11 │
663+
╰────
664+
665+
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts
666+
667+
× Cannot assign to 'eval' in strict mode
668+
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts:4:25]
669+
3 │ export namespace ns {
670+
4 │ export function eval(): void;
671+
· ────
672+
5 │ export function arguments(): void;
673+
╰────
674+
675+
× Cannot assign to 'arguments' in strict mode
676+
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts:5:25]
677+
4 │ export function eval(): void;
678+
5 │ export function arguments(): void;
679+
· ─────────
680+
6 │ }
681+
╰────
682+
683+
× Cannot assign to 'eval' in strict mode
684+
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts:9:18]
685+
8 │
686+
9 │ declare function eval(): void;
687+
· ────
688+
10 │ declare function arguments(): void;
689+
╰────
690+
691+
× Cannot assign to 'arguments' in strict mode
692+
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts:10:18]
693+
9 │ declare function eval(): void;
694+
10 │ declare function arguments(): void;
695+
· ─────────
696+
11 │
697+
╰────
698+
631699
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/explicit-resource-management/valid-for-using-declaration-binding-of/input.js
632700

633701
× Unexpected token

tasks/coverage/snapshots/parser_typescript.snap

Lines changed: 82 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ commit: 81c95189
22

33
parser_typescript Summary:
44
AST Parsed : 6693/6700 (99.90%)
5-
Positive Passed: 6682/6700 (99.73%)
6-
Negative Passed: 1418/5598 (25.33%)
5+
Positive Passed: 6680/6700 (99.70%)
6+
Negative Passed: 1422/5598 (25.40%)
77
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment7.ts
88

99
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment8.ts
@@ -4362,8 +4362,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/classes/c
43624362

43634363
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractConstructorAssignability.ts
43644364

4365-
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractDeclarations.d.ts
4366-
43674365
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractExtends.ts
43684366

43694367
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractFactoryFunction.ts
@@ -7114,10 +7112,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ec
71147112

71157113
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserBlockStatement1.d.ts
71167114

7117-
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserBreakStatement1.d.ts
7118-
7119-
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserContinueStatement1.d.ts
7120-
71217115
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserDebuggerStatement1.d.ts
71227116

71237117
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserDoStatement1.d.ts
@@ -7180,8 +7174,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ec
71807174

71817175
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserWhileStatement1.d.ts
71827176

7183-
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserWithStatement1.d.ts
7184-
71857177
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/StrictMode/parserStrictMode1.ts
71867178

71877179
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/StrictMode/parserStrictMode15-negative.ts
@@ -8471,6 +8463,40 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/elidedEmbeddedSt
84718463
24 │ const enum H {}
84728464
╰────
84738465

8466+
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/evalOrArgumentsInDeclarationFunctions.ts
8467+
8468+
× Cannot assign to 'eval' in strict mode
8469+
╭─[typescript/tests/cases/compiler/evalOrArgumentsInDeclarationFunctions.ts:3:25]
8470+
2 │ export namespace ns {
8471+
3 │ export function eval(): void;
8472+
· ────
8473+
4 │ export function arguments(): void;
8474+
╰────
8475+
8476+
× Cannot assign to 'arguments' in strict mode
8477+
╭─[typescript/tests/cases/compiler/evalOrArgumentsInDeclarationFunctions.ts:4:25]
8478+
3 │ export function eval(): void;
8479+
4 │ export function arguments(): void;
8480+
· ─────────
8481+
5 │ }
8482+
╰────
8483+
8484+
× Cannot assign to 'eval' in strict mode
8485+
╭─[typescript/tests/cases/compiler/evalOrArgumentsInDeclarationFunctions.ts:8:18]
8486+
7 │
8487+
8 │ declare function eval(): void;
8488+
· ────
8489+
9 │ declare function arguments(): void;
8490+
╰────
8491+
8492+
× Cannot assign to 'arguments' in strict mode
8493+
╭─[typescript/tests/cases/compiler/evalOrArgumentsInDeclarationFunctions.ts:9:18]
8494+
8 │ declare function eval(): void;
8495+
9 │ declare function arguments(): void;
8496+
· ─────────
8497+
10 │
8498+
╰────
8499+
84748500
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/moduleResolutionWithExtensions_unexpected2.ts
84758501

84768502
× Expected a semicolon or an implicit semicolon after a statement, but found none
@@ -8630,6 +8656,23 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/es6/moduleExp
86308656
65 │ var y = _;
86318657
╰────
86328658

8659+
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/externalModules/topLevelAwait.3.ts
8660+
8661+
× The keyword 'await' is reserved
8662+
╭─[typescript/tests/cases/conformance/externalModules/topLevelAwait.3.ts:3:15]
8663+
2 │ export {};
8664+
3 │ declare const await: any;
8665+
· ──────────
8666+
4 │ declare class C extends await {}
8667+
╰────
8668+
8669+
× The keyword 'await' is reserved
8670+
╭─[typescript/tests/cases/conformance/externalModules/topLevelAwait.3.ts:4:25]
8671+
3 │ declare const await: any;
8672+
4 │ declare class C extends await {}
8673+
· ─────
8674+
╰────
8675+
86338676
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/moduleResolution/untypedModuleImport.ts
86348677

86358678
× Expected a semicolon or an implicit semicolon after a statement, but found none
@@ -18590,6 +18633,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
1859018633
9 │ }
1859118634
╰────
1859218635

18636+
× TS(1242): 'abstract' modifier can only appear on a class, method, or property declaration.
18637+
╭─[typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractDeclarations.d.ts:2:14]
18638+
1 │ declare abstract class A {
18639+
2 │ abstract constructor() {}
18640+
· ───────────
18641+
3 │ }
18642+
╰────
18643+
1859318644
× Function implementation is missing or not immediately following the declaration.
1859418645
╭─[typescript/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts:46:5]
1859518646
45 │ abstract nom(): boolean;
@@ -28110,6 +28161,20 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
2811028161
3 │ }
2811128162
╰────
2811228163

28164+
× Illegal break statement
28165+
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserBreakStatement1.d.ts:1:1]
28166+
1 │ break;
28167+
· ──────
28168+
╰────
28169+
help: A `break` statement can only be used within an enclosing iteration or switch statement.
28170+
28171+
× Illegal continue statement: no surrounding iteration statement
28172+
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserContinueStatement1.d.ts:1:1]
28173+
1 │ continue;
28174+
· ─────────
28175+
╰────
28176+
help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while`
28177+
2811328178
× Expected `;` but found `Identifier`
2811428179
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement2.ts:1:13]
2811528180
1 │ for (var of X) {
@@ -28262,6 +28327,13 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
2826228327
· ──────
2826328328
╰────
2826428329

28330+
× 'with' statements are not allowed
28331+
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserWithStatement1.d.ts:1:1]
28332+
1 │ with (foo) {
28333+
· ────
28334+
2 │ }
28335+
╰────
28336+
2826528337
× TS(1108): A 'return' statement can only be used within a function body.
2826628338
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserWithStatement2.ts:2:3]
2826728339
1 │ with (1)

tasks/coverage/snapshots/semantic_babel.snap

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ commit: 1d4546bc
22

33
semantic_babel Summary:
44
AST Parsed : 2362/2362 (100.00%)
5-
Positive Passed: 1945/2362 (82.35%)
5+
Positive Passed: 1943/2362 (82.26%)
66
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/annex-b/enabled/3.3-function-in-if-body/input.js
77
Symbol scope ID mismatch for "f":
88
after transform: SymbolId(0): ScopeId(4294967294)
@@ -598,6 +598,18 @@ Cannot assign to 'arguments' in strict mode
598598
Cannot assign to 'eval' in strict mode
599599
Cannot assign to 'arguments' in strict mode
600600
601+
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts/input.ts
602+
Cannot assign to 'eval' in strict mode
603+
Cannot assign to 'arguments' in strict mode
604+
Cannot assign to 'eval' in strict mode
605+
Cannot assign to 'arguments' in strict mode
606+
607+
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/eval-dts-babel-7/input.ts
608+
Cannot assign to 'eval' in strict mode
609+
Cannot assign to 'arguments' in strict mode
610+
Cannot assign to 'eval' in strict mode
611+
Cannot assign to 'arguments' in strict mode
612+
601613
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/function-rest-trailing-comma/input.ts
602614
Bindings mismatch:
603615
after transform: ScopeId(0): ["foo"]

0 commit comments

Comments
 (0)