@@ -192,17 +192,33 @@ function classifyLines(
192192) : Map < number , LineOwner > {
193193 const owners = new Map < number , LineOwner > ( ) ;
194194
195- for ( const sym of structure . symbols ) {
196- const symStart = sym . range . startLine ;
197- const symEnd = sym . range . endLine ;
198- if ( symEnd < startLine || symStart > endLine ) continue ;
199- const from = Math . max ( symStart , startLine ) ;
200- const to = Math . min ( symEnd , endLine ) ;
201- const owner : LineOwner = { type : 'symbol' , symbol : sym } ;
202- for ( let line = from ; line <= to ; line ++ ) {
203- owners . set ( line , owner ) ;
195+ // Walk the symbol tree recursively to find the most specific (deepest) child
196+ // that owns each line. This ensures that for Markdown heading-dominance
197+ // (where H1 spans the whole file), we classify lines by their immediate
198+ // child sections rather than the all-encompassing parent.
199+ const walkSymbols = ( symbols : FileSymbol [ ] ) : void => {
200+ for ( const sym of symbols ) {
201+ const symStart = sym . range . startLine ;
202+ const symEnd = sym . range . endLine ;
203+ if ( symEnd < startLine || symStart > endLine ) continue ;
204+
205+ if ( sym . children . length > 0 ) {
206+ // Recurse into children first — deeper symbols override parent
207+ walkSymbols ( sym . children ) ;
208+ }
209+
210+ // Only claim lines not already claimed by a deeper child
211+ const from = Math . max ( symStart , startLine ) ;
212+ const to = Math . min ( symEnd , endLine ) ;
213+ const owner : LineOwner = { type : 'symbol' , symbol : sym } ;
214+ for ( let line = from ; line <= to ; line ++ ) {
215+ if ( ! owners . has ( line ) ) {
216+ owners . set ( line , owner ) ;
217+ }
218+ }
204219 }
205- }
220+ } ;
221+ walkSymbols ( structure . symbols ) ;
206222
207223 for ( const block of blocks ) {
208224 if ( block . endLine < startLine || block . startLine > endLine ) continue ;
0 commit comments