github.com/opentofu/opentofu@v1.7.1/internal/addrs/check_rule_diagnostic.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package addrs
     7  
     8  import "github.com/opentofu/opentofu/internal/tfdiags"
     9  
    10  // DiagnosticExtraCheckRule provides an interface for diagnostic ExtraInfo to
    11  // retrieve an embedded CheckRule from within a tfdiags.Diagnostic.
    12  type DiagnosticExtraCheckRule interface {
    13  	// DiagnosticOriginatesFromCheckRule returns the CheckRule that the
    14  	// surrounding diagnostic originated from.
    15  	DiagnosticOriginatesFromCheckRule() CheckRule
    16  }
    17  
    18  // DiagnosticOriginatesFromCheckRule checks if the provided diagnostic contains
    19  // a CheckRule as ExtraInfo and returns that CheckRule and true if it does. This
    20  // function returns an empty CheckRule and false if the diagnostic does not
    21  // contain a CheckRule.
    22  func DiagnosticOriginatesFromCheckRule(diag tfdiags.Diagnostic) (CheckRule, bool) {
    23  	maybe := tfdiags.ExtraInfo[DiagnosticExtraCheckRule](diag)
    24  	if maybe == nil {
    25  		return CheckRule{}, false
    26  	}
    27  	return maybe.DiagnosticOriginatesFromCheckRule(), true
    28  }
    29  
    30  // CheckRuleDiagnosticExtra is an object that can be attached to diagnostics
    31  // that originate from check rules.
    32  //
    33  // It implements the DiagnosticExtraCheckRule interface for retrieving the
    34  // concrete CheckRule that spawned the diagnostic.
    35  //
    36  // It also implements the tfdiags.DiagnosticExtraDoNotConsolidate interface, to
    37  // stop diagnostics created by check blocks being consolidated.
    38  //
    39  // It also implements the tfdiags.DiagnosticExtraUnwrapper interface, as nested
    40  // data blocks will attach this struct but do want to lose any extra info
    41  // embedded in the original diagnostic.
    42  type CheckRuleDiagnosticExtra struct {
    43  	CheckRule CheckRule
    44  
    45  	wrapped interface{}
    46  }
    47  
    48  var (
    49  	_ DiagnosticExtraCheckRule                = (*CheckRuleDiagnosticExtra)(nil)
    50  	_ tfdiags.DiagnosticExtraDoNotConsolidate = (*CheckRuleDiagnosticExtra)(nil)
    51  	_ tfdiags.DiagnosticExtraUnwrapper        = (*CheckRuleDiagnosticExtra)(nil)
    52  	_ tfdiags.DiagnosticExtraWrapper          = (*CheckRuleDiagnosticExtra)(nil)
    53  )
    54  
    55  func (c *CheckRuleDiagnosticExtra) UnwrapDiagnosticExtra() interface{} {
    56  	return c.wrapped
    57  }
    58  
    59  func (c *CheckRuleDiagnosticExtra) WrapDiagnosticExtra(inner interface{}) {
    60  	if c.wrapped != nil {
    61  		// This is a logical inconsistency, the caller should know whether they
    62  		// have already wrapped an extra or not.
    63  		panic("Attempted to wrap a diagnostic extra into a CheckRuleDiagnosticExtra that is already wrapping a different extra. This is a bug in OpenTofu, please report it.")
    64  	}
    65  	c.wrapped = inner
    66  }
    67  
    68  func (c *CheckRuleDiagnosticExtra) DoNotConsolidateDiagnostic() bool {
    69  	// Do not consolidate warnings from check blocks.
    70  	return c.CheckRule.Container.CheckableKind() == CheckableCheck
    71  }
    72  
    73  func (c *CheckRuleDiagnosticExtra) DiagnosticOriginatesFromCheckRule() CheckRule {
    74  	return c.CheckRule
    75  }