config.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /* Copyright 2018 The Bazel Authors. All rights reserved.
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package resolve
  13. import (
  14. "flag"
  15. "log"
  16. "strings"
  17. "github.com/bazelbuild/bazel-gazelle/internal/config"
  18. "github.com/bazelbuild/bazel-gazelle/internal/label"
  19. "github.com/bazelbuild/bazel-gazelle/internal/rule"
  20. )
  21. // FindRuleWithOverride searches the current configuration for user-specified
  22. // dependency resolution overrides. Overrides specified later (in configuration
  23. // files in deeper directories, or closer to the end of the file) are
  24. // returned first. If no override is found, label.NoLabel is returned.
  25. func FindRuleWithOverride(c *config.Config, imp ImportSpec, lang string) (label.Label, bool) {
  26. rc := getResolveConfig(c)
  27. for i := len(rc.overrides) - 1; i >= 0; i-- {
  28. o := rc.overrides[i]
  29. if o.matches(imp, lang) {
  30. return o.dep, true
  31. }
  32. }
  33. return label.NoLabel, false
  34. }
  35. type overrideSpec struct {
  36. imp ImportSpec
  37. lang string
  38. dep label.Label
  39. }
  40. func (o overrideSpec) matches(imp ImportSpec, lang string) bool {
  41. return imp.Lang == o.imp.Lang &&
  42. imp.Imp == o.imp.Imp &&
  43. (o.lang == "" || o.lang == lang)
  44. }
  45. type resolveConfig struct {
  46. overrides []overrideSpec
  47. }
  48. const resolveName = "_resolve"
  49. func getResolveConfig(c *config.Config) *resolveConfig {
  50. return c.Exts[resolveName].(*resolveConfig)
  51. }
  52. type Configurer struct{}
  53. func (_ *Configurer) RegisterFlags(fs *flag.FlagSet, cmd string, c *config.Config) {
  54. c.Exts[resolveName] = &resolveConfig{}
  55. }
  56. func (_ *Configurer) CheckFlags(fs *flag.FlagSet, c *config.Config) error { return nil }
  57. func (_ *Configurer) KnownDirectives() []string {
  58. return []string{"resolve"}
  59. }
  60. func (_ *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
  61. rc := getResolveConfig(c)
  62. rcCopy := &resolveConfig{
  63. overrides: rc.overrides[:],
  64. }
  65. if f != nil {
  66. for _, d := range f.Directives {
  67. if d.Key == "resolve" {
  68. parts := strings.Fields(d.Value)
  69. o := overrideSpec{}
  70. var lbl string
  71. if len(parts) == 3 {
  72. o.imp.Lang = parts[0]
  73. o.imp.Imp = parts[1]
  74. lbl = parts[2]
  75. } else if len(parts) == 4 {
  76. o.imp.Lang = parts[0]
  77. o.lang = parts[1]
  78. o.imp.Imp = parts[2]
  79. lbl = parts[3]
  80. } else {
  81. log.Printf("could not parse directive: %s\n\texpected gazelle:resolve source-language [import-language] import-string label", d.Value)
  82. continue
  83. }
  84. var err error
  85. o.dep, err = label.Parse(lbl)
  86. if err != nil {
  87. log.Printf("gazelle:resolve %s: %v", d.Value, err)
  88. continue
  89. }
  90. o.dep = o.dep.Abs("", rel)
  91. rcCopy.overrides = append(rcCopy.overrides, o)
  92. }
  93. }
  94. }
  95. c.Exts[resolveName] = rcCopy
  96. }