Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions java/gazelle/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Configurer struct {
annotationToAttribute annotationToAttribute
annotationToWrapper annotationToWrapper
mavenInstallFile string
javaIndexFile string
}

func NewConfigurer(lang *javaLang) *Configurer {
Expand All @@ -39,6 +40,7 @@ func (jc *Configurer) RegisterFlags(fs *flag.FlagSet, cmd string, c *config.Conf
fs.Var(&jc.annotationToAttribute, "java-annotation-to-attribute", "Mapping of annotations (on test classes) to attributes which should be set for that test rule. Examples: com.example.annotations.FlakyTest=flaky=True com.example.annotations.SlowTest=timeout=\"long\"")
fs.Var(&jc.annotationToWrapper, "java-annotation-to-wrapper", "Mapping of annotations (on test classes) to wrapper rules which should be used around the test rule. Example: com.example.annotations.RequiresNetwork=@some//wrapper:file.bzl=requires_network")
fs.StringVar(&jc.mavenInstallFile, "java-maven-install-file", "", "Path of the maven_install.json file. Defaults to \"maven_install.json\".")
fs.StringVar(&jc.javaIndexFile, "java-index-file", "", "Path of the maven_index.json file. Defaults to \"maven_index.json\".")
}

func (jc *Configurer) CheckFlags(fs *flag.FlagSet, c *config.Config) error {
Expand All @@ -54,6 +56,9 @@ func (jc *Configurer) CheckFlags(fs *flag.FlagSet, c *config.Config) error {
if jc.mavenInstallFile != "" {
cfgs[""].SetMavenInstallFile(jc.mavenInstallFile)
}
if jc.javaIndexFile != "" {
cfgs[""].SetMavenIndexFile(jc.javaIndexFile)
}
return nil
}

Expand All @@ -62,6 +67,7 @@ func (jc *Configurer) KnownDirectives() []string {
javaconfig.JavaExcludeArtifact,
javaconfig.JavaExtensionDirective,
javaconfig.JavaMavenInstallFile,
javaconfig.JavaIndexFile,
javaconfig.JavaModuleGranularityDirective,
javaconfig.JavaTestFileSuffixes,
javaconfig.JavaTestMode,
Expand Down Expand Up @@ -161,6 +167,9 @@ func (jc *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
case javaconfig.JavaMavenInstallFile:
cfg.SetMavenInstallFile(d.Value)

case javaconfig.JavaIndexFile:
cfg.SetMavenIndexFile(d.Value)

case javaconfig.JavaModuleGranularityDirective:
if err := cfg.SetModuleGranularity(d.Value); err != nil {
jc.lang.logger.Fatal().Err(err).Msgf("invalid value for directive %q", javaconfig.JavaModuleGranularityDirective)
Expand Down Expand Up @@ -260,6 +269,7 @@ func (jc *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
if jc.lang.mavenResolver == nil {
resolver, err := maven.NewResolver(
cfg.MavenInstallFile(),
cfg.MavenIndexFile(),
jc.lang.logger,
)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions java/gazelle/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ package gazelle
// rules. This attribute contains a list of package names (as type types.PackageName) it can be imported
// for. Note that the Java plugin currently uses package names, not classes, as its importable unit.
const packagesKey = "_java_packages"
const classesKey = "_java_classes"
43 changes: 30 additions & 13 deletions java/gazelle/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ type javaFile struct {
}

func (jf *javaFile) ClassName() *types.ClassName {
className := types.NewClassName(jf.pkg, strings.TrimSuffix(filepath.Base(jf.pathRelativeToBazelWorkspaceRoot), ".java"))
name := filepath.Base(jf.pathRelativeToBazelWorkspaceRoot)
if strings.HasSuffix(name, ".java") {
name = strings.TrimSuffix(name, ".java")
} else if strings.HasSuffix(name, ".kt") {
name = strings.TrimSuffix(name, ".kt")
}
className := types.NewClassName(jf.pkg, name)
return &className
}

Expand Down Expand Up @@ -155,6 +161,7 @@ func (l javaLang) GenerateRules(args language.GenerateArgs) language.GenerateRes
productionJavaImports := sorted_set.NewSortedSetFn([]types.PackageName{}, types.PackageNameLess)
productionJavaImportedClasses := sorted_set.NewSortedSetFn([]types.ClassName{}, types.ClassNameLess)
nonLocalJavaExports := sorted_set.NewSortedSetFn([]types.PackageName{}, types.PackageNameLess)
nonLocalJavaExportedClasses := sorted_set.NewSortedSetFn([]types.ClassName{}, types.ClassNameLess)

// Files and imports for actual test classes.
testJavaFiles := sorted_set.NewSortedSetFn([]javaFile{}, javaFileLess)
Expand All @@ -180,14 +187,16 @@ func (l javaLang) GenerateRules(args language.GenerateArgs) language.GenerateRes
allPackageNames.Add(mJavaPkg.Name)

if !mJavaPkg.TestPackage {
addNonLocalImportsAndExports(productionJavaImports, productionJavaImportedClasses, nonLocalJavaExports, mJavaPkg.ImportedClasses, mJavaPkg.ImportedPackagesWithoutSpecificClasses, mJavaPkg.ExportedClasses, mJavaPkg.Name, likelyLocalClassNames)
addNonLocalImportsAndExports(productionJavaImports, productionJavaImportedClasses, nonLocalJavaExports, nil, mJavaPkg.ImportedClasses, mJavaPkg.ImportedPackagesWithoutSpecificClasses, mJavaPkg.ExportedClasses, mJavaPkg.Name, likelyLocalClassNames)
for _, f := range mJavaPkg.Files.SortedSlice() {
productionJavaFiles.Add(filepath.Join(mRel, f))
jf := javaFile{pathRelativeToBazelWorkspaceRoot: filepath.Join(mRel, f), pkg: mJavaPkg.Name}
nonLocalJavaExportedClasses.Add(*jf.ClassName())
}
allMains.AddAll(mJavaPkg.Mains)
} else {
// Tests don't get to export things, as things shouldn't depend on them.
addNonLocalImportsAndExports(testJavaImports, testJavaImportedClasses, nil, mJavaPkg.ImportedClasses, mJavaPkg.ImportedPackagesWithoutSpecificClasses, mJavaPkg.ExportedClasses, mJavaPkg.Name, likelyLocalClassNames)
addNonLocalImportsAndExports(testJavaImports, testJavaImportedClasses, nil, nil, mJavaPkg.ImportedClasses, mJavaPkg.ImportedPackagesWithoutSpecificClasses, mJavaPkg.ExportedClasses, mJavaPkg.Name, likelyLocalClassNames)
for _, f := range mJavaPkg.Files.SortedSlice() {
path := filepath.Join(mRel, f)
file := javaFile{
Expand All @@ -205,9 +214,9 @@ func (l javaLang) GenerateRules(args language.GenerateArgs) language.GenerateRes
allPackageNames.Add(javaPkg.Name)
if javaPkg.TestPackage {
// Tests don't get to export things, as things shouldn't depend on them.
addNonLocalImportsAndExports(testJavaImports, testJavaImportedClasses, nil, javaPkg.ImportedClasses, javaPkg.ImportedPackagesWithoutSpecificClasses, javaPkg.ExportedClasses, javaPkg.Name, likelyLocalClassNames)
addNonLocalImportsAndExports(testJavaImports, testJavaImportedClasses, nil, nil, javaPkg.ImportedClasses, javaPkg.ImportedPackagesWithoutSpecificClasses, javaPkg.ExportedClasses, javaPkg.Name, likelyLocalClassNames)
} else {
addNonLocalImportsAndExports(productionJavaImports, productionJavaImportedClasses, nonLocalJavaExports, javaPkg.ImportedClasses, javaPkg.ImportedPackagesWithoutSpecificClasses, javaPkg.ExportedClasses, javaPkg.Name, likelyLocalClassNames)
addNonLocalImportsAndExports(productionJavaImports, productionJavaImportedClasses, nonLocalJavaExports, nil, javaPkg.ImportedClasses, javaPkg.ImportedPackagesWithoutSpecificClasses, javaPkg.ExportedClasses, javaPkg.Name, likelyLocalClassNames)
}
allMains.AddAll(javaPkg.Mains)
for _, f := range srcFilenamesRelativeToPackage {
Expand All @@ -220,6 +229,8 @@ func (l javaLang) GenerateRules(args language.GenerateArgs) language.GenerateRes
accumulateJavaFile(cfg, testJavaFiles, testHelperJavaFiles, separateTestJavaFiles, file, javaPkg.PerClassMetadata, log)
} else {
productionJavaFiles.Add(path)
jf := javaFile{pathRelativeToBazelWorkspaceRoot: path, pkg: javaPkg.Name}
nonLocalJavaExportedClasses.Add(*jf.ClassName())
}
}
for _, annotationClass := range javaPkg.AllAnnotations().SortedSlice() {
Expand Down Expand Up @@ -335,7 +346,7 @@ func (l javaLang) GenerateRules(args language.GenerateArgs) language.GenerateRes
}
}

l.generateJavaLibrary(args.File, args.Rel, filepath.Base(args.Rel), productionJavaFiles.SortedSlice(), resourcesDirectRef, resourcesRuntimeDep, allPackageNames, nonLocalProductionJavaImports, nonLocalProductionJavaImportedClasses, nonLocalJavaExports, annotationProcessorClasses, false, javaLibraryKind, &res, cfg, args.Config.RepoName)
l.generateJavaLibrary(args.File, args.Rel, filepath.Base(args.Rel), productionJavaFiles.SortedSlice(), resourcesDirectRef, resourcesRuntimeDep, allPackageNames, nonLocalProductionJavaImports, nonLocalProductionJavaImportedClasses, nonLocalJavaExports, nonLocalJavaExportedClasses, annotationProcessorClasses, false, javaLibraryKind, &res, cfg, args.Config.RepoName)
}

if cfg.GenerateBinary() {
Expand All @@ -345,6 +356,7 @@ func (l javaLang) GenerateRules(args language.GenerateArgs) language.GenerateRes
// We add special packages to point to testonly libraries which - this accumulates them,
// as well as the existing java imports of tests.
testJavaImportsWithHelpers := testJavaImports.Clone()
testJavaImportedClassesWithHelpers := testJavaImportedClasses.Clone()

if testHelperJavaFiles.Len() > 0 {
// Suites generate their own helper library.
Expand All @@ -355,10 +367,11 @@ func (l javaLang) GenerateRules(args language.GenerateArgs) language.GenerateRes
for _, tf := range testHelperJavaFiles.SortedSlice() {
packages.Add(tf.pkg)
testJavaImportsWithHelpers.Add(tf.pkg)
testJavaImportedClassesWithHelpers.Add(*tf.ClassName())
srcs = append(srcs, tf.pathRelativeToBazelWorkspaceRoot)
}
// Test helper libraries typically don't have resources
l.generateJavaLibrary(args.File, args.Rel, filepath.Base(args.Rel), srcs, "", "", packages, testJavaImports, testJavaImportedClasses, nonLocalJavaExports, annotationProcessorClasses, true, javaLibraryKind, &res, cfg, args.Config.RepoName)
l.generateJavaLibrary(args.File, args.Rel, filepath.Base(args.Rel), srcs, "", "", packages, testJavaImports, testJavaImportedClasses, nonLocalJavaExports, nonLocalJavaExportedClasses, annotationProcessorClasses, true, javaLibraryKind, &res, cfg, args.Config.RepoName)
}
}

Expand All @@ -370,7 +383,7 @@ func (l javaLang) GenerateRules(args language.GenerateArgs) language.GenerateRes
case "file":
for _, tf := range testJavaFiles.SortedSlice() {
separateJavaTestReasons := separateTestJavaFiles[tf]
l.generateJavaTest(args.File, args.Rel, cfg.MavenRepositoryName(), tf, isModule, testJavaImportsWithHelpers, testJavaImportedClasses, annotationProcessorClasses, nil, separateJavaTestReasons.wrapper, separateJavaTestReasons.attributes, &res)
l.generateJavaTest(args.File, args.Rel, cfg.MavenRepositoryName(), tf, isModule, testJavaImportsWithHelpers, testJavaImportedClassesWithHelpers, annotationProcessorClasses, nil, separateJavaTestReasons.wrapper, separateJavaTestReasons.attributes, &res)
}

case "suite":
Expand Down Expand Up @@ -398,7 +411,7 @@ func (l javaLang) GenerateRules(args language.GenerateArgs) language.GenerateRes
packageNames,
cfg.MavenRepositoryName(),
testJavaImportsWithHelpers,
testJavaImportedClasses,
testJavaImportedClassesWithHelpers,
annotationProcessorClasses,
cfg.GetCustomJavaTestFileSuffixes(),
testHelperJavaFiles.Len() > 0,
Expand All @@ -416,7 +429,7 @@ func (l javaLang) GenerateRules(args language.GenerateArgs) language.GenerateRes
testHelperDep = ptr(testHelperLibname(suiteName))
}
separateJavaTestReasons := separateTestJavaFiles[src]
l.generateJavaTest(args.File, args.Rel, cfg.MavenRepositoryName(), src, isModule, testJavaImportsWithHelpers, testJavaImportedClasses, annotationProcessorClasses, testHelperDep, separateJavaTestReasons.wrapper, separateJavaTestReasons.attributes, &res)
l.generateJavaTest(args.File, args.Rel, cfg.MavenRepositoryName(), src, isModule, testJavaImportsWithHelpers, testJavaImportedClassesWithHelpers, annotationProcessorClasses, testHelperDep, separateJavaTestReasons.wrapper, separateJavaTestReasons.attributes, &res)
}
}
}
Expand Down Expand Up @@ -521,11 +534,11 @@ func generateProtoLibraries(args language.GenerateArgs, log zerolog.Logger, res

// We exclude intra-target imports because otherwise we'd get self-dependencies come resolve time.
// toExports is optional and may be nil. All other parameters are required and must be non-nil.
func addNonLocalImportsAndExports(toImports *sorted_set.SortedSet[types.PackageName], toImportedClasses *sorted_set.SortedSet[types.ClassName], toExports *sorted_set.SortedSet[types.PackageName], fromImportedClasses *sorted_set.SortedSet[types.ClassName], fromPackages *sorted_set.SortedSet[types.PackageName], fromExportedClasses *sorted_set.SortedSet[types.ClassName], pkg types.PackageName, localClasses *sorted_set.SortedSet[string]) {
func addNonLocalImportsAndExports(toImports *sorted_set.SortedSet[types.PackageName], toImportedClasses *sorted_set.SortedSet[types.ClassName], toExports *sorted_set.SortedSet[types.PackageName], toExportedClasses *sorted_set.SortedSet[types.ClassName], fromImportedClasses *sorted_set.SortedSet[types.ClassName], fromPackages *sorted_set.SortedSet[types.PackageName], fromExportedClasses *sorted_set.SortedSet[types.ClassName], pkg types.PackageName, localClasses *sorted_set.SortedSet[string]) {
toImports.AddAll(fromPackages)
addFilteringOutOwnPackage(toImports, toImportedClasses, fromImportedClasses, pkg, localClasses)
if toExports != nil {
addFilteringOutOwnPackage(toExports, nil, fromExportedClasses, pkg, localClasses)
addFilteringOutOwnPackage(toExports, toExportedClasses, fromExportedClasses, pkg, localClasses)
}
}

Expand Down Expand Up @@ -597,7 +610,7 @@ func accumulateJavaFile(cfg *javaconfig.Config, testJavaFiles, testHelperJavaFil
}
}

func (l javaLang) generateJavaLibrary(file *rule.File, pathToPackageRelativeToBazelWorkspace, name string, srcsRelativeToBazelWorkspace []string, resourcesDirectRef string, resourcesRuntimeDep string, packages, imports *sorted_set.SortedSet[types.PackageName], importedClasses *sorted_set.SortedSet[types.ClassName], exports *sorted_set.SortedSet[types.PackageName], annotationProcessorClasses *sorted_set.SortedSet[types.ClassName], testonly bool, javaLibraryRuleKind string, res *language.GenerateResult, cfg *javaconfig.Config, repoName string) {
func (l javaLang) generateJavaLibrary(file *rule.File, pathToPackageRelativeToBazelWorkspace, name string, srcsRelativeToBazelWorkspace []string, resourcesDirectRef string, resourcesRuntimeDep string, packages, imports *sorted_set.SortedSet[types.PackageName], importedClasses *sorted_set.SortedSet[types.ClassName], exports *sorted_set.SortedSet[types.PackageName], exportedClasses *sorted_set.SortedSet[types.ClassName], annotationProcessorClasses *sorted_set.SortedSet[types.ClassName], testonly bool, javaLibraryRuleKind string, res *language.GenerateResult, cfg *javaconfig.Config, repoName string) {
r := rule.NewRule(javaLibraryRuleKind, name)

srcs := make([]string, 0, len(srcsRelativeToBazelWorkspace))
Expand Down Expand Up @@ -641,13 +654,17 @@ func (l javaLang) generateJavaLibrary(file *rule.File, pathToPackageRelativeToBa
resolvablePackages = append(resolvablePackages, *types.NewResolvableJavaPackage(pkg, testonly, false))
}
r.SetPrivateAttr(packagesKey, resolvablePackages)
if exportedClasses != nil {
r.SetPrivateAttr(classesKey, exportedClasses.SortedSlice())
}
res.Gen = append(res.Gen, r)

resolveInput := types.ResolveInput{
PackageNames: packages,
ImportedPackageNames: imports,
ImportedClasses: importedClasses,
ExportedPackageNames: exports,
ExportedClassNames: exportedClasses,
AnnotationProcessors: annotationProcessorClasses,
}
res.Imports = append(res.Imports, resolveInput)
Expand Down
2 changes: 1 addition & 1 deletion java/gazelle/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ func TestAddNonLocalImports(t *testing.T) {

depsDst := sorted_set.NewSortedSetFn([]types.PackageName{}, types.PackageNameLess)
exportsDst := sorted_set.NewSortedSetFn([]types.PackageName{}, types.PackageNameLess)
addNonLocalImportsAndExports(depsDst, nil, exportsDst, src, sorted_set.NewSortedSetFn[types.PackageName]([]types.PackageName{}, types.PackageNameLess), sorted_set.NewSortedSetFn([]types.ClassName{}, types.ClassNameLess), types.NewPackageName("com.example.a.b"), sorted_set.NewSortedSet([]string{"Foo", "Bar"}))
addNonLocalImportsAndExports(depsDst, nil, exportsDst, nil, src, sorted_set.NewSortedSetFn[types.PackageName]([]types.PackageName{}, types.PackageNameLess), sorted_set.NewSortedSetFn([]types.ClassName{}, types.ClassNameLess), types.NewPackageName("com.example.a.b"), sorted_set.NewSortedSet([]string{"Foo", "Bar"}))

want := stringsToPackageNames([]string{
"com.another.a.b",
Expand Down
16 changes: 16 additions & 0 deletions java/gazelle/javaconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ const (
// Defaults to "maven_install.json".
JavaMavenInstallFile = "java_maven_install_file"

// JavaIndexFile represents the directive that controls where the index
// file generated by `rules_jvm_external` is located.
// Defaults to "maven_index.json"
JavaIndexFile = "java_index_file"

// JavaModuleGranularityDirective represents the directive that controls whether
// this Java module has a module granularity (Gradle) or a package
// granularity (bazel).
Expand Down Expand Up @@ -105,6 +110,7 @@ func (c *Config) NewChild() *Config {
resolveToJavaExports: c.resolveToJavaExports,
kotlinEnabled: c.kotlinEnabled,
mavenInstallFile: c.mavenInstallFile,
javaIndexFile: c.javaIndexFile,
moduleGranularity: c.moduleGranularity,
repoRoot: c.repoRoot,
testMode: c.testMode,
Expand Down Expand Up @@ -138,6 +144,7 @@ type Config struct {
resolveToJavaExports *types.LateInit[bool]
kotlinEnabled bool
mavenInstallFile string
javaIndexFile string
moduleGranularity string
repoRoot string
testMode string
Expand Down Expand Up @@ -166,6 +173,7 @@ func New(repoRoot string) *Config {
resolveToJavaExports: types.NewLateInit[bool](true),
kotlinEnabled: true,
mavenInstallFile: "maven_install.json",
javaIndexFile: "maven_index.json",
moduleGranularity: "package",
repoRoot: repoRoot,
testMode: "suite",
Expand Down Expand Up @@ -234,6 +242,14 @@ func (c *Config) SetMavenInstallFile(filename string) {
c.mavenInstallFile = filename
}

func (c Config) MavenIndexFile() string {
return filepath.Join(c.repoRoot, c.javaIndexFile)
}

func (c *Config) SetMavenIndexFile(filename string) {
c.javaIndexFile = filename
}

func (c Config) ModuleGranularity() string {
return c.moduleGranularity
}
Expand Down
26 changes: 26 additions & 0 deletions java/gazelle/private/maven/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type lockFile interface {
ListDependencies() []string
GetDependencyCoordinates(name string) string
ListDependencyPackages(name string) []string
ListDependencyClasses(name string) []string
}

type versionnedConfigFile struct {
Expand Down Expand Up @@ -62,6 +63,10 @@ func (f *lockFileV1) ListDependencyPackages(name string) []string {
panic(fmt.Sprintf("did not find package information for %s", name))
}

func (f *lockFileV1) ListDependencyClasses(name string) []string {
return nil
}

type lockFileV2 struct {
AutogeneratedFileDoNotModifyThisFileManually string `json:"__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY"`
InputArtifactsHash int `json:"__INPUT_ARTIFACTS_HASH"`
Expand Down Expand Up @@ -89,11 +94,32 @@ func (f *lockFileV2) ListDependencyPackages(name string) []string {
return f.Packages[name]
}

func (f *lockFileV2) ListDependencyClasses(name string) []string {
return nil
}

type lockFileV2_Artifact struct {
Shasums map[string]string `json:"shasums"`
Version string `json:"version"`
}

type IndexFile struct {
Version int `json:"version"`
Classes map[string]map[string][]string `json:"classes"`
}

func loadIndex(filename string) (*IndexFile, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
var index IndexFile
if err := json.Unmarshal(data, &index); err != nil {
return nil, err
}
return &index, nil
}

func loadConfiguration(filename string) (lockFile, error) {
data, err := os.ReadFile(filename)
if err != nil {
Expand Down
Loading
Loading