@@ -3,25 +3,14 @@ import {
33 TerminalNode ,
44 TerminalKindExtensions
55} from '@nomicfoundation/slang/cst' ;
6- import { createKindCheckFunction } from '../slang-utils/create-kind-check-function.js' ;
76import { MultiLineComment } from '../slang-nodes/MultiLineComment.js' ;
87import { MultiLineNatSpecComment } from '../slang-nodes/MultiLineNatSpecComment.js' ;
98import { SingleLineComment } from '../slang-nodes/SingleLineComment.js' ;
109import { SingleLineNatSpecComment } from '../slang-nodes/SingleLineNatSpecComment.js' ;
1110
12- import type { Edge } from '@nomicfoundation/slang/cst' ;
1311import type { Comment , StrictAstNode } from '../slang-nodes/types.d.ts' ;
1412import type { AstLocation , SlangAstNode } from '../types.d.ts' ;
1513
16- const isCommentOrWhiteSpace = createKindCheckFunction ( [
17- TerminalKind . MultiLineComment ,
18- TerminalKind . MultiLineNatSpecComment ,
19- TerminalKind . SingleLineComment ,
20- TerminalKind . SingleLineNatSpecComment ,
21- TerminalKind . EndOfLine ,
22- TerminalKind . Whitespace
23- ] ) ;
24-
2514const offsets = new Map < number , number > ( ) ;
2615export function clearOffsets ( ) : void {
2716 offsets . clear ( ) ;
@@ -41,19 +30,6 @@ function reversedIterator<T>(children: T[]): Iterable<T> {
4130 } ;
4231}
4332
44- function getOffset ( children : Edge [ ] | Iterable < Edge > ) : number {
45- let offset = 0 ;
46- for ( const { node } of children ) {
47- if ( node . isNonterminalNode ( ) || ! isCommentOrWhiteSpace ( node ) ) {
48- // The node's content starts when we find the first non-terminal token,
49- // or if we find a non-comment, non-whitespace token.
50- return offset ;
51- }
52- offset += node . textLength . utf16 ;
53- }
54- return offset ;
55- }
56-
5733function collectComments (
5834 comments : Comment [ ] ,
5935 node : StrictAstNode | StrictAstNode [ ] | undefined
@@ -88,20 +64,33 @@ export class SlangNode {
8864 } ;
8965 return ;
9066 }
91- const parent = ast . cst ;
92- const children = parent . children ( ) ;
67+ const cst = ast . cst ;
9368
94- const initialOffset = offsets . get ( parent . id ) || 0 ;
69+ const initialOffset = offsets . get ( cst . id ) || 0 ;
9570 let offset = initialOffset ;
71+ let triviaLength = 0 ;
72+ let leadingOffset ;
73+ let trailingOffset ;
74+
75+ if ( enclosePeripheralComments ) {
76+ // We initialize the offsets to 0 to avoid them being updated later.
77+ leadingOffset = 0 ;
78+ trailingOffset = 0 ;
79+ }
9680
97- for ( const { node } of children ) {
81+ for ( const { node } of cst . children ( ) ) {
82+ const textLength = node . textLength . utf16 ;
9883 if (
9984 node . isNonterminalNode ( ) ||
10085 ! TerminalKindExtensions . isTrivia ( node . kind )
10186 ) {
10287 // Also tracking TerminalNodes since some variants that were not
10388 // Identifier or YulIdentifier but were upgraded to TerminalNode
10489 offsets . set ( node . id , offset ) ;
90+ // We assign the `leadingOffset` only once.
91+ leadingOffset ??= triviaLength ;
92+ // Since this is a non trivia node, we reset the accumulated length
93+ triviaLength = 0 ;
10594 } else {
10695 switch ( node . kind ) {
10796 // Since the fetching the comments and calculating offsets are both done
@@ -121,14 +110,17 @@ export class SlangNode {
121110 this . comments . push ( new SingleLineNatSpecComment ( node , offset ) ) ;
122111 break ;
123112 }
113+ // We accumulate the trivia length
114+ triviaLength += textLength ;
124115 }
125116
126- offset += node . textLength . utf16 ;
117+ offset += textLength ;
127118 }
128119
129- const [ leadingOffset , trailingOffset ] = enclosePeripheralComments
130- ? [ 0 , 0 ]
131- : [ getOffset ( children ) , getOffset ( reversedIterator ( children ) ) ] ;
120+ // In case the `leadingOffset` was not initialized
121+ leadingOffset ??= 0 ;
122+ // The remaining `triviaLength` is the `trailingOffset`
123+ trailingOffset ??= triviaLength ;
132124
133125 this . loc = {
134126 start : initialOffset + leadingOffset ,
0 commit comments