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

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package hcl
     5  
     6  // -----------------------------------------------------------------------------
     7  // The methods in this file all have the general pattern of making a best-effort
     8  // to find one or more constructs that contain a given source position.
     9  //
    10  // These all operate by delegating to an optional method of the same name and
    11  // signature on the file's root body, allowing each syntax to potentially
    12  // provide its own implementations of these. For syntaxes that don't implement
    13  // them, the result is always nil.
    14  // -----------------------------------------------------------------------------
    15  
    16  // BlocksAtPos attempts to find all of the blocks that contain the given
    17  // position, ordered so that the outermost block is first and the innermost
    18  // block is last. This is a best-effort method that may not be able to produce
    19  // a complete result for all positions or for all HCL syntaxes.
    20  //
    21  // If the returned slice is non-empty, the first element is guaranteed to
    22  // represent the same block as would be the result of OutermostBlockAtPos and
    23  // the last element the result of InnermostBlockAtPos. However, the
    24  // implementation may return two different objects describing the same block,
    25  // so comparison by pointer identity is not possible.
    26  //
    27  // The result is nil if no blocks at all contain the given position.
    28  func (f *File) BlocksAtPos(pos Pos) []*Block {
    29  	// The root body of the file must implement this interface in order
    30  	// to support BlocksAtPos.
    31  	type Interface interface {
    32  		BlocksAtPos(pos Pos) []*Block
    33  	}
    34  
    35  	impl, ok := f.Body.(Interface)
    36  	if !ok {
    37  		return nil
    38  	}
    39  	return impl.BlocksAtPos(pos)
    40  }
    41  
    42  // OutermostBlockAtPos attempts to find a top-level block in the receiving file
    43  // that contains the given position. This is a best-effort method that may not
    44  // be able to produce a result for all positions or for all HCL syntaxes.
    45  //
    46  // The result is nil if no single block could be selected for any reason.
    47  func (f *File) OutermostBlockAtPos(pos Pos) *Block {
    48  	// The root body of the file must implement this interface in order
    49  	// to support OutermostBlockAtPos.
    50  	type Interface interface {
    51  		OutermostBlockAtPos(pos Pos) *Block
    52  	}
    53  
    54  	impl, ok := f.Body.(Interface)
    55  	if !ok {
    56  		return nil
    57  	}
    58  	return impl.OutermostBlockAtPos(pos)
    59  }
    60  
    61  // InnermostBlockAtPos attempts to find the most deeply-nested block in the
    62  // receiving file that contains the given position. This is a best-effort
    63  // method that may not be able to produce a result for all positions or for
    64  // all HCL syntaxes.
    65  //
    66  // The result is nil if no single block could be selected for any reason.
    67  func (f *File) InnermostBlockAtPos(pos Pos) *Block {
    68  	// The root body of the file must implement this interface in order
    69  	// to support InnermostBlockAtPos.
    70  	type Interface interface {
    71  		InnermostBlockAtPos(pos Pos) *Block
    72  	}
    73  
    74  	impl, ok := f.Body.(Interface)
    75  	if !ok {
    76  		return nil
    77  	}
    78  	return impl.InnermostBlockAtPos(pos)
    79  }
    80  
    81  // OutermostExprAtPos attempts to find an expression in the receiving file
    82  // that contains the given position. This is a best-effort method that may not
    83  // be able to produce a result for all positions or for all HCL syntaxes.
    84  //
    85  // Since expressions are often nested inside one another, this method returns
    86  // the outermost "root" expression that is not contained by any other.
    87  //
    88  // The result is nil if no single expression could be selected for any reason.
    89  func (f *File) OutermostExprAtPos(pos Pos) Expression {
    90  	// The root body of the file must implement this interface in order
    91  	// to support OutermostExprAtPos.
    92  	type Interface interface {
    93  		OutermostExprAtPos(pos Pos) Expression
    94  	}
    95  
    96  	impl, ok := f.Body.(Interface)
    97  	if !ok {
    98  		return nil
    99  	}
   100  	return impl.OutermostExprAtPos(pos)
   101  }
   102  
   103  // AttributeAtPos attempts to find an attribute definition in the receiving
   104  // file that contains the given position. This is a best-effort method that may
   105  // not be able to produce a result for all positions or for all HCL syntaxes.
   106  //
   107  // The result is nil if no single attribute could be selected for any reason.
   108  func (f *File) AttributeAtPos(pos Pos) *Attribute {
   109  	// The root body of the file must implement this interface in order
   110  	// to support OutermostExprAtPos.
   111  	type Interface interface {
   112  		AttributeAtPos(pos Pos) *Attribute
   113  	}
   114  
   115  	impl, ok := f.Body.(Interface)
   116  	if !ok {
   117  		return nil
   118  	}
   119  	return impl.AttributeAtPos(pos)
   120  }