github.com/bazelbuild/bazel-gazelle@v0.36.1-0.20240520142334-61b277ba6fed/cmd/gazelle/metaresolver.go (about) 1 /* Copyright 2019 The Bazel Authors. All rights reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 */ 15 16 package main 17 18 import ( 19 "github.com/bazelbuild/bazel-gazelle/config" 20 "github.com/bazelbuild/bazel-gazelle/label" 21 "github.com/bazelbuild/bazel-gazelle/repo" 22 "github.com/bazelbuild/bazel-gazelle/resolve" 23 "github.com/bazelbuild/bazel-gazelle/rule" 24 ) 25 26 // metaResolver provides a rule.Resolver for any rule.Rule. 27 type metaResolver struct { 28 // builtins provides a map of the language kinds to their resolver. 29 builtins map[string]resolve.Resolver 30 31 // mappedKinds provides a list of replacements used by File.Pkg. 32 mappedKinds map[string][]config.MappedKind 33 } 34 35 func newMetaResolver() *metaResolver { 36 return &metaResolver{ 37 builtins: make(map[string]resolve.Resolver), 38 mappedKinds: make(map[string][]config.MappedKind), 39 } 40 } 41 42 // AddBuiltin registers a builtin kind with its info. 43 func (mr *metaResolver) AddBuiltin(kindName string, resolver resolve.Resolver) { 44 mr.builtins[kindName] = resolver 45 } 46 47 // MappedKind records the fact that the given mapping was applied while 48 // processing the given package. 49 func (mr *metaResolver) MappedKind(pkgRel string, kind config.MappedKind) { 50 mr.mappedKinds[pkgRel] = append(mr.mappedKinds[pkgRel], kind) 51 } 52 53 // Resolver returns a resolver for the given rule and package, and a bool 54 // indicating whether one was found. Empty string may be passed for pkgRel, 55 // which results in consulting the builtin kinds only. 56 func (mr *metaResolver) Resolver(r *rule.Rule, pkgRel string) resolve.Resolver { 57 for _, mappedKind := range mr.mappedKinds[pkgRel] { 58 if mappedKind.KindName == r.Kind() { 59 fromKindResolver := mr.builtins[mappedKind.FromKind] 60 if fromKindResolver == nil { 61 return nil 62 } 63 return inverseMapKindResolver{ 64 fromKind: mappedKind.FromKind, 65 delegate: fromKindResolver, 66 } 67 } 68 } 69 return mr.builtins[r.Kind()] 70 } 71 72 // inverseMapKindResolver applies an inverse of the map_kind 73 // operations to provided rules. This enables language 74 // modules to remain ignorant of mapped kinds. 75 type inverseMapKindResolver struct { 76 fromKind string 77 delegate resolve.Resolver 78 } 79 80 var _ resolve.Resolver = inverseMapKindResolver{} 81 82 func (imkr inverseMapKindResolver) Name() string { 83 return imkr.delegate.Name() 84 } 85 86 func (imkr inverseMapKindResolver) Imports(c *config.Config, r *rule.Rule, f *rule.File) []resolve.ImportSpec { 87 r = imkr.inverseMapKind(r) 88 return imkr.delegate.Imports(c, r, f) 89 } 90 91 func (imkr inverseMapKindResolver) Embeds(r *rule.Rule, from label.Label) []label.Label { 92 r = imkr.inverseMapKind(r) 93 return imkr.delegate.Embeds(r, from) 94 } 95 96 func (imkr inverseMapKindResolver) Resolve(c *config.Config, ix *resolve.RuleIndex, rc *repo.RemoteCache, r *rule.Rule, imports interface{}, from label.Label) { 97 r = imkr.inverseMapKind(r) 98 imkr.delegate.Resolve(c, ix, rc, r, imports, from) 99 } 100 101 func (imkr inverseMapKindResolver) inverseMapKind(r *rule.Rule) *rule.Rule { 102 rCopy := *r 103 rCopy.SetKind(imkr.fromKind) 104 return &rCopy 105 }