gazelle

package
v0.25.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 1, 2024 License: Apache-2.0 Imports: 26 Imported by: 0

README

Gazelle Java extension

This provides an experimental Gazelle extension to generate build files for Java projects.

Usage

In the WORKSPACE file set up the rules_jvm correctly:

load("@contrib_rules_jvm//:repositories.bzl", "contrib_rules_jvm_deps", "contrib_rules_jvm_gazelle_deps")

contrib_rules_jvm_deps()

contrib_rules_jvm_gazelle_deps()

load("@contrib_rules_jvm//:setup.bzl", "contrib_rules_jvm_setup")

contrib_rules_jvm_setup()

load("@contrib_rules_jvm//:gazelle_setup.bzl", "contrib_rules_jvm_gazelle_setup")

contrib_rules_jvm_gazelle_setup()

In the top level BUILD.bazel file, setup Gazelle to use gazelle-languages binary:

load("@bazel_gazelle//:def.bzl", "DEFAULT_LANGUAGES", "gazelle", "gazelle_binary")

# gazelle:prefix github.com/your/project
gazelle(
    name = "gazelle",
    gazelle = ":gazelle_bin",
)

gazelle_binary(
    name = "gazelle_bin",
    languages = DEFAULT_LANGUAGES + [
        "@contrib_rules_jvm//java/gazelle",
    ],
)

Make sure you have everything setup properly by building the gazelle binary: bazel build //:gazelle_bin

To generate BUILD files:

# Run Gazelle with the java extension
bazel run //:gazelle

Requirements

This gazelle plugin requires Go 1.18 or above.

Configuration options

This Gazelle extension supports some configuration options, which are enabled by adding comments to your root BUILD.bazel file. For example, to set java_maven_install_file, you would add the following to your root BUILD.bazel file:

# gazelle:java_maven_install_file project/main_maven_install.json

See javaconfig/config.go for a list of configuration options and their documentation.

Additionally, some configuration can only be done by flag. See the RegisterFlags function in configure.go for a list of these options.

Source code restrictions and limitations

Currently, the gazelle plugin makes the following assumptions about the code it's generating BUILD files for:

  1. All code lives in a non-empty package. Source files must have a package declaration, and classes depended on all themselves have a package declaration.

  2. Packages only exist in one place. Two different directories or dependencies may not contain classes which belong in the same package. The exception to this is that for each package, there may be a single test directory which uses the same package as that package's non-test directory.

  3. There are no circular dependencies that extend beyond a single package. If these are present, and can't easily be removed, you may want to set # gazelle:java_module_granularity module in the BUILD file containing the parent-most class in the dependency cycle, which may fix the problem, but will slow down your builds. Ideally, remove dependency cycles.

  4. Non-test code doesn't depend on test code.

  5. Non-test code used by one package of tests either lives in the same directory as those tests, or lives in a non-test-code directory. We also detect non-test code used from another test package, if that other package doesn't have a corresponding non-test code directory, but require you to manually set the visibility on the depended-on target, because this is an unexpected set-up.

  6. Package names and class/interface names follow standard java conventions; that is: package names are all lower-case, and class and interface names start with Upper Case letters.

  7. Code doesn't use types which it doesn't name only through unnamed means, across multiple calls. For example, if some code calls x.foo().bar() where the return type of foo is defined in another target, and the calling code explicitly uses a type from that target somewhere else. In the case of x.foo(), we add exports so that the caller will have access to the return type of foo(), but do not track dependencies on the return types across multiple calls.

    This limitation could be lifted, but would require us to export all transitively used symbols from every function. This would serve to add direct dependencies between lots of targets, which can slow down compilation and reduce cache hits.

    In our experience, this kind of code is rare in Java - most code tends to either introduce intermediate variables (at which point the type gets used and we detect that a dependency needs to be added), or tends to already use the targets containing the intermediate types somewhere else (at which point the dependency will already exist), but we're open to discussion about this heuristic if it poses problems for a real-world codebase.

If these assumptions are violated, the rest of the generation should still function properly, but the specific files which violate the assumptions (or depend on files which violate the assumptions) will not get complete results. We strive to emit warnings when this happens.

We are also aware of the following limitations. This list is not exhaustive, and is not intentional (i.e. if we can fix these limitations, we would like to):

  1. Runtime dependencies are not detected (e.g. loading classes by reflection).

Troubleshooting

If one forgets to run bazel fetch @maven//..., the code will complain and tell you to run this command.

If one forgets to "Update the Maven mapping", they use out of date data for the rules resolution, and the hash check will fail. An error is printed and the resolution does not happen.

Contibutors documentation

The following are the targets of interest:

  • //java/gazelle implements a Gazelle extension
  • //java/gazelle/private/javaparser/cmd/javaparser-wrapper wraps the java parser with an activity tracker (to stop the parser) and an adapter to prevent self imports.
  • //java/src/com/github/bazel_contrib/contrib_rules_jvm/javaparser/generators:Main is the java parser side process

The maven integration relies on using rules_jvm_external at least as new as https://github.com/bazelbuild/rules_jvm_external/pull/716

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewLanguage

func NewLanguage() language.Language

Types

type Configurer

type Configurer struct {
	// contains filtered or unexported fields
}

Configurer satisfies the config.Configurer interface. It's the language-specific configuration extension.

See config.Configurer for more information.

func NewConfigurer

func NewConfigurer(lang *javaLang) *Configurer

func (*Configurer) CheckFlags

func (jc *Configurer) CheckFlags(fs *flag.FlagSet, c *config.Config) error

func (*Configurer) Configure

func (jc *Configurer) Configure(c *config.Config, rel string, f *rule.File)

func (*Configurer) KnownDirectives

func (jc *Configurer) KnownDirectives() []string

func (*Configurer) RegisterFlags

func (jc *Configurer) RegisterFlags(fs *flag.FlagSet, cmd string, c *config.Config)

type Resolver

type Resolver struct {
	// contains filtered or unexported fields
}

Resolver satisfies the resolve.Resolver interface. It's the language-specific resolver extension.

See resolve.Resolver for more information.

func NewResolver

func NewResolver(lang *javaLang) *Resolver

func (Resolver) Embeds

func (Resolver) Embeds(r *rule.Rule, from label.Label) []label.Label

func (Resolver) Imports

func (jr Resolver) Imports(c *config.Config, r *rule.Rule, f *rule.File) []resolve.ImportSpec

func (Resolver) Name

func (Resolver) Name() string

func (Resolver) Resolve

func (jr Resolver) Resolve(c *config.Config, ix *resolve.RuleIndex, rc *repo.RemoteCache, r *rule.Rule, imports interface{}, from label.Label)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL