Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(copybara): sync commits from Aspect-internal silo #501

Merged
merged 9 commits into from
Aug 14, 2023
Merged
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
4 changes: 4 additions & 0 deletions cmd/aspect/configure/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ configure is based on [gazelle]. We are very grateful to the authors of that sof
The advantage of configure in Aspect CLI is that you don't need to compile the tooling before running it.

[gazelle]: https://github.com/bazelbuild/bazel-gazelle

To change the behavior of configure, you add "directives" to your BUILD files, which are comments
in a special syntax.
Run 'aspect help directives' or see https://docs.aspect.build/v/cli/help/directives for more info.
`,
GroupID: "aspect",
RunE: interceptors.Run(
Expand Down
4 changes: 2 additions & 2 deletions cmd/aspect/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import (
"aspect.build/cli/cmd/aspect/sync"
"aspect.build/cli/cmd/aspect/test"
"aspect.build/cli/cmd/aspect/version"
"aspect.build/cli/docs/help/topics"
help_docs "aspect.build/cli/docs/help/topics"
"aspect.build/cli/pkg/aspect/root/flags"
"aspect.build/cli/pkg/ioutils"
"aspect.build/cli/pkg/plugin/system"
Expand Down Expand Up @@ -168,7 +168,7 @@ func NewCmd(
}

func mustReadFile(f string) string {
result, err := topics.Content.ReadFile(f)
result, err := help_docs.Content.ReadFile(f)
if err != nil {
panic(fmt.Errorf("Internal error: embed data was not readable: %w", err))
}
Expand Down
4 changes: 4 additions & 0 deletions docs/aspect_configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ The advantage of configure in Aspect CLI is that you don't need to compile the t

[gazelle]: https://github.com/bazelbuild/bazel-gazelle

To change the behavior of configure, you add "directives" to your BUILD files, which are comments
in a special syntax.
Run 'aspect help directives' or see https://docs.aspect.build/v/cli/help/directives for more info.


```
aspect configure [flags]
Expand Down
34 changes: 32 additions & 2 deletions docs/help/topics/directives.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,39 @@ within the Bazel package rooted at that file.

## Go

Go directives for generating BUILD files are from the standard [gazelle go plugin](https://github.com/bazelbuild/bazel-gazelle#directives).
Go directives for generating BUILD files are from the standard [gazelle directives].

## JavaScript

JavaScript directives for generating BUILD files follow the same format as [gazelle](https://github.com/bazelbuild/bazel-gazelle). In addition to the generic directives from the [standard gazelle directives](https://github.com/bazelbuild/bazel-gazelle#directives) JavaScript (and TypeScript) specific directives are as follows:
JavaScript directives for generating BUILD files follow the same format as gazelle.
You can use generic directives from the [gazelle directives], as well as the following JS/TS
specific directives.

TypeScript source files are those ending in `.ts`, `.tsx` as well as `.js`, `.mjs`.
Test source files are source files ending with `.spec.ts` (and other ts extensions).
The test file pattern can be configured with the 'js*test*\*' directives.

By default `aspect configure` creates new BUILD files for each directory containing source files.
This can be configured to only edit existing BUILD files using the `js_generation_mode` directive.

Each BUILD file may have a `ts_project` rule for sources, another for tests,
a `npm_package` rule for pnpm workspace projects, and `npm_link_all_packages` for linking node_modules.
Which rules are configured depends on the source files and directives that apply.

Next, all source files are collected into the `srcs` of the `ts_project`,
either the primary rule or tests rule.

Finally, the `import` statements in the source files are parsed, and
dependencies are added to the `deps` attribute of the appropriate
`ts_project` rule which the source file belongs to.

Dependencies may also be found other ways such as from the CommonJS `require` function.

If a `package.json` file exists declaring npm dependencies, a `npm_link_all_packages` rule
is generated for declaring depending on individual NPM packages.

If the `package.json` is a pnpm workspace project a `npm_package` rule may be generated to
enable other projects to declare dependencies on the package.

<!-- prettier-ignore-start -->
| **Directive** | **Default value** |
Expand Down Expand Up @@ -40,3 +68,5 @@ JavaScript directives for generating BUILD files follow the same format as [gaze
| `# gazelle:js_tsconfig _filename_` | `tsconfig.json` |
| Path to a `tsconfig.json` file used to help generate TypeScript rules.<br />This value is inherited by sub-directories and applied relative to each BUILD.<br />The `ts_project(tsconfig)` attribute is *NOT* set and must be done manually if necessary |
<!-- prettier-ignore-end -->

[gazelle directives]: https://github.com/bazelbuild/bazel-gazelle#directives
20 changes: 20 additions & 0 deletions gazelle/js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# JavaScript/TypeScript BUILD file generation

This package automates the creation and maintenance of BUILD files for JavaScript and TypeScript, using [rules_js](https://github.com/aspect-build/rules_js) and [rules_ts](https://github.com/aspect-build/rules_ts). It is a [Gazelle](https://github.com/bazelbuild/bazel-gazelle) `Language` implementation.

## Usage

This feature is included in the [Aspect CLI](https://github.com/aspect-build/aspect-cli), accessed with the [`configure` command](https://docs.aspect.build/v/cli/commands/aspect_configure).
It's also possible to build into your own Gazelle binary.

## Rules

Generated targets include:

- `ts_project` targets for source, tests, and custom targets and their ts/js/npm dependencies
- `npm_package` targets for projects within a pnpm workspace
- `npm_link_all_packages` for linking npm packages

### Directives

See [Aspect CLI Directives](/cli/core/docs/help/topics/directives.md#JavaScript) for a list of supported directives.
2 changes: 1 addition & 1 deletion gazelle/js/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/emirpasic/gods/sets/treeset"
)

// Directives. Keep in sync with documentation in cli/core/docs/help/topics/directives.md
// Directives. Keep in sync with documentation in /docs/help/topics/directives.md
const (
// Directive_TypeScriptExtension represents the directive that controls whether
// this TypeScript generation is enabled or not. Sub-packages inherit this value.
Expand Down
13 changes: 12 additions & 1 deletion gazelle/kotlin/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
load("@bazel_gazelle//:def.bzl", "gazelle_binary")
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
load("//gazelle:gazelle.bzl", "gazelle_generation_test")

# Disable the kotlin extension
Expand Down Expand Up @@ -31,8 +31,13 @@ go_library(
"@bazel_gazelle//resolve:go_default_library",
"@bazel_gazelle//rule:go_default_library",
"@com_github_bazel_contrib_rules_jvm//java/gazelle/javaconfig",
"@com_github_bazel_contrib_rules_jvm//java/gazelle/private/java",
"@com_github_bazel_contrib_rules_jvm//java/gazelle/private/maven",
"@com_github_bazel_contrib_rules_jvm//java/gazelle/private/types",
"@com_github_emirpasic_gods//maps/treemap",
"@com_github_emirpasic_gods//sets/treeset",
"@com_github_emirpasic_gods//utils",
"@com_github_rs_zerolog//:zerolog",
],
)

Expand All @@ -52,3 +57,9 @@ gazelle_binary(
)
for test_workspace in glob(["tests/**/WORKSPACE"])
]

go_test(
name = "kotlin_test",
srcs = ["kotlin_test.go"],
embed = [":kotlin"],
)
5 changes: 5 additions & 0 deletions gazelle/kotlin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Kotlin Gazelle Extension

EXPERIMENTAL: This is a work in progress and is not yet ready for use. Work is ongoing including upcoming support for rules_jvm maven dependencies.

This is a [Gazelle](https://github.com/bazelbuild/bazel-gazelle) `Language` implementation for Kotlin using the [rules_kotlin](https://github.com/bazelbuild/rules_kotlin) `jvm` rules.
31 changes: 27 additions & 4 deletions gazelle/kotlin/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ import (

. "aspect.build/cli/gazelle/common/log"
"aspect.build/cli/gazelle/kotlin/kotlinconfig"
"github.com/bazel-contrib/rules_jvm/java/gazelle/javaconfig"
jvm_javaconfig "github.com/bazel-contrib/rules_jvm/java/gazelle/javaconfig"
jvm_maven "github.com/bazel-contrib/rules_jvm/java/gazelle/private/maven"
"github.com/bazelbuild/bazel-gazelle/config"
"github.com/bazelbuild/bazel-gazelle/rule"
"github.com/rs/zerolog"
)

type Configurer struct {
config.Configurer

lang *kotlinLang

mavenInstallFile string
}

func NewConfigurer(lang *kotlinLang) *Configurer {
Expand All @@ -24,7 +28,7 @@ func NewConfigurer(lang *kotlinLang) *Configurer {

func (kt *Configurer) KnownDirectives() []string {
return []string{
javaconfig.JavaMavenInstallFile,
jvm_javaconfig.JavaMavenInstallFile,
}
}

Expand Down Expand Up @@ -56,15 +60,34 @@ func (kt *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
for _, d := range f.Directives {
switch d.Key {

// TODO: invoke java gazelle.Configure()?
case javaconfig.JavaMavenInstallFile:
// TODO: invoke java gazelle.Configure() to support all jvm directives?
// TODO: JavaMavenRepositoryName: https://github.com/bazel-contrib/rules_jvm/commit/e46bb11bedb2ead45309eae04619caca684f6243

case jvm_javaconfig.JavaMavenInstallFile:
cfg.SetMavenInstallFile(d.Value)
}
}
}

if kt.lang.mavenResolver == nil {
BazelLog.Tracef("Creating Maven resolver: %s", cfg.MavenInstallFile())

// TODO: better zerolog configuration
logger := zerolog.New(BazelLog.Out).Level(zerolog.TraceLevel)

resolver, err := jvm_maven.NewResolver(
cfg.MavenInstallFile(),
logger,
)
if err != nil {
BazelLog.Fatalln("error creating Maven resolver: %s", err.Error())
}
kt.lang.mavenResolver = &resolver
}
}

func (kc *Configurer) RegisterFlags(fs *flag.FlagSet, cmd string, c *config.Config) {
// TODO: support rules_jvm flags such as 'java-maven-install-file'? (see rules_jvm java/gazelle/configure.go)
}

func (kc *Configurer) CheckFlags(fs *flag.FlagSet, c *config.Config) error {
Expand Down
50 changes: 43 additions & 7 deletions gazelle/kotlin/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"math"
"os"
"path"
"strings"
"sync"

gazelle "aspect.build/cli/gazelle/common"
Expand All @@ -14,6 +15,7 @@ import (
"github.com/bazelbuild/bazel-gazelle/language"
"github.com/bazelbuild/bazel-gazelle/resolve"
"github.com/bazelbuild/bazel-gazelle/rule"
"github.com/emirpasic/gods/maps/treemap"
"github.com/emirpasic/gods/sets/treeset"
)

Expand All @@ -34,13 +36,25 @@ func (kt *kotlinLang) GenerateRules(args language.GenerateArgs) language.Generat
// Collect all source files.
sourceFiles := kt.collectSourceFiles(cfg, args)

// TODO: multiple targets (lib, test, ...)
target := NewKotlinTarget()
// TODO: multiple library targets (lib, test, ...)
libTarget := NewKotlinLibTarget()
binTargets := treemap.NewWithStringComparator()

// Parse all source files and group information into target(s)
for p := range kt.parseFiles(args, sourceFiles) {
target.Files.Add(p.File)
target.Packages.Add(p.Package)
var target *KotlinTarget

if p.HasMain {
binTarget := NewKotlinBinTarget(p.File, p.Package)
binTargets.Put(p.File, binTarget)

target = &binTarget.KotlinTarget
} else {
libTarget.Files.Add(p.File)
libTarget.Packages.Add(p.Package)

target = &libTarget.KotlinTarget
}

for _, impt := range p.Imports {
target.Imports.Add(ImportStatement{
Expand All @@ -55,14 +69,19 @@ func (kt *kotlinLang) GenerateRules(args language.GenerateArgs) language.Generat

var result language.GenerateResult

targetName := gazelle.ToDefaultTargetName(args, "root")
libTargetName := gazelle.ToDefaultTargetName(args, "root")
kt.addLibraryRule(libTargetName, libTarget, args, false, &result)

kt.addLibraryRule(targetName, target, args, false, &result)
for _, v := range binTargets.Values() {
binTarget := v.(*KotlinBinTarget)
binTargetName := toBinaryTargetName(binTarget.File)
kt.addBinaryRule(binTargetName, binTarget, args, &result)
}

return result
}

func (kt *kotlinLang) addLibraryRule(targetName string, target *KotlinTarget, args language.GenerateArgs, isTestRule bool, result *language.GenerateResult) {
func (kt *kotlinLang) addLibraryRule(targetName string, target *KotlinLibTarget, args language.GenerateArgs, isTestRule bool, result *language.GenerateResult) {
// TODO: check for rule collisions

// Generate nothing if there are no source files. Remove any existing rules.
Expand Down Expand Up @@ -96,6 +115,23 @@ func (kt *kotlinLang) addLibraryRule(targetName string, target *KotlinTarget, ar
BazelLog.Infof("add rule '%s' '%s:%s'", ktLibrary.Kind(), args.Rel, ktLibrary.Name())
}

func (kt *kotlinLang) addBinaryRule(targetName string, target *KotlinBinTarget, args language.GenerateArgs, result *language.GenerateResult) {
main_class := strings.TrimSuffix(target.File, ".kt")
if target.Package != "" {
main_class = target.Package + "." + main_class
}

ktBinary := rule.NewRule(KtJvmBinary, targetName)
ktBinary.SetAttr("srcs", []string{target.File})
ktBinary.SetAttr("main_class", main_class)
ktBinary.SetPrivateAttr(packagesKey, target)

result.Gen = append(result.Gen, ktBinary)
result.Imports = append(result.Imports, target)

BazelLog.Infof("add rule '%s' '%s:%s'", ktBinary.Kind(), args.Rel, ktBinary.Name())
}

// TODO: put in common?
func (kt *kotlinLang) parseFiles(args language.GenerateArgs, sources *treeset.Set) chan *parser.ParseResult {
// The channel of all files to parse.
Expand Down
Loading
Loading