From 55886ff808c63c678e8ee1e9020b00138835b832 Mon Sep 17 00:00:00 2001 From: Colin Heathman Date: Wed, 9 Oct 2024 10:50:57 -0700 Subject: [PATCH] Added directive js_collect_pages which can be used in a NextJS style page root to mark each direct leaf as a page --- examples/nextjs/.bazelignore | 1 + examples/nextjs/apps/alpha/pages/BUILD.bazel | 57 +++--- .../nextjs/apps/alpha/pages/api/BUILD.bazel | 9 + gazelle/configure.go | 84 ++++++--- gazelle/generate.go | 165 ++++++++++++++---- gazelle/resolve.go | 9 +- go.mod | 4 +- go.sum | 3 - tests/BUILD | 1 + tests/collect_pages/BUILD.in | 13 ++ tests/collect_pages/BUILD.out | 13 ++ tests/collect_pages/WORKSPACE | 1 + tests/collect_pages/index.ts | 1 + tests/collect_pages/src/pages/404.ts | 1 + tests/collect_pages/src/pages/BUILD.in | 1 + tests/collect_pages/src/pages/BUILD.out | 12 ++ tests/collect_pages/src/pages/index.ts | 1 + .../collect_pages/src/pages/my_page/BUILD.in | 0 .../collect_pages/src/pages/my_page/BUILD.out | 9 + .../collect_pages/src/pages/my_page/index.ts | 1 + .../src/pages/my_page/module_file.ts | 1 + tests/collect_pages/src/pages2/BUILD.in | 1 + tests/collect_pages/src/pages2/BUILD.out | 8 + .../collect_pages/src/pages2/my_page/BUILD.in | 0 .../src/pages2/my_page/BUILD.out | 9 + .../collect_pages/src/pages2/my_page/index.ts | 1 + .../src/pages2/my_page/module_file.ts | 1 + tests/test_runner.go | 4 +- 28 files changed, 311 insertions(+), 100 deletions(-) create mode 100644 examples/nextjs/apps/alpha/pages/api/BUILD.bazel create mode 100644 tests/collect_pages/BUILD.in create mode 100644 tests/collect_pages/BUILD.out create mode 100644 tests/collect_pages/WORKSPACE create mode 100644 tests/collect_pages/index.ts create mode 100644 tests/collect_pages/src/pages/404.ts create mode 100644 tests/collect_pages/src/pages/BUILD.in create mode 100644 tests/collect_pages/src/pages/BUILD.out create mode 100644 tests/collect_pages/src/pages/index.ts create mode 100644 tests/collect_pages/src/pages/my_page/BUILD.in create mode 100644 tests/collect_pages/src/pages/my_page/BUILD.out create mode 100644 tests/collect_pages/src/pages/my_page/index.ts create mode 100644 tests/collect_pages/src/pages/my_page/module_file.ts create mode 100644 tests/collect_pages/src/pages2/BUILD.in create mode 100644 tests/collect_pages/src/pages2/BUILD.out create mode 100644 tests/collect_pages/src/pages2/my_page/BUILD.in create mode 100644 tests/collect_pages/src/pages2/my_page/BUILD.out create mode 100644 tests/collect_pages/src/pages2/my_page/index.ts create mode 100644 tests/collect_pages/src/pages2/my_page/module_file.ts diff --git a/examples/nextjs/.bazelignore b/examples/nextjs/.bazelignore index 2e445f9..4dff4db 100644 --- a/examples/nextjs/.bazelignore +++ b/examples/nextjs/.bazelignore @@ -1,5 +1,6 @@ node_modules apps/alpha/node_modules +apps/alpha/pages/__snapshots__ packages/one/node_modules app/.next bazel-out diff --git a/examples/nextjs/apps/alpha/pages/BUILD.bazel b/examples/nextjs/apps/alpha/pages/BUILD.bazel index b87b560..7c767a3 100644 --- a/examples/nextjs/apps/alpha/pages/BUILD.bazel +++ b/examples/nextjs/apps/alpha/pages/BUILD.bazel @@ -1,35 +1,10 @@ load("//bazel:jest_test.bzl", "jest_test") load("//bazel:ts_project.bzl", "ts_project") -# gazelle:js_collect_all - -ts_project( - name = "pages", - srcs = [ - "_app.tsx", - "api/hello.ts", - "index.tsx", - ], - data = [ - "//:node_modules/@nextjs-example/one", - "//:node_modules/next", - "//:node_modules/react", - "//apps/alpha:node_modules/is-even", - "//apps/alpha/styles:assets", - ], - visibility = ["//apps/alpha:__subpackages__"], - deps = [ - "//:node_modules/@nextjs-example/one", - "//:node_modules/@types/react", - "//:node_modules/next", - "//:node_modules/react", - "//apps/alpha:node_modules/@types/is-even", - "//apps/alpha:node_modules/is-even", - ], -) +# gazelle:nextjs_pages_root jest_test( - name = "pages_test", + name = "index.test", srcs = ["index.test.tsx"], config = "//apps/alpha:jest.config", data = [ @@ -42,7 +17,7 @@ jest_test( "//:node_modules/react", "//apps/alpha:package_json", ], - snapshots = ["__snapshots__"], + snapshots = ["__snapshots__/index.test.tsx.snap"], visibility = ["//apps/alpha:__subpackages__"], deps = [ ":pages", @@ -52,5 +27,31 @@ jest_test( "//:node_modules/jest-environment-jsdom", "//:node_modules/jest-transform-stub", "//:node_modules/react", + "//apps/alpha/pages/api", + ], +) + +ts_project( + name = "pages", + srcs = [ + "_app.tsx", + "index.tsx", + ], + data = [ + "//:node_modules/@nextjs-example/one", + "//:node_modules/next", + "//:node_modules/react", + "//apps/alpha:node_modules/is-even", + "//apps/alpha/styles:assets", + ], + visibility = ["//apps/alpha:__subpackages__"], + deps = [ + "//:node_modules/@nextjs-example/one", + "//:node_modules/@types/react", + "//:node_modules/next", + "//:node_modules/react", + "//apps/alpha:node_modules/@types/is-even", + "//apps/alpha:node_modules/is-even", + "//apps/alpha/pages/api", ], ) diff --git a/examples/nextjs/apps/alpha/pages/api/BUILD.bazel b/examples/nextjs/apps/alpha/pages/api/BUILD.bazel new file mode 100644 index 0000000..6dec4a6 --- /dev/null +++ b/examples/nextjs/apps/alpha/pages/api/BUILD.bazel @@ -0,0 +1,9 @@ +load("//bazel:ts_project.bzl", "ts_project") + +ts_project( + name = "api", + srcs = ["hello.ts"], + data = ["//:node_modules/next"], + visibility = ["//apps/alpha:__subpackages__"], + deps = ["//:node_modules/next"], +) diff --git a/gazelle/configure.go b/gazelle/configure.go index ba816c5..280b065 100644 --- a/gazelle/configure.go +++ b/gazelle/configure.go @@ -66,11 +66,16 @@ type JsConfig struct { CollectWebAssets bool CollectAllAssets bool CollectedAssets map[string]bool + CollectPages bool + CollectedPages map[string]bool + CollectPageFiles bool + CollectedPageFiles map[string]bool CollectAll bool CollectAllRoot string CollectAllSources map[string]bool Fix bool JSRoot string + NextPagesRoot string WebAssetSuffixes map[string]bool Quiet bool Verbose bool @@ -97,21 +102,26 @@ func NewJsConfig() *JsConfig { Visibility: Visibility{ Labels: []string{}, }, - CollectBarrels: false, - CollectWebAssets: false, - CollectAllAssets: false, - CollectedAssets: make(map[string]bool), - CollectAll: false, - CollectAllRoot: "", - CollectAllSources: make(map[string]bool), - Fix: false, - JSRoot: "/", - WebAssetSuffixes: make(map[string]bool), - Quiet: false, - Verbose: false, - DefaultNpmLabel: "//:node_modules/", - JestTestsPerShard: -1, - JestConfig: "", + CollectBarrels: false, + CollectWebAssets: false, + CollectAllAssets: false, + CollectedAssets: make(map[string]bool), + CollectPages: false, + CollectedPages: make(map[string]bool), + CollectPageFiles: false, + CollectedPageFiles: make(map[string]bool), + CollectAll: false, + CollectAllRoot: "", + CollectAllSources: make(map[string]bool), + Fix: false, + JSRoot: "/", + NextPagesRoot: "", + WebAssetSuffixes: make(map[string]bool), + Quiet: false, + Verbose: false, + DefaultNpmLabel: "//:node_modules/", + JestTestsPerShard: -1, + JestConfig: "", } } @@ -159,6 +169,14 @@ func (parent *JsConfig) NewChild() *JsConfig { child.CollectAllAssets = parent.CollectAllAssets child.CollectedAssets = parent.CollectedAssets // Reinitialized on change to JSRoot + child.NextPagesRoot = parent.NextPagesRoot + if parent.CollectPages { // If the parent is collecting pages, the child should collect page files + child.CollectPages = false + child.CollectPageFiles = true + child.CollectedPages = parent.CollectedPages + child.CollectedPageFiles = make(map[string]bool) + } + child.CollectAll = parent.CollectAll child.CollectAllRoot = parent.CollectAllRoot child.CollectAllSources = parent.CollectAllSources // Copy reference, reinitialized on change to CollectAll @@ -223,6 +241,7 @@ func (*JS) KnownDirectives() []string { return []string{ "js_extension", "js_root", + "nextjs_pages_root", "js_lookup_types", "js_fix", "js_package_file", @@ -286,7 +305,7 @@ func (*JS) Configure(c *config.Config, rel string, f *rule.File) { case "disabled": jsConfig.Enabled = false default: - log.Fatalf(Err("failed to read directive %s: %s, only \"enabled\", and \"disabled\" are valid", directive.Key, directive.Value)) + log.Fatal(Err("failed to read directive %s: %s, only \"enabled\", and \"disabled\" are valid", directive.Key, directive.Value)) } case "js_lookup_types": @@ -298,7 +317,7 @@ func (*JS) Configure(c *config.Config, rel string, f *rule.File) { case "js_package_file": values := strings.Split(directive.Value, " ") if len(values) != 2 { - log.Fatalf(Err("failed to read directive %s: %s, expected 2 values", directive.Key, directive.Value)) + log.Fatal(Err("failed to read directive %s: %s, expected 2 values", directive.Key, directive.Value)) } jsConfig.PackageFile = values[0] npmLabel := values[1] @@ -311,7 +330,7 @@ func (*JS) Configure(c *config.Config, rel string, f *rule.File) { data, err := os.ReadFile(path.Join(c.RepoRoot, f.Pkg, jsConfig.PackageFile)) if err != nil { - log.Fatalf(Err("failed to open %s: %v", directive.Value, err)) + log.Fatal(Err("failed to open %s: %v", directive.Value, err)) } // Read dependencies from file @@ -323,14 +342,14 @@ func (*JS) Configure(c *config.Config, rel string, f *rule.File) { DevDependencies: make(map[string]string), } if err := json.Unmarshal(data, &newDeps); err != nil { - log.Fatalf(Err("failed to parse %s: %v", directive.Value, err)) + log.Fatal(Err("failed to parse %s: %v", directive.Value, err)) } // Store npmLabel in dependencies - for k, _ := range newDeps.Dependencies { + for k := range newDeps.Dependencies { jsConfig.NpmDependencies.Dependencies[k] = npmLabel } - for k, _ := range newDeps.DevDependencies { + for k := range newDeps.DevDependencies { jsConfig.NpmDependencies.DevDependencies[k] = npmLabel } @@ -346,7 +365,7 @@ func (*JS) Configure(c *config.Config, rel string, f *rule.File) { var err error if jsConfig.ImportAliasPattern, err = regexp.Compile(strings.Join(keyPatterns, "|")); err != nil { - log.Fatalf(Err("failed to parse %s: %v", directive.Value, err)) + log.Fatal(Err("failed to parse %s: %v", directive.Value, err)) } case "js_visibility": @@ -360,12 +379,23 @@ func (*JS) Configure(c *config.Config, rel string, f *rule.File) { case "js_root": jSRoot, err := filepath.Rel(".", f.Pkg) if err != nil { - log.Fatalf(Err("failed to read directive %s: %v", directive.Key, err)) + log.Fatal(Err("failed to read directive %s: %v", directive.Key, err)) } else { jsConfig.JSRoot = jSRoot jsConfig.CollectedAssets = make(map[string]bool) } + case "nextjs_pages_root": + nextPagesRoot, err := filepath.Rel(".", f.Pkg) + if err != nil { + log.Fatal(Err("failed to read directive %s: %v", directive.Key, err)) + } else { + jsConfig.NextPagesRoot = nextPagesRoot + jsConfig.CollectPages = true + jsConfig.CollectedPages = make(map[string]bool) + jsConfig.CollectPageFiles = false + } + case "js_collect_barrels": jsConfig.CollectBarrels = readBoolDirective(directive) @@ -387,7 +417,7 @@ func (*JS) Configure(c *config.Config, rel string, f *rule.File) { case "js_collect_all": collectRoot, err := filepath.Rel(".", f.Pkg) if err != nil { - log.Fatalf(Err("failed to read directive %s: %v", directive.Key, err)) + log.Fatal(Err("failed to read directive %s: %v", directive.Key, err)) } else { jsConfig.CollectAllRoot = collectRoot jsConfig.CollectAll = true @@ -410,7 +440,7 @@ func (*JS) Configure(c *config.Config, rel string, f *rule.File) { if len(vals) > 1 { val, err := strconv.ParseBool(directive.Value) if err != nil { - log.Fatalf(Err("failed to read directive %s: %v", directive.Key, err)) + log.Fatal(Err("failed to read directive %s: %v", directive.Key, err)) } status = val } @@ -516,7 +546,7 @@ func readBoolDirective(directive rule.Directive) bool { } else { val, err := strconv.ParseBool(directive.Value) if err != nil { - log.Fatalf(Err("failed to read directive %s: %v", directive.Key, err)) + log.Fatal(Err("failed to read directive %s: %v", directive.Key, err)) } return val } @@ -528,7 +558,7 @@ func readIntDirective(directive rule.Directive) int { } else { val, err := strconv.ParseInt(directive.Value, 10, 32) if err != nil { - log.Fatalf(Err("failed to read directive %s: %v", directive.Key, err)) + log.Fatal(Err("failed to read directive %s: %v", directive.Key, err)) } return int(val) } diff --git a/gazelle/generate.go b/gazelle/generate.go index 2e2e07f..607c00d 100644 --- a/gazelle/generate.go +++ b/gazelle/generate.go @@ -128,19 +128,35 @@ func (lang *JS) GenerateRules(args language.GenerateArgs) language.GenerateResul return language.GenerateResult{} } + if jsConfig.CollectPageFiles { + + var pagesDepth = len(strings.Split(jsConfig.NextPagesRoot, "/")) + var selfDepth = len(strings.Split(args.Rel, "/")) + + if pagesDepth+2 < selfDepth { + // if we are at more than one level deeper, then collect all files for the page + for _, fileName := range args.RegularFiles { + path := strings.TrimPrefix( + strings.TrimPrefix( + path.Join(args.Rel, fileName), + jsConfig.NextPagesRoot, + ), + "/", + ) + jsConfig.CollectedPages[path] = true + } + return language.GenerateResult{} + } + } + pkgName := PkgName(args.Rel) generatedRules := make([]*rule.Rule, 0) generatedImports := make([]interface{}, 0) - var jestSources, - tsSources, - jsSources, - webAssetsSet, - isBarrel, - isJSRoot = lang.collectSources(args, jsConfig) + var sources = lang.collectSources(args, jsConfig) - if !jsConfig.Quiet && isBarrel && len(tsSources) > 0 && len(jsSources) > 0 { + if !jsConfig.Quiet && sources.isBarrel && len(sources.tsSources) > 0 && len(sources.jsSources) > 0 { log.Print(Warn("[WARN] ts and js files mixed in package %s", pkgName)) } @@ -152,41 +168,88 @@ func (lang *JS) GenerateRules(args language.GenerateArgs) language.GenerateResul } // add "jest_test" rule(s) - generatedTestRules, generatedTestImports := lang.genJestTest(args, jsConfig, jestSources) + generatedTestRules, generatedTestImports := lang.genJestTest(args, jsConfig, sources.jestSources) generatedRules = append(generatedRules, generatedTestRules...) generatedImports = append(generatedImports, generatedTestImports...) - appendTSExt := len(jsSources) > 0 + appendTSExt := len(sources.jsSources) > 0 + + absJSRoot := path.Join(args.Config.RepoRoot, jsConfig.JSRoot) + isJSRoot := absJSRoot == args.Dir - if len(jsSources) > 0 && jsConfig.CollectAll { + if len(sources.jsSources) > 0 && jsConfig.CollectAll { // add combined "ts_project" rule with js sources - generatedTSRules, generatedTSImports := lang.genRules(args, jsConfig, isBarrel, isJSRoot, pkgName, append(tsSources, jsSources...), false, "ts_project") + generatedTSRules, generatedTSImports := lang.genRules( + args, + jsConfig, + sources.isBarrel, + isJSRoot, + pkgName, + append(sources.tsSources, sources.jsSources...), + false, + "ts_project", + ) generatedRules = append(generatedRules, generatedTSRules...) generatedImports = append(generatedImports, generatedTSImports...) } else { // add "ts_project" rule(s) - generatedTSRules, generatedTSImports := lang.genRules(args, jsConfig, isBarrel, isJSRoot, pkgName, tsSources, appendTSExt, "ts_project") + generatedTSRules, generatedTSImports := lang.genRules( + args, + jsConfig, + sources.isBarrel, + isJSRoot, + pkgName, + sources.tsSources, + appendTSExt, + "ts_project", + ) generatedRules = append(generatedRules, generatedTSRules...) generatedImports = append(generatedImports, generatedTSImports...) // add "js_library" rule(s) appendTSExt = false - generatedJSRules, generatedJSImports := lang.genRules(args, jsConfig, isBarrel, isJSRoot, pkgName, jsSources, appendTSExt, "js_library") + generatedJSRules, generatedJSImports := lang.genRules( + args, + jsConfig, + sources.isBarrel, + isJSRoot, + pkgName, + sources.jsSources, + appendTSExt, + "js_library", + ) generatedRules = append(generatedRules, generatedJSRules...) generatedImports = append(generatedImports, generatedJSImports...) } // add "web_assets" rule(s) - generatedWARules, generatedWAImports := lang.genWebAssets(args, webAssetsSet, jsConfig) + generatedWARules, generatedWAImports := lang.genWebAssets( + args, + sources.webAssetsSet, + jsConfig, + ) generatedRules = append(generatedRules, generatedWARules...) generatedImports = append(generatedImports, generatedWAImports...) // add "all_assets" "web_assets" rule - generatedAWARules, generatedAWAImports := lang.genAllAssets(args, isJSRoot, jsConfig) + generatedAWARules, generatedAWAImports := lang.genAllAssets( + args, + isJSRoot, + jsConfig, + ) generatedRules = append(generatedRules, generatedAWARules...) generatedImports = append(generatedImports, generatedAWAImports...) + generatedTSRules, generatedTSImports := lang.genEmptyPageRule( + args, + jsConfig, + pkgName, + append(sources.tsSources, sources.jsSources...), + ) + generatedRules = append(generatedRules, generatedTSRules...) + generatedImports = append(generatedImports, generatedTSImports...) + existingRules := lang.readExistingRules(args, true) lang.pruneManagedRules(existingRules, generatedRules) @@ -197,7 +260,15 @@ func (lang *JS) GenerateRules(args language.GenerateArgs) language.GenerateResul } } -func (lang *JS) collectSources(args language.GenerateArgs, jsConfig *JsConfig) ([]string, []string, []string, map[string]bool, bool, bool) { +type collectedSources struct { + jestSources []string + tsSources []string + jsSources []string + webAssetsSet map[string]bool + isBarrel bool +} + +func (lang *JS) collectSources(args language.GenerateArgs, jsConfig *JsConfig) collectedSources { managedFiles := make(map[string]bool) jestSources := []string{} @@ -207,9 +278,6 @@ func (lang *JS) collectSources(args language.GenerateArgs, jsConfig *JsConfig) ( isBarrel := false - absJSRoot := path.Join(args.Config.RepoRoot, jsConfig.JSRoot) - isJSRoot := absJSRoot == args.Dir - for _, baseName := range lang.gatherFiles(args, jsConfig) { alwaysIgnoredFiles := map[string]bool{ @@ -256,12 +324,13 @@ func (lang *JS) collectSources(args language.GenerateArgs, jsConfig *JsConfig) ( } - return jestSources, - tsSources, - jsSources, - webAssetsSet, - isBarrel, - isJSRoot + return collectedSources{ + jestSources: jestSources, + tsSources: tsSources, + jsSources: jsSources, + webAssetsSet: webAssetsSet, + isBarrel: isBarrel, + } } func (lang *JS) isWebAsset(jsConfig *JsConfig, baseName string) bool { @@ -276,7 +345,12 @@ func (lang *JS) isWebAsset(jsConfig *JsConfig, baseName string) bool { func (lang *JS) gatherFiles(args language.GenerateArgs, jsConfig *JsConfig) []string { allFiles := args.RegularFiles if jsConfig.CollectAll { - for file, _ := range jsConfig.CollectAllSources { + for file := range jsConfig.CollectAllSources { + allFiles = append(allFiles, file) + } + } + if jsConfig.CollectPageFiles { + for file := range jsConfig.CollectedPageFiles { allFiles = append(allFiles, file) } } @@ -297,11 +371,11 @@ func readFileAndParse(filePath string, rel string) (*imports, int) { data, err := os.ReadFile(filePath) if err != nil { - log.Fatalf(Err("Error reading %s: %v", filePath, err)) + log.Fatal(Err("Error reading %s: %v", filePath, err)) } jsImports, testCount, err := ParseJS(data) if err != nil { - log.Fatalf(Err("Error parsing %s: %v", filePath, err)) + log.Fatal(Err("Error parsing %s: %v", filePath, err)) } for _, imp := range jsImports { if rel != "" && strings.HasPrefix(imp, ".") { @@ -394,13 +468,6 @@ func (lang *JS) genJestTest(args language.GenerateArgs, jsConfig *JsConfig, jest return generatedRules, generatedImports } -type testRuleArgs struct { - ruleType string - extension string - filePath string - baseName string -} - func (lang *JS) addJestAttributes(args language.GenerateArgs, jsConfig *JsConfig, baseName string, r *rule.Rule, jestTestCount int, collectedSnapshots []string) { if jsConfig.JestConfig == "" && !jsConfig.Quiet { log.Print(Warn("[%s/%s] no config for jest_test, use gazelle:js_jest_config directive", args.Rel, baseName)) @@ -449,7 +516,7 @@ func (lang *JS) genRules(args language.GenerateArgs, jsConfig *JsConfig, isBarre if appendTSExt { name = name + "_ts" } - if jsConfig.CollectAll { + if jsConfig.CollectAll || jsConfig.CollectPages || jsConfig.CollectPageFiles { // add as a folder for _, existingRule := range lang.readExistingRules(args, false) { // Look for existing rules with the same name, but different kind @@ -469,6 +536,12 @@ func (lang *JS) genRules(args language.GenerateArgs, jsConfig *JsConfig, isBarre srcs: sources, imports: imports, }, jsConfig) + + if jsConfig.CollectPageFiles { + // record this rule as a page + fqName := fmt.Sprintf("//%s:%s", path.Join(args.Rel), name) + jsConfig.CollectedPages[fqName] = true + } generatedRules = append(generatedRules, folderRule) generatedImports = append(generatedImports, folderImports) @@ -562,7 +635,7 @@ func (lang *JS) makeModuleRules(args moduleRuleArgs, jsConfig *JsConfig) ([]*imp // which, if it's local, transitively belongs in the moduleSet recAddTransitiveSet := func(src string) { // for each import that the source file has - for imp, _ := range moduleSet[src].set { + for imp := range moduleSet[src].set { // if that import is local to this directory if isLocalImport(args.cwd, imp) { // check the remainderSet to see if the src file corresponding to the import @@ -606,7 +679,7 @@ func (lang *JS) makeModuleRules(args moduleRuleArgs, jsConfig *JsConfig) ([]*imp remainderSrcs := make([]string, 0) remainderImportsList := make([]imports, 0) keys := make([]string, 0) - for k, _ := range remainderSet { + for k := range remainderSet { keys = append(keys, k) } sort.Strings(keys) @@ -765,6 +838,22 @@ func (lang *JS) genAllAssets(args language.GenerateArgs, isJSRoot bool, jsConfig return generatedRules, generatedImports } +func (lang *JS) genEmptyPageRule(args language.GenerateArgs, jsConfig *JsConfig, pkgName string, sources []string) ([]*rule.Rule, []interface{}) { + generatedRules := make([]*rule.Rule, 0) + generatedImports := make([]interface{}, 0) + + if len(sources) == 0 && jsConfig.CollectPages { + + // Add an empty `js_library` rule. This will be given `deps` later in resolve.go + r := rule.NewRule(getKind(args.Config, "js_library"), pkgName) + + generatedRules = append(generatedRules, r) + generatedImports = append(generatedImports, &noImports) + } + + return generatedRules, generatedImports +} + func (lang *JS) readExistingRules(args language.GenerateArgs, managedOnly bool) map[string]*rule.Rule { existingRules := make(map[string]*rule.Rule) diff --git a/gazelle/resolve.go b/gazelle/resolve.go index 55ddb90..c1d762b 100644 --- a/gazelle/resolve.go +++ b/gazelle/resolve.go @@ -128,7 +128,7 @@ func (lang *JS) Imports(c *config.Config, r *rule.Rule, f *rule.File) []resolve. dir := filepath.Dir(src) subDirectories[dir] = true } - for subDirectory, _ := range subDirectories { + for subDirectory := range subDirectories { root := strings.TrimSuffix(base, f.Pkg) relPath := strings.TrimPrefix(subDirectory, root) path := fmt.Sprintf("%s/%s", f.Pkg, relPath) @@ -282,6 +282,13 @@ func (lang *JS) Resolve(c *config.Config, ix *resolve.RuleIndex, rc *repo.Remote dataSet[fmt.Sprintf("//%s:package_json", packageLocation)] = true } + // Add in page dependencies if they exist + if jsConfig.CollectPages && len(jsConfig.CollectedPages) > 0 { + for fqName := range jsConfig.CollectedPages { + depSet[fqName] = true + } + } + deps := []string{} for dep := range depSet { deps = append(deps, dep) diff --git a/go.mod b/go.mod index 063f2b9..5ea1e43 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/bazelbuild/rules_python -go 1.19 +go 1.21 + +toolchain go1.23.2 require ( github.com/bazelbuild/bazel-gazelle v0.34.0 diff --git a/go.sum b/go.sum index 401a761..6c64912 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/bazelbuild/bazel-gazelle v0.33.0/go.mod h1:6BWjSqjc2gr7YfzMRCbkHiJZy5YRxIKj7iLButu58Jk= github.com/bazelbuild/bazel-gazelle v0.34.0 h1:YHkwssgvCXDRU7sLCq1kGqaGYO9pKNR1Wku7UT2LhoY= github.com/bazelbuild/bazel-gazelle v0.34.0/go.mod h1:3wXzAC5rTs8eTQ+t+eTqleUE9W4dDComgXgqDjnI5s4= -github.com/bazelbuild/buildtools v0.0.0-20230831140646-386244e73fc4 h1:6Z/4LXt5mdhuFAx4QhwM0D5pTs1ljYGmhgF3O9OCMF0= -github.com/bazelbuild/buildtools v0.0.0-20230831140646-386244e73fc4/go.mod h1:689QdV3hBP7Vo9dJMmzhoYIyo/9iMhEmHkJcnaPRCbo= github.com/bazelbuild/buildtools v0.0.0-20231017121127-23aa65d4e117 h1:VUHCI4QRifAGYsbVJYqJndLf7YqV12YthB+PLFsEKqo= github.com/bazelbuild/buildtools v0.0.0-20231017121127-23aa65d4e117/go.mod h1:689QdV3hBP7Vo9dJMmzhoYIyo/9iMhEmHkJcnaPRCbo= github.com/bazelbuild/rules_go v0.42.0 h1:aY2smc3JWyUKOjGYmOKVLX70fPK9ON0rtwQojuIeUHc= diff --git a/tests/BUILD b/tests/BUILD index 01457a7..2743f26 100644 --- a/tests/BUILD +++ b/tests/BUILD @@ -49,6 +49,7 @@ go_binary( "collect_all_test_shards", "collect_asset_modules", "collect_asset_singletons", + "collect_pages", "default_npm_label", "disabled", "disjoint_module", diff --git a/tests/collect_pages/BUILD.in b/tests/collect_pages/BUILD.in new file mode 100644 index 0000000..922c5ff --- /dev/null +++ b/tests/collect_pages/BUILD.in @@ -0,0 +1,13 @@ +load("@aspect_rules_ts//ts:defs.bzl", "ts_project") + +# gazelle:js_root +# gazelle:js_verbose + +ts_project( + name = "index", + srcs = ["index.ts"], + deps = [ + "//src/pages", # keep + "//src/pages2", # keep + ], +) diff --git a/tests/collect_pages/BUILD.out b/tests/collect_pages/BUILD.out new file mode 100644 index 0000000..922c5ff --- /dev/null +++ b/tests/collect_pages/BUILD.out @@ -0,0 +1,13 @@ +load("@aspect_rules_ts//ts:defs.bzl", "ts_project") + +# gazelle:js_root +# gazelle:js_verbose + +ts_project( + name = "index", + srcs = ["index.ts"], + deps = [ + "//src/pages", # keep + "//src/pages2", # keep + ], +) diff --git a/tests/collect_pages/WORKSPACE b/tests/collect_pages/WORKSPACE new file mode 100644 index 0000000..ed7beb4 --- /dev/null +++ b/tests/collect_pages/WORKSPACE @@ -0,0 +1 @@ +workspace(name = "simple_module") diff --git a/tests/collect_pages/index.ts b/tests/collect_pages/index.ts new file mode 100644 index 0000000..4a15097 --- /dev/null +++ b/tests/collect_pages/index.ts @@ -0,0 +1 @@ +var _ = "index"; diff --git a/tests/collect_pages/src/pages/404.ts b/tests/collect_pages/src/pages/404.ts new file mode 100644 index 0000000..797190f --- /dev/null +++ b/tests/collect_pages/src/pages/404.ts @@ -0,0 +1 @@ +export var some_private_var = "Hello" diff --git a/tests/collect_pages/src/pages/BUILD.in b/tests/collect_pages/src/pages/BUILD.in new file mode 100644 index 0000000..047ea93 --- /dev/null +++ b/tests/collect_pages/src/pages/BUILD.in @@ -0,0 +1 @@ +# gazelle:nextjs_pages_root diff --git a/tests/collect_pages/src/pages/BUILD.out b/tests/collect_pages/src/pages/BUILD.out new file mode 100644 index 0000000..7590b22 --- /dev/null +++ b/tests/collect_pages/src/pages/BUILD.out @@ -0,0 +1,12 @@ +load("@aspect_rules_ts//ts:defs.bzl", "ts_project") + +# gazelle:nextjs_pages_root + +ts_project( + name = "pages", + srcs = [ + "404.ts", + "index.ts", + ], + deps = ["//src/pages/my_page"], +) diff --git a/tests/collect_pages/src/pages/index.ts b/tests/collect_pages/src/pages/index.ts new file mode 100644 index 0000000..91610f6 --- /dev/null +++ b/tests/collect_pages/src/pages/index.ts @@ -0,0 +1 @@ +export var some_private_var = "Index" diff --git a/tests/collect_pages/src/pages/my_page/BUILD.in b/tests/collect_pages/src/pages/my_page/BUILD.in new file mode 100644 index 0000000..e69de29 diff --git a/tests/collect_pages/src/pages/my_page/BUILD.out b/tests/collect_pages/src/pages/my_page/BUILD.out new file mode 100644 index 0000000..8ea55d8 --- /dev/null +++ b/tests/collect_pages/src/pages/my_page/BUILD.out @@ -0,0 +1,9 @@ +load("@aspect_rules_ts//ts:defs.bzl", "ts_project") + +ts_project( + name = "my_page", + srcs = [ + "index.ts", + "module_file.ts", + ], +) diff --git a/tests/collect_pages/src/pages/my_page/index.ts b/tests/collect_pages/src/pages/my_page/index.ts new file mode 100644 index 0000000..5b6309c --- /dev/null +++ b/tests/collect_pages/src/pages/my_page/index.ts @@ -0,0 +1 @@ +export { some_private_var as some_var } from "./module_file" diff --git a/tests/collect_pages/src/pages/my_page/module_file.ts b/tests/collect_pages/src/pages/my_page/module_file.ts new file mode 100644 index 0000000..797190f --- /dev/null +++ b/tests/collect_pages/src/pages/my_page/module_file.ts @@ -0,0 +1 @@ +export var some_private_var = "Hello" diff --git a/tests/collect_pages/src/pages2/BUILD.in b/tests/collect_pages/src/pages2/BUILD.in new file mode 100644 index 0000000..047ea93 --- /dev/null +++ b/tests/collect_pages/src/pages2/BUILD.in @@ -0,0 +1 @@ +# gazelle:nextjs_pages_root diff --git a/tests/collect_pages/src/pages2/BUILD.out b/tests/collect_pages/src/pages2/BUILD.out new file mode 100644 index 0000000..c54fcb7 --- /dev/null +++ b/tests/collect_pages/src/pages2/BUILD.out @@ -0,0 +1,8 @@ +load("@aspect_rules_js//js:defs.bzl", "js_library") + +# gazelle:nextjs_pages_root + +js_library( + name = "pages2", + deps = ["//src/pages2/my_page"], +) diff --git a/tests/collect_pages/src/pages2/my_page/BUILD.in b/tests/collect_pages/src/pages2/my_page/BUILD.in new file mode 100644 index 0000000..e69de29 diff --git a/tests/collect_pages/src/pages2/my_page/BUILD.out b/tests/collect_pages/src/pages2/my_page/BUILD.out new file mode 100644 index 0000000..8ea55d8 --- /dev/null +++ b/tests/collect_pages/src/pages2/my_page/BUILD.out @@ -0,0 +1,9 @@ +load("@aspect_rules_ts//ts:defs.bzl", "ts_project") + +ts_project( + name = "my_page", + srcs = [ + "index.ts", + "module_file.ts", + ], +) diff --git a/tests/collect_pages/src/pages2/my_page/index.ts b/tests/collect_pages/src/pages2/my_page/index.ts new file mode 100644 index 0000000..5b6309c --- /dev/null +++ b/tests/collect_pages/src/pages2/my_page/index.ts @@ -0,0 +1 @@ +export { some_private_var as some_var } from "./module_file" diff --git a/tests/collect_pages/src/pages2/my_page/module_file.ts b/tests/collect_pages/src/pages2/my_page/module_file.ts new file mode 100644 index 0000000..797190f --- /dev/null +++ b/tests/collect_pages/src/pages2/my_page/module_file.ts @@ -0,0 +1 @@ +export var some_private_var = "Hello" diff --git a/tests/test_runner.go b/tests/test_runner.go index 6de6b06..ab46423 100644 --- a/tests/test_runner.go +++ b/tests/test_runner.go @@ -32,7 +32,7 @@ func main() { // Wrap test with InternalTest so that it can be run by testing.Main theTest := testing.InternalTest{ - Name: fmt.Sprintf("example_%s", name), + Name: fmt.Sprintf("test_%s", name), F: func(t *testing.T) { RunTest(t, name) }, } @@ -90,7 +90,7 @@ func RunTest(t *testing.T, name string) { // Read file contents content, err := os.ReadFile(f.Path) if err != nil { - t.Errorf("ioutil.ReadFile(%q) error: %v", f.Path, err) + t.Errorf("os.ReadFile(%q) error: %v", f.Path, err) } // Add file to inputs or goldens