Skip to content

Commit

Permalink
Add SemanticDB Provider
Browse files Browse the repository at this point in the history
  • Loading branch information
pcj committed Sep 26, 2024
1 parent 3df1813 commit 4cb22d2
Show file tree
Hide file tree
Showing 86 changed files with 10,830 additions and 428 deletions.
24 changes: 23 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,28 @@ scalacache_protos:
mv build/stack/gazelle/scala/cache/build/stack/gazelle/scala/cache/*.go build/stack/gazelle/scala/cache/
rm -rf build/stack/gazelle/scala/cache/build

.PHONY: scalapb_protos
scalapb_protos:
bazel run //scalapb:scalapb_go_compiled_sources.update
mv scalapb/scalapb/scalapb.pb.go scalapb/scalapb.pb.go
rm -rf scalapb/scalapb

.PHONY: semanticdb_protos
semanticdb_protos:
bazel run //scala/meta/semanticdb:semanticdb_go_compiled_sources.update
mv scala/meta/semanticdb/scala/meta/semanticdb/semanticdb.pb.go scala/meta/semanticdb/semanticdb.pb.go
rm -rf scala/meta/semanticdb/scala

.PHONY: protos
protos: jarindex_protos parser_protos scalacache_protos
protos: jarindex_protos parser_protos scalacache_protos scalapb_protos semanticdb_protos
echo "Done."

.PHONY: docs
docs:
bazel build //docs/architecture:all
cp -f bazel-bin/docs/architecture/components.png docs/architecture
cp -f bazel-bin/docs/architecture/sequence.png docs/architecture

.PHONY: tidy
gazelle:
bazel run //:gazelle
Expand All @@ -55,5 +73,9 @@ mocks:
.PHONY: gen
gen: mocks protos

.PHONY: goldens
goldens:
bazel run //pkg/semanticdb:semanticdb_test -- -update

update_provider_test_golden_files:
bazel run pkg/provider:provider_test -- -update
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -472,8 +472,8 @@ func (p *bazelDepsProvider) loadFile(dir string, filename string, scope resolver
}

// CanProvide implements part of the resolver.SymbolProvider interface.
func (p *bazelDepsProvider) CanProvide(dep label.Label, knownRule func(from label.Label) (*rule.Rule, bool)) bool {
if dep.Repo == "bazel_deps" {
func (p *bazelDepsProvider) CanProvide(dep *resolver.ImportLabel, knownRule func(from label.Label) (*rule.Rule, bool)) bool {
if dep.Label.Repo == "bazel_deps" {
return true
}
return false
Expand Down Expand Up @@ -934,10 +934,10 @@ Generates:
```bazel
scala_binary(
name = "app",
# deps: ❌ AbstractServiceBase<ERROR> symbol not found (EXTENDS of foo.allocation.Main)
# deps: ✅ akka.NotUsed<CLASS> @maven//:com_typesafe_akka_akka_actor_2_12<jarindex> (DIRECT of BusinessFlows.scala)
# deps: ✅ java.time.format.DateTimeFormatter<CLASS> NO-LABEL<java> (DIRECT of RequestHandler.scala)
# deps: ✅ scala.concurrent.ExecutionContext<PACKAGE> @maven//:org_scala_lang_scala_library<maven> (DIRECT of RequestHandler.scala)
# import: ❌ AbstractServiceBase<ERROR> symbol not found (EXTENDS of foo.allocation.Main)
# import: ✅ akka.NotUsed<CLASS> @maven//:com_typesafe_akka_akka_actor_2_12<jarindex> (DIRECT of BusinessFlows.scala)
# import: ✅ java.time.format.DateTimeFormatter<CLASS> NO-LABEL<java> (DIRECT of RequestHandler.scala)
# import: ✅ scala.concurrent.ExecutionContext<PACKAGE> @maven//:org_scala_lang_scala_library<maven> (DIRECT of RequestHandler.scala)
srcs = glob(["src/main/**/*.scala"]),
main_class = "foo.allocation.Main",
)
Expand Down
210 changes: 143 additions & 67 deletions build/stack/gazelle/scala/parse/file.pb.go

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion build/stack/gazelle/scala/parse/file.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ option go_package = "github.com/stackb/scala-gazelle/build/stack/gazelle/scala/p
option java_package = "build.stack.gazelle.scala.parse";
option java_multiple_files = true;

// FileSet represents a set of Files
message FileSet {
repeated File files = 1;
}

// File represents a parsed file named in a scala rule.srcs list.
// next: 2 (was sha256, can be re-used)
message File {
// filename is the (relative) source filename
string filename = 1;
// semantic_imports is a list of types used by the file, typically
// discovered using semanticdb.
repeated string semantic_imports = 2;
// imports is a list of required imports.
repeated string imports = 3;
// packages is a list of provided top-level classes.
Expand Down
36 changes: 20 additions & 16 deletions build/stack/gazelle/scala/parse/import.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions build/stack/gazelle/scala/parse/import.proto
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,6 @@ enum ImportKind {
// An import required as a transitive dependency of some direct/initial
// dependency.
TRANSITIVE = 6;
// An import that was derived from the semanticdb type list for the file.option
SEMANTIC = 7;
}
2 changes: 1 addition & 1 deletion cmd/mergeindex/mergeindex.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func readParamsFile(filename string) ([]string, error) {
}

func parseFlags(args []string) (files []string, err error) {
fs := flag.NewFlagSet("mergeindex", flag.ExitOnError) // flag.ContinueOnError
fs := flag.NewFlagSet("mergeindex", flag.ExitOnError)
fs.StringVar(&predefinedLabels, "predefined", "", "a comma-separated list of labels to be considered predefined")
fs.StringVar(&outputFile, "output_file", "", "the output file to write")
fs.Usage = func() {
Expand Down
20 changes: 20 additions & 0 deletions cmd/semanticdbextract/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")

go_library(
name = "semanticdbextract_lib",
srcs = ["semanticdbextract.go"],
importpath = "github.com/stackb/scala-gazelle/cmd/semanticdbextract",
visibility = ["//visibility:private"],
deps = [
"//pkg/collections",
"//pkg/protobuf",
"//pkg/semanticdb",
"//scala/meta/semanticdb",
],
)

go_binary(
name = "semanticdbextract",
embed = [":semanticdbextract_lib"],
visibility = ["//visibility:public"],
)
110 changes: 110 additions & 0 deletions cmd/semanticdbextract/semanticdbextract.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package main

import (
"flag"
"fmt"
"log"
"os"
"sort"

"github.com/stackb/scala-gazelle/pkg/collections"
"github.com/stackb/scala-gazelle/pkg/protobuf"
"github.com/stackb/scala-gazelle/pkg/semanticdb"

spb "github.com/stackb/scala-gazelle/scala/meta/semanticdb"
)

var (
jarFile string
outputFile string
)

func main() {
log.SetPrefix("semanticdbextract: ")
log.SetFlags(0) // don't print timestamps

if err := run(os.Args[1:]); err != nil {
log.Fatal(err)
}
}

func run(args []string) error {
args, err := collections.ReadArgsParamsFile(args)
if err != nil {
return fmt.Errorf("failed to read params file: %v", err)
}

err = parseFlags(args)
if err != nil {
return fmt.Errorf("failed to parse args: %v", err)
}

doc, err := extract(jarFile)
if err != nil {
return fmt.Errorf("failed to merge files: %v", err)
}

if err := protobuf.WriteStableJSONFile(outputFile, doc); err != nil {
return fmt.Errorf("failed to write output file: %v", err)
}

return nil
}

func parseFlags(args []string) (err error) {
fs := flag.NewFlagSet("semanticdbextract", flag.ExitOnError)
fs.StringVar(&jarFile, "jar_file", "", "the jar file to read")
fs.StringVar(&outputFile, "output_file", "", "the output file to write")
fs.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "usage: semanticdbextract @PARAMS_FILE | semanticdbextract OPTIONS")
fs.PrintDefaults()
}
if err = fs.Parse(args); err != nil {
return err
}

if jarFile == "" {
log.Fatal("-jar_file is required")
}
if outputFile == "" {
log.Fatal("-output_file is required")
}

files := fs.Args()
if len(files) != 0 {
err = fmt.Errorf("semanticdbextract positional args should be empty")
}

return
}

func extract(filename string) (*spb.TextDocuments, error) {
docs := new(spb.TextDocuments)
seen := make(map[string]bool)

addDocument := func(doc *spb.TextDocument) {
if seen[doc.Uri] {
return
}
seen[doc.Uri] = true
docs.Documents = append(docs.Documents, doc)
}

group, err := semanticdb.ReadJarFile(filename)
if err != nil {
return nil, err
}
for _, docs := range group {
for _, doc := range docs.Documents {
addDocument(doc)
}
}

sort.Slice(docs.Documents, func(i, j int) bool {
a := docs.Documents[i].Uri
b := docs.Documents[j].Uri
return a < b
})

return docs, nil
}
21 changes: 21 additions & 0 deletions cmd/semanticdbmerge/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")

go_library(
name = "semanticdbmerge_lib",
srcs = ["semanticdbmerge.go"],
importpath = "github.com/stackb/scala-gazelle/cmd/semanticdbmerge",
visibility = ["//visibility:private"],
deps = [
"//build/stack/gazelle/scala/parse",
"//pkg/collections",
"//pkg/protobuf",
"//pkg/semanticdb",
"//scala/meta/semanticdb",
],
)

go_binary(
name = "semanticdbmerge",
embed = [":semanticdbmerge_lib"],
visibility = ["//visibility:public"],
)
Loading

0 comments on commit 4cb22d2

Please sign in to comment.