github.com/opentofu/opentofu@v1.7.1/internal/lang/globalref/analyzer.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 globalref 7 8 import ( 9 "fmt" 10 11 "github.com/opentofu/opentofu/internal/addrs" 12 "github.com/opentofu/opentofu/internal/configs" 13 "github.com/opentofu/opentofu/internal/providers" 14 ) 15 16 // Analyzer is the main component of this package, serving as a container for 17 // various state that the analysis algorithms depend on either for their core 18 // functionality or for producing results more quickly. 19 // 20 // Global reference analysis is currently intended only for "best effort" 21 // use-cases related to giving hints to the user or tailoring UI output. 22 // Avoid using it for anything that would cause changes to the analyzer being 23 // considered a breaking change under the v1 compatibility promises, because 24 // we expect to continue to refine and evolve these rules over time in ways 25 // that may cause us to detect either more or fewer references than today. 26 // Typically we will conservatively return more references than would be 27 // necessary dynamically, but that isn't guaranteed for all situations. 28 // 29 // In particular, we currently typically don't distinguish between multiple 30 // instances of the same module, and so we overgeneralize references from 31 // one instance of a module as references from the same location in all 32 // instances of that module. We may make this more precise in future, which 33 // would then remove various detected references from the analysis results. 34 // 35 // Each Analyzer works with a particular configs.Config object which it assumes 36 // represents the root module of a configuration. Config objects are typically 37 // immutable by convention anyway, but it's particularly important not to 38 // modify a configuration while it's attached to a live Analyzer, because 39 // the Analyzer contains caches derived from data in the configuration tree. 40 type Analyzer struct { 41 cfg *configs.Config 42 providerSchemas map[addrs.Provider]providers.ProviderSchema 43 } 44 45 // NewAnalyzer constructs a new analyzer bound to the given configuration and 46 // provider schemas. 47 // 48 // The given object must represent a root module, or this function will panic. 49 // 50 // The given provider schemas must cover at least all of the providers used 51 // in the given configuration. If not then analysis results will be silently 52 // incomplete for any decision that requires checking schema. 53 func NewAnalyzer(cfg *configs.Config, providerSchemas map[addrs.Provider]providers.ProviderSchema) *Analyzer { 54 if !cfg.Path.IsRoot() { 55 panic(fmt.Sprintf("constructing an Analyzer with non-root module %s", cfg.Path)) 56 } 57 58 ret := &Analyzer{ 59 cfg: cfg, 60 providerSchemas: providerSchemas, 61 } 62 return ret 63 } 64 65 // ModuleConfig retrieves a module configuration from the configuration the 66 // analyzer belongs to, or nil if there is no module with the given address. 67 func (a *Analyzer) ModuleConfig(addr addrs.ModuleInstance) *configs.Module { 68 modCfg := a.cfg.DescendentForInstance(addr) 69 if modCfg == nil { 70 return nil 71 } 72 return modCfg.Module 73 }