@@ -467,7 +467,24 @@ export default class Analyzer {
467467 }
468468
469469 if ( ! parent && ( ! declaration || continueSearching ) ) {
470- for ( const u of this . getReachableUris ( { fromUri : uri } ) ) {
470+ // After processing, this should put uris higher in the sourcing tree
471+ // ahead so the declaration found is from the first definition.
472+ let uris : Set < string > | string [ ] = this . findAllSourcedUris ( { uri } )
473+
474+ for ( const u1 of uris ) {
475+ for ( const u2 of this . findAllSourcedUris ( { uri : u1 } ) ) {
476+ if ( uris . has ( u2 ) ) {
477+ uris . delete ( u2 )
478+ uris . add ( u2 )
479+ }
480+ }
481+ }
482+
483+ uris = Array . from ( uris )
484+ uris . reverse ( )
485+ uris . push ( uri )
486+
487+ for ( const u of uris ) {
471488 const root = this . uriToAnalyzedDocument [ u ] ?. tree . rootNode
472489
473490 if ( ! root ) {
@@ -501,67 +518,6 @@ export default class Analyzer {
501518 }
502519 }
503520
504- /**
505- * Like findOriginalDeclaration, but only searches within the file and doesn't
506- * take parent scopes into consideration.
507- *
508- * TODO: Improve handling of multiple variable assignments and declarations in
509- * one declaration command.
510- */
511- public findOriginalDeclarationWithinFile ( {
512- uri,
513- word,
514- kind,
515- } : {
516- uri : string
517- word : string
518- kind : LSP . SymbolKind
519- } ) : LSP . Location | null {
520- const rootNode = this . uriToAnalyzedDocument [ uri ] ?. tree . rootNode
521-
522- if ( ! rootNode ) {
523- return null
524- }
525-
526- let declaration : Parser . SyntaxNode | null | undefined
527- let continueSearching = false
528-
529- TreeSitterUtil . forEach ( rootNode , ( n ) => {
530- if ( ( declaration && ! continueSearching ) || n . type === 'subshell' ) {
531- return false
532- }
533-
534- let definedSymbol : Parser . SyntaxNode | null | undefined
535-
536- if (
537- kind === LSP . SymbolKind . Variable &&
538- ( [ 'declaration_command' , 'variable_assignment' , 'for_statement' ] . includes (
539- n . type ,
540- ) ||
541- ( n . type === 'command' && n . text . includes ( ':=' ) ) )
542- ) {
543- definedSymbol = n . descendantsOfType ( 'variable_name' ) . at ( 0 )
544- } else if ( kind === LSP . SymbolKind . Function && n . type === 'function_definition' ) {
545- definedSymbol = n . firstNamedChild
546- }
547-
548- if ( definedSymbol ?. text === word ) {
549- declaration = definedSymbol
550- continueSearching = n . type === 'command'
551- }
552-
553- if ( n . type === 'function_definition' ) {
554- return false
555- }
556-
557- return true
558- } )
559-
560- return declaration
561- ? LSP . Location . create ( uri , TreeSitterUtil . range ( declaration ) )
562- : null
563- }
564-
565521 /**
566522 * Find all the locations where the given word was defined or referenced.
567523 * This will include commands, functions, variables, etc.
@@ -630,14 +586,12 @@ export default class Analyzer {
630586 word,
631587 kind,
632588 start,
633- end,
634589 scope,
635590 } : {
636591 uri : string
637592 word : string
638593 kind : LSP . SymbolKind
639594 start ?: LSP . Position
640- end ?: LSP . Position
641595 scope ?: LSP . Range
642596 } ) : LSP . Range [ ] {
643597 const scopeNode = scope
@@ -663,22 +617,6 @@ export default class Analyzer {
663617 const startPosition = start
664618 ? { row : start . line , column : start . character }
665619 : baseNode . startPosition
666- // Special handling for cases like
667- // var="
668- // $var
669- // "
670- let endPosition
671- if ( end ) {
672- const endNode = baseNode . descendantForPosition ( {
673- row : end . line ,
674- column : end . character ,
675- } )
676- const parentNode =
677- endNode . type === 'variable_name'
678- ? TreeSitterUtil . findParentOfType ( endNode , 'variable_assignment' )
679- : null
680- parentNode && ( { endPosition } = parentNode )
681- }
682620
683621 const ignoredRanges : LSP . Range [ ] = [ ]
684622 const filterVariables = ( n : Parser . SyntaxNode ) => {
@@ -696,27 +634,19 @@ export default class Analyzer {
696634 const definedVariable = definition ?. descendantsOfType ( 'variable_name' ) ?. at ( 0 )
697635
698636 // Special handling for var="$var" cases
699- if ( definedVariable ?. text === word ) {
700- if ( n . equals ( definedVariable ) ) {
701- // `end?.line` is assumed to be the same as the variable's declaration
702- // line; handles cases where $var should be renamed but var shouldn't.
703- if ( definition ?. startPosition . row === end ?. line ) {
704- return false
705- }
706- } else {
707- // `start?.line` is assumed to be the same as the variable's original
708- // declaration line; handles cases where var should be renamed but
709- // $var shouldn't.
710- if ( definition ?. startPosition . row === start ?. line ) {
711- return false
712- }
713-
714- // Returning true here is a good enough heuristic for most cases. It
715- // breaks down when redeclaration happens in multiple nested scopes,
716- // handling those more complex situations can be done later on if use
717- // cases arise.
718- return true
637+ if ( definedVariable ?. text === word && ! n . equals ( definedVariable ) ) {
638+ // `start?.line` is assumed to be the same as the variable's original
639+ // declaration line; handles cases where var should be renamed but
640+ // $var shouldn't.
641+ if ( definition ?. startPosition . row === start ?. line ) {
642+ return false
719643 }
644+
645+ // Returning true here is a good enough heuristic for most cases. It
646+ // breaks down when redeclaration happens in multiple nested scopes,
647+ // handling those more complex situations can be done later on if use
648+ // cases arise.
649+ return true
720650 }
721651
722652 if ( ! parentScope || baseNode . equals ( parentScope ) ) {
@@ -778,7 +708,7 @@ export default class Analyzer {
778708 }
779709
780710 return baseNode
781- . descendantsOfType ( typeOfDescendants , startPosition , endPosition )
711+ . descendantsOfType ( typeOfDescendants , startPosition )
782712 . filter ( kind === LSP . SymbolKind . Variable ? filterVariables : filterFunctions )
783713 . map ( ( n ) => {
784714 if ( n . type === 'function_definition' && n . firstNamedChild ) {
0 commit comments