@@ -23,8 +23,9 @@ function extractCommentsFromJsonc(jsoncString: string): Record<string, any> {
2323 return { } ;
2424 }
2525
26- // Track nesting context
27- const contextStack : Array < { key : string ; isArray : boolean } > = [ ] ;
26+ // Track nesting context with array indices
27+ const contextStack : Array < { key : string ; isArray : boolean ; arrayIndex ?: number } > = [ ] ;
28+ let arrayObjectCount : Record < number , number > = { } ; // Track object count per array depth
2829
2930 for ( let i = 0 ; i < lines . length ; i ++ ) {
3031 const line = lines [ i ] ;
@@ -42,12 +43,12 @@ function extractCommentsFromJsonc(jsoncString: string): Record<string, any> {
4243 const keyMatch = line . match ( / ^ \s * [ " ' ] ? ( [ ^ " ' : , \s ] + ) [ " ' ] ? \s * : / ) ;
4344 if ( keyMatch ) {
4445 const key = keyMatch [ 1 ] ;
45- const path = contextStack . map ( ( ctx ) => ctx . key ) . filter ( Boolean ) ;
46+ const path = contextStack . map ( ( ctx ) => ctx . arrayIndex !== undefined ? String ( ctx . arrayIndex ) : ctx . key ) . filter ( Boolean ) ;
4647 keyInfo = { key, path } ;
4748 }
4849 } else {
4950 // For standalone comments, find the next key
50- keyInfo = findAssociatedKey ( lines , commentData . lineIndex , contextStack ) ;
51+ keyInfo = findAssociatedKey ( lines , commentData . lineIndex , contextStack , arrayObjectCount ) ;
5152 }
5253
5354 if ( keyInfo && keyInfo . key ) {
@@ -60,7 +61,7 @@ function extractCommentsFromJsonc(jsoncString: string): Record<string, any> {
6061 }
6162
6263 // Update context for object/array nesting
63- updateContext ( contextStack , line , result ) ;
64+ updateContext ( contextStack , line , result , arrayObjectCount ) ;
6465 }
6566
6667 return comments ;
@@ -166,7 +167,8 @@ function extractBlockComment(
166167function findAssociatedKey (
167168 lines : string [ ] ,
168169 commentLineIndex : number ,
169- contextStack : Array < { key : string ; isArray : boolean } > ,
170+ contextStack : Array < { key : string ; isArray : boolean ; arrayIndex ?: number } > ,
171+ arrayObjectCount : Record < number , number > ,
170172) : { key : string | null ; path : string [ ] } {
171173 // Look for the next key after the comment
172174 for ( let i = commentLineIndex + 1 ; i < lines . length ; i ++ ) {
@@ -175,18 +177,50 @@ function findAssociatedKey(
175177 if (
176178 ! line ||
177179 line . startsWith ( "//" ) ||
178- line . startsWith ( "/*" ) ||
179- line === "{" ||
180- line === "}"
180+ line . startsWith ( "/*" )
181181 ) {
182182 continue ;
183183 }
184184
185+ // Check if we're about to enter an array object
186+ if ( line === "{" && contextStack . length > 0 ) {
187+ const parent = contextStack [ contextStack . length - 1 ] ;
188+ if ( parent . isArray ) {
189+ // Get the current array index from arrayObjectCount
190+ const depth = contextStack . length - 1 ;
191+ const arrayIndex = arrayObjectCount [ depth ] || 0 ;
192+
193+ // Continue looking for the key inside this object
194+ for ( let j = i + 1 ; j < lines . length ; j ++ ) {
195+ const innerLine = lines [ j ] . trim ( ) ;
196+ if ( ! innerLine || innerLine . startsWith ( "//" ) || innerLine . startsWith ( "/*" ) ) continue ;
197+
198+ const keyMatch = innerLine . match ( / ^ \s * [ " ' ] ? ( [ ^ " ' : , \s ] + ) [ " ' ] ? \s * : / ) ;
199+ if ( keyMatch ) {
200+ const key = keyMatch [ 1 ] ;
201+ const path = contextStack
202+ . map ( ( ctx ) => ctx . arrayIndex !== undefined ? String ( ctx . arrayIndex ) : ctx . key )
203+ . filter ( Boolean ) ;
204+ path . push ( String ( arrayIndex ) ) ;
205+ return { key, path } ;
206+ }
207+
208+ if ( innerLine === "}" ) break ;
209+ }
210+ }
211+ }
212+
213+ if ( line === "{" || line === "}" ) {
214+ continue ;
215+ }
216+
185217 // Extract key from line
186218 const keyMatch = line . match ( / ^ \s * [ " ' ] ? ( [ ^ " ' : , \s ] + ) [ " ' ] ? \s * : / ) ;
187219 if ( keyMatch ) {
188220 const key = keyMatch [ 1 ] ;
189- const path = contextStack . map ( ( ctx ) => ctx . key ) . filter ( Boolean ) ;
221+ const path = contextStack
222+ . map ( ( ctx ) => ctx . arrayIndex !== undefined ? String ( ctx . arrayIndex ) : ctx . key )
223+ . filter ( Boolean ) ;
190224 return { key, path } ;
191225 }
192226 }
@@ -195,12 +229,23 @@ function findAssociatedKey(
195229}
196230
197231function updateContext (
198- contextStack : Array < { key : string ; isArray : boolean } > ,
232+ contextStack : Array < { key : string ; isArray : boolean ; arrayIndex ?: number } > ,
199233 line : string ,
200234 parsedJson : any ,
235+ arrayObjectCount : Record < number , number > ,
201236) : void {
202- // This is a simplified context tracking - in a full implementation,
203- // you'd want more sophisticated AST-based tracking
237+ const trimmed = line . trim ( ) ;
238+
239+ // Track opening of arrays
240+ const arrayMatch = line . match ( / ^ \s * [ " ' ] ? ( [ ^ " ' : , \s ] + ) [ " ' ] ? \s * : \s * \[ / ) ;
241+ if ( arrayMatch ) {
242+ const depth = contextStack . length ;
243+ arrayObjectCount [ depth ] = 0 ; // Initialize counter for this array
244+ contextStack . push ( { key : arrayMatch [ 1 ] , isArray : true } ) ;
245+ return ;
246+ }
247+
248+ // Track opening of objects
204249 const openBraces = ( line . match ( / \{ / g) || [ ] ) . length ;
205250 const closeBraces = ( line . match ( / \} / g) || [ ] ) . length ;
206251
@@ -209,13 +254,37 @@ function updateContext(
209254 const keyMatch = line . match ( / ^ \s * [ " ' ] ? ( [ ^ " ' : , \s ] + ) [ " ' ] ? \s * : \s * \{ / ) ;
210255 if ( keyMatch ) {
211256 contextStack . push ( { key : keyMatch [ 1 ] , isArray : false } ) ;
257+ } else if ( trimmed === '{' && contextStack . length > 0 ) {
258+ // This is an object within an array
259+ const parent = contextStack [ contextStack . length - 1 ] ;
260+ if ( parent . isArray ) {
261+ const depth = contextStack . length - 1 ;
262+ const arrayIndex = arrayObjectCount [ depth ] || 0 ;
263+ contextStack . push ( { key : '' , isArray : false , arrayIndex } ) ;
264+ arrayObjectCount [ depth ] ++ ;
265+ }
212266 }
213- } else if ( closeBraces > openBraces ) {
214- // Pop context when closing braces
267+ }
268+
269+ // Track closing of objects and arrays
270+ const openBrackets = ( line . match ( / \[ / g) || [ ] ) . length ;
271+ const closeBrackets = ( line . match ( / \] / g) || [ ] ) . length ;
272+
273+ if ( closeBraces > openBraces ) {
215274 for ( let i = 0 ; i < closeBraces - openBraces ; i ++ ) {
216275 contextStack . pop ( ) ;
217276 }
218277 }
278+
279+ if ( closeBrackets > openBrackets ) {
280+ for ( let i = 0 ; i < closeBrackets - openBrackets ; i ++ ) {
281+ const popped = contextStack . pop ( ) ;
282+ if ( popped ?. isArray ) {
283+ const depth = contextStack . length ;
284+ delete arrayObjectCount [ depth ] ; // Clean up counter
285+ }
286+ }
287+ }
219288}
220289
221290function setCommentAtPath (
0 commit comments