language package
diff --git a/internal/go_repository_tools_srcs.bzl b/internal/go_repository_tools_srcs.bzl index da90ef0..9dac61f 100644 --- a/internal/go_repository_tools_srcs.bzl +++ b/internal/go_repository_tools_srcs.bzl
@@ -156,6 +156,8 @@ Label("//v2/internal/wspace:finder.go"), Label("//v2/label:BUILD.bazel"), Label("//v2/label:label.go"), + Label("//v2/language:BUILD.bazel"), + Label("//v2/language:lang.go"), Label("//v2/merger:BUILD.bazel"), Label("//v2/merger:fix.go"), Label("//v2/merger:merger.go"),
diff --git a/language/BUILD.bazel b/language/BUILD.bazel index 77e2950..d680f66 100644 --- a/language/BUILD.bazel +++ b/language/BUILD.bazel
@@ -12,10 +12,10 @@ visibility = ["//visibility:public"], deps = [ "//config", - "//label", "//repo", "//resolve", - "//rule", + "//v2/label", + "//v2/rule", ], )
diff --git a/language/base.go b/language/base.go index bc2d8db..5107975 100644 --- a/language/base.go +++ b/language/base.go
@@ -18,11 +18,11 @@ import ( "flag" + "github.com/bazel-contrib/bazel-gazelle/v2/label" + "github.com/bazel-contrib/bazel-gazelle/v2/rule" "github.com/bazelbuild/bazel-gazelle/config" - "github.com/bazelbuild/bazel-gazelle/label" "github.com/bazelbuild/bazel-gazelle/repo" "github.com/bazelbuild/bazel-gazelle/resolve" - "github.com/bazelbuild/bazel-gazelle/rule" ) // BaseLang implements the minimum of language.Language interface.
diff --git a/language/lang.go b/language/lang.go index da8d81e..7673e31 100644 --- a/language/lang.go +++ b/language/lang.go
@@ -22,9 +22,9 @@ package language import ( + "github.com/bazel-contrib/bazel-gazelle/v2/rule" "github.com/bazelbuild/bazel-gazelle/config" "github.com/bazelbuild/bazel-gazelle/resolve" - "github.com/bazelbuild/bazel-gazelle/rule" ) // Language describes an extension for Gazelle that provides support for @@ -60,6 +60,9 @@ // // * Merging generated rules into existing rules: languages provide metadata // that helps with rule matching, merging, and deletion. +// +// Deprecated: use github.com/bazel-contrib/bazel-gazelle/v2/language.Language +// or other smaller v2 interfaces instead. type Language interface { // TODO(jayconrod): is embedding Configurer strictly necessary? config.Configurer
diff --git a/language/update.go b/language/update.go index cebf73a..b42d955 100644 --- a/language/update.go +++ b/language/update.go
@@ -16,9 +16,9 @@ package language import ( + "github.com/bazel-contrib/bazel-gazelle/v2/rule" "github.com/bazelbuild/bazel-gazelle/config" "github.com/bazelbuild/bazel-gazelle/repo" - "github.com/bazelbuild/bazel-gazelle/rule" ) // RepoUpdater may be implemented by languages that support updating
diff --git a/v2/BUILD.bazel b/v2/BUILD.bazel index 392c64f..1db2421 100644 --- a/v2/BUILD.bazel +++ b/v2/BUILD.bazel
@@ -12,6 +12,7 @@ "//v2/flag:all_files", "//v2/internal:all_files", "//v2/label:all_files", + "//v2/language:all_files", "//v2/merger:all_files", "//v2/pathtools:all_files", "//v2/resolve:all_files",
diff --git a/v2/language/BUILD.bazel b/v2/language/BUILD.bazel new file mode 100644 index 0000000..49c6c6d --- /dev/null +++ b/v2/language/BUILD.bazel
@@ -0,0 +1,22 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "language", + srcs = ["lang.go"], + importpath = "github.com/bazel-contrib/bazel-gazelle/v2/language", + visibility = ["//visibility:public"], + deps = [ + "//v2/config", + "//v2/rule", + ], +) + +filegroup( + name = "all_files", + testonly = True, + srcs = [ + "BUILD.bazel", + "lang.go", + ], + visibility = ["//visibility:public"], +)
diff --git a/v2/language/lang.go b/v2/language/lang.go new file mode 100644 index 0000000..0304b3b --- /dev/null +++ b/v2/language/lang.go
@@ -0,0 +1,163 @@ +/* Copyright 2018 The Bazel Authors. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package language provides interfaces for language extensions in Gazelle. +// +// To implement a new extension, define a type that implements [Language] +// and other interfaces listed here. You will likely also want to implement +// [github.com/bazel-contrib/bazel-gazelle/v2/config.Configurer], +// [github.com/bazel-contrib/bazel-gazelle/v2/resolve.Indexer], and +// [github.com/bazel-contrib/bazel-gazelle/v2/resolve.Resolver]. Then define +// a function `NewV2()` that returns a value of your type. `gazelle_binary` +// generates code that calls this function when Gazelle starts. +// +// These interfaces are designd for extensibility. Most interfaces are optional, +// and most have only one method. Most methods accept arguments and return +// results as struct values, so more fields may be added in the future without +// breaking compatibility. +package language + +import ( + "context" + + "github.com/bazel-contrib/bazel-gazelle/v2/config" + "github.com/bazel-contrib/bazel-gazelle/v2/rule" +) + +// Language is a marker interface for extensions. It is the only mandatory +// interface that extensions must implement. +type Language interface { + // Name returns the name of the extension, like "go" or "cc". Name must always + // return the same value. + Name() string +} + +// Generator has methods for generating new rules. +// +// Most extensions that implement Generator should also implement +// [github.com/bazel-contrib/bazel-gazelle/v2/resolve.Indexer] and +// [github.com/bazel-contrib/bazel-gazelle/v2/resolve.Resolver] to support +// dependency resolution. But this is not necessary if generated rules' +// dependencies can be completely determined without indexing other rules +// in the repo. +type Generator interface { + // Kinds returns a map from rule names to information on how to match and + // merge attributes that may be found in rules of those kinds. All kinds of + // rules generated for this language may be found here. + Kinds() map[string]rule.KindInfo + + // Generate reads source files in a directory and produces a list of rules + // that should appear in that directory's build file. + Generate(context.Context, GenerateArgs) (GenerateResult, error) +} + +type GenerateArgs struct { + // Config is the configuration for the current directory. + Config *config.Config + + // Dir is the canonical absolute path to the directory. + Dir string + + // Rel is the slash-separated path to the directory, relative to the + // repository root ("" for the root directory itself). This may be used + // as the package name in labels. + Rel string + + // File is the build file for the directory. File is nil if there is + // no existing build file. + File *rule.File + + // Subdirs is a list of subdirectories in the directory, including + // symbolic links to directories that Gazelle will follow. + // RegularFiles is a list of regular files including other symbolic + // links. + // GenFiles is a list of generated files in the directory + // (usually these are mentioned as "out" or "outs" attributes in rules). + // These slices must not be modified. + Subdirs, RegularFiles, GenFiles []string + + // OtherEmpty is a list of empty rules generated by other languages. + // OtherGen is a list of generated rules generated by other languages. + OtherEmpty, OtherGen []*rule.Rule +} + +type GenerateResult struct { + // Gen is a list of rules generated from files found in the directory + // GenerateRules was asked to process. These will be merged with existing + // rules or added to the build file. + Gen []*rule.Rule + + // Empty is a list of rules that cannot be built with the files found in the + // directory GenerateRules was asked to process. These will be merged with + // existing rules. If the merged rules are empty, they will be deleted. + Empty []*rule.Rule + + // Imports contains information about the imported libraries for each + // rule in Gen. Gen and Imports must have the same length, since they + // correspond. These values are passed to Resolve after merge. The type + // is opaque since different languages may use different representations. + // + // TODO(v2): make this optional or eliminate it + Imports []any + + // RelsToIndex is a list of additional directories to index for dependency + // resolution, expressed as slash-separated paths relative to the repository + // root, or "" for the root directory itself. If indexing is enabled, + // libraries in these directories are indexed before dependencies are + // resolved. Subdirectories are not recursively indexed. This list may + // contain non-existent directories. + RelsToIndex []string +} + +// Fixer supports repairing deprecated usage of rules in a BUILD file. +// Fix is called in a directory Gazelle will update after the BUILD file is +// parsed, before new rules are generated and before rules are indexed. +// Fix should only perform destructive changes (like deleting or renaming rules) +// if `args.Config.ShouldFix` is true. +type Fixer interface { + Fix(context.Context, FixArgs) error +} + +type FixArgs struct { + // Config is the configuration for the current directory. + Config *config.Config + + // Rel is the slash-separated path to the directory, relative to the + // repository root ("" for the root directory itself). This may be used + // as the package name in labels. + Rel string + + // File is the build file for the directory. File is nil if there is + // no existing build file. + File *rule.File +} + +type OnStarter interface { + // Called when Gazelle starts, before walking the directory tree and before + // Configure is called on any extension. + OnStart(context.Context) error +} + +type OnResolver interface { + // Called after Gazelle generates rules in all directories it will visit + // but before Gazelle performs dependency resolution. + OnResolve(context.Context) error +} + +type OnFinisher interface { + // Called after Gazelle has resolved dependencies on all rules and written + // updated build files. + OnFinish(context.Context) error +}