github.com/bazelbuild/bazel-gazelle@v0.36.1-0.20240520142334-61b277ba6fed/language/lang.go (about) 1 /* Copyright 2018 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 language provides an interface for language extensions in Gazelle. 17 // Support for a new language can be added by defining a package with a 18 // function named "New" that returns a value assignable to this interface. 19 // 20 // TODO(jayconrod): document how to incorporate languages into a gazelle 21 // binary that can be run by Bazel. 22 package language 23 24 import ( 25 "github.com/bazelbuild/bazel-gazelle/config" 26 "github.com/bazelbuild/bazel-gazelle/resolve" 27 "github.com/bazelbuild/bazel-gazelle/rule" 28 ) 29 30 // Language describes an extension for Gazelle that provides support for 31 // a set of Bazel rules. 32 // 33 // Languages are used primarily by the fix and update commands. The order 34 // in which languages are used matters, since languages may depend on 35 // one another. For example, go depends on proto, since go_proto_libraries 36 // are generated from metadata stored in proto_libraries. 37 // 38 // A single instance of Language is created for each fix / update run. Some 39 // state may be stored in this instance, but stateless behavior is encouraged, 40 // especially since some operations may be concurrent in the future. 41 // 42 // # Tasks languages are used for 43 // 44 // * Configuration (embedded interface config.Configurer). Languages may 45 // define command line flags and alter the configuration in a directory 46 // based on directives in build files. 47 // 48 // * Fixing deprecated usage of rules in build files. 49 // 50 // * Generating rules from source files in a directory. 51 // 52 // * Resolving library imports (embedded interface resolve.Resolver). For 53 // example, import strings like "github.com/foo/bar" in Go can be resolved 54 // into Bazel labels like "@com_github_foo_bar//:go_default_library". 55 // 56 // # Tasks languages support 57 // 58 // * Generating load statements: languages list files and symbols that may 59 // be loaded. 60 // 61 // * Merging generated rules into existing rules: languages provide metadata 62 // that helps with rule matching, merging, and deletion. 63 type Language interface { 64 // TODO(jayconrod): is embedding Configurer strictly necessary? 65 config.Configurer 66 resolve.Resolver 67 68 // Kinds returns a map of maps rule names (kinds) and information on how to 69 // match and merge attributes that may be found in rules of those kinds. All 70 // kinds of rules generated for this language may be found here. 71 Kinds() map[string]rule.KindInfo 72 73 // GenerateRules extracts build metadata from source files in a directory. 74 // GenerateRules is called in each directory where an update is requested 75 // in depth-first post-order. 76 // 77 // args contains the arguments for GenerateRules. This is passed as a 78 // struct to avoid breaking implementations in the future when new 79 // fields are added. 80 // 81 // A GenerateResult struct is returned. Optional fields may be added to this 82 // type in the future. 83 // 84 // Any non-fatal errors this function encounters should be logged using 85 // log.Print. 86 GenerateRules(args GenerateArgs) GenerateResult 87 88 // Loads returns .bzl files and symbols they define. Every rule generated by 89 // GenerateRules, now or in the past, should be loadable from one of these 90 // files. 91 // 92 // Deprecated: Implement ModuleAwareLanguage's ApparentLoads. 93 Loads() []rule.LoadInfo 94 95 // Fix repairs deprecated usage of language-specific rules in f. This is 96 // called before the file is indexed. Unless c.ShouldFix is true, fixes 97 // that delete or rename rules should not be performed. 98 Fix(c *config.Config, f *rule.File) 99 } 100 101 // FinishableLanguage allows a Language to be notified when Generate is finished 102 // being called. 103 type FinishableLanguage interface { 104 // DoneGeneratingRules is called when all calls to GenerateRules have been 105 // completed. 106 // This allows for hooks to be called, for instance to release resources 107 // such as shutting down a background server. 108 // No further calls will be made to GenerateRules on this Language instance 109 // after this method has been called. 110 DoneGeneratingRules() 111 } 112 113 type ModuleAwareLanguage interface { 114 // ApparentLoads returns .bzl files and symbols they define. Every rule 115 // generated by GenerateRules, now or in the past, should be loadable from 116 // one of these files. 117 // 118 // The moduleToApparentName argument is a function that resolves a given 119 // Bazel module name to the apparent repository name configured for this 120 // module in the MODULE.bazel file, or the empty string if there is no such 121 // module or the MODULE.bazel file doesn't exist. Languages should use the 122 // non-empty value returned by this function to form the repository part of 123 // the load statements they return and fall back to using the legacy 124 // WORKSPACE name otherwise. 125 // 126 // See https://bazel.build/external/overview#concepts for more information 127 // on repository names. 128 // 129 // Example: For a project with these lines in its MODULE.bazel file: 130 // 131 // bazel_dep(name = "rules_go", version = "0.38.1", repo_name = "my_rules_go") 132 // bazel_dep(name = "gazelle", version = "0.27.0") 133 // 134 // moduleToApparentName["rules_go"] == "my_rules_go" 135 // moduleToApparentName["gazelle"] == "gazelle" 136 // moduleToApparentName["foobar"] == "" 137 ApparentLoads(moduleToApparentName func(string) string) []rule.LoadInfo 138 } 139 140 // GenerateArgs contains arguments for language.GenerateRules. Arguments are 141 // passed in a struct value so that new fields may be added in the future 142 // without breaking existing implementations. 143 type GenerateArgs struct { 144 // Config is the configuration for the directory where rules are being 145 // generated. 146 Config *config.Config 147 148 // Dir is the canonical absolute path to the directory. 149 Dir string 150 151 // Rel is the slash-separated path to the directory, relative to the 152 // repository root ("" for the root directory itself). This may be used 153 // as the package name in labels. 154 Rel string 155 156 // File is the build file for the directory. File is nil if there is 157 // no existing build file. 158 File *rule.File 159 160 // Subdirs is a list of subdirectories in the directory, including 161 // symbolic links to directories that Gazelle will follow. 162 // RegularFiles is a list of regular files including other symbolic 163 // links. 164 // GeneratedFiles is a list of generated files in the directory 165 // (usually these are mentioned as "out" or "outs" attributes in rules). 166 Subdirs, RegularFiles, GenFiles []string 167 168 // OtherEmpty is a list of empty rules generated by other languages. 169 // OtherGen is a list of generated rules generated by other languages. 170 OtherEmpty, OtherGen []*rule.Rule 171 } 172 173 // GenerateResult contains return values for language.GenerateRules. 174 // Results are returned through a struct value so that new (optional) 175 // fields may be added without breaking existing implementations. 176 type GenerateResult struct { 177 // Gen is a list of rules generated from files found in the directory 178 // GenerateRules was asked to process. These will be merged with existing 179 // rules or added to the build file. 180 Gen []*rule.Rule 181 182 // Empty is a list of rules that cannot be built with the files found in the 183 // directory GenerateRules was asked to process. These will be merged with 184 // existing rules. If the merged rules are empty, they will be deleted. 185 Empty []*rule.Rule 186 187 // Imports contains information about the imported libraries for each 188 // rule in Gen. Gen and Imports must have the same length, since they 189 // correspond. These values are passed to Resolve after merge. The type 190 // is opaque since different languages may use different representations. 191 Imports []interface{} 192 }