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  }