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
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"
44 changes: 31 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 All @@ -390,6 +403,7 @@ func (l javaLang) GenerateRules(args language.GenerateArgs) language.GenerateRes
srcs = append(srcs, strings.TrimPrefix(filepath.ToSlash(src.pathRelativeToBazelWorkspaceRoot), args.Rel+"/"))
}
}
sort.Strings(srcs)
if len(srcs) > 0 {
l.generateJavaTestSuite(
args.File,
Expand All @@ -398,7 +412,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 +430,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 +535,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 +611,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 +655,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
9 changes: 9 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,6 +94,10 @@ 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"`
Expand Down
27 changes: 23 additions & 4 deletions java/gazelle/private/maven/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,22 @@ func (e *MultipleExternalImportsError) Error() string {

type Resolver interface {
Resolve(pkg types.PackageName, excludedArtifacts map[string]struct{}, mavenRepositoryName string) (label.Label, error)
ResolveClass(className types.ClassName, excludedArtifacts map[string]struct{}, mavenRepositoryName string) (label.Label, error)
}

// resolver finds Maven provided packages by reading the maven_install.json
// file from rules_jvm_external.
type resolver struct {
data *multiset.StringMultiSet
logger zerolog.Logger
data *multiset.StringMultiSet
classIndex map[string]string
logger zerolog.Logger
}

func NewResolver(installFile string, logger zerolog.Logger) (Resolver, error) {
r := resolver{
data: multiset.NewStringMultiSet(),
logger: logger.With().Str("_c", "maven-resolver").Logger(),
data: multiset.NewStringMultiSet(),
classIndex: make(map[string]string),
logger: logger.With().Str("_c", "maven-resolver").Logger(),
}

c, err := loadConfiguration(installFile)
Expand All @@ -65,6 +68,9 @@ func NewResolver(installFile string, logger zerolog.Logger) (Resolver, error) {
for _, pkg := range c.ListDependencyPackages(depName) {
r.data.Add(pkg, coords.ArtifactString())
}
for _, class := range c.ListDependencyClasses(depName) {
r.classIndex[class] = coords.ArtifactString()
}
}

return &r, nil
Expand Down Expand Up @@ -105,6 +111,19 @@ func (r *resolver) Resolve(pkg types.PackageName, excludedArtifacts map[string]s
}
}

func (r *resolver) ResolveClass(className types.ClassName, excludedArtifacts map[string]struct{}, mavenRepositoryName string) (label.Label, error) {
artifact, found := r.classIndex[className.FullyQualifiedClassName()]
if !found {
return label.NoLabel, nil
}

if _, excluded := excludedArtifacts[LabelFromArtifact(mavenRepositoryName, artifact).String()]; excluded {
return label.NoLabel, nil
}

return LabelFromArtifact(mavenRepositoryName, artifact), nil
}

func LabelFromArtifact(mavenRepositoryName string, artifact string) label.Label {
return label.New(mavenRepositoryName, "", bazel.CleanupLabel(artifact))
}
1 change: 1 addition & 0 deletions java/gazelle/private/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ type ResolveInput struct {
ImportedPackageNames *sorted_set.SortedSet[PackageName]
ImportedClasses *sorted_set.SortedSet[ClassName]
ExportedPackageNames *sorted_set.SortedSet[PackageName]
ExportedClassNames *sorted_set.SortedSet[ClassName]
AnnotationProcessors *sorted_set.SortedSet[ClassName]
}

Expand Down
Loading
Loading