github.com/hashicorp/hcl/v2@v2.20.0/json/navigation.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package json
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  )
    10  
    11  type navigation struct {
    12  	root node
    13  }
    14  
    15  // Implementation of hcled.ContextString
    16  func (n navigation) ContextString(offset int) string {
    17  	steps := navigationStepsRev(n.root, offset)
    18  	if steps == nil {
    19  		return ""
    20  	}
    21  
    22  	// We built our slice backwards, so we'll reverse it in-place now.
    23  	half := len(steps) / 2 // integer division
    24  	for i := 0; i < half; i++ {
    25  		steps[i], steps[len(steps)-1-i] = steps[len(steps)-1-i], steps[i]
    26  	}
    27  
    28  	ret := strings.Join(steps, "")
    29  	if len(ret) > 0 && ret[0] == '.' {
    30  		ret = ret[1:]
    31  	}
    32  	return ret
    33  }
    34  
    35  func navigationStepsRev(v node, offset int) []string {
    36  	switch tv := v.(type) {
    37  	case *objectVal:
    38  		// Do any of our properties have an object that contains the target
    39  		// offset?
    40  		for _, attr := range tv.Attrs {
    41  			k := attr.Name
    42  			av := attr.Value
    43  
    44  			switch av.(type) {
    45  			case *objectVal, *arrayVal:
    46  				// okay
    47  			default:
    48  				continue
    49  			}
    50  
    51  			if av.Range().ContainsOffset(offset) {
    52  				return append(navigationStepsRev(av, offset), "."+k)
    53  			}
    54  		}
    55  	case *arrayVal:
    56  		// Do any of our elements contain the target offset?
    57  		for i, elem := range tv.Values {
    58  
    59  			switch elem.(type) {
    60  			case *objectVal, *arrayVal:
    61  				// okay
    62  			default:
    63  				continue
    64  			}
    65  
    66  			if elem.Range().ContainsOffset(offset) {
    67  				return append(navigationStepsRev(elem, offset), fmt.Sprintf("[%d]", i))
    68  			}
    69  		}
    70  	}
    71  
    72  	return nil
    73  }