├── .bazelci └── config.yaml ├── .gitignore ├── AUTHORS ├── BUILD ├── CONTRIBUTING.md ├── CONTRIBUTORS ├── LICENSE ├── README.md ├── WORKSPACE ├── bazel ├── BUILD.bazel ├── bazel.go └── bazel_test.go ├── bazeldepsresolver ├── BUILD.bazel ├── bazeldepsresolver.go └── bazeldepsresolver_test.go ├── buildozer ├── BUILD.bazel ├── buildozer.go └── buildozer_test.go ├── cli ├── BUILD.bazel ├── cli.go └── cli_test.go ├── cmd ├── jadep │ ├── BUILD.bazel │ └── jadep.go └── list_classes_in_jar │ ├── BUILD.bazel │ └── list_classes_in_jar.go ├── color ├── BUILD.bazel └── color.go ├── compat ├── BUILD └── compat.go ├── dictresolver ├── BUILD.bazel ├── dictresolver.go └── dictresolver_test.go ├── filter ├── BUILD.bazel ├── filter.go └── filter_test.go ├── flow-sequence.svg ├── fsresolver ├── BUILD.bazel ├── fsresolver.go └── fsresolver_test.go ├── future ├── BUILD.bazel └── future.go ├── graphs ├── BUILD.bazel └── graphs.go ├── grpcloader ├── BUILD ├── grpcloader.go ├── grpcloader_test.go └── mockworkspace_test.go ├── jadep.cast ├── jadeplib ├── BUILD.bazel ├── UserInteractionHandler.go ├── UserInteractionHandler_test.go ├── jadeplib.go └── jadeplib_test.go ├── jadepmain ├── BUILD.bazel ├── customization.go └── jadepmain.go ├── java └── com │ └── google │ └── devtools │ └── javatools │ └── jade │ └── pkgloader │ ├── BUILD │ ├── BazelPackageLoaderFactory.java │ ├── GrpcLocalServer.java │ ├── Lib.java │ ├── OperatingSystem.java │ ├── PackageLoaderFactory.java │ ├── Serializer.java │ ├── messages_proto │ ├── BUILD │ └── messages.proto │ └── services_proto │ ├── BUILD │ └── services.proto ├── javatests └── com │ └── google │ └── devtools │ └── javatools │ └── jade │ └── pkgloader │ ├── BUILD │ ├── BazelPackageLoaderFactoryTest.java │ ├── LibTest.java │ ├── MockWorkspace.java │ └── SerializerTest.java ├── lang └── java │ ├── parser │ ├── BUILD.bazel │ ├── parser.go │ ├── parser_test.go │ └── xrefs │ │ ├── BUILD.bazel │ │ ├── xrefs.go │ │ └── xrefs_test.go │ └── ruleconsts │ ├── BUILD.bazel │ ├── ruleconsts.go │ └── ruleconsts_test.go ├── listclassesinjar ├── BUILD.bazel ├── listclassesinjar.go └── listclassesinjar_test.go ├── loadertest ├── BUILD.bazel └── loadertest.go ├── maven_deps.yaml ├── pkgloaderfakes ├── BUILD.bazel └── pkgloaderfakes.go ├── pkgloading ├── BUILD.bazel ├── pkgloading.go └── pkgloading_test.go ├── resolverutil ├── BUILD.bazel ├── resolverutil.go └── resolverutil_test.go ├── scripts └── pkgloader_server.sh ├── sortingdepsranker ├── BUILD.bazel └── sortingdepsranker.go ├── thirdparty ├── BUILD ├── golang │ └── parsers │ │ ├── ast │ │ ├── BUILD.bazel │ │ └── ast.go │ │ ├── java │ │ ├── BUILD │ │ ├── go_filter.ltp │ │ ├── go_listener.ltp │ │ ├── go_parser.ltp │ │ ├── init.go │ │ └── java.tm │ │ ├── lang │ │ ├── BUILD.bazel │ │ └── lang.proto │ │ ├── node │ │ ├── BUILD.bazel │ │ └── node.go │ │ ├── parsers │ │ ├── BUILD.bazel │ │ └── parsers.go │ │ ├── public │ │ └── token │ │ │ ├── BUILD.bazel │ │ │ └── token.proto │ │ └── util │ │ └── offset │ │ ├── BUILD.bazel │ │ └── offset.go ├── jvm │ ├── args4j │ │ └── BUILD │ ├── com │ │ └── google │ │ │ ├── api │ │ │ └── grpc │ │ │ │ └── BUILD │ │ │ ├── code │ │ │ ├── findbugs │ │ │ │ └── BUILD │ │ │ └── gson │ │ │ │ └── BUILD │ │ │ ├── errorprone │ │ │ └── BUILD │ │ │ ├── guava │ │ │ └── BUILD │ │ │ ├── instrumentation │ │ │ └── BUILD │ │ │ ├── j2objc │ │ │ └── BUILD │ │ │ ├── protobuf │ │ │ └── BUILD │ │ │ └── truth │ │ │ └── BUILD │ ├── io │ │ ├── grpc │ │ │ └── BUILD │ │ ├── netty │ │ │ └── BUILD │ │ └── opencensus │ │ │ └── BUILD │ ├── junit │ │ └── BUILD │ └── org │ │ ├── codehaus │ │ └── mojo │ │ │ └── BUILD │ │ ├── hamcrest │ │ └── BUILD │ │ └── textmapper │ │ └── BUILD └── maven.bzl └── vlog ├── BUILD.bazel └── vlog.go /.bazelci/config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | platforms: 3 | ubuntu1604: 4 | build_targets: 5 | - "//cmd/jadep" 6 | - "//java/com/google/devtools/javatools/jade/pkgloader:GrpcLocalServer_deploy.jar" 7 | - "//:jdk_android_builtin_class_names" 8 | build_flags: 9 | - "--nocheck_visibility" 10 | test_targets: 11 | - "//..." 12 | test_flags: 13 | - "--nocheck_visibility" 14 | macos: 15 | build_targets: 16 | - "//cmd/jadep" 17 | - "//java/com/google/devtools/javatools/jade/pkgloader:GrpcLocalServer_deploy.jar" 18 | - "//:jdk_android_builtin_class_names" 19 | build_flags: 20 | - "--nocheck_visibility" 21 | test_targets: 22 | - "//..." 23 | test_flags: 24 | - "--nocheck_visibility" 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bazel-* 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This the official list of Bazel authors for copyright purposes. 2 | # This file is distinct from the CONTRIBUTORS files. 3 | # See the latter for an explanation. 4 | 5 | # Names should be added to this file as: 6 | # Name or Organization 7 | # The email address is not required for organizations. 8 | 9 | Google Inc. -------------------------------------------------------------------------------- /BUILD: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:def.bzl", "gazelle") 2 | 3 | gazelle( 4 | name = "gazelle", 5 | prefix = "github.com/bazelbuild/tools_jvm_autodeps", 6 | ) 7 | 8 | genrule( 9 | name = "jdk_android_builtin_class_names", 10 | outs = ["jdk_android_builtin_class_names.txt"], 11 | cmd = "$(location //cmd/list_classes_in_jar) $(JAVABASE)/jre/lib/rt.jar > $@", 12 | toolchains = ["@bazel_tools//tools/jdk:current_java_runtime"], 13 | tools = ["//cmd/list_classes_in_jar"], 14 | ) 15 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | 19 | ### Contribution process 20 | 21 | 1. Explain your idea and discuss your plan in a GitHub Issue. 22 | 1. Prepare a git commit with your change. Don't forget to 23 | add tests. 24 | Run the existing tests with `bazel test //...`. 25 | 1. [Create a pull request](https://help.github.com/articles/creating-a-pull-request/). 26 | This will start the code review process. **All submissions, including 27 | submissions by project members, require review.** 28 | 1. You may be asked to make some changes. You'll also need to sign the CLA at 29 | this point, if you haven't done so already. Our continuous integration bots 30 | will test your change automatically on supported platforms. Once everything 31 | looks good, your change will be merged. 32 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # People who have agreed to one of the CLAs and can contribute patches. 2 | # The AUTHORS file lists the copyright holders; this file 3 | # lists people. For example, Google employees are listed here 4 | # but not in AUTHORS, because Google holds the copyright. 5 | # 6 | # https://developers.google.com/open-source/cla/individual 7 | # https://developers.google.com/open-source/cla/corporate 8 | # 9 | # Names should be added to this file as: 10 | # Name 11 | 12 | Carmi Grushko 13 | -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- 1 | # Bazel code, required for PackageLoader 2 | 3 | http_archive( 4 | name = "io_bazel", 5 | sha256 = "23e4281c3628cbd746da3f51330109bbf69780bd64461b63b386efae37203f20", 6 | urls = ["https://releases.bazel.build/0.17.1/release/bazel-0.17.1-dist.zip"], 7 | ) 8 | 9 | # Buildozer, to manipulate BUILD files 10 | 11 | http_archive( 12 | name = "com_github_bazelbuild_buildtools", 13 | strip_prefix = "buildtools-b8569631d3e67c7b83279157dc659903f92e919b", 14 | type = "zip", 15 | urls = ["https://github.com/bazelbuild/buildtools/archive/b8569631d3e67c7b83279157dc659903f92e919b.zip"], 16 | ) 17 | 18 | # Protobuf 19 | 20 | http_archive( 21 | name = "com_google_protobuf", 22 | sha256 = "1f8b9b202e9a4e467ff0b0f25facb1642727cdf5e69092038f15b37c75b99e45", 23 | strip_prefix = "protobuf-3.5.1", 24 | urls = ["https://github.com/google/protobuf/archive/v3.5.1.zip"], 25 | ) 26 | 27 | # Go - bind external repos 28 | 29 | http_archive( 30 | name = "io_bazel_rules_go", 31 | sha256 = "4d8d6244320dd751590f9100cf39fd7a4b75cd901e1f3ffdfd6f048328883695", 32 | url = "https://github.com/bazelbuild/rules_go/releases/download/0.9.0/rules_go-0.9.0.tar.gz", 33 | ) 34 | 35 | http_archive( 36 | name = "bazel_gazelle", 37 | sha256 = "0103991d994db55b3b5d7b06336f8ae355739635e0c2379dea16b8213ea5a223", 38 | url = "https://github.com/bazelbuild/bazel-gazelle/releases/download/0.9/bazel-gazelle-0.9.tar.gz", 39 | ) 40 | 41 | # gRPC for Go 42 | 43 | load("@io_bazel_rules_go//go:def.bzl", "go_repository", "go_rules_dependencies", "go_register_toolchains") 44 | 45 | go_repository( 46 | name = "org_golang_google_grpc", 47 | build_file_proto_mode = "disable", # use existing generated code 48 | commit = "8e4536a86ab602859c20df5ebfd0bd4228d08655", # v1.10.0 49 | importpath = "google.golang.org/grpc", 50 | ) 51 | 52 | # Go - load additional repos. 53 | 54 | go_rules_dependencies() 55 | 56 | go_register_toolchains() 57 | 58 | load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") 59 | 60 | gazelle_dependencies() 61 | 62 | go_repository( 63 | name = "com_github_google_go_cmp", 64 | commit = "v0.2.0", 65 | importpath = "github.com/google/go-cmp", 66 | ) 67 | 68 | # Maven jars 69 | 70 | load("//thirdparty:maven.bzl", "maven_dependencies") 71 | 72 | maven_dependencies() 73 | 74 | # gRPC for Java 75 | 76 | http_archive( 77 | name = "grpc_java", 78 | sha256 = "b4c9839b672213686ee9633a6089a913e50b1040d9f7486bd09d17032a2a90d3", 79 | strip_prefix = "grpc-java-1.10.0", 80 | urls = [ 81 | "https://github.com/grpc/grpc-java/archive/v1.10.0.zip", 82 | ], 83 | ) 84 | 85 | # Bind Guava and GSON for @com_google_protobuf//:protobuf_java_util 86 | 87 | bind( 88 | name = "guava", 89 | actual = "//thirdparty/jvm/com/google/guava", 90 | ) 91 | 92 | bind( 93 | name = "gson", 94 | actual = "//thirdparty/jvm/com/google/code/gson", 95 | ) 96 | -------------------------------------------------------------------------------- /bazel/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["bazel.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/bazel", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_test( 11 | name = "go_default_test", 12 | srcs = ["bazel_test.go"], 13 | embed = [":go_default_library"], 14 | deps = ["@com_github_google_go_cmp//cmp:go_default_library"], 15 | ) 16 | -------------------------------------------------------------------------------- /bazel/bazel_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package bazel 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/google/go-cmp/cmp" 21 | ) 22 | 23 | func TestLabelSplit(t *testing.T) { 24 | var tests = []struct { 25 | label string 26 | wantPkgName string 27 | wantRuleName string 28 | }{ 29 | {"//foo:bar", "foo", "bar"}, 30 | {"//foo/bar", "foo/bar", "bar"}, 31 | {"//foo/bar/zoo", "foo/bar/zoo", "zoo"}, 32 | {"//foo", "foo", "foo"}, 33 | {"@r//foo", "@r//foo", "foo"}, 34 | } 35 | 36 | for _, tt := range tests { 37 | pkgName, ruleName := Label(tt.label).Split() 38 | if pkgName != tt.wantPkgName || ruleName != tt.wantRuleName { 39 | t.Errorf("Label(%s).Split() = (%s, %s), want (%s, %s)", tt.label, pkgName, ruleName, tt.wantPkgName, tt.wantRuleName) 40 | } 41 | } 42 | } 43 | 44 | func TestParseRelativeLabel(t *testing.T) { 45 | tests := []struct { 46 | pkgName, s string 47 | want Label 48 | }{ 49 | {"", "//foo", "//foo:foo"}, 50 | {"", "//foo:foo", "//foo:foo"}, 51 | {"", "//foo:bar", "//foo:bar"}, 52 | {"foo", ":bar", "//foo:bar"}, 53 | {"foo", "bar", "//foo:bar"}, 54 | {"@r//foo", "bar", "@r//foo:bar"}, 55 | {"dontcare", "//foo/bar:bar", "//foo/bar:bar"}, 56 | {"dontcare", "//foo/bar:baz", "//foo/bar:baz"}, 57 | {"dontcare", "@r//foo/bar:baz", "@r//foo/bar:baz"}, 58 | } 59 | for _, tt := range tests { 60 | got, err := ParseRelativeLabel(tt.pkgName, tt.s) 61 | if err != nil { 62 | t.Errorf("ParseLabel(%s, %s) has error %v, want nil", tt.pkgName, tt.s, err) 63 | } 64 | if got != tt.want { 65 | t.Errorf("ParseLabel(%s, %s) = %v, want %v", tt.pkgName, tt.s, got, tt.want) 66 | } 67 | } 68 | } 69 | 70 | func TestParseRelativeLabelErrors(t *testing.T) { 71 | tests := []struct { 72 | pkgName, s string 73 | wantErr string 74 | }{ 75 | {"dontcare", "foo:bar", `label "foo:bar" doesn't start with // or @, but also contains a colon`}, 76 | {"@r//foo//", "bar", `package name "@r//foo//" contains '//' more than once`}, 77 | } 78 | for _, tt := range tests { 79 | _, err := ParseRelativeLabel(tt.pkgName, tt.s) 80 | if diff := cmp.Diff(err.Error(), tt.wantErr); diff != "" { 81 | t.Errorf("ParseLabel(%s, %s) returns the wrong error (-got +want): %v", tt.pkgName, tt.s, diff) 82 | } 83 | } 84 | } 85 | 86 | func TestParseAbsoluteLabel(t *testing.T) { 87 | tests := []struct { 88 | s string 89 | wantErr string 90 | want Label 91 | }{ 92 | {"//foo", "", "//foo:foo"}, 93 | {"//foo/bar", "", "//foo/bar:bar"}, 94 | {"foo", `absolute label must start with // or @, "foo" is neither`, ""}, 95 | {":foo", `absolute label must start with // or @, ":foo" is neither`, ""}, 96 | {"//foo:fo:o", `target name "foo" contains ':'`, ""}, 97 | {"@//:foo", "", "@//:foo"}, 98 | {"@//asd//:foo", `package name "@//asd//" contains '//' more than once`, ""}, 99 | {"//foo:foo", "", "//foo:foo"}, 100 | {"//foo/bar:foo", "", "//foo/bar:foo"}, 101 | {"@r//foo/bar:foo", "", "@r//foo/bar:foo"}, 102 | // TODO(b/36533053): Remove once fixed. 103 | {"////foo/bar:foo", "", "//foo/bar:foo"}, 104 | } 105 | for _, tt := range tests { 106 | got, err := ParseAbsoluteLabel(tt.s) 107 | if err == nil { 108 | if tt.wantErr != "" { 109 | t.Errorf("Got no error, want %q", tt.wantErr) 110 | } 111 | } else { 112 | if diff := cmp.Diff(err.Error(), tt.wantErr); diff != "" { 113 | t.Errorf("ParseAbsoluteLabel(%s) returns the wrong error (-got +want): %v", tt.s, diff) 114 | } 115 | } 116 | if diff := cmp.Diff(got, tt.want); diff != "" { 117 | t.Errorf("ParseAbsoluteLabel(%s) returns the wrong label (-got +want): %v", tt.s, diff) 118 | } 119 | } 120 | } 121 | 122 | func TestLabelListAttr(t *testing.T) { 123 | tests := []struct { 124 | rule *Rule 125 | attr string 126 | want []Label 127 | }{ 128 | { 129 | rule: &Rule{PkgName: "x", Attrs: map[string]interface{}{"deps": []string{"//foo:bar", "//foo", "bar"}}}, 130 | attr: "deps", 131 | want: []Label{"//foo:bar", "//foo:foo", "//x:bar"}, 132 | }, 133 | } 134 | for _, tt := range tests { 135 | got := tt.rule.LabelListAttr(tt.attr) 136 | if diff := cmp.Diff(got, tt.want); diff != "" { 137 | t.Errorf("rule.LabelListAttr(%s) has diff (-got +want):\nrule = %v\n\ndiff = %v", tt.attr, tt.rule, diff) 138 | } 139 | } 140 | } 141 | 142 | func TestLabelAttr(t *testing.T) { 143 | tests := []struct { 144 | rule *Rule 145 | attr string 146 | want Label 147 | wantErr string 148 | }{ 149 | { 150 | rule: &Rule{PkgName: "x", Attrs: map[string]interface{}{"attr": "//foo:bar"}}, 151 | attr: "attr", 152 | want: Label("//foo:bar"), 153 | }, 154 | { 155 | rule: &Rule{PkgName: "x", Attrs: map[string]interface{}{"attr": "//foo"}}, 156 | attr: "attr", 157 | want: Label("//foo:foo"), 158 | }, 159 | { 160 | rule: &Rule{PkgName: "x", Attrs: map[string]interface{}{"attr": ":bar"}}, 161 | attr: "attr", 162 | want: Label("//x:bar"), 163 | }, 164 | { 165 | rule: &Rule{PkgName: "x", Attrs: map[string]interface{}{"attr": []string(nil)}}, 166 | attr: "attr", 167 | wantErr: "//x:'s attr is not a string, can't parse to label", 168 | }, 169 | { 170 | rule: &Rule{PkgName: "x", Attrs: map[string]interface{}{"attr": "a:"}}, 171 | attr: "attr", 172 | wantErr: `can't read //x:'s attr as label: label "a:" doesn't start with // or @, but also contains a colon`, 173 | }, 174 | } 175 | for _, tt := range tests { 176 | got, err := tt.rule.LabelAttr(tt.attr) 177 | if err == nil { 178 | if tt.wantErr != "" { 179 | t.Errorf("Got no error, want %q", tt.wantErr) 180 | } 181 | } else { 182 | if diff := cmp.Diff(err.Error(), tt.wantErr); diff != "" { 183 | t.Errorf("rule.LabelListAttr(%s) returns the wrong error (-got +want): %v", tt.attr, diff) 184 | } 185 | } 186 | if diff := cmp.Diff(got, tt.want); diff != "" { 187 | t.Errorf("rule.LabelListAttr(%s) has diff (-got +want):\nrule = %v\n\ndiff = %v", tt.attr, tt.rule, diff) 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /bazeldepsresolver/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["bazeldepsresolver.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/bazeldepsresolver", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//bazel:go_default_library", 10 | "//jadeplib:go_default_library", 11 | "//listclassesinjar:go_default_library", 12 | "//pkgloading:go_default_library", 13 | ], 14 | ) 15 | 16 | go_test( 17 | name = "go_default_test", 18 | srcs = ["bazeldepsresolver_test.go"], 19 | embed = [":go_default_library"], 20 | deps = [ 21 | "//bazel:go_default_library", 22 | "//jadeplib:go_default_library", 23 | "//loadertest:go_default_library", 24 | "@com_github_google_go_cmp//cmp:go_default_library", 25 | ], 26 | ) 27 | -------------------------------------------------------------------------------- /bazeldepsresolver/bazeldepsresolver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package bazeldepsresolver resolves Java class names to precompiled jars set up by https://github.com/johnynek/bazel-deps/. 16 | // NewResolver queries the file-system under the provided directory, and follows java_library, bind and java_import rules to 17 | // the jars they reference. It then lists their contents. 18 | // When resolving class names, it follows reverse edges back from class names to the java_library rules that transitively export them. 19 | package bazeldepsresolver 20 | 21 | import ( 22 | "fmt" 23 | "log" 24 | "os" 25 | "path/filepath" 26 | "time" 27 | 28 | "context" 29 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 30 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 31 | "github.com/bazelbuild/tools_jvm_autodeps/listclassesinjar" 32 | "github.com/bazelbuild/tools_jvm_autodeps/pkgloading" 33 | ) 34 | 35 | // Resolver resolves class names according to a third-party directory structue created by https://github.com/johnynek/bazel-deps/. 36 | type Resolver struct { 37 | thirdPartyDir string 38 | 39 | parent map[*bazel.Rule]*bazel.Rule 40 | classToRule map[jadeplib.ClassName]*bazel.Rule 41 | 42 | loader pkgloading.Loader 43 | } 44 | 45 | // NewResolver returns a new Resolver. 46 | // thirdPartyDir is a directory relative to the workspace directory, e.g. "thirdparty/jvm". 47 | func NewResolver(ctx context.Context, workspaceDir, thirdPartyDir string, loader pkgloading.Loader) (*Resolver, error) { 48 | if filepath.IsAbs(thirdPartyDir) { 49 | return nil, fmt.Errorf("thirdPartyDir %s must be a relative path", thirdPartyDir) 50 | } 51 | stopwatch := time.Now() 52 | 53 | // Prefetch 'external' because bazel-deps always uses it. 54 | go loader.Load(ctx, []string{"external"}) 55 | 56 | dirs := allPackages(workspaceDir, thirdPartyDir) 57 | pkgs, err := loader.Load(ctx, dirs) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | var layer []*bazel.Rule 63 | parent := make(map[*bazel.Rule]*bazel.Rule) 64 | classToRule := make(map[jadeplib.ClassName]*bazel.Rule) 65 | seenLabels := make(map[bazel.Label]bool) 66 | 67 | for _, pkg := range pkgs { 68 | for _, rule := range pkg.Rules { 69 | layer = append(layer, rule) 70 | } 71 | } 72 | 73 | // BFS 74 | for len(layer) > 0 { 75 | var toLoad []bazel.Label 76 | parentLabels := make(map[bazel.Label]*bazel.Rule) 77 | // Construct next layer 78 | for _, rule := range layer { 79 | var candidates []bazel.Label 80 | switch rule.Schema { 81 | case "java_library": 82 | candidates = append(candidates, rule.LabelListAttr("exports")...) 83 | case "bind": 84 | if l, err := rule.LabelAttr("actual"); err == nil { 85 | candidates = append(candidates, l) 86 | } 87 | case "java_import": 88 | listJar(ctx, rule, pkgs, classToRule) 89 | } 90 | 91 | for _, candidate := range candidates { 92 | if !seenLabels[candidate] { 93 | seenLabels[candidate] = true 94 | toLoad = append(toLoad, candidate) 95 | parentLabels[candidate] = rule 96 | } 97 | } 98 | } 99 | // Load rules in next layer 100 | rules, newPkgs, err := pkgloading.LoadRules(ctx, loader, toLoad) 101 | if err != nil { 102 | return nil, err 103 | } 104 | for pkgName, pkg := range newPkgs { 105 | pkgs[pkgName] = pkg 106 | } 107 | // Fill out nextLayer 108 | var nextLayer []*bazel.Rule 109 | for u, v := range parentLabels { 110 | if ru := rules[u]; ru != nil { 111 | nextLayer = append(nextLayer, ru) 112 | parent[ru] = v 113 | } 114 | } 115 | layer = nextLayer 116 | } 117 | log.Printf("Created bazel-deps resolver (%dms)", int64(time.Now().Sub(stopwatch)/time.Millisecond)) 118 | 119 | return &Resolver{thirdPartyDir, parent, classToRule, loader}, nil 120 | } 121 | 122 | // allPackages returns all directories rooted at 'dir', relative to workspaceDir. 123 | func allPackages(workspaceDir, dir string) []string { 124 | var result []string 125 | filepath.Walk(filepath.Join(workspaceDir, dir), func(path string, info os.FileInfo, err error) error { 126 | if err != nil { 127 | return err 128 | } 129 | if info.IsDir() { 130 | relPath, err := filepath.Rel(workspaceDir, path) 131 | if err != nil { 132 | return err 133 | } 134 | result = append(result, relPath) 135 | } 136 | return nil 137 | }) 138 | return result 139 | } 140 | 141 | func listJar(ctx context.Context, rule *bazel.Rule, pkgs map[string]*bazel.Package, classToRule map[jadeplib.ClassName]*bazel.Rule) error { 142 | pkg := pkgs[rule.PkgName] 143 | if pkg == nil { 144 | return fmt.Errorf("can't find package object for rule %s - this is a bug in bazeldepsresolver", rule.Label()) 145 | } 146 | pkgPath := pkg.Path 147 | for _, jar := range rule.StringListAttr("jars") { 148 | fileName := filepath.Join(pkgPath, jar) 149 | cls, err := listclassesinjar.List(fileName) 150 | if err != nil { 151 | log.Printf("Warning: unable to list classes in jar %s", fileName) 152 | } 153 | for _, c := range cls { 154 | classToRule[c] = rule 155 | } 156 | } 157 | return nil 158 | } 159 | 160 | // Name returns a description of the resolver. 161 | func (r *Resolver) Name() string { 162 | return "github.com/johnynek/bazel-deps/" 163 | } 164 | 165 | // Resolve resolves class names according to an in-memory map. 166 | func (r *Resolver) Resolve(ctx context.Context, classNames []jadeplib.ClassName, consumingRules map[bazel.Label]map[bazel.Label]bool) (map[jadeplib.ClassName][]*bazel.Rule, error) { 167 | result := make(map[jadeplib.ClassName][]*bazel.Rule) 168 | for _, cls := range classNames { 169 | rule := r.classToRule[cls] 170 | if rule == nil { 171 | continue 172 | } 173 | for r.parent[rule] != nil { 174 | rule = r.parent[rule] 175 | } 176 | result[cls] = append(result[cls], rule) 177 | } 178 | 179 | return result, nil 180 | } 181 | -------------------------------------------------------------------------------- /bazeldepsresolver/bazeldepsresolver_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package bazeldepsresolver 16 | 17 | import ( 18 | "archive/zip" 19 | "io/ioutil" 20 | "os" 21 | "path/filepath" 22 | "testing" 23 | 24 | "context" 25 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 26 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 27 | "github.com/bazelbuild/tools_jvm_autodeps/loadertest" 28 | "github.com/google/go-cmp/cmp" 29 | ) 30 | 31 | func TestEndToEnd(t *testing.T) { 32 | type attrs = map[string]interface{} 33 | 34 | tmpdir, err := ioutil.TempDir("", "bazel_deps_resolver") 35 | if err != nil { 36 | t.Errorf("error called ioutil.TempDir: %v", err) 37 | } 38 | defer os.RemoveAll(tmpdir) 39 | root := filepath.Join(tmpdir, "root") 40 | externalRepositoriesRoot := filepath.Join(root, "external") 41 | workspace := filepath.Join(root, "workspace") 42 | thirdPartyDir := "thirdparty/jvm" 43 | 44 | type jar struct { 45 | fileName string 46 | files []string 47 | } 48 | type newResolverArgs struct { 49 | pkgs map[string]*bazel.Package 50 | jars []jar 51 | } 52 | tests := []struct { 53 | name string 54 | newResolverArgs newResolverArgs 55 | classNames []jadeplib.ClassName 56 | want map[jadeplib.ClassName][]bazel.Label 57 | }{ 58 | { 59 | name: "basic", 60 | newResolverArgs: newResolverArgs{ 61 | pkgs: map[string]*bazel.Package{ 62 | "thirdparty/jvm/guava": { 63 | Path: filepath.Join(workspace, "thirdparty/jvm/guava"), 64 | Rules: map[string]*bazel.Rule{ 65 | "guava": { 66 | Schema: "java_library", 67 | PkgName: "thirdparty/jvm/guava", 68 | Attrs: attrs{"name": "guava", "exports": []string{"//external:guava"}}, 69 | }, 70 | }, 71 | }, 72 | "thirdparty/jvm/org/junit": { 73 | Path: filepath.Join(workspace, "thirdparty/jvm/org/junit"), 74 | Rules: map[string]*bazel.Rule{ 75 | "junit": { 76 | Schema: "java_library", 77 | PkgName: "thirdparty/jvm/org/junit", 78 | Attrs: attrs{"name": "junit", "exports": []string{"//external:junit"}}, 79 | }, 80 | }, 81 | }, 82 | "external": { 83 | Path: workspace, 84 | Rules: map[string]*bazel.Rule{ 85 | "guava": { 86 | Schema: "bind", 87 | PkgName: "external", 88 | Attrs: attrs{"actual": "@guava//jar:guava"}, 89 | }, 90 | "junit": { 91 | Schema: "bind", 92 | PkgName: "external", 93 | Attrs: attrs{"actual": "@junit//jar:junit"}, 94 | }, 95 | }, 96 | }, 97 | "@guava//jar": { 98 | Path: filepath.Join(externalRepositoriesRoot, "guava/jar"), 99 | Rules: map[string]*bazel.Rule{ 100 | "guava": { 101 | Schema: "java_import", 102 | PkgName: "@guava//jar", 103 | Attrs: attrs{"jars": []string{"guava.jar"}}, 104 | }, 105 | }, 106 | }, 107 | "@junit//jar": { 108 | Path: filepath.Join(externalRepositoriesRoot, "junit/jar"), 109 | Rules: map[string]*bazel.Rule{ 110 | "junit": { 111 | Schema: "java_import", 112 | PkgName: "@junit//jar", 113 | Attrs: attrs{"jars": []string{"junit.jar"}}, 114 | }, 115 | }, 116 | }, 117 | }, 118 | jars: []jar{ 119 | { 120 | fileName: filepath.Join(externalRepositoriesRoot, "guava/jar/guava.jar"), 121 | files: []string{"com/ImmutableList.class"}, 122 | }, 123 | { 124 | fileName: filepath.Join(externalRepositoriesRoot, "junit/jar/junit.jar"), 125 | files: []string{"com/RunWith.class"}, 126 | }, 127 | }, 128 | }, 129 | classNames: []jadeplib.ClassName{"com.ImmutableList", "com.RunWith", "com.Unknown"}, 130 | want: map[jadeplib.ClassName][]bazel.Label{ 131 | "com.ImmutableList": {"//thirdparty/jvm/guava:guava"}, 132 | "com.RunWith": {"//thirdparty/jvm/org/junit:junit"}, 133 | }, 134 | }, 135 | } 136 | for _, tt := range tests { 137 | t.Run(tt.name, func(t *testing.T) { 138 | defer os.RemoveAll(root) 139 | 140 | // Create BUILD files. 141 | err := createBuildFileDir(tt.newResolverArgs.pkgs) 142 | if err != nil { 143 | t.Fatal(err) 144 | } 145 | 146 | // Write Jar files. 147 | for _, jar := range tt.newResolverArgs.jars { 148 | err := writeZipFile(jar.fileName, jar.files) 149 | if err != nil { 150 | t.Fatal(err) 151 | } 152 | } 153 | 154 | // Create resolver. 155 | loader := &loadertest.StubLoader{Pkgs: tt.newResolverArgs.pkgs} 156 | resolver, err := NewResolver(context.Background(), workspace, thirdPartyDir, loader) 157 | if err != nil { 158 | t.Fatalf("NewResolver: got err = %v, want nil", err) 159 | } 160 | 161 | // Resolve class names. 162 | got, err := resolver.Resolve(context.Background(), tt.classNames, nil) 163 | if err != nil { 164 | t.Fatalf("Resolver: got err = %v, want nil", err) 165 | } 166 | 167 | gotLabels := make(map[jadeplib.ClassName][]bazel.Label) 168 | for cls, rules := range got { 169 | for _, r := range rules { 170 | gotLabels[cls] = append(gotLabels[cls], r.Label()) 171 | } 172 | } 173 | if diff := cmp.Diff(gotLabels, tt.want); diff != "" { 174 | t.Errorf("Resolve(%s) diff: (-got +want)\n%s", tt.classNames, diff) 175 | } 176 | }) 177 | } 178 | } 179 | 180 | func createBuildFileDir(pkgs map[string]*bazel.Package) error { 181 | for _, pkg := range pkgs { 182 | err := os.MkdirAll(pkg.Path, 0700) 183 | if err != nil { 184 | return err 185 | } 186 | } 187 | return nil 188 | } 189 | 190 | func writeZipFile(fileName string, zipFileNames []string) error { 191 | f, err := os.Create(fileName) 192 | if err != nil { 193 | return err 194 | } 195 | defer f.Close() 196 | 197 | w := zip.NewWriter(f) 198 | for _, fileName := range zipFileNames { 199 | f, err := w.Create(fileName) 200 | if err != nil { 201 | return err 202 | } 203 | _, err = f.Write([]byte("")) 204 | if err != nil { 205 | return err 206 | } 207 | } 208 | 209 | err = w.Close() 210 | if err != nil { 211 | return err 212 | } 213 | return nil 214 | } 215 | -------------------------------------------------------------------------------- /buildozer/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["buildozer.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/buildozer", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//bazel:go_default_library", 10 | "@com_github_bazelbuild_buildtools//edit:go_default_library", 11 | ], 12 | ) 13 | 14 | go_test( 15 | name = "go_default_test", 16 | srcs = ["buildozer_test.go"], 17 | embed = [":go_default_library"], 18 | deps = ["//bazel:go_default_library"], 19 | ) 20 | -------------------------------------------------------------------------------- /buildozer/buildozer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package buildozer provides functions to work with Buildozer 16 | package buildozer 17 | 18 | import ( 19 | "bytes" 20 | "fmt" 21 | "io/ioutil" 22 | "os" 23 | "path/filepath" 24 | "strings" 25 | 26 | "github.com/bazelbuild/buildtools/edit" 27 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 28 | ) 29 | 30 | // Ref returns a token that Buildozer can use to manipulate a function call. 31 | // When a rule is instatiated directly (not through a Bazel macro), its reference equals its label. 32 | // Otherwise, if the macro has a name attribute, the reference looks like a label whose name is the macro's name. 33 | // Finally, if there's no name attribute, the reference is //: where line is where the macro starts in the BUILD file. 34 | func Ref(rule *bazel.Rule) (string, error) { 35 | if _, ok := rule.Attrs["generator_function"]; !ok { 36 | // Not a macro 37 | return string(rule.Label()), nil 38 | } 39 | name, ok := rule.Attrs["generator_name"].(string) 40 | if !ok { 41 | loc, _ := rule.Attrs["generator_location"].(string) 42 | parts := strings.Split(loc, ":") 43 | if len(parts) != 2 { 44 | return "", fmt.Errorf("expected rule's generator_location (%q) to have exactly one colon", loc) 45 | } 46 | name = "%" + parts[1] 47 | } 48 | return "//" + rule.PkgName + ":" + name, nil 49 | } 50 | 51 | // NewRule uses Buildozer to create a new rule based on the attributes of 'rule'. 52 | // Used attributes are Name, PkgName, Schema and srcs. 53 | func NewRule(workspaceRoot string, rule *bazel.Rule) error { 54 | pkgName := rule.PkgName 55 | name := rule.Name() 56 | buildFile := filepath.Join(workspaceRoot, pkgName, "BUILD") 57 | if _, err := os.Stat(buildFile); os.IsNotExist(err) { 58 | if err := ioutil.WriteFile(buildFile, nil, 0666); err != nil { 59 | return fmt.Errorf("error writing %s:\n%v", buildFile, err) 60 | } 61 | } 62 | err := exec(workspaceRoot, []string{ 63 | fmt.Sprintf("new %s %s", rule.Schema, name), 64 | fmt.Sprintf("//%s:__pkg__", pkgName), 65 | }, []int{0}) 66 | if err != nil { 67 | return err 68 | } 69 | err = exec(workspaceRoot, []string{ 70 | fmt.Sprintf("add srcs %s", strings.Join(rule.StringListAttr("srcs"), " ")), 71 | fmt.Sprintf("//%s:%s", pkgName, name), 72 | }, []int{0}) 73 | if err != nil { 74 | return err 75 | } 76 | return nil 77 | } 78 | 79 | // AddDepsToRules on (rule -> labels) adds labels to rule. 80 | func AddDepsToRules(workspaceRoot string, missingDeps map[*bazel.Rule][]bazel.Label) error { 81 | for rule, labels := range missingDeps { 82 | labelToModify, err := Ref(rule) 83 | if err != nil { 84 | return fmt.Errorf("error getting buildozer reference for %v:\n%v", rule, err) 85 | } 86 | var deps bytes.Buffer 87 | for _, l := range labels { 88 | deps.WriteString(string(l)) 89 | deps.WriteString(" ") 90 | } 91 | err = exec(workspaceRoot, []string{fmt.Sprintf("add deps %s", deps.String()), labelToModify}, []int{0, 3}) 92 | if err != nil { 93 | return err 94 | } 95 | } 96 | return nil 97 | } 98 | 99 | // exec calls Buildozer and returns an error if its exit code isn't one of allowedReturnedCodes. 100 | // args is a single command line, e.g. ["add deps", "//foo:bar", "//target"]. 101 | func exec(workspaceRoot string, args []string, allowedReturnedCodes []int) error { 102 | opts := &edit.Options{ 103 | NumIO: 200, 104 | KeepGoing: true, 105 | PreferEOLComments: true, 106 | RootDir: workspaceRoot, 107 | Quiet: true, 108 | } 109 | retval := edit.Buildozer(opts, args) 110 | for _, allowed := range allowedReturnedCodes { 111 | if retval == allowed { 112 | return nil 113 | } 114 | } 115 | return fmt.Errorf("buildozer returned %d, want one of %v, while executing %v", retval, allowedReturnedCodes, args) 116 | } 117 | -------------------------------------------------------------------------------- /buildozer/buildozer_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package buildozer 16 | 17 | import ( 18 | "io/ioutil" 19 | "os" 20 | "path/filepath" 21 | "testing" 22 | 23 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 24 | ) 25 | 26 | func TestRef(t *testing.T) { 27 | type Attrs = map[string]interface{} 28 | tests := []struct { 29 | desc string 30 | rule *bazel.Rule 31 | want string 32 | }{ 33 | { 34 | desc: "Rule instantiated directly", 35 | rule: bazel.NewRule("schema", "x/y", "foo", nil), 36 | want: "//x/y:foo", 37 | }, 38 | { 39 | desc: "Rule instantiated by a macro that has a name attribute", 40 | rule: bazel.NewRule("schema", "x/y", "foo_lib", Attrs{"generator_name": "foo", "generator_function": "some_macro"}), 41 | want: "//x/y:foo", 42 | }, 43 | { 44 | desc: "Rule instantiated by a macro that doesn't have a name attribute", 45 | rule: bazel.NewRule("schema", "x/y", "foo_lib", Attrs{"generator_location": "x/y/BUILD:78", "generator_function": "some_macro"}), 46 | want: "//x/y:%78", 47 | }, 48 | } 49 | 50 | for _, tt := range tests { 51 | tt := tt 52 | t.Run(tt.desc, func(t *testing.T) { 53 | got, err := Ref(tt.rule) 54 | if err != nil { 55 | t.Errorf("Ref returns error %v, want nil", err) 56 | return 57 | } 58 | if got != tt.want { 59 | t.Errorf("Ref returned %s, want %s", got, tt.want) 60 | } 61 | }) 62 | } 63 | } 64 | 65 | func TestNewRule(t *testing.T) { 66 | type Attrs = map[string]interface{} 67 | type file struct{ fileName, content string } 68 | tests := []struct { 69 | rule *bazel.Rule 70 | wantFile file 71 | }{ 72 | { 73 | rule: bazel.NewRule("java_test", "javatests/com", "FooTest", Attrs{"srcs": []string{"FooTest.java"}}), 74 | wantFile: file{ 75 | fileName: "javatests/com/BUILD", 76 | content: `java_test( 77 | name = "FooTest", 78 | srcs = ["FooTest.java"], 79 | ) 80 | `, 81 | }, 82 | }, 83 | { 84 | rule: bazel.NewRule("java_library", "java/com", "Foo", Attrs{"srcs": []string{"Foo.java"}}), 85 | wantFile: file{ 86 | fileName: "java/com/BUILD", 87 | content: `java_library( 88 | name = "Foo", 89 | srcs = ["Foo.java"], 90 | ) 91 | `, 92 | }, 93 | }, 94 | { 95 | rule: bazel.NewRule("java_library", "", "Foo", Attrs{"srcs": []string{"Foo.java"}}), 96 | wantFile: file{ 97 | fileName: "BUILD", 98 | content: `java_library( 99 | name = "Foo", 100 | srcs = ["Foo.java"], 101 | ) 102 | `, 103 | }, 104 | }, 105 | { 106 | rule: bazel.NewRule("android_test", "javatests/android", "FooTest", Attrs{"srcs": []string{"FooTest.java"}}), 107 | wantFile: file{ 108 | fileName: "javatests/android/BUILD", 109 | content: `android_test( 110 | name = "FooTest", 111 | srcs = ["FooTest.java"], 112 | ) 113 | `, 114 | }, 115 | }, 116 | } 117 | 118 | tmpDir, err := ioutil.TempDir("", "") 119 | if err != nil { 120 | t.Errorf("Can't create temp directory:\n%v", err) 121 | return 122 | } 123 | workspaceRoot := filepath.Join(tmpDir, "repo") 124 | 125 | for _, tt := range tests { 126 | tt := tt 127 | t.Run(string(tt.rule.Label()), func(t *testing.T) { 128 | createFiles(t, workspaceRoot, []string{"WORKSPACE"}) 129 | os.MkdirAll(filepath.Join(workspaceRoot, tt.rule.PkgName), os.ModePerm) 130 | defer os.RemoveAll(workspaceRoot) 131 | err := NewRule(workspaceRoot, tt.rule) 132 | if err != nil { 133 | t.Fatalf("NewRule() returned error %v, want nil", err) 134 | } 135 | b, err := ioutil.ReadFile(filepath.Join(workspaceRoot, tt.wantFile.fileName)) 136 | if err != nil { 137 | t.Fatal(err) 138 | } 139 | if string(b) != tt.wantFile.content { 140 | t.Errorf("NewRule created file %s with content\n%s\nbut wanted\n%s", tt.wantFile.fileName, string(b), tt.wantFile.content) 141 | } 142 | }) 143 | } 144 | } 145 | 146 | func TestAddDepsToRules(t *testing.T) { 147 | type file struct{ fileName, content string } 148 | tests := []struct { 149 | desc string 150 | missingDeps map[*bazel.Rule][]bazel.Label 151 | buildFile string 152 | initialContent string 153 | wantContent string 154 | }{ 155 | { 156 | desc: "basic", 157 | missingDeps: map[*bazel.Rule][]bazel.Label{ 158 | bazel.NewRule("java_library", "x", "Foo", nil): {"//y:Bar1", "//y:Bar2"}, 159 | bazel.NewRule("java_test", "x", "FooTest", nil): {"//y:BarTest"}, 160 | }, 161 | buildFile: "x/BUILD", 162 | initialContent: ` 163 | java_library(name = "Foo") 164 | java_test(name = "FooTest") 165 | `, 166 | wantContent: `java_library( 167 | name = "Foo", 168 | deps = [ 169 | "//y:Bar1", 170 | "//y:Bar2", 171 | ], 172 | ) 173 | 174 | java_test( 175 | name = "FooTest", 176 | deps = ["//y:BarTest"], 177 | ) 178 | `, 179 | }, 180 | } 181 | 182 | tmpDir, err := ioutil.TempDir("", "") 183 | if err != nil { 184 | t.Errorf("Can't create temp directory:\n%v", err) 185 | return 186 | } 187 | workspaceRoot := filepath.Join(tmpDir, "repo") 188 | 189 | for _, tt := range tests { 190 | tt := tt 191 | t.Run(tt.desc, func(t *testing.T) { 192 | createFiles(t, workspaceRoot, []string{"WORKSPACE", tt.buildFile}) 193 | defer os.RemoveAll(workspaceRoot) 194 | err := ioutil.WriteFile(filepath.Join(workspaceRoot, tt.buildFile), []byte(tt.initialContent), os.ModePerm) 195 | if err != nil { 196 | t.Fatal(err) 197 | } 198 | err = AddDepsToRules(workspaceRoot, tt.missingDeps) 199 | if err != nil { 200 | t.Fatalf("AddDepsToRules returned error = %v, want nil", err) 201 | } 202 | b, err := ioutil.ReadFile(filepath.Join(workspaceRoot, tt.buildFile)) 203 | if err != nil { 204 | t.Fatal(err) 205 | } 206 | if string(b) != tt.wantContent { 207 | t.Errorf("AddDepsToRules created file %s with content\n%s\nbut wanted\n%s", tt.buildFile, string(b), tt.wantContent) 208 | } 209 | }) 210 | } 211 | } 212 | 213 | func createFiles(t *testing.T, workDir string, fileNames []string) func() { 214 | for _, f := range fileNames { 215 | err := os.MkdirAll(filepath.Join(workDir, filepath.Dir(f)), os.ModePerm) 216 | if err != nil { 217 | t.Fatalf("Can't create directory %q:\n%v", filepath.Join(workDir, filepath.Dir(f)), err) 218 | } 219 | err = ioutil.WriteFile(filepath.Join(workDir, f), []byte("# empty"), os.ModePerm) 220 | if err != nil { 221 | t.Fatalf("Can't create file %q:\n%v", f, err) 222 | } 223 | } 224 | return func() { 225 | for _, f := range fileNames { 226 | os.Remove(f) 227 | } 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /cli/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["cli.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/cli", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//bazel:go_default_library", 10 | "//buildozer:go_default_library", 11 | "//color:go_default_library", 12 | "//future:go_default_library", 13 | "//jadeplib:go_default_library", 14 | "//lang/java/parser:go_default_library", 15 | "//pkgloading:go_default_library", 16 | "//vlog:go_default_library", 17 | ], 18 | ) 19 | 20 | go_test( 21 | name = "go_default_test", 22 | srcs = ["cli_test.go"], 23 | embed = [":go_default_library"], 24 | deps = [ 25 | "//bazel:go_default_library", 26 | "//jadeplib:go_default_library", 27 | "//loadertest:go_default_library", 28 | "@com_github_google_go_cmp//cmp:go_default_library", 29 | "@com_github_google_go_cmp//cmp/cmpopts:go_default_library", 30 | ], 31 | ) 32 | -------------------------------------------------------------------------------- /cmd/jadep/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["jadep.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/cmd/jadep", 7 | visibility = ["//visibility:private"], 8 | deps = [ 9 | "//bazeldepsresolver:go_default_library", 10 | "//cli:go_default_library", 11 | "//filter:go_default_library", 12 | "//grpcloader:go_default_library", 13 | "//jadeplib:go_default_library", 14 | "//jadepmain:go_default_library", 15 | "//pkgloading:go_default_library", 16 | "//sortingdepsranker:go_default_library", 17 | ], 18 | ) 19 | 20 | go_binary( 21 | name = "jadep", 22 | embed = [":go_default_library"], 23 | visibility = ["//visibility:public"], 24 | ) 25 | -------------------------------------------------------------------------------- /cmd/jadep/jadep.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // The jadep command adds `BUILD` dependencies that a Java file needs. 16 | package main 17 | 18 | import ( 19 | "fmt" 20 | "log" 21 | "os" 22 | "os/user" 23 | "path/filepath" 24 | "strings" 25 | "time" 26 | 27 | "flag" 28 | "context" 29 | 30 | "github.com/bazelbuild/tools_jvm_autodeps/bazeldepsresolver" 31 | "github.com/bazelbuild/tools_jvm_autodeps/cli" 32 | "github.com/bazelbuild/tools_jvm_autodeps/filter" 33 | "github.com/bazelbuild/tools_jvm_autodeps/grpcloader" 34 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 35 | "github.com/bazelbuild/tools_jvm_autodeps/jadepmain" 36 | "github.com/bazelbuild/tools_jvm_autodeps/pkgloading" 37 | "github.com/bazelbuild/tools_jvm_autodeps/sortingdepsranker" 38 | ) 39 | 40 | var flags jadepmain.Flags 41 | var strContentRoots, strClassNames, strBlacklist string 42 | 43 | var ( 44 | bazelInstallBase = flag.String("bazel_install_base", "", "the value of 'bazel info install_base'") 45 | bazelOutputBase = flag.String("bazel_output_base", "", "the value of 'bazel info output_base'") 46 | 47 | thirdpartyJvmDir = flag.String("thirdparty_jvm_dir", "thirdparty/jvm", "the directory where https://github.com/johnynek/bazel-deps placed its generated BUILD files") 48 | ) 49 | 50 | func init() { 51 | log.Printf("Jadep - fix BUILD for Java code") 52 | u, err := user.Current() 53 | if err != nil { 54 | log.Fatalf("Error getting current user") 55 | } 56 | 57 | flag.StringVar(&flags.Workspace, "workspace", "", "a Bazel WORKSPACE directory to operate in. Defaults to working directory") 58 | flag.StringVar(&strContentRoots, "content_roots", "src/main/java,src/test/java", "locations of Java sources relative to -workspace (comma delimited)") 59 | flag.BoolVar(&flags.DryRun, "dry_run", false, "only prints missing/unknown deps") 60 | flag.StringVar(&strClassNames, "classnames", "", "when present, Jade will find dependencies for these class names instead of parsing the Java file to look for class names without dependencies (comma delimited).") 61 | flag.StringVar(&strBlacklist, "blacklist", `.*\.R$`, "a list of regular expressions matching names of classes for which we will not look for BUILD rules (comma delimited).") 62 | flag.StringVar(&flags.BlacklistedPackageList, "blacklisted_package_list", filepath.Join(u.HomeDir, "jadep/blacklisted_packages.txt"), "File containing BUILD package names that Jade will not load. Usual use-case: package takes too long to load and doesn't contain anything we need.") 63 | flag.StringVar(&flags.BuiltinClassList, "builtin_classlist", filepath.Join(u.HomeDir, "jadep/jdk_android_builtin_class_names.txt"), "File containing class names that don't need deps, e.g. JDK classes. One class name per line, sorted.") 64 | flag.StringVar(&flags.PkgLoaderExecutable, "pkgloader_executable", filepath.Join(u.HomeDir, "jadep/pkgloader_server.sh"), "path to a package loader server executable. Started when Jade fails to connect to --pkg_loader_bind_location") 65 | flag.StringVar(&flags.PkgLoaderAddress, "pkgloader_address", "", "Address of a pkgloader service. "+ 66 | "If prefixed with unix://, assumed to be a Unix domain socket. "+ 67 | "If Jade fails to connect and this flag is prefixed with one of unix:// or localhost:, it starts the executable pointed at by --pkgloader_executable. "+ 68 | "Note that other forms, including IP addresses, will not cause Jade to start a server. "+ 69 | "localhost:0 is unsupported. "+ 70 | "The defaut is unix:///pkgloader.socket") 71 | flag.DurationVar(&flags.RPCDeadline, "rpc_deadline", 15*time.Second, "Time before giving up on RPC connections.") 72 | flag.StringVar(&flags.Cpuprofile, "cpuprofile", "", "write cpu profile to file") 73 | flag.IntVar(&flags.Vlevel, "vlevel", 0, "Enable V-leveled logging at the specified level") 74 | flag.BoolVar(&flags.Color, "color", true, "Colorize output. If stdout or stderr are not terminals, the output will not be colorized and this flag will have no effect") 75 | } 76 | 77 | func main() { 78 | flag.Parse() 79 | flags.ContentRoots = strings.Split(strContentRoots, ",") 80 | if strClassNames == "" { 81 | flags.ClassNames = nil 82 | } else { 83 | flags.ClassNames = strings.Split(strClassNames, ",") 84 | } 85 | flags.Blacklist = strings.Split(strBlacklist, ",") 86 | 87 | workspaceDir, _, err := cli.Workspace(flags.Workspace) 88 | if err != nil { 89 | log.Fatalf("Can't find root of workspace: %v", err) 90 | } 91 | 92 | bazelInstallBase := *bazelInstallBase 93 | bazelOutputBase := *bazelOutputBase 94 | if bazelInstallBase == "" || bazelOutputBase == "" { 95 | install, output, err := guessBazelBases(workspaceDir) 96 | if err != nil { 97 | log.Fatalf("Can't find Bazel install and output bases. Explicitly pass --bazel_install_base and --bazel_output_base.\n%v", err) 98 | } 99 | if bazelInstallBase == "" { 100 | bazelInstallBase = install 101 | } 102 | if bazelOutputBase == "" { 103 | bazelOutputBase = output 104 | } 105 | } 106 | 107 | jadepmain.Main(customization{workspaceDir, bazelInstallBase, bazelOutputBase}, &flags, flag.Args()) 108 | } 109 | 110 | // guessBazelBases guesses the output and install bases of the current Bazel workspace. 111 | // It is a horrible piece of hack and I'm ashamed of it. 112 | func guessBazelBases(workspaceDir string) (installBase string, outputBase string, err error) { 113 | bazelOut, err := os.Readlink(filepath.Join(workspaceDir, "bazel-out")) 114 | if err != nil { 115 | return "", "", fmt.Errorf("couldn't resolve the bazel-out/ symlink: %v", err) 116 | } 117 | outputBase = filepath.Dir(filepath.Dir(filepath.Dir(bazelOut))) 118 | installBase, err = os.Readlink(filepath.Join(outputBase, "install")) 119 | if err != nil { 120 | return "", "", fmt.Errorf("couldn't resolve the install base symlink: %v", err) 121 | } 122 | return installBase, outputBase, nil 123 | } 124 | 125 | type customization struct { 126 | workspaceDir string 127 | bazelInstallBase string 128 | bazelOutputBase string 129 | } 130 | 131 | func (c customization) LoadDataSources(ctx context.Context) jadepmain.DataSources { 132 | return nil 133 | } 134 | 135 | func (c customization) NewDepsRanker(data jadepmain.DataSources) jadeplib.DepsRanker { 136 | return &sortingdepsranker.Ranker{} 137 | } 138 | 139 | func (c customization) NewResolvers(loader pkgloading.Loader, data interface{}) []jadeplib.Resolver { 140 | r, err := bazeldepsresolver.NewResolver(context.Background(), c.workspaceDir, *thirdpartyJvmDir, loader) 141 | if err != nil { 142 | log.Printf("Warning: couldn't create bazel-deps resolver: %v", err) 143 | return nil 144 | } 145 | return []jadeplib.Resolver{r} 146 | } 147 | 148 | func (c customization) NewLoader(ctx context.Context, flags *jadepmain.Flags, workspaceDir string) (pkgloading.Loader, func(), error) { 149 | return grpcloader.Connect(ctx, flags.PkgLoaderExecutable, flags.PkgLoaderAddress, flags.RPCDeadline, workspaceDir, c.bazelInstallBase, c.bazelOutputBase, keys(filter.RuleKindsToLoad)) 150 | } 151 | 152 | func keys(m map[string]bool) []string { 153 | ret := make([]string, 0, len(m)) 154 | for k := range m { 155 | ret = append(ret, k) 156 | } 157 | return ret 158 | } 159 | -------------------------------------------------------------------------------- /cmd/list_classes_in_jar/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["list_classes_in_jar.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/cmd/list_classes_in_jar", 7 | visibility = ["//visibility:private"], 8 | deps = [ 9 | "//jadeplib:go_default_library", 10 | "//listclassesinjar:go_default_library", 11 | ], 12 | ) 13 | 14 | go_binary( 15 | name = "list_classes_in_jar", 16 | embed = [":go_default_library"], 17 | visibility = ["//visibility:public"], 18 | ) 19 | -------------------------------------------------------------------------------- /cmd/list_classes_in_jar/list_classes_in_jar.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Program list_classes_in_jar consumes .jar files and prints a sorted list of Java classes they contains to stdout. 16 | // Jade consumes the result in order to avoid looking for dependencies for built-in class names. 17 | // 18 | // The program takes the .jar file names on the command line. 19 | package main 20 | 21 | import ( 22 | "fmt" 23 | "log" 24 | "os" 25 | "sort" 26 | 27 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 28 | "github.com/bazelbuild/tools_jvm_autodeps/listclassesinjar" 29 | ) 30 | 31 | func main() { 32 | if len(os.Args) < 2 { 33 | log.Fatalf("Usage: %s jar1 ...", os.Args[0]) 34 | } 35 | 36 | var classes []string 37 | seen := make(map[jadeplib.ClassName]bool) 38 | for i := 1; i < len(os.Args); i++ { 39 | cls, err := listclassesinjar.List(os.Args[i]) 40 | if err != nil { 41 | log.Fatal(err) 42 | } 43 | for _, c := range cls { 44 | if !seen[c] { 45 | seen[c] = true 46 | classes = append(classes, string(c)) 47 | } 48 | } 49 | } 50 | sort.Strings(classes) 51 | for _, p := range classes { 52 | fmt.Println(p) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /color/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["color.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/color", 7 | visibility = ["//visibility:public"], 8 | ) 9 | -------------------------------------------------------------------------------- /color/color.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package color colorizes output sent to a terminal 16 | package color 17 | 18 | const keyEscape = 27 19 | 20 | var ( 21 | // Enabled decides whether the colorization functions (e.g. Green()) are no-ops. 22 | Enabled = true 23 | 24 | black = []byte{keyEscape, '[', '3', '0', 'm'} 25 | red = []byte{keyEscape, '[', '3', '1', 'm'} 26 | green = []byte{keyEscape, '[', '3', '2', 'm'} 27 | yellow = []byte{keyEscape, '[', '3', '3', 'm'} 28 | blue = []byte{keyEscape, '[', '3', '4', 'm'} 29 | magenta = []byte{keyEscape, '[', '3', '5', 'm'} 30 | cyan = []byte{keyEscape, '[', '3', '6', 'm'} 31 | white = []byte{keyEscape, '[', '3', '7', 'm'} 32 | darkGray = []byte{keyEscape, '[', '9', '0', 'm'} 33 | 34 | bold = []byte{keyEscape, '[', '1', 'm'} 35 | 36 | reset = []byte{keyEscape, '[', '0', 'm'} 37 | ) 38 | 39 | func wrap(s string, codes []byte) string { 40 | if !Enabled { 41 | return s 42 | } 43 | return string(codes) + s + string(reset) 44 | } 45 | 46 | // Bold returns s wrapped in ANSI codes which cause terminals to display it bold. 47 | func Bold(s string) string { 48 | return wrap(s, bold) 49 | } 50 | 51 | // Green returns s wrapped in ANSI codes which cause terminals to display it green. 52 | func Green(s string) string { 53 | return wrap(s, green) 54 | } 55 | 56 | // Magenta returns s wrapped in ANSI codes which cause terminals to display it magenta. 57 | func Magenta(s string) string { 58 | return wrap(s, magenta) 59 | } 60 | 61 | // BoldMagenta returns s wrapped in ANSI codes which cause terminals to display it bold magenta. 62 | func BoldMagenta(s string) string { 63 | return wrap(wrap(s, magenta), bold) 64 | } 65 | 66 | // BoldGreen returns s wrapped in ANSI codes which cause terminals to display it bold green. 67 | func BoldGreen(s string) string { 68 | return wrap(wrap(s, green), bold) 69 | } 70 | 71 | // DarkGray returns s wrapped in ANSI codes which cause terminals to display it dark gray. 72 | func DarkGray(s string) string { 73 | return wrap(s, darkGray) 74 | } 75 | -------------------------------------------------------------------------------- /compat/BUILD: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | # keep 4 | go_library( 5 | name = "go_default_library", 6 | srcs = ["compat.go"], 7 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/compat", 8 | visibility = ["//visibility:public"], 9 | deps = ["@io_bazel_rules_go//go/tools/bazel:go_default_library"], 10 | ) 11 | -------------------------------------------------------------------------------- /compat/compat.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package compat 16 | 17 | import ( 18 | "context" 19 | "net" 20 | "os" 21 | 22 | "github.com/bazelbuild/rules_go/go/tools/bazel" 23 | ) 24 | 25 | func FileStat(ctx context.Context, name string) (interface{}, error) { 26 | return os.Stat(name) 27 | } 28 | 29 | func NewLocalSpan(ctx context.Context, name string) (context.Context, func()) { 30 | return ctx, func() {} 31 | } 32 | 33 | func RunfilesPath(path string) string { 34 | r, _ := bazel.Runfile(path) 35 | return r 36 | } 37 | 38 | func PickUnusedPort() (int, func(), error) { 39 | l, err := net.Listen("tcp", ":0") 40 | if err != nil { 41 | return 0, nil, err 42 | } 43 | defer l.Close() 44 | return l.Addr().(*net.TCPAddr).Port, func() {}, nil 45 | } 46 | -------------------------------------------------------------------------------- /dictresolver/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["dictresolver.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/dictresolver", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//bazel:go_default_library", 10 | "//future:go_default_library", 11 | "//jadeplib:go_default_library", 12 | "//pkgloading:go_default_library", 13 | "//resolverutil:go_default_library", 14 | ], 15 | ) 16 | 17 | go_test( 18 | name = "go_default_test", 19 | srcs = ["dictresolver_test.go"], 20 | embed = [":go_default_library"], 21 | deps = [ 22 | "//bazel:go_default_library", 23 | "//future:go_default_library", 24 | "//jadeplib:go_default_library", 25 | "//loadertest:go_default_library", 26 | "//pkgloaderfakes:go_default_library", 27 | "@com_github_google_go_cmp//cmp:go_default_library", 28 | ], 29 | ) 30 | -------------------------------------------------------------------------------- /dictresolver/dictresolver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package dictresolver resolves according to an in-memory map. 16 | package dictresolver 17 | 18 | import ( 19 | "encoding/csv" 20 | "fmt" 21 | "io" 22 | 23 | "context" 24 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 25 | "github.com/bazelbuild/tools_jvm_autodeps/future" 26 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 27 | "github.com/bazelbuild/tools_jvm_autodeps/pkgloading" 28 | "github.com/bazelbuild/tools_jvm_autodeps/resolverutil" 29 | ) 30 | 31 | // Resolver resolves class names according to an in-memory map. 32 | type Resolver struct { 33 | name string 34 | 35 | // dict is a map[jadeplib.ClassName][]bazel.Label. Resolver resolves class name C to the Bazel rules dict[c]. 36 | dict *future.Value 37 | 38 | loader pkgloading.Loader 39 | } 40 | 41 | // NewResolver returns a new Resolver. 42 | func NewResolver(name string, dict *future.Value, loader pkgloading.Loader) *Resolver { 43 | return &Resolver{name, dict, loader} 44 | } 45 | 46 | // Name returns a description of the resolver. 47 | func (r *Resolver) Name() string { 48 | return r.name 49 | } 50 | 51 | // Resolve resolves class names according to an in-memory map. 52 | func (r *Resolver) Resolve(ctx context.Context, classNames []jadeplib.ClassName, consumingRules map[bazel.Label]map[bazel.Label]bool) (map[jadeplib.ClassName][]*bazel.Rule, error) { 53 | dict := r.dict.Get().(map[jadeplib.ClassName][]bazel.Label) 54 | 55 | candidates := make(map[jadeplib.ClassName][]bazel.Label) 56 | for _, cls := range classNames { 57 | if labels, ok := dict[cls]; ok { 58 | candidates[cls] = append(candidates[cls], labels...) 59 | } 60 | } 61 | 62 | // Skip LoadRules call for class names that are already satisfied by a consuming rule. 63 | alreadySat := resolverutil.SatisfiedByExistingDeps(consumingRules, candidates) 64 | for cls := range alreadySat { 65 | delete(candidates, cls) 66 | } 67 | 68 | // Load rules mentioned in 'candidates'. 69 | var labels []bazel.Label 70 | for _, c := range candidates { 71 | labels = append(labels, c...) 72 | } 73 | rules, _, err := pkgloading.LoadRules(ctx, r.loader, labels) 74 | if err != nil { 75 | return nil, err 76 | } 77 | 78 | // Convert 'candidates' to a map class name --> rule. 79 | result := make(map[jadeplib.ClassName][]*bazel.Rule) 80 | for classname, labels := range alreadySat { 81 | for _, label := range labels { 82 | p, r := label.Split() 83 | result[classname] = append(result[classname], bazel.NewRule("", p, r, nil)) 84 | } 85 | } 86 | for classname, labels := range candidates { 87 | result[classname] = nil 88 | for _, label := range labels { 89 | if r, ok := rules[label]; ok { 90 | result[classname] = append(result[classname], r) 91 | } 92 | } 93 | } 94 | 95 | return result, nil 96 | } 97 | 98 | // ReadDictFromCSV reads a className --> []bazel.Label map from a CSV file. 99 | // The format is: 100 | // className,label1,label2,... 101 | // 102 | // If there are no labels, a mapping to nil is returned. 103 | // Labels must be in absolute form. Invalid labels are silently ignored. 104 | func ReadDictFromCSV(reader io.Reader) (map[jadeplib.ClassName][]bazel.Label, error) { 105 | r := csv.NewReader(reader) 106 | r.ReuseRecord = true 107 | r.FieldsPerRecord = -1 // allow each record to have different number of columns. 108 | result := make(map[jadeplib.ClassName][]bazel.Label) 109 | for { 110 | record, err := r.Read() 111 | if err == io.EOF { 112 | break 113 | } 114 | if err != nil { 115 | return nil, fmt.Errorf("error reading CSV file: %v", err) 116 | } 117 | cls := jadeplib.ClassName(record[0]) 118 | result[cls] = nil 119 | for i := 1; i < len(record); i++ { 120 | lbl, err := bazel.ParseAbsoluteLabel(record[i]) 121 | if err == nil { 122 | result[cls] = append(result[cls], lbl) 123 | } 124 | } 125 | } 126 | return result, nil 127 | } 128 | -------------------------------------------------------------------------------- /dictresolver/dictresolver_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package dictresolver 16 | 17 | import ( 18 | "strings" 19 | "testing" 20 | 21 | "context" 22 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 23 | "github.com/bazelbuild/tools_jvm_autodeps/future" 24 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 25 | "github.com/bazelbuild/tools_jvm_autodeps/loadertest" 26 | "github.com/bazelbuild/tools_jvm_autodeps/pkgloaderfakes" 27 | "github.com/google/go-cmp/cmp" 28 | ) 29 | 30 | func TestResolve(t *testing.T) { 31 | tests := []struct { 32 | desc string 33 | existingPkgs map[string]*bazel.Package 34 | dict map[jadeplib.ClassName][]bazel.Label 35 | classNamesToResolve []jadeplib.ClassName 36 | consumingRules map[bazel.Label]map[bazel.Label]bool 37 | expectedLoads [][]string 38 | want map[jadeplib.ClassName][]*bazel.Rule 39 | }{ 40 | { 41 | desc: "when dict maps to nil, return a mapping to nil. " + 42 | "This is used by the JDK resolver, when we want some class namers to not require any Bazel deps at all.", 43 | dict: map[jadeplib.ClassName][]bazel.Label{"java.lang.Thread": nil, "java.util.HashSet": nil, "java.util.concurrent.Executor": nil}, 44 | classNamesToResolve: []jadeplib.ClassName{"java.lang.Thread", "com.Foo", "java.util.concurrent.Executor", "javax.inject.Inject"}, 45 | want: map[jadeplib.ClassName][]*bazel.Rule{ 46 | "java.lang.Thread": nil, 47 | "java.util.concurrent.Executor": nil, 48 | }, 49 | }, 50 | { 51 | desc: "dict points to a label, see that we load it and return it.", 52 | existingPkgs: map[string]*bazel.Package{ 53 | "foo": pkgloaderfakes.Pkg([]*bazel.Rule{ 54 | bazel.NewRule("dontcare", "foo", "Foo", nil), 55 | bazel.NewRule("dontcare", "foo", "Foo2", nil), 56 | }), 57 | }, 58 | dict: map[jadeplib.ClassName][]bazel.Label{"com.Foo": {"//foo:Foo", "//foo:Foo2"}}, 59 | classNamesToResolve: []jadeplib.ClassName{"com.Foo"}, 60 | expectedLoads: [][]string{{"foo"}}, 61 | want: map[jadeplib.ClassName][]*bazel.Rule{ 62 | "com.Foo": { 63 | bazel.NewRule("dontcare", "foo", "Foo", nil), 64 | bazel.NewRule("dontcare", "foo", "Foo2", nil), 65 | }, 66 | }, 67 | }, 68 | { 69 | desc: "Don't load packages for classes that are already satisfied, but return labels for them", 70 | existingPkgs: nil, 71 | dict: map[jadeplib.ClassName][]bazel.Label{"com.ImmutableList": {"//third_party/java_src:collect"}}, 72 | classNamesToResolve: []jadeplib.ClassName{"com.ImmutableList"}, 73 | consumingRules: map[bazel.Label]map[bazel.Label]bool{ 74 | "//:consumer": {"//third_party/java_src:collect": true}, 75 | }, 76 | expectedLoads: nil, 77 | want: map[jadeplib.ClassName][]*bazel.Rule{ 78 | "com.ImmutableList": {bazel.NewRule("", "third_party/java_src", "collect", nil)}, 79 | }, 80 | }, 81 | } 82 | 83 | for _, tt := range tests { 84 | tt := tt 85 | t.Run(tt.desc, func(t *testing.T) { 86 | loader := &loadertest.StubLoader{Pkgs: tt.existingPkgs} 87 | resolver := NewResolver("dict resolver", future.Immediate(tt.dict), loader) 88 | got, err := resolver.Resolve(context.Background(), tt.classNamesToResolve, tt.consumingRules) 89 | if err != nil { 90 | t.Fatalf("Unexpected from Resolve(%v) error:%v", tt.classNamesToResolve, err) 91 | } 92 | if diff := cmp.Diff(got, tt.want); diff != "" { 93 | t.Errorf("Resolve(%v) diff: (-got +want)\n%s", tt.classNamesToResolve, diff) 94 | } 95 | if diff := cmp.Diff(loader.RecordedCalls, tt.expectedLoads); diff != "" { 96 | t.Errorf("%s: Diffs in Load() calls to loader (-got +want):\n%s", tt.desc, diff) 97 | } 98 | }) 99 | } 100 | } 101 | 102 | func TestReadDictFromCSV(t *testing.T) { 103 | tests := []struct { 104 | desc string 105 | csv string 106 | want map[jadeplib.ClassName][]bazel.Label 107 | }{ 108 | { 109 | desc: "records with only one column result in mappings to nil", 110 | csv: `com.Foo`, 111 | want: map[jadeplib.ClassName][]bazel.Label{"com.Foo": nil}, 112 | }, 113 | { 114 | desc: "records with variable number of columns are ok", 115 | csv: `com.Foo,//:Foo1,//:Foo2 116 | com.Bar,//:Bar 117 | com.Zee`, 118 | want: map[jadeplib.ClassName][]bazel.Label{"com.Foo": {"//:Foo1", "//:Foo2"}, "com.Bar": {"//:Bar"}, "com.Zee": nil}, 119 | }, 120 | { 121 | desc: "invalid labels are silently ignored", 122 | csv: `com.Foo,blabla`, 123 | want: map[jadeplib.ClassName][]bazel.Label{"com.Foo": nil}, 124 | }, 125 | } 126 | for _, tt := range tests { 127 | tt := tt 128 | t.Run(tt.desc, func(t *testing.T) { 129 | got, err := ReadDictFromCSV(strings.NewReader(tt.csv)) 130 | if err != nil { 131 | t.Fatalf("Unexpected error: %v", err) 132 | } 133 | if diff := cmp.Diff(got, tt.want); diff != "" { 134 | t.Errorf("ReadDictFromCSV diff: (-got +want)\n%s", diff) 135 | } 136 | }) 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /filter/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["filter.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/filter", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//bazel:go_default_library", 10 | "//compat:go_default_library", 11 | "//pkgloading:go_default_library", 12 | ], 13 | ) 14 | 15 | go_test( 16 | name = "go_default_test", 17 | srcs = ["filter_test.go"], 18 | embed = [":go_default_library"], 19 | deps = [ 20 | "//bazel:go_default_library", 21 | "//loadertest:go_default_library", 22 | "@com_github_google_go_cmp//cmp:go_default_library", 23 | ], 24 | ) 25 | -------------------------------------------------------------------------------- /fsresolver/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["fsresolver.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/fsresolver", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//bazel:go_default_library", 10 | "//filter:go_default_library", 11 | "//graphs:go_default_library", 12 | "//jadeplib:go_default_library", 13 | "//pkgloading:go_default_library", 14 | "//vlog:go_default_library", 15 | ], 16 | ) 17 | 18 | go_test( 19 | name = "go_default_test", 20 | srcs = ["fsresolver_test.go"], 21 | embed = [":go_default_library"], 22 | deps = [ 23 | "//bazel:go_default_library", 24 | "//jadeplib:go_default_library", 25 | "//loadertest:go_default_library", 26 | "//pkgloaderfakes:go_default_library", 27 | "@com_github_google_go_cmp//cmp:go_default_library", 28 | ], 29 | ) 30 | -------------------------------------------------------------------------------- /fsresolver/fsresolver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package fsresolver resolves class names to Bazel rules using the file system. 16 | package fsresolver 17 | 18 | import ( 19 | "log" 20 | "path/filepath" 21 | "strings" 22 | 23 | "context" 24 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 25 | "github.com/bazelbuild/tools_jvm_autodeps/filter" 26 | "github.com/bazelbuild/tools_jvm_autodeps/graphs" 27 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 28 | "github.com/bazelbuild/tools_jvm_autodeps/pkgloading" 29 | "github.com/bazelbuild/tools_jvm_autodeps/vlog" 30 | ) 31 | 32 | // Resolver uses the file system to resolve class names to Bazel rules. 33 | type Resolver struct { 34 | // contentRoots specifies where the Java files are located. 35 | contentRoots []string 36 | // workspaceDir is a path to the root of a Bazel workspace. 37 | workspaceDir string 38 | 39 | // loader loads BUILD files. 40 | loader pkgloading.Loader 41 | } 42 | 43 | // NewResolver returns a new Resolver. 44 | func NewResolver(contentRoots []string, workspaceDir string, loader pkgloading.Loader) *Resolver { 45 | return &Resolver{contentRoots, workspaceDir, loader} 46 | } 47 | 48 | // Name returns a description of the resolver. 49 | func (r *Resolver) Name() string { 50 | return "file system" 51 | } 52 | 53 | // Resolve finds Bazel rules that provide the classes in 54 | // 'classnames', by looking at the local filesystem. A classname 55 | // 'a.b.c.D' is transformed into the filename '[content root]/a/b/c/D.java". 56 | // We then look for a Bazel rule that has that filename in its 'srcs' attribute. 57 | // 58 | // Returns: 59 | // (1) a map from each classname to a list of java_library rules that provide the classnames 60 | // (2) a list of classnames that could not be resolved by this file system approach. 61 | func (r *Resolver) Resolve(ctx context.Context, classNames []jadeplib.ClassName, consumingRules map[bazel.Label]map[bazel.Label]bool) (map[jadeplib.ClassName][]*bazel.Rule, error) { 62 | classToFile := make(map[jadeplib.ClassName][]string) 63 | var filenames []string 64 | 65 | for _, cls := range classNames { 66 | classToFiles := classToFiles(r.contentRoots, cls) 67 | classToFile[cls] = classToFiles 68 | filenames = append(filenames, classToFiles...) 69 | } 70 | 71 | packages, fileToPkgName, err := pkgloading.Siblings(ctx, r.loader, r.workspaceDir, filenames) 72 | if err != nil { 73 | return nil, err 74 | } 75 | 76 | result := make(map[jadeplib.ClassName][]*bazel.Rule) 77 | 78 | for _, cls := range classNames { 79 | for _, filename := range classToFile[cls] { 80 | if pkgName, ok := fileToPkgName[filename]; ok { 81 | pkg := packages[pkgName] 82 | if pkg == nil { 83 | vlog.V(3).Printf("Package %s for file %s was not returned from Loader", pkgName, filename) 84 | continue 85 | } 86 | relativeFilename, err := filepath.Rel(pkgName, filename) 87 | if err != nil { 88 | log.Printf("Error in filepath.Rel(%s, %s):%v", pkgName, filename, err) 89 | continue 90 | } 91 | graph := make(map[string][]string) 92 | 93 | for ruleName, rule := range pkg.Rules { 94 | for _, s := range rule.StringListAttr("exports") { 95 | graph[s] = append(graph[s], ruleName) 96 | } 97 | for _, src := range rule.StringListAttr("srcs") { 98 | if src == relativeFilename { 99 | graph[relativeFilename] = append(graph[relativeFilename], ruleName) 100 | } 101 | if r := pkg.Rules[src]; r != nil && r.Schema == "filegroup" { 102 | graph[src] = append(graph[src], ruleName) 103 | } 104 | } 105 | } 106 | 107 | graphs.DFS(graph, relativeFilename, func(node string) { 108 | if rule, ok := pkg.Rules[node]; ok { 109 | if filter.JavaDependencyRuleKinds[rule.Schema] { 110 | result[cls] = append(result[cls], rule) 111 | } 112 | } 113 | }) 114 | } 115 | } 116 | } 117 | return result, nil 118 | } 119 | 120 | // classToFiles converts a class name into a file name by changing 121 | // package to directory separators and adding the content 122 | // root to the front of the class name and the ".java" to the back. 123 | // For example if the contentRoot is java and the class name is 124 | // com.Foo then the output will be java/com/Foo.java. 125 | func classToFiles(contentRoots []string, className jadeplib.ClassName) []string { 126 | var result []string 127 | for _, root := range contentRoots { 128 | segments := append([]string{root}, strings.Split(string(className), ".")...) 129 | result = append(result, filepath.Join(segments...)+".java") 130 | } 131 | return result 132 | } 133 | -------------------------------------------------------------------------------- /future/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["future.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/future", 7 | visibility = ["//visibility:public"], 8 | ) 9 | -------------------------------------------------------------------------------- /future/future.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package future implements future/promise primitives. 16 | package future 17 | 18 | // Value implements a future/promise for an arbitrary value. 19 | type Value struct { 20 | value interface{} 21 | 22 | // ready is a broadcast channel 23 | ready chan bool 24 | } 25 | 26 | // NewValue returns a new Value future, whose value is computed by f(). 27 | // f() is called concurrently - NewValue doesn't block. 28 | func NewValue(f func() interface{}) *Value { 29 | result := &Value{nil, make(chan bool)} 30 | go func() { 31 | result.value = f() 32 | close(result.ready) 33 | }() 34 | return result 35 | } 36 | 37 | // Get returns the value computed by the function given to NewValue. 38 | // It blocks until the value is ready. 39 | func (f *Value) Get() interface{} { 40 | <-f.ready 41 | return f.value 42 | } 43 | 44 | // Immediate returns a Value which resolves to 'value'. 45 | func Immediate(value interface{}) *Value { 46 | return NewValue(func() interface{} { return value }) 47 | } 48 | -------------------------------------------------------------------------------- /graphs/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["graphs.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/graphs", 7 | visibility = ["//visibility:public"], 8 | ) 9 | -------------------------------------------------------------------------------- /graphs/graphs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package graphs provides functions related to graphs. 16 | package graphs 17 | 18 | // DFS runs a DFS on the provided graph. 19 | // f is called when a node is visited. 20 | func DFS(graph map[string][]string, startingNode string, f func(node string)) { 21 | visited := make(map[string]bool) 22 | var visit func(u string) 23 | visit = func(u string) { 24 | if _, ok := visited[u]; ok { 25 | return 26 | } 27 | visited[u] = true 28 | f(u) 29 | 30 | for _, v := range graph[u] { 31 | visit(v) 32 | } 33 | } 34 | 35 | visit(startingNode) 36 | } 37 | -------------------------------------------------------------------------------- /grpcloader/BUILD: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_test( 4 | name = "go_default_test", 5 | srcs = [ 6 | "grpcloader_test.go", 7 | "mockworkspace_test.go", 8 | ], 9 | args = ["--pkg_loader_executable=$(location //java/com/google/devtools/javatools/jade/pkgloader:GrpcLocalServer)"], 10 | data = [ 11 | "//java/com/google/devtools/javatools/jade/pkgloader:GrpcLocalServer", 12 | ], 13 | embed = [":go_default_library"], 14 | deps = [ 15 | "//bazel:go_default_library", 16 | "//compat:go_default_library", 17 | "//java/com/google/devtools/javatools/jade/pkgloader/services_proto:go_default_library", 18 | "@com_github_google_go_cmp//cmp:go_default_library", 19 | "@org_golang_google_grpc//:go_default_library", 20 | ], 21 | ) 22 | 23 | go_library( 24 | name = "go_default_library", 25 | srcs = ["grpcloader.go"], 26 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/grpcloader", 27 | visibility = ["//visibility:public"], 28 | deps = [ 29 | "//bazel:go_default_library", 30 | "//java/com/google/devtools/javatools/jade/pkgloader/messages_proto:go_default_library", 31 | "//java/com/google/devtools/javatools/jade/pkgloader/services_proto:go_default_library", 32 | "//vlog:go_default_library", 33 | "@com_github_golang_protobuf//proto:go_default_library", 34 | "@org_golang_google_grpc//:go_default_library", 35 | "@org_golang_google_grpc//codes:go_default_library", 36 | "@org_golang_google_grpc//status:go_default_library", 37 | ], 38 | ) 39 | -------------------------------------------------------------------------------- /grpcloader/mockworkspace_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package grpcloader 16 | 17 | import ( 18 | "fmt" 19 | "io/ioutil" 20 | "os" 21 | "path/filepath" 22 | ) 23 | 24 | // create() creates a Bazel workspace for use with PackageLoader. 25 | // Its behavior is tied to a specific version of Bazel, and might stop working if Bazel changes 26 | // significantly. Still, I think it's easier to update this once in a while than to interface with 27 | // Bazel. 28 | // 29 | // This is a Go version of javatests/com/google/devtools/javatools/jade/pkgloader/MockWorkspace.java 30 | func createWorkspace() (workspaceRoot, installBase, outputBase string, err error) { 31 | tmpRoot, err := ioutil.TempDir("", "jadep") 32 | if err != nil { 33 | return "", "", "", fmt.Errorf("error calling ioutil.TempDir: %v", err) 34 | } 35 | workspaceRoot = filepath.Join(tmpRoot, "workspace") 36 | installBase = filepath.Join(tmpRoot, "install_base") 37 | outputBase = filepath.Join(tmpRoot, "output_base") 38 | 39 | embeddedBinaries := filepath.Join(installBase, "_embedded_binaries/") 40 | embeddedTools, err := mockEmbeddedTools(embeddedBinaries) 41 | if err != nil { 42 | return "", "", "", err 43 | } 44 | 45 | bazelToolsRepo := filepath.Join(outputBase, "external/") 46 | if err := os.MkdirAll(bazelToolsRepo, 0700); err != nil { 47 | return "", "", "", fmt.Errorf("error calling MkdirAll: %v", err) 48 | } 49 | if err := os.Symlink(embeddedTools, filepath.Join(bazelToolsRepo, "bazel_tools")); err != nil { 50 | return "", "", "", fmt.Errorf("error calling Symlink: %v", err) 51 | } 52 | 53 | return workspaceRoot, installBase, outputBase, nil 54 | } 55 | 56 | func mockEmbeddedTools(embeddedBinaries string) (string, error) { 57 | tools := filepath.Join(embeddedBinaries, "embedded_tools") 58 | 59 | if err := os.MkdirAll(filepath.Join(tools, "tools/cpp"), 0700); err != nil { 60 | return "", fmt.Errorf("error calling MkdirAll: %v", err) 61 | } 62 | if err := os.MkdirAll(filepath.Join(tools, "tools/osx"), 0700); err != nil { 63 | return "", fmt.Errorf("error calling MkdirAll: %v", err) 64 | } 65 | 66 | if err := ioutil.WriteFile(filepath.Join(tools, "WORKSPACE"), nil, 0666); err != nil { 67 | return "", fmt.Errorf("error calling WriteFile: %v", err) 68 | } 69 | if err := ioutil.WriteFile(filepath.Join(tools, "tools/cpp/BUILD"), nil, 0666); err != nil { 70 | return "", fmt.Errorf("error calling WriteFile: %v", err) 71 | } 72 | 73 | contents := ` 74 | def cc_configure(*args, **kwargs): 75 | pass` 76 | if err := ioutil.WriteFile(filepath.Join(tools, "tools/cpp/cc_configure.bzl"), []byte(contents), 0666); err != nil { 77 | return "", fmt.Errorf("error calling WriteFile: %v", err) 78 | } 79 | if err := ioutil.WriteFile(filepath.Join(tools, "tools/osx/BUILD"), nil, 0666); err != nil { 80 | return "", fmt.Errorf("error calling WriteFile: %v", err) 81 | } 82 | 83 | contents = ` 84 | def xcode_configure(*args, **kwargs): 85 | pass` 86 | if err := ioutil.WriteFile(filepath.Join(tools, "tools/osx/xcode_configure.bzl"), []byte(contents), 0666); err != nil { 87 | return "", fmt.Errorf("error calling WriteFile: %v", err) 88 | } 89 | 90 | return tools, nil 91 | } 92 | -------------------------------------------------------------------------------- /jadep.cast: -------------------------------------------------------------------------------- 1 | {"version": 2, "width": 120, "height": 40, "timestamp": 1526877923, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}} 2 | [0.011789, "o", "\u001b[?1034h\u001b[32m~/code/bazel\u001b[m\u001b[32m$\u001b[m "] 3 | [0.848076, "o", "j"] 4 | [1.016956, "o", "a"] 5 | [1.254394, "o", "d"] 6 | [1.451884, "o", "e"] 7 | [1.57144, "o", "p"] 8 | [1.659466, "o", " "] 9 | [1.987171, "o", "src/"] 10 | [1.987438, "o", "main/java/com/goog"] 11 | [1.987487, "o", "le/d"] 12 | [1.987532, "o", "evt"] 13 | [1.987772, "o", "ools/build/lib/"] 14 | [1.987831, "o", "rule"] 15 | [1.988072, "o", "s/java/proto/Rp"] 16 | [1.98811, "o", "cS"] 17 | [1.988249, "o", "upport.j"] 18 | [1.988286, "o", "av"] 19 | [1.988443, "o", "a"] 20 | [2.588186, "o", "\r\n"] 21 | [2.675971, "o", "2018/05/21 00:45:26 Jadep - fix BUILD for Java code\r\n"] 22 | [2.679402, "o", "2018/05/21 00:45:26 WARNING: Error while reading \"/Users/USER/jadep/blacklisted_packages.txt\": open /Users/USER/jadep/blacklisted_packages.txt: no such file or directory\r\n2018/05/21 00:45:26 Connecting to gRPC server at unix:///Users/USER/pkgloader.socket\r\n"] 23 | [2.687237, "o", "2018/05/21 00:45:26 Created bazel-deps resolver (0ms)\r\n"] 24 | [3.010936, "o", "2018/05/21 00:45:26 Fixing: //src/main/java/com/google/devtools/build/lib:RpcSupport\r\n"] 25 | [3.020185, "o", "2018/05/21 00:45:26 Found 9 classes in 1 Java file(s) (9ms)\r\n"] 26 | [3.020388, "o", "2018/05/21 00:45:26 Resolved 1/9 classes using Built-in JDK/Android (0ms)\r\n"] 27 | [3.230697, "o", "2018/05/21 00:45:27 Resolved 7/8 classes using file system (210ms)\r\n2018/05/21 00:45:27 Resolved 0/1 classes using github.com/johnynek/bazel-deps/ (0ms)\r\n"] 28 | [3.230939, "o", "2018/05/21 00:45:27 Ranking dependencies (0ms)\r\n\r\nThe BUILD rule //src/main/java/com/google/devtools/build/lib:RpcSupport is missing a dependency. Choose one of the options below:\r\n\r\nThe BUILD rule //src/main/java/com/google/devtools/build/lib:RpcSupport is missing a dependency. Choose one of the options below:\r\n[2] //src/main/java/com/google/devtools/build/lib:shared-base-rules\r\n[1] //src/main/java/com/google/devtools/build/lib:proto-rules\r\n[0] None\r\nFor class: \u001b[1mcom.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder\u001b[0m\r\nSuggestion: \u001b[1m//src/main/java/com/google/devtools/build/lib:proto-rules\u001b[0m\r\nHit Enter to accept, or a number to choose: "] 29 | [4.844608, "o", "2"] 30 | [5.761771, "o", "\r\n"] 31 | [5.761958, "o", "\r\nThe BUILD rule //src/main/java/com/google/devtools/build/lib:RpcSupport is missing a dependency. Choose one of the options below:\r\n\r\nThe BUILD rule //src/main/java/com/google/devtools/build/lib:RpcSupport is missing a dependency. Choose one of the options below:\r\n[3] //src/main/java/com/google/devtools/build/lib:build-base\r\n[2] //src/main/java/com/google/devtools/build/lib:build\r\n[1] //src/main/java/com/google/devtools/build/lib:all-build-rules\r\n[0] None\r\nFor class: \u001b[1mcom.google.devtools.build.lib.analysis.TransitiveInfoCollection\u001b[0m\r\nSuggestion: \u001b[1m//src/main/java/com/google/devtools/build/lib:all-build-rules\u001b[0m\r\nHit Enter to accept, or a number to choose: "] 32 | [7.272607, "o", "2"] 33 | [7.630273, "o", "\b \b"] 34 | [7.759515, "o", "3"] 35 | [8.142489, "o", "\r\n"] 36 | [8.142713, "o", "\r\nThe BUILD rule //src/main/java/com/google/devtools/build/lib:RpcSupport is missing a dependency. Choose one of the options below:\r\n[5] //src/main/java/com/google/devtools/build/lib:query2\r\n[4] //src/main/java/com/google/devtools/build/lib:packages-internal\r\n[3] //src/main/java/com/google/devtools/build/lib:packages\r\n[2] //src/main/java/com/google/devtools/build/lib:build\r\n[1] //src/main/java/com/google/devtools/build/lib:all-build-rules\r\n[0] None\r\nFor class: \u001b[1mcom.google.devtools.build.lib.packages.AspectDefinition\u001b[0m\r\nSuggestion: \u001b[1m//src/main/java/com/google/devtools/build/lib:all-build-rules\u001b[0m\r\nHit Enter to accept, or a number to choose: "] 37 | [10.255219, "o", "1"] 38 | [10.758348, "o", "\b \b"] 39 | [11.746979, "o", "2"] 40 | [12.167411, "o", "\b \b"] 41 | [12.345573, "o", "4"] 42 | [12.481432, "o", "\r\n"] 43 | [12.498353, "o", "2018/05/21 00:45:36 \r\n2018/05/21 00:45:36 \u001b[1m\u001b[32mAdded to //src/main/java/com/google/devtools/build/lib:RpcSupport\u001b[0m\u001b[0m\r\n2018/05/21 00:45:36 \u001b[1m\u001b[32m-----------------------------------------------------------------\u001b[0m\u001b[0m\r\n2018/05/21 00:45:36 \u001b[32m+DEP\u001b[0m //src/main/java/com/google/devtools/build/lib/collect/nestedset:nestedset\r\n2018/05/21 00:45:36 \u001b[32m+DEP\u001b[0m //src/main/java/com/google/devtools/build/lib:shared-base-rules\r\n2018/05/21 00:45:36 \u001b[32m+DEP\u001b[0m //src/main/java/com/google/devtools/build/lib/actions:actions\r\n2018/05/21 00:45:36 \u001b[32m+DEP\u001b[0m //src/main/java/com/google/devtools/build/lib:build-base\r\n2018/05/21 00:45:36 \u001b[32m+DEP\u001b[0m //src/main/java/com/google/devtools/build/lib:packages-internal\r\n2018/05/21 00:45:36 \r\n2018/05/21 00:45:36 \u001b[1m\u001b[35mCouldn't find BUILD rules for class names:\u001b[0m\u001b[0m\r\n2018/05/21 00:45:36 \u001b[1m\u001b[35m------------------------------------------\u001b[0m\u001b[0m\r\n2018/05/21 00:45:36 \u001b[35m?DEP\u001b[0m\u001b[90m for \u001b[0mcom.google.common.collect.ImmutableList\r\n"] 44 | [12.503621, "o", "\u001b[32m~/code/bazel\u001b[m\u001b[32m$\u001b[m "] 45 | [14.226399, "o", "exit\r\n"] 46 | -------------------------------------------------------------------------------- /jadeplib/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = [ 6 | "UserInteractionHandler.go", 7 | "jadeplib.go", 8 | ], 9 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/jadeplib", 10 | visibility = ["//visibility:public"], 11 | deps = [ 12 | "//bazel:go_default_library", 13 | "//color:go_default_library", 14 | "//compat:go_default_library", 15 | "//filter:go_default_library", 16 | "//future:go_default_library", 17 | "//pkgloading:go_default_library", 18 | "//vlog:go_default_library", 19 | ], 20 | ) 21 | 22 | go_test( 23 | name = "go_default_test", 24 | srcs = [ 25 | "UserInteractionHandler_test.go", 26 | "jadeplib_test.go", 27 | ], 28 | embed = [":go_default_library"], 29 | deps = [ 30 | "//bazel:go_default_library", 31 | "//future:go_default_library", 32 | "//pkgloaderfakes:go_default_library", 33 | "//sortingdepsranker:go_default_library", 34 | "@com_github_google_go_cmp//cmp:go_default_library", 35 | "@com_github_google_go_cmp//cmp/cmpopts:go_default_library", 36 | ], 37 | ) 38 | -------------------------------------------------------------------------------- /jadeplib/UserInteractionHandler.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package jadeplib 16 | 17 | import ( 18 | "fmt" 19 | "io" 20 | "strconv" 21 | 22 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 23 | "github.com/bazelbuild/tools_jvm_autodeps/color" 24 | ) 25 | 26 | // ask takes in a list of printable interfaces. It returns the 27 | // input from the user indicating which interfaces is wanted. 28 | // ask keeps asking the user for input until a valid input is given. 29 | // If reading from stdin fails, returns an error. 30 | func ask(in io.Reader, description string, options []bazel.Label) (int, error) { 31 | if len(options) == 1 { 32 | return 1, nil 33 | } 34 | for i := len(options) - 1; i >= 0; i-- { 35 | fmt.Printf("[%v] %v\n", i+1, options[i]) 36 | } 37 | fmt.Println("[0] None") 38 | 39 | fmt.Print(description) 40 | for { 41 | var i string 42 | if _, err := fmt.Fscanln(in, &i); err != nil { 43 | if err == io.EOF { 44 | return -1, fmt.Errorf("Error reading stdin: %v", err) 45 | } 46 | return 1, nil 47 | } 48 | idx, err := strconv.Atoi(i) 49 | if err != nil { 50 | fmt.Println("Error occurred when converting input to integer. Please try again.") 51 | continue 52 | } 53 | if idx <= len(options) && idx >= 0 { 54 | return idx, nil 55 | } 56 | fmt.Println("Invalid index inputted. Please try again.") 57 | } 58 | } 59 | 60 | // SelectDepsToAdd asks the user to choose which deps to add to their rules to satisfy missing dependencies. 61 | func SelectDepsToAdd(in io.Reader, missingDepsMap map[*bazel.Rule]map[ClassName][]bazel.Label) (map[*bazel.Rule][]bazel.Label, error) { 62 | depsToAdd := make(map[*bazel.Rule][]bazel.Label) 63 | for rule, classToRules := range missingDepsMap { 64 | addedDeps := make(map[bazel.Label]bool) 65 | for class, rules := range classToRules { 66 | if depAlreadySatisfied(addedDeps, rules) { 67 | continue 68 | } 69 | fmt.Println() 70 | fmt.Printf("The BUILD rule %s is missing a dependency. Choose one of the options below:\n", rule.Label()) 71 | description := fmt.Sprintf(`For class: %s 72 | Suggestion: %s 73 | Hit Enter to accept, or a number to choose: `, color.Bold(string(class)), color.Bold(string(rules[0]))) 74 | idx, err := ask(in, description, rules) 75 | if err != nil { 76 | return nil, err 77 | } 78 | if idx != 0 { 79 | addedDeps[rules[idx-1]] = true 80 | depsToAdd[rule] = append(depsToAdd[rule], rules[(idx-1)]) 81 | } 82 | } 83 | } 84 | return depsToAdd, nil 85 | } 86 | 87 | func depAlreadySatisfied(addedDeps map[bazel.Label]bool, rules []bazel.Label) bool { 88 | for _, rule := range rules { 89 | if _, ok := addedDeps[rule]; ok { 90 | return true 91 | } 92 | } 93 | return false 94 | } 95 | -------------------------------------------------------------------------------- /jadeplib/UserInteractionHandler_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package jadeplib 16 | 17 | import ( 18 | "bytes" 19 | "testing" 20 | 21 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 22 | "github.com/google/go-cmp/cmp" 23 | ) 24 | 25 | func TestUserInteractionHandler(t *testing.T) { 26 | var tests = []struct { 27 | input string 28 | rules []bazel.Label 29 | want int 30 | }{ 31 | {"5 \n", []bazel.Label{"", "", "", "", ""}, 5}, 32 | {"\n", []bazel.Label{"", "", "", "", ""}, 1}, 33 | {"1 \n", []bazel.Label{"", ""}, 1}, 34 | {"1 1\n 1\n", []bazel.Label{""}, 1}, 35 | {"e\n 2\n 1\n", []bazel.Label{""}, 1}, 36 | {"", []bazel.Label{""}, 1}, 37 | } 38 | for idx, test := range tests { 39 | in := bytes.NewReader([]byte(test.input)) 40 | i, err := ask(in, "description", test.rules) 41 | if err != nil { 42 | t.Errorf("Test case %d returned unexpected error:\n%v", idx, err) 43 | } 44 | if i != test.want { 45 | t.Errorf("ask returned index %v, want %v", i, test.want) 46 | } 47 | } 48 | } 49 | 50 | func TestUserInteractionHandlerNoStdin(t *testing.T) { 51 | in := bytes.NewReader(nil) 52 | _, err := ask(in, "description", []bazel.Label{"", ""}) 53 | wantErr := "Error reading stdin: EOF" 54 | if err.Error() != wantErr { 55 | t.Errorf("Want error %q, got: %v", wantErr, err) 56 | } 57 | } 58 | 59 | func TestSelectDepsToAdd(t *testing.T) { 60 | var tests = []struct { 61 | desc string 62 | missingDepsMap map[*bazel.Rule]map[ClassName][]bazel.Label 63 | input string 64 | want map[*bazel.Rule][]bazel.Label 65 | }{ 66 | { 67 | desc: "Basic test to check if deps are added to the Map", 68 | missingDepsMap: map[*bazel.Rule]map[ClassName][]bazel.Label{ 69 | bazel.NewRule("", "java/y", "Jade", nil): {"x.Foo": {"//java/x:Missing"}}, 70 | }, 71 | input: "1\n", 72 | want: map[*bazel.Rule][]bazel.Label{ 73 | bazel.NewRule("", "java/y", "Jade", nil): {"//java/x:Missing"}, 74 | }, 75 | }, 76 | { 77 | desc: "Test to check if satisfying rule is reused", 78 | missingDepsMap: map[*bazel.Rule]map[ClassName][]bazel.Label{ 79 | bazel.NewRule("", "java/a", "Jade", nil): {"b.Foo": {"//java/b:Foo"}, "c.Bar": {"//java/b:Foo", "//java/c:Bar"}}, 80 | }, 81 | input: "1\n", 82 | want: map[*bazel.Rule][]bazel.Label{ 83 | bazel.NewRule("", "java/a", "Jade", nil): {"//java/b:Foo"}, 84 | }, 85 | }, 86 | } 87 | for _, test := range tests { 88 | in := bytes.NewReader([]byte(test.input)) 89 | actual, err := SelectDepsToAdd(in, test.missingDepsMap) 90 | if err != nil { 91 | t.Errorf("%s: SelectDepsToAdd(%s, %s) returned unexpected error:\n%v", test.desc, test.input, test.missingDepsMap, err) 92 | } 93 | if diff := cmp.Diff(actual, test.want, sortRuleKeys); diff != "" { 94 | t.Errorf("Diff in SelectDepsToAdd (-got +want):\n%s", diff) 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /jadepmain/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = [ 6 | "customization.go", 7 | "jadepmain.go", 8 | ], 9 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/jadepmain", 10 | visibility = ["//visibility:public"], 11 | deps = [ 12 | "//bazel:go_default_library", 13 | "//buildozer:go_default_library", 14 | "//cli:go_default_library", 15 | "//color:go_default_library", 16 | "//dictresolver:go_default_library", 17 | "//fsresolver:go_default_library", 18 | "//future:go_default_library", 19 | "//jadeplib:go_default_library", 20 | "//lang/java/ruleconsts:go_default_library", 21 | "//pkgloading:go_default_library", 22 | "//vlog:go_default_library", 23 | ], 24 | ) 25 | -------------------------------------------------------------------------------- /jadepmain/customization.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package jadepmain 16 | 17 | import ( 18 | "time" 19 | 20 | "context" 21 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 22 | "github.com/bazelbuild/tools_jvm_autodeps/pkgloading" 23 | ) 24 | 25 | // Customization is the specialization point for Main. 26 | type Customization interface { 27 | // LoadDataSources loads any specialized data sources to be used by NewResolvers. 28 | LoadDataSources(context.Context) DataSources 29 | 30 | // NewDepsRanker returns the DepsRanker to be used in Jadep. 31 | NewDepsRanker(DataSources) jadeplib.DepsRanker 32 | 33 | // NewResolvers returns any specialized resolvers an organization has. 34 | // For example, an organization which employs Kythe to index their depot might implement a resolver that takes advantage of that index. 35 | NewResolvers(loader pkgloading.Loader, data interface{}) []jadeplib.Resolver 36 | 37 | // NewLoader returns a new Loader which will be used to load Bazel packages. 38 | NewLoader(ctx context.Context, flags *Flags, workspaceDir string) (pkgloading.Loader, func(), error) 39 | } 40 | 41 | // DataSources is customized by users of jadepmain.Main to pass information between Customization.LoadDataSources and NewDepsRanker, NewResolvers. 42 | type DataSources interface{} 43 | 44 | // Flags gathers command-line flags that jadepmain uses. 45 | type Flags struct { 46 | // See corresponding flag in jadep.go 47 | Workspace string 48 | 49 | // See corresponding flag in jadep.go 50 | ContentRoots []string 51 | 52 | // See corresponding flag in jadep.go 53 | DryRun bool 54 | 55 | // See corresponding flag in jadep.go 56 | ClassNames []string 57 | 58 | // See corresponding flag in jadep.go 59 | Blacklist []string 60 | 61 | // See corresponding flag in jadep.go 62 | BlacklistedPackageList string 63 | 64 | // See corresponding flag in jadep.go 65 | BuiltinClassList string 66 | 67 | // See corresponding flag in jadep.go 68 | PkgLoaderExecutable string 69 | 70 | // See corresponding flag in jadep.go 71 | PkgLoaderAddress string 72 | 73 | // See corresponding flag in jadep.go 74 | RPCDeadline time.Duration 75 | 76 | // See corresponding flag in jadep.go 77 | Cpuprofile string 78 | 79 | // See corresponding flag in jadep.go 80 | Vlevel int 81 | 82 | // See corresponding flag in jadep.go 83 | Color bool 84 | } 85 | -------------------------------------------------------------------------------- /jadepmain/jadepmain.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package jadepmain contains Jadep's main() function. 16 | // Its purpose is to allow organizations to build specialized Jadep binaries without forking the main repo. 17 | package jadepmain 18 | 19 | import ( 20 | "io/ioutil" 21 | "log" 22 | "os" 23 | "os/user" 24 | "path/filepath" 25 | "runtime" 26 | "strings" 27 | 28 | "context" 29 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 30 | "github.com/bazelbuild/tools_jvm_autodeps/buildozer" 31 | "github.com/bazelbuild/tools_jvm_autodeps/cli" 32 | "github.com/bazelbuild/tools_jvm_autodeps/color" 33 | "github.com/bazelbuild/tools_jvm_autodeps/dictresolver" 34 | "github.com/bazelbuild/tools_jvm_autodeps/fsresolver" 35 | "github.com/bazelbuild/tools_jvm_autodeps/future" 36 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 37 | "github.com/bazelbuild/tools_jvm_autodeps/lang/java/ruleconsts" 38 | "github.com/bazelbuild/tools_jvm_autodeps/pkgloading" 39 | "github.com/bazelbuild/tools_jvm_autodeps/vlog" 40 | ) 41 | 42 | // Main is an entry point to Jadep program. 43 | // Its purpose is to allow organizations to build their own specialized Jadep's without forking the main repo. 44 | // This function should only be called from a main.main() function, as it uses and modifies global variables. 45 | // args are the non-flag command-line arguments. 46 | func Main(custom Customization, flags *Flags, args []string) { 47 | runtime.GOMAXPROCS(runtime.NumCPU()) 48 | vlog.Level = flags.Vlevel 49 | color.Enabled = flags.Color 50 | ctx := context.Background() 51 | stopProfiler := cli.StartProfiler(flags.Cpuprofile) 52 | defer stopProfiler() 53 | if len(args) == 0 { 54 | log.Fatalln("Must provide at least one Java file or BUILD rule to process.") 55 | } 56 | vlog.V(3).Printf("Processing files/rules: %v", args) 57 | wd, relWorkingDir, err := cli.Workspace(flags.Workspace) 58 | if err != nil { 59 | log.Fatalf("Can't find root of workspace: %v", err) 60 | } 61 | config := jadeplib.Config{WorkspaceDir: wd} 62 | 63 | blacklistedPackageList := readFileLines(flags.BlacklistedPackageList) 64 | builtinClassList := readDictFromCSV(flags.BuiltinClassList) 65 | implicitImports := jadeplib.ImplicitImports(builtinClassList) 66 | 67 | dataSources := custom.LoadDataSources(ctx) 68 | 69 | var cleanup func() 70 | config.Loader, cleanup = newLoader(ctx, custom, flags, config.WorkspaceDir, blacklistedPackageList.Get().([]string)) 71 | defer cleanup() 72 | 73 | config.DepsRanker = custom.NewDepsRanker(dataSources) 74 | 75 | config.Resolvers = []jadeplib.Resolver{ 76 | dictresolver.NewResolver("Built-in JDK/Android", builtinClassList, config.Loader), 77 | fsresolver.NewResolver(flags.ContentRoots, config.WorkspaceDir, config.Loader), 78 | } 79 | config.Resolvers = append(config.Resolvers, custom.NewResolvers(config.Loader, dataSources)...) 80 | 81 | for _, arg := range args { 82 | rulesToFix, err := cli.RulesToFix(ctx, config, relWorkingDir, arg, ruleconsts.NewRuleNamingRules, ruleconsts.DefaultNewRuleKind) 83 | if err != nil { 84 | log.Fatal(err) 85 | } 86 | cli.LogRulesToFix(rulesToFix) 87 | classNamesToResolve := cli.ClassNamesToResolve(ctx, filepath.Join(config.WorkspaceDir, relWorkingDir), config.Loader, arg, flags.ClassNames, implicitImports, flags.Blacklist) 88 | missingDepsMap, unresClasses, err := jadeplib.MissingDeps(ctx, config, rulesToFix, classNamesToResolve) 89 | if err != nil { 90 | log.Printf("WARNING: Error computing missing dependencies:\n%v.", err) 91 | continue 92 | } 93 | 94 | if flags.DryRun { 95 | cli.ReportMissingDeps(missingDepsMap) 96 | } else { 97 | // for each rule that's missing deps, which deps to add 98 | depsToAdd, err := jadeplib.SelectDepsToAdd(os.Stdin, missingDepsMap) 99 | if err != nil { 100 | log.Printf("WARNING: Error asking user to choose dependencies to add:\n%v", err) 101 | continue 102 | } 103 | err = buildozer.AddDepsToRules(config.WorkspaceDir, depsToAdd) 104 | if err != nil { 105 | log.Printf("WARNING: error adding missing deps to rules:\n%v", err) 106 | continue 107 | } 108 | cli.ReportAddedDeps(depsToAdd) 109 | } 110 | cli.ReportUnresolvedClassnames(unresClasses) 111 | } 112 | } 113 | 114 | func newLoader(ctx context.Context, custom Customization, flags *Flags, workspaceDir string, blacklistedPackageList []string) (pkgloading.Loader, func()) { 115 | if flags.PkgLoaderAddress == "" { 116 | flags.PkgLoaderAddress = defaultPkgLoaderAddress() 117 | } 118 | rpcLoader, cleanup, err := custom.NewLoader(ctx, flags, workspaceDir) 119 | if err != nil { 120 | log.Fatalf("Error connecting to PackageLoader service:\n%v", err) 121 | } 122 | filteringLoader := &pkgloading.FilteringLoader{rpcLoader, listToSet(blacklistedPackageList)} 123 | return pkgloading.NewCachingLoader(filteringLoader), cleanup 124 | } 125 | 126 | func defaultPkgLoaderAddress() string { 127 | u, err := user.Current() 128 | if err != nil { 129 | log.Fatalf("Error getting current user. Pass a non-empty --pkg_loader_bind_location explicitly to avoid needing it") 130 | } 131 | return "unix://" + filepath.Join(u.HomeDir, "pkgloader.socket") 132 | } 133 | 134 | func readFileLines(fileName string) *future.Value { 135 | return future.NewValue(func() interface{} { 136 | content, err := ioutil.ReadFile(fileName) 137 | if err != nil { 138 | log.Printf("WARNING: Error while reading %q: %v", fileName, err) 139 | return []string(nil) 140 | } 141 | return strings.Split(string(content), "\n") 142 | }) 143 | } 144 | 145 | // readDictFromCSV reads a CSV whose first column is a class name, and the rest of the columns are Bazel rules that resolve it. 146 | // The return type is a future that wraps a map[jadeplib.ClassName][]bazel.Label 147 | func readDictFromCSV(fileName string) *future.Value { 148 | return future.NewValue(func() interface{} { 149 | f, err := os.Open(fileName) 150 | if err != nil { 151 | log.Printf("Error opening %s: %v", fileName, err) 152 | return map[jadeplib.ClassName][]bazel.Label(nil) 153 | } 154 | result, err := dictresolver.ReadDictFromCSV(f) 155 | if err != nil { 156 | log.Printf("Error while reading %q: %v", fileName, err) 157 | return map[jadeplib.ClassName][]bazel.Label(nil) 158 | } 159 | return result 160 | }) 161 | } 162 | 163 | func listToSet(strs []string) map[string]bool { 164 | ret := make(map[string]bool) 165 | for _, s := range strs { 166 | ret[s] = true 167 | } 168 | return ret 169 | } 170 | -------------------------------------------------------------------------------- /java/com/google/devtools/javatools/jade/pkgloader/BUILD: -------------------------------------------------------------------------------- 1 | package(default_visibility = [ 2 | "//grpcloader:__subpackages__", 3 | ]) 4 | 5 | java_binary( 6 | name = "GrpcLocalServer", 7 | srcs = ["GrpcLocalServer.java"], 8 | deps = [ 9 | ":BazelPackageLoaderFactory", 10 | ":Lib", 11 | ":OperatingSystem", 12 | ":PackageLoaderFactory", 13 | ":Serializer", 14 | "//java/com/google/devtools/javatools/jade/pkgloader/services_proto:services_java_grpc", 15 | "//java/com/google/devtools/javatools/jade/pkgloader/services_proto:services_java_proto", 16 | "//thirdparty/jvm/args4j", 17 | "//thirdparty/jvm/com/google/guava", 18 | "//thirdparty/jvm/io/grpc:grpc_core", 19 | "//thirdparty/jvm/io/grpc:grpc_netty", 20 | "//thirdparty/jvm/io/grpc:grpc_services", 21 | "//thirdparty/jvm/io/grpc:grpc_stub", 22 | "//thirdparty/jvm/io/netty:netty_all", 23 | "@io_bazel//src/main/java/com/google/devtools/build/lib:events", 24 | "@io_bazel//src/main/java/com/google/devtools/build/lib:packages", 25 | "@io_bazel//src/main/java/com/google/devtools/build/lib:unix", 26 | "@io_bazel//src/main/java/com/google/devtools/build/lib/skyframe/packages", 27 | "@io_bazel//src/main/java/com/google/devtools/build/lib/vfs", 28 | ], 29 | ) 30 | 31 | java_library( 32 | name = "Lib", 33 | srcs = ["Lib.java"], 34 | deps = [ 35 | ":PackageLoaderFactory", 36 | ":Serializer", 37 | "//java/com/google/devtools/javatools/jade/pkgloader/services_proto:services_java_proto", 38 | "//thirdparty/jvm/com/google/guava", 39 | "@io_bazel//src/main/java/com/google/devtools/build/lib:events", 40 | "@io_bazel//src/main/java/com/google/devtools/build/lib:packages", 41 | "@io_bazel//src/main/java/com/google/devtools/build/lib/skyframe/packages", 42 | "@io_bazel//src/main/java/com/google/devtools/build/lib/vfs", 43 | ], 44 | ) 45 | 46 | java_library( 47 | name = "Serializer", 48 | srcs = ["Serializer.java"], 49 | deps = [ 50 | "//java/com/google/devtools/javatools/jade/pkgloader/messages_proto:messages_java_proto", 51 | "//thirdparty/jvm/com/google/guava", 52 | "@io_bazel//src/main/java/com/google/devtools/build/lib:packages", 53 | ], 54 | ) 55 | 56 | java_library( 57 | name = "PackageLoaderFactory", 58 | srcs = ["PackageLoaderFactory.java"], 59 | deps = [ 60 | "@io_bazel//src/main/java/com/google/devtools/build/lib/skyframe/packages", 61 | "@io_bazel//src/main/java/com/google/devtools/build/lib/vfs", 62 | ], 63 | ) 64 | 65 | java_library( 66 | name = "BazelPackageLoaderFactory", 67 | srcs = ["BazelPackageLoaderFactory.java"], 68 | deps = [ 69 | ":PackageLoaderFactory", 70 | "//thirdparty/jvm/com/google/guava", 71 | "@io_bazel//src/main/java/com/google/devtools/build/lib:events", 72 | "@io_bazel//src/main/java/com/google/devtools/build/lib/skyframe/packages", 73 | "@io_bazel//src/main/java/com/google/devtools/build/lib/vfs", 74 | ], 75 | ) 76 | 77 | java_library( 78 | name = "OperatingSystem", 79 | srcs = ["OperatingSystem.java"], 80 | ) 81 | -------------------------------------------------------------------------------- /java/com/google/devtools/javatools/jade/pkgloader/BazelPackageLoaderFactory.java: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.javatools.jade.pkgloader; 16 | 17 | import com.google.common.eventbus.EventBus; 18 | import com.google.devtools.build.lib.events.PrintingEventHandler; 19 | import com.google.devtools.build.lib.events.Reporter; 20 | import com.google.devtools.build.lib.skyframe.packages.BazelPackageLoader; 21 | import com.google.devtools.build.lib.skyframe.packages.PackageLoader; 22 | import com.google.devtools.build.lib.vfs.Path; 23 | 24 | public class BazelPackageLoaderFactory implements PackageLoaderFactory { 25 | private static final Reporter REPORTER = 26 | new Reporter(new EventBus(), PrintingEventHandler.ERRORS_TO_STDERR); 27 | 28 | @Override 29 | public PackageLoader create(Path workspaceDir, Path installBase, Path outputBase) { 30 | return BazelPackageLoader.builder(workspaceDir, installBase, outputBase) 31 | .useDefaultSkylarkSemantics() 32 | .setReporter(REPORTER) 33 | .setLegacyGlobbingThreads(400) 34 | .setSkyframeThreads(300) 35 | .build(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /java/com/google/devtools/javatools/jade/pkgloader/Lib.java: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.javatools.jade.pkgloader; 16 | 17 | 18 | import com.google.common.collect.ImmutableMap; 19 | import com.google.common.collect.ImmutableSet; 20 | import com.google.devtools.build.lib.cmdline.LabelSyntaxException; 21 | import com.google.devtools.build.lib.cmdline.PackageIdentifier; 22 | import com.google.devtools.build.lib.packages.NoSuchPackageException; 23 | import com.google.devtools.build.lib.skyframe.packages.PackageLoader; 24 | import com.google.devtools.build.lib.vfs.FileSystem; 25 | import com.google.protos.java.com.google.devtools.javatools.jade.pkgloader.services.Services.LoaderRequest; 26 | import com.google.protos.java.com.google.devtools.javatools.jade.pkgloader.services.Services.LoaderResponse; 27 | import java.util.HashMap; 28 | import java.util.HashSet; 29 | import java.util.Set; 30 | import java.util.logging.Level; 31 | import java.util.logging.Logger; 32 | 33 | /** `pkgloader` allows clients to load Bazel packages without calling Bazel. */ 34 | public class Lib { 35 | 36 | private static final Logger logger = Logger.getLogger("Lib"); 37 | 38 | /** load loads packages according to 'request', in the file system 'fileSystem'. */ 39 | static LoaderResponse load( 40 | PackageLoaderFactory packageLoaderFactory, FileSystem fileSystem, LoaderRequest request) { 41 | logger.info("Start of 'load'"); 42 | PackageLoader loader = 43 | packageLoaderFactory.create( 44 | fileSystem.getPath(request.getWorkspaceDir()), 45 | fileSystem.getPath(request.getInstallBase()), 46 | fileSystem.getPath(request.getOutputBase())); 47 | 48 | HashSet pkgIds = new HashSet<>(); 49 | HashMap pkgNames = new HashMap<>(); 50 | for (String pkgName : request.getPackagesList()) { 51 | try { 52 | PackageIdentifier pkgId = PackageIdentifier.parse(pkgName).makeAbsolute(); 53 | pkgIds.add(pkgId); 54 | pkgNames.put(pkgId, pkgName); 55 | } catch (LabelSyntaxException e) { 56 | // TODO: return an error to load()'s caller for propagation to the user. 57 | logger.log(Level.WARNING, "Invalid package label", e); 58 | } 59 | } 60 | ImmutableMap pkgs; 61 | try { 62 | pkgs = loader.loadPackages(pkgIds); 63 | } catch (Exception e) { 64 | return LoaderResponse.getDefaultInstance(); 65 | } 66 | 67 | Set ruleKindsToSerialize = ImmutableSet.copyOf(request.getRuleKindsToSerializeList()); 68 | 69 | LoaderResponse.Builder response = LoaderResponse.newBuilder(); 70 | pkgs.forEach( 71 | (pkgId, pkg) -> { 72 | try { 73 | response.putPkgs( 74 | pkgNames.get(pkgId), 75 | Serializer.serialize(pkg.get(), ruleKindsToSerialize)); 76 | } catch (NoSuchPackageException e) { 77 | logger.log(Level.FINE, String.format("No such package: %s", pkgId), e); 78 | } 79 | }); 80 | logger.info("End of 'load'"); 81 | return response.build(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /java/com/google/devtools/javatools/jade/pkgloader/OperatingSystem.java: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.javatools.jade.pkgloader; 16 | 17 | import java.util.Locale; 18 | import java.util.logging.Logger; 19 | 20 | enum OperatingSystem { 21 | LINUX, 22 | MACOS, 23 | OTHER; 24 | 25 | private static final Logger logger = Logger.getLogger("OperatingSystem"); 26 | 27 | static OperatingSystem detect() { 28 | final String name; 29 | try { 30 | name = System.getProperty("os.name").toLowerCase(Locale.UK).trim(); 31 | } catch (Exception e) { 32 | logger.warning("Can't detect current OS, assuming 'other'."); 33 | return OTHER; 34 | } 35 | if (name.startsWith("mac") || name.contains("bsd") || name.startsWith("darwin")) { 36 | return MACOS; 37 | } 38 | 39 | if (name.startsWith("linux")) { 40 | return LINUX; 41 | } 42 | 43 | return OTHER; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /java/com/google/devtools/javatools/jade/pkgloader/PackageLoaderFactory.java: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.javatools.jade.pkgloader; 16 | 17 | import com.google.devtools.build.lib.skyframe.packages.PackageLoader; 18 | import com.google.devtools.build.lib.vfs.Path; 19 | 20 | public interface PackageLoaderFactory { 21 | PackageLoader create(Path workspaceDir, Path installBase, Path outputBase); 22 | } 23 | -------------------------------------------------------------------------------- /java/com/google/devtools/javatools/jade/pkgloader/messages_proto/BUILD: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 3 | 4 | package(default_visibility = [ 5 | "//grpcloader:__subpackages__", 6 | "//java/com/google/devtools/javatools/jade/pkgloader:__subpackages__", 7 | ]) 8 | 9 | proto_library( 10 | name = "java_com_google_devtools_javatools_jade_pkgloader_messages_proto", 11 | srcs = ["messages.proto"], 12 | ) 13 | 14 | java_proto_library( 15 | name = "messages_java_proto", 16 | deps = [":java_com_google_devtools_javatools_jade_pkgloader_messages_proto"], 17 | ) 18 | 19 | go_proto_library( 20 | name = "java_com_google_devtools_javatools_jade_pkgloader_messages_go_proto", 21 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/java/com/google/devtools/javatools/jade/pkgloader/messages_proto", 22 | proto = ":java_com_google_devtools_javatools_jade_pkgloader_messages_proto", 23 | ) 24 | 25 | go_library( 26 | name = "go_default_library", 27 | embed = [":java_com_google_devtools_javatools_jade_pkgloader_messages_go_proto"], 28 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/java/com/google/devtools/javatools/jade/pkgloader/messages_proto", 29 | ) 30 | -------------------------------------------------------------------------------- /java/com/google/devtools/javatools/jade/pkgloader/messages_proto/messages.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto2"; 16 | 17 | package java.com.google.devtools.javatools.jade.pkgloader.messages; 18 | 19 | // Get the same class names internally and in Bazel. 20 | option java_package = "com.google.protos.java.com.google.devtools.javatools.jade.pkgloader.messages"; 21 | 22 | message Pkg { 23 | // keys = file names, defined in this Bazel package. 24 | // values = name of rule that defined that file name. 25 | // e.g., "libGrokRpcCacheKeyProvider.jar" -> "GrokRpcCacheKeyProvider" (for 26 | // generated target) e.g., "StringUtilitiesTest.java" -> "" (for source file) 27 | map files = 1; 28 | 29 | // keys = rule names, e.g., "BUILDFileNameHacksTest" 30 | // values = rule data. 31 | map rules = 2; 32 | 33 | // keys = package_group names, e.g. "base_implementation" 34 | // values = package group data. 35 | map package_groups = 3; 36 | 37 | // The package's default_visibility attribute. 38 | repeated string default_visibility = 4; 39 | 40 | // Path is the absolute path to the directory that contains this package's 41 | // BUILD file. 42 | optional string path = 5; 43 | } 44 | 45 | message Rule { 46 | // E.g., "java_test" 47 | optional string kind = 1; 48 | 49 | // E.g., "javatests/com/google/devtools/javatools/jade/BUILD:294:10" 50 | optional string position = 2; 51 | 52 | // keys = attribute name, e.g. "deps" 53 | // values = attribute contents 54 | map attributes = 3; 55 | } 56 | 57 | message PackageGroup { 58 | // See 59 | // https://docs.bazel.build/versions/master/be/functions.html#package_group.packages 60 | repeated string package_specs = 1; 61 | 62 | // See 63 | // https://docs.bazel.build/versions/master/be/functions.html#package_group.includes 64 | repeated string includes = 2; 65 | } 66 | 67 | message Attribute { 68 | oneof value { 69 | string s = 1; 70 | Strings list_of_strings = 2; 71 | bool b = 3; 72 | int32 i = 4; 73 | 74 | // When set, this value means that the attribute exists but we don't support 75 | // representing it here. For example, 'deps = select(...)' will be returned 76 | // as unknown. 77 | // The value itself doesn't matter. 78 | bool unknown = 5; 79 | } 80 | } 81 | 82 | message Strings { repeated string str = 1; } 83 | -------------------------------------------------------------------------------- /java/com/google/devtools/javatools/jade/pkgloader/services_proto/BUILD: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 3 | load("@grpc_java//:java_grpc_library.bzl", "java_grpc_library") 4 | 5 | package(default_visibility = [ 6 | "//grpcloader:__subpackages__", 7 | "//java/com/google/devtools/javatools/jade/pkgloader:__subpackages__", 8 | ]) 9 | 10 | proto_library( 11 | name = "java_com_google_devtools_javatools_jade_pkgloader_services_proto", 12 | srcs = ["services.proto"], 13 | deps = ["//java/com/google/devtools/javatools/jade/pkgloader/messages_proto:java_com_google_devtools_javatools_jade_pkgloader_messages_proto"], 14 | ) 15 | 16 | java_proto_library( 17 | name = "services_java_proto", 18 | deps = [":java_com_google_devtools_javatools_jade_pkgloader_services_proto"], 19 | ) 20 | 21 | java_grpc_library( 22 | name = "services_java_grpc", 23 | srcs = [":java_com_google_devtools_javatools_jade_pkgloader_services_proto"], 24 | deps = [":services_java_proto"], 25 | ) 26 | 27 | go_proto_library( 28 | name = "java_com_google_devtools_javatools_jade_pkgloader_services_go_proto", 29 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 30 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/java/com/google/devtools/javatools/jade/pkgloader/services_proto", 31 | proto = ":java_com_google_devtools_javatools_jade_pkgloader_services_proto", 32 | deps = ["//java/com/google/devtools/javatools/jade/pkgloader/messages_proto:go_default_library"], 33 | ) 34 | 35 | go_library( 36 | name = "go_default_library", 37 | embed = [":java_com_google_devtools_javatools_jade_pkgloader_services_go_proto"], 38 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/java/com/google/devtools/javatools/jade/pkgloader/services_proto", 39 | ) 40 | -------------------------------------------------------------------------------- /java/com/google/devtools/javatools/jade/pkgloader/services_proto/services.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto2"; 16 | 17 | package java.com.google.devtools.javatools.jade.pkgloader.services; 18 | 19 | // Get the same class names internally and in Bazel. 20 | option java_package = "com.google.protos.java.com.google.devtools.javatools.jade.pkgloader.services"; 21 | 22 | import "java/com/google/devtools/javatools/jade/pkgloader/messages_proto/messages.proto"; 23 | 24 | message LoaderRequest { 25 | // workspace_dir is a path to a directory that contains a project's WORKSPACE 26 | // file. 27 | optional string workspace_dir = 1; 28 | 29 | // install_base is the path to the Bazel's install dir. It can be obtained by 30 | // `bazel info install_base`. 31 | // This field is necessary when loading Bazel workspaces. 32 | // On non-Bazel workspaces, set it to "/" (or leave it unset to use the default). 33 | optional string install_base = 4 [default = "/"]; 34 | 35 | // install_base is the path to the Bazel's output dir. It can be obtained by 36 | // `bazel info output_base`. 37 | // This field is necessary when loading Bazel workspaces. 38 | // On non-Bazel workspaces, set it to "/" (or leave it unset to use the default). 39 | optional string output_base = 5 [default = "/"]; 40 | 41 | // E.g., "java/com/Foo". 42 | repeated string packages = 2; 43 | 44 | // E.g., "java_library", "java_test", etc. 45 | // If empty, will serialize all rule kinds. 46 | // Use this filter to reduce unnecessary work and get faster responses. 47 | repeated string rule_kinds_to_serialize = 3; 48 | } 49 | 50 | // Response from the 'Load' RPC. 51 | // For each requested package in LoaderRequest, we return the list of rule 52 | // labels defined in it. 53 | // Packages that failed to load (e.g., because they don't exist) are silently 54 | // ignored. 55 | message LoaderResponse { 56 | // keys = package name 57 | // values = labels of rules in that package. 58 | map 59 | pkgs = 1; 60 | } 61 | 62 | service PackageLoader { 63 | // `pkgloader` allows clients to load Bazel packages without calling Bazel. 64 | rpc Load(LoaderRequest) returns (LoaderResponse) { 65 | // option security_level = PRIVACY_AND_INTEGRITY; 66 | // option deadline = 10.0; 67 | } 68 | } 69 | 70 | message Empty {} 71 | 72 | message VersionResponse { 73 | optional string version = 1; 74 | } 75 | 76 | // VersionManagement is used by Jade to restart old PackageLoader services. 77 | // It should only be implemented in a server that runs locally on the user's 78 | // workstation. 79 | service VersionManagement { 80 | // Version returns the version of the server. 81 | // The version is set by a command-line flag when starting the server. 82 | rpc Version(Empty) returns (VersionResponse) { 83 | } 84 | 85 | // Shutdown immediately shuts down the server. 86 | // Outstanding requests are dropped. 87 | // Callers should expect an RPC error with code Unavailable. 88 | rpc Shutdown(Empty) returns (Empty) { 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /javatests/com/google/devtools/javatools/jade/pkgloader/BUILD: -------------------------------------------------------------------------------- 1 | java_test( 2 | name = "SerializerTest", 3 | srcs = ["SerializerTest.java"], 4 | deps = [ 5 | ":MockWorkspace", 6 | "//java/com/google/devtools/javatools/jade/pkgloader:BazelPackageLoaderFactory", 7 | "//java/com/google/devtools/javatools/jade/pkgloader:PackageLoaderFactory", 8 | "//java/com/google/devtools/javatools/jade/pkgloader:Serializer", 9 | "//java/com/google/devtools/javatools/jade/pkgloader/messages_proto:messages_java_proto", 10 | "//thirdparty/jvm/com/google/guava", 11 | "//thirdparty/jvm/com/google/truth", 12 | "//thirdparty/jvm/junit", 13 | "@io_bazel//src/main/java/com/google/devtools/build/lib:packages", 14 | "@io_bazel//src/main/java/com/google/devtools/build/lib/skyframe/packages", 15 | "@io_bazel//src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs", 16 | ], 17 | ) 18 | 19 | java_test( 20 | name = "BazelPackageLoaderFactoryTest", 21 | srcs = ["BazelPackageLoaderFactoryTest.java"], 22 | deps = [ 23 | "//java/com/google/devtools/javatools/jade/pkgloader:BazelPackageLoaderFactory", 24 | "//thirdparty/jvm/junit", 25 | ], 26 | ) 27 | 28 | java_test( 29 | name = "LibTest", 30 | srcs = ["LibTest.java"], 31 | deps = [ 32 | ":MockWorkspace", 33 | "//java/com/google/devtools/javatools/jade/pkgloader:BazelPackageLoaderFactory", 34 | "//java/com/google/devtools/javatools/jade/pkgloader:Lib", 35 | "//java/com/google/devtools/javatools/jade/pkgloader:PackageLoaderFactory", 36 | "//java/com/google/devtools/javatools/jade/pkgloader/services_proto:services_java_proto", 37 | "//thirdparty/jvm/com/google/truth", 38 | "//thirdparty/jvm/junit", 39 | "@io_bazel//src/main/java/com/google/devtools/build/lib/vfs", 40 | "@io_bazel//src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs", 41 | ], 42 | ) 43 | 44 | java_library( 45 | name = "MockWorkspace", 46 | srcs = ["MockWorkspace.java"], 47 | deps = [ 48 | "@io_bazel//src/main/java/com/google/devtools/build/lib/vfs", 49 | ], 50 | ) 51 | -------------------------------------------------------------------------------- /javatests/com/google/devtools/javatools/jade/pkgloader/BazelPackageLoaderFactoryTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.javatools.jade.pkgloader; 16 | 17 | import org.junit.Test; 18 | import org.junit.runner.RunWith; 19 | import org.junit.runners.JUnit4; 20 | 21 | @RunWith(JUnit4.class) 22 | public class BazelPackageLoaderFactoryTest { 23 | 24 | /** 25 | * Test that BazelPackageLoaderFactory builds. Testing it here avoids having exporting to GitHub 26 | * to check it builds. 27 | */ 28 | @Test 29 | public void compiles() { 30 | new BazelPackageLoaderFactory(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /javatests/com/google/devtools/javatools/jade/pkgloader/LibTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.javatools.jade.pkgloader; 16 | 17 | import static com.google.common.truth.Truth.assertThat; 18 | import static java.nio.charset.StandardCharsets.UTF_8; 19 | 20 | import com.google.devtools.build.lib.vfs.DigestHashFunction; 21 | import com.google.devtools.build.lib.vfs.FileSystem; 22 | import com.google.devtools.build.lib.vfs.FileSystemUtils; 23 | import com.google.devtools.build.lib.vfs.Path; 24 | import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem; 25 | import com.google.protos.java.com.google.devtools.javatools.jade.pkgloader.services.Services.LoaderRequest; 26 | import com.google.protos.java.com.google.devtools.javatools.jade.pkgloader.services.Services.LoaderResponse; 27 | import java.io.IOException; 28 | import org.junit.Before; 29 | import org.junit.Test; 30 | import org.junit.runner.RunWith; 31 | import org.junit.runners.JUnit4; 32 | 33 | @RunWith(JUnit4.class) 34 | public class LibTest { 35 | private static final PackageLoaderFactory PACKAGE_LOADER_FACTORY = 36 | new BazelPackageLoaderFactory(); 37 | 38 | private static final FileSystem FILESYSTEM = new InMemoryFileSystem(DigestHashFunction.MD5); 39 | private Path workspaceRoot; 40 | private Path installBase; 41 | private Path outputBase; 42 | 43 | @Before 44 | public void setUp() throws IOException { 45 | workspaceRoot = FILESYSTEM.getPath("/workspace/"); 46 | installBase = FILESYSTEM.getPath("/install_base/"); 47 | outputBase = FILESYSTEM.getPath("/output_base/"); 48 | MockWorkspace.create(workspaceRoot, installBase, outputBase); 49 | } 50 | 51 | @Test 52 | public void basic() throws Exception { 53 | workspaceRoot.getRelative("foo/bar").createDirectoryAndParents(); 54 | FileSystemUtils.writeLinesAs( 55 | workspaceRoot.getRelative("foo/bar/BUILD"), UTF_8, "sh_library(name = 'Foo')"); 56 | 57 | LoaderRequest request = 58 | LoaderRequest.newBuilder() 59 | .setWorkspaceDir(workspaceRoot.getPathString()) 60 | .setInstallBase(installBase.getPathString()) 61 | .setOutputBase(outputBase.getPathString()) 62 | .addPackages("foo/bar") 63 | .build(); 64 | LoaderResponse response = Lib.load(PACKAGE_LOADER_FACTORY, FILESYSTEM, request); 65 | 66 | assertThat(response.getPkgsMap()).hasSize(1); 67 | assertThat(response.getPkgsMap()).containsKey("foo/bar"); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /javatests/com/google/devtools/javatools/jade/pkgloader/MockWorkspace.java: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.javatools.jade.pkgloader; 16 | 17 | import com.google.devtools.build.lib.vfs.FileSystemUtils; 18 | import com.google.devtools.build.lib.vfs.Path; 19 | import java.io.IOException; 20 | 21 | /** 22 | * MockWorkspace creates Bazel workspace directories with all required files, for testing purposes. 23 | */ 24 | public class MockWorkspace { 25 | 26 | /** 27 | * create() creates a Bazel workspace for use with PackageLoader. 28 | * 29 | * Its behavior is tied to a specific version of Bazel, and might stop working if Bazel changes 30 | * significantly. Still, I think it's easier to update this once in a while than to interface with 31 | * Bazel. 32 | * 33 | * This is a Java version of grpcloader/mockworkspace_test.go. 34 | */ 35 | static void create(Path workspaceRoot, Path installBase, Path outputBase) throws IOException { 36 | workspaceRoot.createDirectoryAndParents(); 37 | FileSystemUtils.writeContent(workspaceRoot.getRelative("WORKSPACE"), new byte[0]); 38 | 39 | Path embeddedBinaries = installBase.getRelative("_embedded_binaries/"); 40 | Path embeddedTools = mockEmbeddedTools(embeddedBinaries); 41 | 42 | Path bazelToolsRepo = outputBase.getRelative("external/"); 43 | bazelToolsRepo.createDirectoryAndParents(); 44 | bazelToolsRepo.getChild("bazel_tools").createSymbolicLink(embeddedTools); 45 | } 46 | 47 | private static Path mockEmbeddedTools(Path embeddedBinaries) throws IOException { 48 | Path tools = embeddedBinaries.getRelative("embedded_tools"); 49 | tools.getRelative("tools/cpp").createDirectoryAndParents(); 50 | tools.getRelative("tools/osx").createDirectoryAndParents(); 51 | FileSystemUtils.writeIsoLatin1(tools.getRelative("WORKSPACE"), ""); 52 | FileSystemUtils.writeIsoLatin1(tools.getRelative("tools/cpp/BUILD"), ""); 53 | FileSystemUtils.writeIsoLatin1( 54 | tools.getRelative("tools/cpp/cc_configure.bzl"), 55 | "def cc_configure(*args, **kwargs):", 56 | " pass"); 57 | FileSystemUtils.writeIsoLatin1(tools.getRelative("tools/osx/BUILD"), ""); 58 | FileSystemUtils.writeIsoLatin1( 59 | tools.getRelative("tools/osx/xcode_configure.bzl"), 60 | "def xcode_configure(*args, **kwargs):", 61 | " pass"); 62 | 63 | return tools; 64 | } 65 | } -------------------------------------------------------------------------------- /lang/java/parser/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["parser.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/lang/java/parser", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//jadeplib:go_default_library", 10 | "//lang/java/parser/xrefs:go_default_library", 11 | "//thirdparty/golang/parsers/ast:go_default_library", 12 | "//thirdparty/golang/parsers/java:go_default_library", 13 | "//thirdparty/golang/parsers/lang:go_default_library", 14 | "//thirdparty/golang/parsers/node:go_default_library", 15 | ], 16 | ) 17 | 18 | go_test( 19 | name = "go_default_test", 20 | srcs = ["parser_test.go"], 21 | embed = [":go_default_library"], 22 | deps = [ 23 | "//thirdparty/golang/parsers/parsers:go_default_library", 24 | "@com_github_google_go_cmp//cmp:go_default_library", 25 | "@com_github_google_go_cmp//cmp/cmpopts:go_default_library", 26 | ], 27 | ) 28 | -------------------------------------------------------------------------------- /lang/java/parser/parser.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package parser provides functions to parse Java code and reason about its contents. 16 | package parser 17 | 18 | import ( 19 | "bytes" 20 | "io/ioutil" 21 | "log" 22 | "sort" 23 | "strings" 24 | "sync" 25 | "unicode" 26 | 27 | "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/ast" 28 | "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/node" 29 | "context" 30 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 31 | "github.com/bazelbuild/tools_jvm_autodeps/lang/java/parser/xrefs" 32 | 33 | lpb "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/lang" 34 | 35 | // Import the java parser so it can register itself. 36 | _ "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/java" 37 | ) 38 | 39 | // ReferencedClasses returns the set of class names that the provided Java source files reference. 40 | // This includes (a) imports (b) simple names we think are class names, which are assumed to be in the same package (c) fully-qualified names. 41 | // implicitImports is a sorted slice of classes that do not require an import. In Java, these are the classes in java.lang, such as "System" and "Integer". 42 | func ReferencedClasses(ctx context.Context, javaFileNames []string, implicitImports []string) []jadeplib.ClassName { 43 | var mu sync.Mutex 44 | var wg sync.WaitGroup 45 | var result []jadeplib.ClassName 46 | classNameSeen := make(map[string]bool) 47 | for _, fileName := range javaFileNames { 48 | fileName := fileName 49 | wg.Add(1) 50 | go func() { 51 | defer wg.Done() 52 | source, err := ioutil.ReadFile(fileName) 53 | if err != nil { 54 | log.Printf("Error reading %q:\n%v", fileName, err) 55 | return 56 | } 57 | 58 | classes, err := referencedClasses(ctx, fileName, string(source), implicitImports) 59 | if err != nil { 60 | log.Printf("Error parsing %q:\n%v", fileName, err) 61 | return 62 | } 63 | 64 | mu.Lock() 65 | for _, c := range classes { 66 | if !classNameSeen[c] { 67 | classNameSeen[c] = true 68 | result = append(result, jadeplib.ClassName(c)) 69 | } 70 | } 71 | mu.Unlock() 72 | }() 73 | } 74 | wg.Wait() 75 | 76 | return result 77 | } 78 | 79 | // referencedClasses returns the set of class names that a Java source code references. 80 | // An error is returned if the source can't be parsed. 81 | // The path parameter is only used for tagging, not for reading a file. 82 | func referencedClasses(ctx context.Context, path, source string, builtInClasses []string) ([]string, error) { 83 | tree, err := ast.Build(ctx, lpb.Language_JAVA, path, source, ast.Options{}) 84 | if err != nil { 85 | return nil, err 86 | } 87 | pkg := packageName(tree) 88 | resolver := xrefs.NewResolver(tree) 89 | bindings := resolver.Resolve() 90 | 91 | seen := make(map[string]bool) 92 | // Mark all classes defined in this file as already seen, so we don't report them. 93 | // This is a workaround for the fact that Resolve() doesn't bind fully-qualified names yet. 94 | rootST := resolver.SymbolTables[tree.Root()] 95 | if rootST != nil { 96 | for className := range rootST.Types { 97 | if pkg != "" { 98 | seen[pkg+"."+className] = true 99 | } 100 | } 101 | } 102 | 103 | var result []string 104 | visit := func(n ast.Node) { 105 | switch n.Type() { 106 | case node.JavaTypeName, 107 | node.JavaTypeOrExprName, 108 | node.JavaExprName: 109 | ids := n.ChildrenOfType(node.JavaIdentifier) 110 | if _, ok := bindings[ids[0]]; ok { 111 | // Symbol is defined somewhere in this class, no need to report it. 112 | break 113 | } 114 | className, idx := ExtractClassNameFromQualifiedName(idsToStrs(ids)) 115 | if idx < 0 { 116 | if n.Type() != node.JavaTypeName { 117 | break 118 | } 119 | className = joinIDs(ids) 120 | } 121 | if idx == 0 { 122 | if isBuiltin(builtInClasses, className) { 123 | break 124 | } 125 | if pkg != "" { 126 | className = pkg + "." + className 127 | } 128 | } 129 | if !seen[className] { 130 | seen[className] = true 131 | result = append(result, className) 132 | } 133 | 134 | case node.JavaImport: 135 | name := n.Child(node.OneOf(node.JavaName, node.JavaNameStar)) 136 | onDemand := name.Type() == node.JavaNameStar 137 | static := n.FirstChildOfType(node.JavaStatic).IsValid() 138 | ids := name.ChildrenOfType(node.JavaIdentifier) 139 | className, idx := ExtractClassNameFromQualifiedName(idsToStrs(ids)) 140 | if idx < 0 { 141 | if onDemand && !static { 142 | break 143 | } 144 | className = joinIDs(ids) 145 | } 146 | if !seen[className] { 147 | seen[className] = true 148 | result = append(result, className) 149 | } 150 | } 151 | } 152 | 153 | tree.ForEach(node.Any, visit) 154 | return result, nil 155 | } 156 | 157 | // isBuiltin returns true iff 's' is in 'strings'. 158 | // 'strings' is assumed to be sorted. 159 | // It is intended to filter out built-in class names, such as String, Object, etc. 160 | func isBuiltin(strings []string, s string) bool { 161 | i := sort.SearchStrings(strings, s) 162 | return i < len(strings) && strings[i] == s 163 | } 164 | 165 | // packageName returns the package name of a tree, if it exists. 166 | // For example, "com.google.common.collect". 167 | func packageName(tree *ast.Tree) string { 168 | p := tree.Root().FirstChildOfType(node.JavaPackage) 169 | return joinIDs(p.FirstChildOfType(node.JavaName).ChildrenOfType(node.JavaIdentifier)) 170 | } 171 | 172 | // joinIDs joins the texts of a set of nodes which are assumed to have type node.JavaIdentifier. 173 | func joinIDs(ids []ast.Node) string { 174 | var b bytes.Buffer 175 | for i, id := range ids { 176 | if i > 0 { 177 | b.WriteString(".") 178 | } 179 | b.WriteString(id.Text()) 180 | } 181 | return b.String() 182 | } 183 | 184 | func idsToStrs(ids []ast.Node) []string { 185 | ret := make([]string, len(ids)) 186 | for i, id := range ids { 187 | ret[i] = id.Text() 188 | } 189 | return ret 190 | } 191 | 192 | // ExtractClassNameFromQualifiedName returns a top-level class name from parts and the index of the top-level part. 193 | // If the class has an unconventional name (see below), returns an empty string and -1. 194 | // By "class name" we mean a Java name according to convention, e.g. com.google.Foo. 195 | // That is, a potentially empty package prefix (all lower case), then a top-level class name (starting with a capital letter). 196 | func ExtractClassNameFromQualifiedName(parts []string) (string, int) { 197 | var result []string 198 | for i, txt := range parts { 199 | result = append(result, txt) 200 | if looksLikeSimpleClassName(txt) { 201 | return strings.Join(result, "."), i 202 | } 203 | if isLowerCase(txt) { 204 | continue 205 | } 206 | return "", -1 207 | } 208 | return "", -1 209 | } 210 | 211 | func isLowerCase(s string) bool { 212 | for _, r := range s { 213 | if unicode.IsUpper(r) { 214 | return false 215 | } 216 | } 217 | return true 218 | } 219 | 220 | // looksLikeSimpleClassName returns true if 's' has the form ^[A-Z][a-zA-Z0-9]*$. 221 | func looksLikeSimpleClassName(s string) bool { 222 | if s == "" { 223 | return false 224 | } 225 | ranges := []*unicode.RangeTable{unicode.Digit, unicode.Number, unicode.Letter} 226 | for index, r := range s { 227 | if index == 0 { 228 | if !unicode.IsUpper(r) { 229 | return false 230 | } 231 | } else if !unicode.IsOneOf(ranges, r) { 232 | return false 233 | } 234 | } 235 | return true 236 | } 237 | -------------------------------------------------------------------------------- /lang/java/parser/xrefs/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["xrefs.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/lang/java/parser/xrefs", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//thirdparty/golang/parsers/ast:go_default_library", 10 | "//thirdparty/golang/parsers/node:go_default_library", 11 | ], 12 | ) 13 | 14 | go_test( 15 | name = "go_default_test", 16 | srcs = ["xrefs_test.go"], 17 | embed = [":go_default_library"], 18 | deps = [ 19 | "//thirdparty/golang/parsers/ast:go_default_library", 20 | "//thirdparty/golang/parsers/java:go_default_library", 21 | "//thirdparty/golang/parsers/lang:go_default_library", 22 | "//thirdparty/golang/parsers/node:go_default_library", 23 | "@com_github_google_go_cmp//cmp:go_default_library", 24 | ], 25 | ) 26 | -------------------------------------------------------------------------------- /lang/java/ruleconsts/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["ruleconsts.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/lang/java/ruleconsts", 7 | visibility = ["//visibility:public"], 8 | deps = ["//jadeplib:go_default_library"], 9 | ) 10 | 11 | go_test( 12 | name = "go_default_test", 13 | srcs = ["ruleconsts_test.go"], 14 | embed = [":go_default_library"], 15 | ) 16 | -------------------------------------------------------------------------------- /lang/java/ruleconsts/ruleconsts.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package ruleconsts defines constants related to names and kinds of Java rules. 16 | package ruleconsts 17 | 18 | import ( 19 | "regexp" 20 | 21 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 22 | ) 23 | 24 | var ( 25 | // NewRuleNamingRules specifies how to name, and which kind, should new rules have, based on the file names they srcs. 26 | // See jadeplib.NamingRule for requirements for the regexps. 27 | NewRuleNamingRules = []jadeplib.NamingRule{ 28 | {FileNameMatcher: androidTestRegexp, RuleKind: "android_test"}, 29 | {FileNameMatcher: androidLibraryRegexp, RuleKind: "android_library"}, 30 | {FileNameMatcher: javaTestRegexp, RuleKind: "java_test"}, 31 | } 32 | 33 | androidTestRegexp = regexp.MustCompile(`^javatests/com/google/android/(.*/)?.*Test\.java$`) 34 | androidLibraryRegexp = regexp.MustCompile(`^java(tests)?/com/google/android/(.*/)?.+\.java$`) 35 | javaTestRegexp = regexp.MustCompile(`^javatests/(.*/)?.*Test\.java$`) 36 | ) 37 | 38 | // DefaultNewRuleKind is used to create new rules when NewRuleNamingRules can't be used. 39 | const DefaultNewRuleKind = "java_library" 40 | -------------------------------------------------------------------------------- /lang/java/ruleconsts/ruleconsts_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package ruleconsts 16 | 17 | import ( 18 | "regexp" 19 | "testing" 20 | ) 21 | 22 | func TestNewRuleNamingRules(t *testing.T) { 23 | tests := []struct { 24 | re *regexp.Regexp 25 | s string 26 | want bool 27 | }{ 28 | // androidTestRegexp 29 | { 30 | re: androidTestRegexp, 31 | s: "javatests/com/google/android/FooTest.java", 32 | want: true, 33 | }, 34 | { 35 | re: androidTestRegexp, 36 | s: "javatests/com/google/android/Test.java", 37 | want: true, 38 | }, 39 | { 40 | re: androidTestRegexp, 41 | s: "javatests/com/google/android/blabla1/blabla2/FooTest.java", 42 | want: true, 43 | }, 44 | { 45 | re: androidTestRegexp, 46 | s: "javatests/com/google/android/Foo.java", 47 | want: false, 48 | }, 49 | { 50 | re: androidTestRegexp, 51 | s: "javatests/com/google/FooTest.java", 52 | want: false, 53 | }, 54 | // androidLibraryRegexp 55 | { 56 | re: androidLibraryRegexp, 57 | s: "javatests/com/google/android/FooTest.java", 58 | want: true, 59 | }, 60 | { 61 | re: androidLibraryRegexp, 62 | s: "javatests/com/google/android/blabla1/blabla2/FooTest.java", 63 | want: true, 64 | }, 65 | { 66 | re: androidLibraryRegexp, 67 | s: "javatests/com/google/android/Foo.java", 68 | want: true, 69 | }, 70 | { 71 | re: androidLibraryRegexp, 72 | s: "java/com/google/android/Foo.java", 73 | want: true, 74 | }, 75 | { 76 | re: androidLibraryRegexp, 77 | s: "javatests/com/google/FooTest.java", 78 | want: false, 79 | }, 80 | // javaTestRegexp 81 | { 82 | re: javaTestRegexp, 83 | s: "javatests/com/google/android/FooTest.java", 84 | want: true, 85 | }, 86 | { 87 | re: javaTestRegexp, 88 | s: "javatests/com/google/Test.java", 89 | want: true, 90 | }, 91 | { 92 | re: javaTestRegexp, 93 | s: "javatests/com/google/FooTest.java", 94 | want: true, 95 | }, 96 | } 97 | 98 | for _, tt := range tests { 99 | m := tt.re.FindStringSubmatch(tt.s) 100 | if m != nil != tt.want { 101 | t.Errorf("Matching %v on %q = %v, want %v", tt.re, tt.s, m != nil, tt.want) 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /listclassesinjar/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["listclassesinjar.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/listclassesinjar", 7 | visibility = ["//visibility:public"], 8 | deps = ["//jadeplib:go_default_library"], 9 | ) 10 | 11 | go_test( 12 | name = "go_default_test", 13 | srcs = ["listclassesinjar_test.go"], 14 | embed = [":go_default_library"], 15 | deps = [ 16 | "//jadeplib:go_default_library", 17 | "@com_github_google_go_cmp//cmp:go_default_library", 18 | ], 19 | ) 20 | -------------------------------------------------------------------------------- /listclassesinjar/listclassesinjar.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package listclassesinjar lists class names in Jar files. 16 | package listclassesinjar 17 | 18 | import ( 19 | "archive/zip" 20 | "fmt" 21 | "strings" 22 | 23 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 24 | ) 25 | 26 | // List returns the list of Java class names in the Jar named fileName. 27 | // Only top-level class names are returned. 28 | func List(fileName string) ([]jadeplib.ClassName, error) { 29 | var result []jadeplib.ClassName 30 | 31 | r, err := zip.OpenReader(fileName) 32 | if err != nil { 33 | return nil, fmt.Errorf("error opening file %s:\n%v", fileName, err) 34 | } 35 | defer r.Close() 36 | 37 | for _, f := range r.File { 38 | fn := f.Name 39 | if strings.Contains(fn, "$") || !strings.HasSuffix(fn, ".class") || strings.HasSuffix(fn, "/package-info.class") { 40 | continue 41 | } 42 | c := strings.Replace(strings.TrimSuffix(fn, ".class"), "/", ".", -1) 43 | result = append(result, jadeplib.ClassName(c)) 44 | } 45 | return result, nil 46 | } 47 | -------------------------------------------------------------------------------- /listclassesinjar/listclassesinjar_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package listclassesinjar 16 | 17 | import ( 18 | "archive/zip" 19 | "io/ioutil" 20 | "os" 21 | "testing" 22 | 23 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 24 | "github.com/google/go-cmp/cmp" 25 | ) 26 | 27 | func TestList(t *testing.T) { 28 | type args struct { 29 | fileName string 30 | zipFileNames []string 31 | } 32 | tests := []struct { 33 | name string 34 | args args 35 | want []jadeplib.ClassName 36 | }{ 37 | { 38 | name: "basic", 39 | args: args{ 40 | fileName: "", 41 | zipFileNames: []string{ 42 | "com/foo/Bar.class", 43 | "com/Zoo.class", 44 | "com/google/common/truth/package-info.class", 45 | "META-INF/MANIFEST.MF", 46 | "META-INF/maven/com.google.truth/truth/pom.properties", 47 | "com/foo/Bar$1.class", 48 | "com/foo/Bar$1Inner.class", 49 | "com/foo/$1.class", 50 | }, 51 | }, 52 | want: []jadeplib.ClassName{ 53 | "com.foo.Bar", 54 | "com.Zoo", 55 | }, 56 | }, 57 | } 58 | for _, tt := range tests { 59 | t.Run(tt.name, func(t *testing.T) { 60 | fn, err := writeZipFile(tt.args.fileName, tt.args.zipFileNames) 61 | if err != nil { 62 | t.Fatal(err) 63 | } 64 | defer os.Remove(fn) 65 | 66 | got, err := List(fn) 67 | if err != nil { 68 | t.Errorf("List() error = %v, want nil", err) 69 | return 70 | } 71 | if diff := cmp.Diff(got, tt.want); diff != "" { 72 | t.Errorf("List() returned diff (-got +want): %v", diff) 73 | } 74 | }) 75 | } 76 | } 77 | 78 | func writeZipFile(fileName string, zipFileNames []string) (string, error) { 79 | tmpfile, err := ioutil.TempFile("", "zip") 80 | if err != nil { 81 | return "", err 82 | } 83 | defer tmpfile.Close() 84 | 85 | w := zip.NewWriter(tmpfile) 86 | for _, fileName := range zipFileNames { 87 | f, err := w.Create(fileName) 88 | if err != nil { 89 | return "", err 90 | } 91 | _, err = f.Write([]byte("")) 92 | if err != nil { 93 | return "", err 94 | } 95 | } 96 | 97 | err = w.Close() 98 | if err != nil { 99 | return "", err 100 | } 101 | return tmpfile.Name(), nil 102 | } 103 | -------------------------------------------------------------------------------- /loadertest/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["loadertest.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/loadertest", 7 | visibility = ["//visibility:public"], 8 | deps = ["//bazel:go_default_library"], 9 | ) 10 | -------------------------------------------------------------------------------- /loadertest/loadertest.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package loadertest provides test Loaders. 16 | package loadertest 17 | 18 | import ( 19 | "sort" 20 | 21 | "context" 22 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 23 | ) 24 | 25 | // StubLoader is a Loader that returns a preset response. 26 | // It also records the parameters to its Load function. 27 | type StubLoader struct { 28 | Pkgs map[string]*bazel.Package 29 | 30 | // RecordedCalls[i] contains the 'packages' parameter passed to the i'th call to the Load method (after sorting). 31 | RecordedCalls [][]string 32 | } 33 | 34 | // Load returns bazel.Package objects that are both in packages and in StubLoader.Pkgs. 35 | func (l *StubLoader) Load(ctx context.Context, packages []string) (map[string]*bazel.Package, error) { 36 | l.recordCall(packages) 37 | 38 | result := make(map[string]*bazel.Package) 39 | for _, pkgName := range packages { 40 | if p, ok := l.Pkgs[pkgName]; ok { 41 | result[pkgName] = p 42 | } 43 | } 44 | return result, nil 45 | } 46 | 47 | func (l *StubLoader) recordCall(packages []string) { 48 | sortedPkgs := make([]string, len(packages)) 49 | copy(sortedPkgs, packages) 50 | sort.Strings(sortedPkgs) 51 | l.RecordedCalls = append(l.RecordedCalls, sortedPkgs) 52 | } 53 | -------------------------------------------------------------------------------- /maven_deps.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 The Jadep Authors 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # A configuration file for https://github.com/johnynek/bazel-deps, 16 | # a tool to manage JVM third-party dependencies from Maven Central. 17 | options: 18 | languages: [ "java" ] 19 | resolvers: 20 | - id: "mavencentral" 21 | type: "default" 22 | url: https://repo.maven.apache.org/maven2/ 23 | transitivity: runtime_deps 24 | versionConflictPolicy: highest 25 | thirdPartyDirectory: "thirdparty/jvm" 26 | 27 | dependencies: 28 | junit: 29 | junit: 30 | lang: java 31 | version: "4.12" 32 | 33 | com.google.guava: 34 | guava: 35 | version: "23.0" 36 | lang: java 37 | 38 | com.google.truth: 39 | truth: 40 | version: "0.35" 41 | lang: java 42 | 43 | io.netty: 44 | netty-all: 45 | version: "4.1.22.Final" 46 | lang: java 47 | 48 | io.grpc: 49 | grpc: 50 | version: "1.10.0" 51 | lang: java 52 | modules: [services, core, netty, stub] 53 | 54 | org.textmapper: 55 | textmapper: 56 | version: "0.9.18" 57 | lang: java 58 | 59 | # For java_grpc_library 60 | com.google.code.findbugs: 61 | jsr305: 62 | version: "3.0.2" 63 | lang: java 64 | 65 | # For java_grpc_library 66 | com.google.code.gson: 67 | gson: 68 | version: "2.8.2" 69 | lang: java 70 | 71 | args4j: 72 | args4j: 73 | version: "2.33" 74 | lang: java 75 | -------------------------------------------------------------------------------- /pkgloaderfakes/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["pkgloaderfakes.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/pkgloaderfakes", 7 | visibility = ["//visibility:public"], 8 | deps = ["//bazel:go_default_library"], 9 | ) 10 | -------------------------------------------------------------------------------- /pkgloaderfakes/pkgloaderfakes.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package pkgloaderfakes provides fakes for structs returned from pkgloaderclient. 16 | package pkgloaderfakes 17 | 18 | import "github.com/bazelbuild/tools_jvm_autodeps/bazel" 19 | 20 | // Pkg creates a Bazel package from a list of rules, as if they were returned by pkgloaderclient.Loader. 21 | func Pkg(rules []*bazel.Rule) *bazel.Package { 22 | resFiles := map[string]string{"BUILD": ""} 23 | resRules := make(map[string]*bazel.Rule) 24 | for _, r := range rules { 25 | resRules[r.Attrs["name"].(string)] = r 26 | srcs, _ := r.Attrs["srcs"].([]string) 27 | for _, src := range srcs { 28 | resFiles[src] = "" 29 | } 30 | } 31 | return &bazel.Package{ 32 | DefaultVisibility: []bazel.Label{"//visibility:private"}, 33 | Files: resFiles, 34 | Rules: resRules, 35 | } 36 | } 37 | 38 | // JavaLibrary creates a java_library Bazel rule as if it were returned by pkgloaderclient.Loader. 39 | // TODO(bazel-team): Replace this with a version that calls Rule() directly. 40 | func JavaLibrary(pkgName string, name string, srcs []string, deps []string, exports []string) *bazel.Rule { 41 | return rule("java_library", pkgName, name, srcs, deps, exports) 42 | } 43 | 44 | // JavaBinary creates a java_binary Bazel rule as if it were returned by pkgloaderclient.Loader. 45 | // TODO(bazel-team): Replace this with a version that calls Rule() directly. 46 | func JavaBinary(pkgName string, name string, srcs []string, deps []string, exports []string) *bazel.Rule { 47 | return rule("java_binary", pkgName, name, srcs, deps, exports) 48 | } 49 | 50 | func rule(kind string, pkgName string, name string, srcs []string, deps []string, exports []string) *bazel.Rule { 51 | var ms []RuleModifier 52 | if srcs != nil { 53 | ms = append(ms, Srcs(srcs...)) 54 | } 55 | if deps != nil { 56 | ms = append(ms, Deps(deps...)) 57 | } 58 | if exports != nil { 59 | ms = append(ms, Exports(exports...)) 60 | } 61 | return Rule(kind, pkgName, name, ms...) 62 | } 63 | 64 | // RuleModifier is used by Rule to modify a newly created bazel.Rule object. 65 | // See AttrModifier for an example. 66 | type RuleModifier interface { 67 | Apply(r *bazel.Rule) 68 | } 69 | 70 | // Rule creates a bazel.Rule and applies modifiers to it. 71 | // Example: Rule("java_library", "x", "Foo", Srcs("Foo.java")) 72 | func Rule(schema, pkgName, ruleName string, modifiers ...RuleModifier) *bazel.Rule { 73 | result := bazel.NewRule(schema, pkgName, ruleName, nil) 74 | for _, m := range modifiers { 75 | m.Apply(result) 76 | } 77 | return result 78 | } 79 | 80 | // AttrModifier is a RuleModifier that changes the attribute named AttrName to Value. 81 | type AttrModifier struct { 82 | RuleModifier 83 | AttrName string 84 | Value interface{} 85 | } 86 | 87 | // Attr returns a new AttrModifier that changes attrName to value. 88 | // For example, Rule("java_library", "x", "Foo", Attr("deps", "Foo.java")) 89 | func Attr(attrName string, value interface{}) *AttrModifier { 90 | return &AttrModifier{AttrName: attrName, Value: value} 91 | } 92 | 93 | // Apply applies the attribute change as specified by AttrModifier. 94 | func (m *AttrModifier) Apply(rule *bazel.Rule) { 95 | rule.Attrs[m.AttrName] = m.Value 96 | } 97 | 98 | // Srcs is a convenience wrapper around Attr("srcs", value). 99 | func Srcs(value ...string) *AttrModifier { 100 | return Attr("srcs", value) 101 | } 102 | 103 | // Deps is a convenience wrapper around Attr("srcs", value). 104 | func Deps(value ...string) *AttrModifier { 105 | return Attr("deps", value) 106 | } 107 | 108 | // Exports is a convenience wrapper around Attr("srcs", value). 109 | func Exports(value ...string) *AttrModifier { 110 | return Attr("exports", value) 111 | } 112 | -------------------------------------------------------------------------------- /pkgloading/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["pkgloading.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/pkgloading", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//bazel:go_default_library", 10 | "//compat:go_default_library", 11 | ], 12 | ) 13 | 14 | go_test( 15 | name = "go_default_test", 16 | srcs = ["pkgloading_test.go"], 17 | embed = [":go_default_library"], 18 | deps = [ 19 | "//bazel:go_default_library", 20 | "//loadertest:go_default_library", 21 | "//pkgloaderfakes:go_default_library", 22 | "@com_github_google_go_cmp//cmp:go_default_library", 23 | ], 24 | ) 25 | -------------------------------------------------------------------------------- /resolverutil/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["resolverutil.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/resolverutil", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//bazel:go_default_library", 10 | "//jadeplib:go_default_library", 11 | ], 12 | ) 13 | 14 | go_test( 15 | name = "go_default_test", 16 | srcs = ["resolverutil_test.go"], 17 | embed = [":go_default_library"], 18 | deps = [ 19 | "//bazel:go_default_library", 20 | "//jadeplib:go_default_library", 21 | "@com_github_google_go_cmp//cmp:go_default_library", 22 | "@com_github_google_go_cmp//cmp/cmpopts:go_default_library", 23 | ], 24 | ) 25 | -------------------------------------------------------------------------------- /resolverutil/resolverutil.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package resolverutil provides functions that help implement resolvers. 16 | package resolverutil 17 | 18 | import ( 19 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 20 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 21 | ) 22 | 23 | // SatisfiedByExistingDeps finds class names for which a satisfying dependency appears in the consuming rules. 24 | // In a sense, it returns the intersection of consumingRules and satisfyingRules. 25 | // It is used as an optimization to return faster when we know the consuming rules already have a dependency for certain class names. 26 | // For each class name, it checks whether every consuming rule has at least one dependency that this class name can be satisfied with. 27 | // It returns class names for which this holds, with the list of satisfying dependencies that covers all consuming rules. 28 | func SatisfiedByExistingDeps(consumingRules map[bazel.Label]map[bazel.Label]bool, satisfyingRules map[jadeplib.ClassName][]bazel.Label) map[jadeplib.ClassName][]bazel.Label { 29 | if len(consumingRules) == 0 { 30 | return nil 31 | } 32 | 33 | alreadySatisfied := make(map[jadeplib.ClassName][]bazel.Label) 34 | 35 | classLoop: 36 | for cls, possibleDeps := range satisfyingRules { 37 | var existingSatisfyingDeps []bazel.Label 38 | for consumingRule, existingDeps := range consumingRules { 39 | satisfied := false 40 | for _, d := range possibleDeps { 41 | if consumingRule == d || existingDeps[d] { 42 | existingSatisfyingDeps = append(existingSatisfyingDeps, d) 43 | satisfied = true 44 | break 45 | } 46 | } 47 | if !satisfied { 48 | continue classLoop 49 | } 50 | } 51 | alreadySatisfied[cls] = existingSatisfyingDeps 52 | } 53 | 54 | return alreadySatisfied 55 | } 56 | -------------------------------------------------------------------------------- /resolverutil/resolverutil_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package resolverutil 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 21 | "github.com/bazelbuild/tools_jvm_autodeps/jadeplib" 22 | "github.com/google/go-cmp/cmp" 23 | "github.com/google/go-cmp/cmp/cmpopts" 24 | ) 25 | 26 | func TestSatisfiedByExistingDeps(t *testing.T) { 27 | tests := []struct { 28 | desc string 29 | consumingRules map[bazel.Label]map[bazel.Label]bool 30 | satisfyingRules map[jadeplib.ClassName][]bazel.Label 31 | want map[jadeplib.ClassName][]bazel.Label 32 | }{ 33 | { 34 | desc: "No consuming rules at all", 35 | consumingRules: map[bazel.Label]map[bazel.Label]bool{}, 36 | satisfyingRules: map[jadeplib.ClassName][]bazel.Label{}, 37 | want: nil, 38 | }, 39 | { 40 | desc: "Single consuming rule that doesn't contain any satisfying dep", 41 | consumingRules: map[bazel.Label]map[bazel.Label]bool{ 42 | "//:foo": {"//:bar": true}, 43 | }, 44 | satisfyingRules: map[jadeplib.ClassName][]bazel.Label{ 45 | "com.Zed": {"//:Zed"}, 46 | }, 47 | want: map[jadeplib.ClassName][]bazel.Label{}, 48 | }, 49 | { 50 | desc: "Single consuming rule that contains a satisfying dep", 51 | consumingRules: map[bazel.Label]map[bazel.Label]bool{ 52 | "//:foo": {"//:bar1": true, "//:bar2": true}, 53 | }, 54 | satisfyingRules: map[jadeplib.ClassName][]bazel.Label{ 55 | "com.Bar": {"//:bar1", "//:other"}, 56 | }, 57 | want: map[jadeplib.ClassName][]bazel.Label{ 58 | "com.Bar": {"//:bar1"}, 59 | }, 60 | }, 61 | { 62 | desc: "Multiple consuming rule that all contain some satisfying dep for each class name, though not the same. We return a single satisfying dep for each consuming rule", 63 | consumingRules: map[bazel.Label]map[bazel.Label]bool{ 64 | "//:foo1": {"//:bar1": true, "//:bar2": true, "//:unrelated1": true}, 65 | "//:foo2": {"//:bar3": true, "//:bar4": true, "//:unrelated2": true}, 66 | }, 67 | satisfyingRules: map[jadeplib.ClassName][]bazel.Label{ 68 | "com.Bar1": {"//:bar1", "//:bar4", "//:emmo1"}, 69 | "com.Bar2": {"//:bar2", "//:bar3", "//:emmo2"}, 70 | }, 71 | want: map[jadeplib.ClassName][]bazel.Label{ 72 | "com.Bar1": {"//:bar1", "//:bar4"}, 73 | "com.Bar2": {"//:bar2", "//:bar3"}, 74 | }, 75 | }, 76 | } 77 | 78 | opt := cmpopts.SortSlices(func(a, b bazel.Label) bool { return a < b }) 79 | 80 | for _, tt := range tests { 81 | t.Run(tt.desc, func(t *testing.T) { 82 | got := SatisfiedByExistingDeps(tt.consumingRules, tt.satisfyingRules) 83 | if diff := cmp.Diff(got, tt.want, opt); diff != "" { 84 | t.Errorf("SatisfiedByExistingDeps returned diff (-want +got):\n%s", diff) 85 | } 86 | }) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /scripts/pkgloader_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2018 The Jadep Authors. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | java -jar "$(dirname $0)/GrpcLocalServer_deploy.jar" $@ 18 | -------------------------------------------------------------------------------- /sortingdepsranker/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["sortingdepsranker.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/sortingdepsranker", 7 | visibility = ["//visibility:public"], 8 | deps = ["//bazel:go_default_library"], 9 | ) 10 | -------------------------------------------------------------------------------- /sortingdepsranker/sortingdepsranker.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package sortingdepsranker ranks deps by simply sorting labels lexicographically. 16 | package sortingdepsranker 17 | 18 | import ( 19 | "context" 20 | "github.com/bazelbuild/tools_jvm_autodeps/bazel" 21 | ) 22 | 23 | // Ranker is a jadeplib.DepsRanker that ranks labels by their lexicographic order. 24 | type Ranker struct{} 25 | 26 | // Less returns true iff label1 < label2. 27 | func (r *Ranker) Less(ctx context.Context, label1, label2 bazel.Label) bool { 28 | return label1 < label2 29 | } 30 | -------------------------------------------------------------------------------- /thirdparty/BUILD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cgrushko/tools_jvm_autodeps/62694dd50b91955fdfe67d0c0583fd25d78e5389/thirdparty/BUILD -------------------------------------------------------------------------------- /thirdparty/golang/parsers/ast/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["ast.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/ast", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//thirdparty/golang/parsers/lang:go_default_library", 10 | "//thirdparty/golang/parsers/node:go_default_library", 11 | "//thirdparty/golang/parsers/parsers:go_default_library", 12 | "//thirdparty/golang/parsers/util/offset:go_default_library", 13 | ], 14 | ) 15 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/java/BUILD: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | java_binary( 4 | name = "textmapper_tool", 5 | main_class = "org.textmapper.tool.Tool", 6 | runtime_deps = ["//thirdparty/jvm/org/textmapper"], 7 | ) 8 | 9 | genrule( 10 | name = "syntax", 11 | srcs = [ 12 | "java.tm", 13 | "go_filter.ltp", 14 | "go_listener.ltp", 15 | "go_parser.ltp", 16 | ], 17 | outs = [ 18 | "lexer.go", 19 | "lexer_tables.go", 20 | "listener.go", 21 | "parser.go", 22 | "parser_tables.go", 23 | "token.go", 24 | ], 25 | cmd = 26 | "$(location :textmapper_tool)" + 27 | " $(location :java.tm) -o $(@D) -i thirdparty/golang/parsers/java", 28 | tools = [":textmapper_tool"], 29 | ) 30 | 31 | go_library( 32 | name = "go_default_library", 33 | srcs = [ 34 | "init.go", 35 | "lexer.go", 36 | "lexer_tables.go", 37 | "listener.go", 38 | "parser.go", 39 | "parser_tables.go", 40 | "token.go", 41 | ], 42 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/java", 43 | visibility = ["//visibility:public"], 44 | deps = [ 45 | "//thirdparty/golang/parsers/lang:go_default_library", 46 | "//thirdparty/golang/parsers/node:go_default_library", 47 | "//thirdparty/golang/parsers/parsers:go_default_library", 48 | "//thirdparty/golang/parsers/public/token:go_default_library", 49 | ], 50 | ) 51 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/java/go_filter.ltp: -------------------------------------------------------------------------------- 1 | ${query package() = context.opts.package.replaceAll('/[^/]+$','/selector')} 2 | ${query filterFilename() = 'selector.go'} 3 | 4 | ${query oneOfRef() = '"github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/node".OneOf'} 5 | ${query nodeSelectorTypeRef() = '"github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/node".Selector'} -------------------------------------------------------------------------------- /thirdparty/golang/parsers/java/go_listener.ltp: -------------------------------------------------------------------------------- 1 | ${template listener-} 2 | package ${self->go.package()} 3 | 4 | type Listener func(t ${self->go_listener.nodeTypeRef()}, offset, endoffset int) 5 | 6 | const ( 7 | ${foreach rangeType in syntax.rangeTypes-} 8 | ${rangeType->asRangeTypeName()} = ${rangeType->nodeTypeValueRef()} 9 | ${end-} 10 | ${foreach name in opts.extraTypes-} 11 | ${name} = ${name->nodeTypeValueRef()} 12 | ${end-} 13 | ${foreach name in opts.reportTokens.collect(tok|tok->go_token.tokenNodeName())-} 14 | ${name->asRangeTypeName()} = ${name->nodeTypeValueRef()} 15 | ${end-} 16 | ) 17 | 18 | ${call allTypes-} 19 | ${call categories-} 20 | ${call rules-} 21 | ${end} 22 | 23 | ${template allTypes-} 24 | var AllTypes = [...]node.TypeDescriptor{ 25 | ${foreach rangeType in syntax.rangeTypes-} 26 | {${rangeType->nodeTypeValueRef()}, "${rangeType->asRangeTypeName()->withLangPrefix()}"}, 27 | ${end-} 28 | ${foreach name in opts.extraTypes-} 29 | {${name->nodeTypeValueRef()}, "${name->withLangPrefix()}"}, 30 | ${end-} 31 | ${foreach name in opts.reportTokens.select(it|it.nameText != 'invalid_token') 32 | .collect(tok|tok->go_token.tokenNodeName())-} 33 | {${name->nodeTypeValueRef()}, "${name->asRangeTypeName()->withLangPrefix()}"}, 34 | ${end-} 35 | } 36 | 37 | ${end} 38 | 39 | ${template rules-} 40 | var rule${self->nodeType()} = [...]${self->nodeTypeRef()}{ 41 | ${foreach rule in syntax.rules-} 42 | ${v = rule.rangeType(), v == '' || v == 'File' ? 0 : v->nodeTypeValueRef()}, // ${rule} 43 | ${end-} 44 | } 45 | 46 | ${end} 47 | 48 | ${query nodeTypeRef() = '"github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/node".Type'} 49 | ${query nodeTypeValueRef() = 50 | '"github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/node".' + self->asRangeTypeName()->withLangPrefix()} 51 | 52 | ${query langPrefix() = util.toFirstUpper(context.opts.lang)} 53 | 54 | ${query withLangPrefix() = 55 | ['SyntaxProblem', 'InvalidToken'].contains(self) 56 | ? self 57 | : self->langPrefix() + self} 58 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/java/go_parser.ltp: -------------------------------------------------------------------------------- 1 | ${template onAfterShift-} 2 | ${call base-} 3 | if p.IncludeAllTokens { 4 | n := Token(p.next.symbol) 5 | switch { 6 | case n >= keywordStart && n < keywordEnd: 7 | p.listener(node.Keyword, p.next.offset, p.next.endoffset) 8 | case n >= punctuationStart && n < punctuationEnd: 9 | p.listener(node.Punctuation, p.next.offset, p.next.endoffset) 10 | } 11 | } 12 | ${end} 13 | 14 | ${template stateVars} 15 | IncludeAllTokens bool 16 | ${end} 17 | ${template initStateVars} 18 | p.IncludeAllTokens = false 19 | ${end} 20 | 21 | ${template parserAction($)-} 22 | ${if customRanges()-} 23 | ${foreach range in customRanges()-} 24 | p.listener(${range.rangeType()}, ${range.first().offset}, ${range.last().endoffset}) 25 | ${end-} 26 | ${end-} 27 | ${if codeTemplate()-} 28 | ${eval codeTemplate()} 29 | ${else if context.opts.genast && context->go_ast.astcode(self)-} 30 | ${eval context->go_ast.astcode(self), '#[generated action for ' + self + ']'} 31 | ${end-} 32 | ${end} -------------------------------------------------------------------------------- /thirdparty/golang/parsers/java/init.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package java 16 | 17 | import ( 18 | lpb "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/lang" 19 | "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/node" 20 | "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/parsers" 21 | tpb "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/public/token" 22 | "context" 23 | ) 24 | 25 | const ( 26 | keywordStart = ABSTRACT 27 | keywordEnd = WITH + 1 28 | punctuationStart = LPAREN 29 | punctuationEnd = GTGTGTASSIGN + 1 30 | ) 31 | 32 | func lex(ctx context.Context, source string, listener parsers.LexerListener) { 33 | l := new(Lexer) 34 | l.Init(source) 35 | for tok := l.Next(); tok != EOI; tok = l.Next() { 36 | s, e := l.Pos() 37 | 38 | switch { 39 | case tok >= keywordStart && tok < keywordEnd: 40 | listener(tpb.TokenType_KEYWORD, s, e) 41 | continue 42 | case tok >= punctuationStart && tok < punctuationEnd: 43 | listener(tpb.TokenType_PUNCTUATION, s, e) 44 | continue 45 | } 46 | switch tok { 47 | case IDENTIFIER: 48 | listener(tpb.TokenType_IDENTIFIER, s, e) 49 | case TRADITIONALCOMMENT, ENDOFLINECOMMENT: 50 | listener(tpb.TokenType_COMMENT, s, e) 51 | case INTEGERLITERAL, FLOATINGPOINTLITERAL: 52 | listener(tpb.TokenType_NUMERIC_LITERAL, s, e) 53 | case CHARACTERLITERAL, STRINGLITERAL: 54 | listener(tpb.TokenType_STRING_LITERAL, s, e) 55 | case INVALID_TOKEN: 56 | listener(tpb.TokenType_ERROR_TOKEN, s, e) 57 | } 58 | } 59 | } 60 | 61 | func parse(ctx context.Context, source string, listener parsers.ParserListener, opts parsers.Options) error { 62 | l := new(Lexer) 63 | l.Init(source) 64 | p := new(Parser) 65 | p.Init(Listener(listener)) 66 | p.IncludeAllTokens = opts.IncludeAllTokens 67 | if err := p.Parse(ctx, l); err != nil { 68 | if se, ok := err.(SyntaxError); ok { 69 | return parsers.SyntaxError{ 70 | Description: "syntax error", 71 | Line: se.Line, 72 | Offset: se.Offset, 73 | Length: se.Endoffset - se.Offset, 74 | } 75 | } 76 | return err 77 | } 78 | listener(node.JavaFile, 0, len(source)) 79 | return nil 80 | } 81 | 82 | func init() { 83 | parsers.RegisterLexer(lpb.Language_JAVA, lex) 84 | parsers.RegisterParser(lpb.Language_JAVA, parse) 85 | if err := node.RegisterTypes(lpb.Language_JAVA, AllTypes[:]); err != nil { 86 | panic(err) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/lang/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 3 | 4 | proto_library( 5 | name = "lang_proto", 6 | srcs = ["lang.proto"], 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_proto_library( 11 | name = "lang_go_proto", 12 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/lang", 13 | proto = ":lang_proto", 14 | visibility = ["//visibility:public"], 15 | ) 16 | 17 | go_library( 18 | name = "go_default_library", 19 | embed = [":lang_go_proto"], 20 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/lang", 21 | visibility = ["//visibility:public"], 22 | ) 23 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/lang/lang.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto2"; 16 | 17 | enum Language { 18 | UNKNOWN_LANG = 0; 19 | JAVA = 3; 20 | } 21 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/node/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["node.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/node", 7 | visibility = ["//visibility:public"], 8 | deps = ["//thirdparty/golang/parsers/lang:go_default_library"], 9 | ) 10 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/parsers/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["parsers.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/parsers", 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//thirdparty/golang/parsers/lang:go_default_library", 10 | "//thirdparty/golang/parsers/node:go_default_library", 11 | "//thirdparty/golang/parsers/public/token:go_default_library", 12 | ], 13 | ) 14 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/parsers/parsers.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package parsers is the main entry point for lexing and parsing source code 16 | // for IDE and presentation purposes. 17 | package parsers 18 | 19 | import ( 20 | "errors" 21 | "fmt" 22 | 23 | lpb "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/lang" 24 | "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/node" 25 | tpb "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/public/token" 26 | "context" 27 | ) 28 | 29 | // Version is the global version of the parsers toolkit, which advances every 30 | // time we make an incompatible change in one of the parsers. 31 | const Version = 1 32 | 33 | var ( 34 | // ErrUnsupportedLanguage indicates that the given language is not supported yet. 35 | ErrUnsupportedLanguage = errors.New("unsupported language") 36 | ) 37 | 38 | // SyntaxError wraps low-level parsing errors and points to the first token 39 | // that was not consumed by the parser. 40 | type SyntaxError struct { 41 | Description string 42 | Line int 43 | Offset int 44 | Length int 45 | } 46 | 47 | func (se SyntaxError) Error() string { 48 | return fmt.Sprintf("%d: %s", se.Line, se.Description) 49 | } 50 | 51 | // LexerListener receives all non-whitespace tokens of the language (including 52 | // comments) in the order of their appearance in the input string. 53 | // 54 | // The given ranges are non-empty and never overlap (may touch though). 55 | type LexerListener func(t tpb.TokenType, offset, endoffset int) 56 | 57 | // HasLexer returns whether the language has a registered lexer. 58 | func HasLexer(lang lpb.Language) bool { 59 | _, ok := lexers[lang] 60 | return ok 61 | } 62 | 63 | // Lex tokenizes "source" in the given language. It returns tokens from a 64 | // unified set of token classes shared by all languages and can be used for 65 | // syntax highlighting, detecting non-whitespace changes in a file, or 66 | // enumerating all tokens of a certain class in a language-independent way. 67 | // 68 | // We expect all lexers to be cheap and process the input at least at 100MB/s. 69 | // The function returns an error only if no lexer is registered for the language. 70 | func Lex(ctx context.Context, lang lpb.Language, source string, listener LexerListener) error { 71 | if lexer, ok := lexers[lang]; ok { 72 | lexer(ctx, source, listener) 73 | return nil 74 | } 75 | return ErrUnsupportedLanguage 76 | } 77 | 78 | // ErrorHandler is a function which receives all non-fatal parser errors and decides whether we 79 | // should continue parsing. If it returns false, the last error gets returned as the main outcome 80 | // from the parser. 81 | type ErrorHandler func(err SyntaxError) bool 82 | 83 | // Options contains parameters that control parsing behavior. 84 | type Options struct { 85 | // Adds node.Punctuation and node.Keyword nodes to the parse tree. 86 | IncludeAllTokens bool 87 | 88 | // A callback function which decides whether the parser should try to recover and continue 89 | // parsing. Successful error recovery leads to one or more SyntaxProblem or InvalidToken nodes 90 | // in the tree. 91 | // 92 | // Never called on syntactically valid input. 93 | // Leave unset to disable error recovery. 94 | ShouldTryToRecover ErrorHandler 95 | } 96 | 97 | // ParserListener gets all parsed source ranges in the left-to-right and 98 | // parent-after-children order. Any two of the reported ranges either don't 99 | // overlap, or contain one another. 100 | // 101 | // For some types, the range can be empty, indicating the position for a node 102 | // rather than the node itself (such as InsertedSemicolon). Empty nodes do not 103 | // become parents of other empty nodes. 104 | // 105 | // Note: errors reported via ShouldTryToRecover might be reported out of order 106 | // with ParserListener, but SyntaxProblem nodes produced by error recovery will 107 | // be delivered here as usual syntactic constructs. 108 | type ParserListener func(t node.Type, offset, endoffset int) 109 | 110 | // HasParser returns whether the language has a registered parser. 111 | func HasParser(lang lpb.Language) bool { 112 | _, ok := parsers[lang] 113 | return ok 114 | } 115 | 116 | // Parse uses a parser for the given language to report all syntactic elements 117 | // from "source". It is the responsibility of the caller to decide which nodes 118 | // need to be preserved and build an AST. The function returns true if the 119 | // parsing succeeds, i.e. there were no syntax errors, or the parser was able 120 | // to recover from all of them. Broken code is reported as nodes of the 121 | // SyntaxProblem category. 122 | // 123 | // The provided error handler is called for all positions where the parser 124 | // stumbled upon a syntax error or skipped an unrecognized token. 125 | // 126 | // Note: parsing is slower than lexing but one can expect at least 10MB/s 127 | // of throughput (and usually no memory allocations) from this function. 128 | func Parse(ctx context.Context, lang lpb.Language, source string, pl ParserListener, opts Options) error { 129 | if parser, ok := parsers[lang]; ok { 130 | return parser(ctx, source, pl, opts) 131 | } 132 | return ErrUnsupportedLanguage 133 | } 134 | 135 | // Parser is an actual implementation of the parser for some language. 136 | type Parser func(ctx context.Context, source string, l ParserListener, opts Options) error 137 | 138 | // Lexer is an actual implementation of the lexer for some language. 139 | type Lexer func(ctx context.Context, source string, l LexerListener) 140 | 141 | var lexers = map[lpb.Language]Lexer{} 142 | var parsers = map[lpb.Language]Parser{} 143 | 144 | // RegisterLexer adds the lexer implementation to the registry. 145 | func RegisterLexer(l lpb.Language, lexer Lexer) { 146 | lexers[l] = lexer 147 | } 148 | 149 | // RegisterParser adds the parser implementation to the registry. 150 | func RegisterParser(l lpb.Language, parser Parser) { 151 | parsers[l] = parser 152 | } 153 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/public/token/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 3 | 4 | proto_library( 5 | name = "token_proto", 6 | srcs = ["token.proto"], 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_proto_library( 11 | name = "token_go_proto", 12 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/public/token", 13 | proto = ":token_proto", 14 | visibility = ["//visibility:public"], 15 | ) 16 | 17 | go_library( 18 | name = "go_default_library", 19 | embed = [":token_go_proto"], 20 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/public/token", 21 | visibility = ["//visibility:public"], 22 | ) 23 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/public/token/token.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto2"; 16 | 17 | // Types of tokens produced by a tokenizer. 18 | enum TokenType { 19 | // EOI marks an end-of-input. 20 | EOI = 0; 21 | 22 | // ERROR_TOKEN is produced for unrecognized parts of the input. 23 | ERROR_TOKEN = 1; 24 | 25 | // Common classes of tokens. 26 | KEYWORD = 2; 27 | STRING_LITERAL = 3; 28 | COMMENT = 4; 29 | IDENTIFIER = 5; 30 | NUMERIC_LITERAL = 6; 31 | 32 | // Various language-specific extensions. 33 | MACRO = 7; // For C++ 34 | CLASS_NAME = 8; // For Java 35 | CONST_NAME = 9; // For Java 36 | JAVADOC = 10; // For JavaDoc-like comments (Java and JavaScript). 37 | JAVADOC_TAG = 11; 38 | TASK_TAG = 12; // For TODOs in comments 39 | ESCAPE_SEQUENCE = 13; 40 | 41 | PUNCTUATION = 22; 42 | }; 43 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/util/offset/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["offset.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/thirdparty/golang/parsers/util/offset", 7 | visibility = ["//visibility:public"], 8 | ) 9 | -------------------------------------------------------------------------------- /thirdparty/golang/parsers/util/offset/offset.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package offset provides a helper converting byte offsets in a string into (line, column) pairs, 16 | // where 'column' represents the number of runes from the beginning of the line. 17 | package offset 18 | 19 | import ( 20 | "fmt" 21 | "sort" 22 | "unicode/utf8" 23 | ) 24 | 25 | var ( 26 | errInvalidLine = fmt.Errorf("invalid line number") 27 | errInvalidColumn = fmt.Errorf("invalid column number") 28 | errInvalidOffset = fmt.Errorf("invalid offset value") 29 | ) 30 | 31 | // Range contains the start and end byte offsets of a range of a string (both 0-based). 32 | type Range struct { 33 | Offset int 34 | EndOffset int 35 | } 36 | 37 | // Empty reports whether r is empty. 38 | func (r Range) Empty() bool { 39 | return r.Offset == r.EndOffset 40 | } 41 | 42 | // Contains checks if the offset belongs to the range (inclusive on both sides). 43 | func (r Range) Contains(offset int) bool { 44 | return r.Offset <= offset && offset <= r.EndOffset 45 | } 46 | 47 | // ContainsRange checks if the given range is fully contained in "this" range. 48 | func (r Range) ContainsRange(or Range) bool { 49 | return r.Offset <= or.Offset && or.EndOffset <= r.EndOffset 50 | } 51 | 52 | func (r Range) String() string { 53 | return fmt.Sprintf("(%v, %v)", r.Offset, r.EndOffset) 54 | } 55 | 56 | // Mapper converts file locations between byte offset and line-and-column representations. 57 | // Lines and columns are 0-based and represent characters (runes), while offsets refer to byte offsets. 58 | type Mapper struct { 59 | offsets []int // byte offsets for beginning of lines 60 | content string 61 | } 62 | 63 | // NewMapper returns an offset mapper for the content provided as input. 64 | func NewMapper(content string) *Mapper { 65 | m := &Mapper{ 66 | content: content, 67 | } 68 | 69 | // Precompute line offsets, for easy deduction of the line number for a global offset 70 | m.offsets = make([]int, 0, 32) 71 | m.offsets = append(m.offsets, 0) // First line starts at offset 0. 72 | for offset, r := range content { 73 | if r == '\n' { 74 | m.offsets = append(m.offsets, offset+1) 75 | } 76 | } 77 | 78 | // Introduce an artificial last line. 79 | m.offsets = append(m.offsets, len(content)) 80 | 81 | return m 82 | } 83 | 84 | // ByteOffset returns the global byte offset equivalent to the (line, column) values which represent runes. 85 | // Line and column are 0-based values. 86 | func (m *Mapper) ByteOffset(line, column int) (int, error) { 87 | if line < 0 || line >= len(m.offsets)-1 { 88 | return 0, errInvalidLine 89 | } 90 | if column < 0 { 91 | return 0, errInvalidColumn 92 | } 93 | if column == 0 { 94 | return m.offsets[line], nil 95 | } 96 | 97 | lineText := m.content[m.offsets[line]:m.offsets[line+1]] 98 | 99 | columnIndex := 0 100 | for offset := range lineText { 101 | columnIndex++ 102 | if columnIndex == column+1 { 103 | return m.offsets[line] + offset, nil 104 | } 105 | } 106 | if line == len(m.offsets)-2 && utf8.RuneCountInString(lineText) == column { 107 | // The line and column point to the end of file. 108 | return len(m.content), nil 109 | } 110 | 111 | return 0, errInvalidColumn 112 | } 113 | 114 | // LineAndColumn returns line and column values (rune-based) from a global byte offset. 115 | // If the offset is pointing a byte in the middle of a rune, then it returns the column right after the rune. 116 | // Both the line and column are 0-based. 117 | // Returns an error if the input offset is negative or greater than the length of the source content. 118 | func (m *Mapper) LineAndColumn(byteOffset int) (line, column int, err error) { 119 | if byteOffset > len(m.content) || byteOffset < 0 { 120 | err = errInvalidOffset 121 | return 122 | } 123 | if byteOffset == len(m.content) { 124 | // Offset points to end of file. 125 | line = len(m.offsets) - 2 126 | column = utf8.RuneCountInString(m.content[m.offsets[line]:m.offsets[line+1]]) 127 | return 128 | } 129 | 130 | line = sort.Search(len(m.offsets), func(i int) bool { 131 | return m.offsets[i] > byteOffset 132 | }) - 1 133 | 134 | lineStartOffset := m.offsets[line] 135 | 136 | lineText := m.content[m.offsets[line]:m.offsets[line+1]] 137 | 138 | column = -1 139 | for lineOffset := range lineText { 140 | column++ 141 | if lineOffset+lineStartOffset >= byteOffset { 142 | return 143 | } 144 | } 145 | return 146 | } 147 | 148 | // LineOffsets returns a list with the starting file offsets for each line. 149 | // The first element is 0, while the last element is len(content). 150 | func (m *Mapper) LineOffsets() []int { 151 | // Remove the last, artificial line. 152 | return m.offsets[:len(m.offsets)-1] 153 | } 154 | 155 | // NumLines returns the number of lines in the input. 156 | func (m *Mapper) NumLines() int { 157 | return len(m.offsets) - 1 158 | } 159 | 160 | // Len returns the length of the input. 161 | func (m *Mapper) Len() int { 162 | return len(m.content) 163 | } 164 | -------------------------------------------------------------------------------- /thirdparty/jvm/args4j/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "args4j", 3 | exports = [ 4 | "//external:jar/args4j/args4j" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | -------------------------------------------------------------------------------- /thirdparty/jvm/com/google/api/grpc/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "proto_google_common_protos", 3 | exports = [ 4 | "//external:jar/com/google/api/grpc/proto_google_common_protos" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | -------------------------------------------------------------------------------- /thirdparty/jvm/com/google/code/findbugs/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "jsr305", 3 | exports = [ 4 | "//external:jar/com/google/code/findbugs/jsr305" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | -------------------------------------------------------------------------------- /thirdparty/jvm/com/google/code/gson/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "gson", 3 | exports = [ 4 | "//external:jar/com/google/code/gson/gson" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | -------------------------------------------------------------------------------- /thirdparty/jvm/com/google/errorprone/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "error_prone_annotations", 3 | exports = [ 4 | "//external:jar/com/google/errorprone/error_prone_annotations" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | -------------------------------------------------------------------------------- /thirdparty/jvm/com/google/guava/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "guava", 3 | exports = [ 4 | "//external:jar/com/google/guava/guava" 5 | ], 6 | runtime_deps = [ 7 | "//thirdparty/jvm/com/google/code/findbugs:jsr305", 8 | "//thirdparty/jvm/com/google/errorprone:error_prone_annotations", 9 | "//thirdparty/jvm/com/google/j2objc:j2objc_annotations", 10 | "//thirdparty/jvm/org/codehaus/mojo:animal_sniffer_annotations" 11 | ], 12 | visibility = [ 13 | "//visibility:public" 14 | ] 15 | ) 16 | 17 | 18 | -------------------------------------------------------------------------------- /thirdparty/jvm/com/google/instrumentation/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "instrumentation_api", 3 | exports = [ 4 | "//external:jar/com/google/instrumentation/instrumentation_api" 5 | ], 6 | runtime_deps = [ 7 | "//thirdparty/jvm/com/google/code/findbugs:jsr305" 8 | ], 9 | visibility = [ 10 | "//visibility:public" 11 | ] 12 | ) 13 | 14 | 15 | -------------------------------------------------------------------------------- /thirdparty/jvm/com/google/j2objc/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "j2objc_annotations", 3 | exports = [ 4 | "//external:jar/com/google/j2objc/j2objc_annotations" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | -------------------------------------------------------------------------------- /thirdparty/jvm/com/google/protobuf/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "protobuf_java", 3 | exports = [ 4 | "//external:jar/com/google/protobuf/protobuf_java" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | 13 | java_library( 14 | name = "protobuf_java_util", 15 | exports = [ 16 | "//external:jar/com/google/protobuf/protobuf_java_util" 17 | ], 18 | visibility = [ 19 | "//visibility:public" 20 | ] 21 | ) 22 | 23 | 24 | -------------------------------------------------------------------------------- /thirdparty/jvm/com/google/truth/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "truth", 3 | exports = [ 4 | "//external:jar/com/google/truth/truth" 5 | ], 6 | runtime_deps = [ 7 | "//thirdparty/jvm/com/google/errorprone:error_prone_annotations", 8 | "//thirdparty/jvm/com/google/guava:guava", 9 | "//thirdparty/jvm/junit:junit" 10 | ], 11 | visibility = [ 12 | "//visibility:public" 13 | ] 14 | ) 15 | 16 | 17 | -------------------------------------------------------------------------------- /thirdparty/jvm/io/grpc/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "grpc_context", 3 | exports = [ 4 | "//external:jar/io/grpc/grpc_context" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | 13 | java_library( 14 | name = "grpc_core", 15 | exports = [ 16 | "//external:jar/io/grpc/grpc_core" 17 | ], 18 | runtime_deps = [ 19 | "//thirdparty/jvm/com/google/code/findbugs:jsr305", 20 | "//thirdparty/jvm/com/google/code/gson:gson", 21 | "//thirdparty/jvm/com/google/errorprone:error_prone_annotations", 22 | "//thirdparty/jvm/com/google/guava:guava", 23 | "//thirdparty/jvm/io/opencensus:opencensus_api", 24 | "//thirdparty/jvm/io/opencensus:opencensus_contrib_grpc_metrics", 25 | ":grpc_context" 26 | ], 27 | visibility = [ 28 | "//visibility:public" 29 | ] 30 | ) 31 | 32 | 33 | 34 | java_library( 35 | name = "grpc_netty", 36 | exports = [ 37 | "//external:jar/io/grpc/grpc_netty" 38 | ], 39 | runtime_deps = [ 40 | "//thirdparty/jvm/io/netty:netty_codec_http2", 41 | "//thirdparty/jvm/io/netty:netty_handler_proxy", 42 | ":grpc_core" 43 | ], 44 | visibility = [ 45 | "//visibility:public" 46 | ] 47 | ) 48 | 49 | 50 | 51 | java_library( 52 | name = "grpc_protobuf", 53 | exports = [ 54 | "//external:jar/io/grpc/grpc_protobuf" 55 | ], 56 | runtime_deps = [ 57 | "//thirdparty/jvm/com/google/api/grpc:proto_google_common_protos", 58 | "//thirdparty/jvm/com/google/guava:guava", 59 | "//thirdparty/jvm/com/google/protobuf:protobuf_java", 60 | "//thirdparty/jvm/com/google/protobuf:protobuf_java_util", 61 | ":grpc_core", 62 | ":grpc_protobuf_lite" 63 | ], 64 | visibility = [ 65 | "//visibility:public" 66 | ] 67 | ) 68 | 69 | 70 | 71 | java_library( 72 | name = "grpc_protobuf_lite", 73 | exports = [ 74 | "//external:jar/io/grpc/grpc_protobuf_lite" 75 | ], 76 | visibility = [ 77 | "//visibility:public" 78 | ] 79 | ) 80 | 81 | 82 | 83 | java_library( 84 | name = "grpc_services", 85 | exports = [ 86 | "//external:jar/io/grpc/grpc_services" 87 | ], 88 | runtime_deps = [ 89 | "//thirdparty/jvm/com/google/instrumentation:instrumentation_api", 90 | ":grpc_protobuf", 91 | ":grpc_stub" 92 | ], 93 | visibility = [ 94 | "//visibility:public" 95 | ] 96 | ) 97 | 98 | 99 | 100 | java_library( 101 | name = "grpc_stub", 102 | exports = [ 103 | "//external:jar/io/grpc/grpc_stub" 104 | ], 105 | runtime_deps = [ 106 | ":grpc_core" 107 | ], 108 | visibility = [ 109 | "//visibility:public" 110 | ] 111 | ) 112 | 113 | 114 | -------------------------------------------------------------------------------- /thirdparty/jvm/io/netty/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "netty_all", 3 | exports = [ 4 | "//external:jar/io/netty/netty_all" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | 13 | java_library( 14 | name = "netty_buffer", 15 | exports = [ 16 | "//external:jar/io/netty/netty_buffer" 17 | ], 18 | runtime_deps = [ 19 | ":netty_common" 20 | ], 21 | visibility = [ 22 | "//visibility:public" 23 | ] 24 | ) 25 | 26 | 27 | 28 | java_library( 29 | name = "netty_codec", 30 | exports = [ 31 | "//external:jar/io/netty/netty_codec" 32 | ], 33 | visibility = [ 34 | "//visibility:public" 35 | ] 36 | ) 37 | 38 | 39 | 40 | java_library( 41 | name = "netty_codec_http", 42 | exports = [ 43 | "//external:jar/io/netty/netty_codec_http" 44 | ], 45 | runtime_deps = [ 46 | ":netty_codec" 47 | ], 48 | visibility = [ 49 | "//visibility:public" 50 | ] 51 | ) 52 | 53 | 54 | 55 | java_library( 56 | name = "netty_codec_http2", 57 | exports = [ 58 | "//external:jar/io/netty/netty_codec_http2" 59 | ], 60 | runtime_deps = [ 61 | ":netty_codec_http", 62 | ":netty_handler" 63 | ], 64 | visibility = [ 65 | "//visibility:public" 66 | ] 67 | ) 68 | 69 | 70 | 71 | java_library( 72 | name = "netty_codec_socks", 73 | exports = [ 74 | "//external:jar/io/netty/netty_codec_socks" 75 | ], 76 | visibility = [ 77 | "//visibility:public" 78 | ] 79 | ) 80 | 81 | 82 | 83 | java_library( 84 | name = "netty_common", 85 | exports = [ 86 | "//external:jar/io/netty/netty_common" 87 | ], 88 | visibility = [ 89 | "//visibility:public" 90 | ] 91 | ) 92 | 93 | 94 | 95 | java_library( 96 | name = "netty_handler", 97 | exports = [ 98 | "//external:jar/io/netty/netty_handler" 99 | ], 100 | runtime_deps = [ 101 | ":netty_buffer" 102 | ], 103 | visibility = [ 104 | "//visibility:public" 105 | ] 106 | ) 107 | 108 | 109 | 110 | java_library( 111 | name = "netty_handler_proxy", 112 | exports = [ 113 | "//external:jar/io/netty/netty_handler_proxy" 114 | ], 115 | runtime_deps = [ 116 | ":netty_codec_socks", 117 | ":netty_transport" 118 | ], 119 | visibility = [ 120 | "//visibility:public" 121 | ] 122 | ) 123 | 124 | 125 | 126 | java_library( 127 | name = "netty_resolver", 128 | exports = [ 129 | "//external:jar/io/netty/netty_resolver" 130 | ], 131 | visibility = [ 132 | "//visibility:public" 133 | ] 134 | ) 135 | 136 | 137 | 138 | java_library( 139 | name = "netty_transport", 140 | exports = [ 141 | "//external:jar/io/netty/netty_transport" 142 | ], 143 | runtime_deps = [ 144 | ":netty_resolver" 145 | ], 146 | visibility = [ 147 | "//visibility:public" 148 | ] 149 | ) 150 | 151 | 152 | -------------------------------------------------------------------------------- /thirdparty/jvm/io/opencensus/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "opencensus_api", 3 | exports = [ 4 | "//external:jar/io/opencensus/opencensus_api" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | 13 | java_library( 14 | name = "opencensus_contrib_grpc_metrics", 15 | exports = [ 16 | "//external:jar/io/opencensus/opencensus_contrib_grpc_metrics" 17 | ], 18 | visibility = [ 19 | "//visibility:public" 20 | ] 21 | ) 22 | 23 | 24 | -------------------------------------------------------------------------------- /thirdparty/jvm/junit/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "junit", 3 | exports = [ 4 | "//external:jar/junit/junit" 5 | ], 6 | runtime_deps = [ 7 | "//thirdparty/jvm/org/hamcrest:hamcrest_core" 8 | ], 9 | visibility = [ 10 | "//visibility:public" 11 | ] 12 | ) 13 | 14 | 15 | -------------------------------------------------------------------------------- /thirdparty/jvm/org/codehaus/mojo/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "animal_sniffer_annotations", 3 | exports = [ 4 | "//external:jar/org/codehaus/mojo/animal_sniffer_annotations" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | -------------------------------------------------------------------------------- /thirdparty/jvm/org/hamcrest/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "hamcrest_core", 3 | exports = [ 4 | "//external:jar/org/hamcrest/hamcrest_core" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | -------------------------------------------------------------------------------- /thirdparty/jvm/org/textmapper/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "lapg", 3 | exports = [ 4 | "//external:jar/org/textmapper/lapg" 5 | ], 6 | visibility = [ 7 | "//visibility:public" 8 | ] 9 | ) 10 | 11 | 12 | 13 | java_library( 14 | name = "templates", 15 | exports = [ 16 | "//external:jar/org/textmapper/templates" 17 | ], 18 | visibility = [ 19 | "//visibility:public" 20 | ] 21 | ) 22 | 23 | 24 | 25 | java_library( 26 | name = "textmapper", 27 | exports = [ 28 | "//external:jar/org/textmapper/textmapper" 29 | ], 30 | runtime_deps = [ 31 | ":lapg", 32 | ":templates" 33 | ], 34 | visibility = [ 35 | "//visibility:public" 36 | ] 37 | ) 38 | 39 | 40 | -------------------------------------------------------------------------------- /vlog/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "go_default_library", 5 | srcs = ["vlog.go"], 6 | importpath = "github.com/bazelbuild/tools_jvm_autodeps/vlog", 7 | visibility = ["//visibility:public"], 8 | ) 9 | -------------------------------------------------------------------------------- /vlog/vlog.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Jadep Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package vlog implements conditional verbose/debug logging. 16 | package vlog 17 | 18 | import ( 19 | "log" 20 | ) 21 | 22 | // Level controls which verbose logging statements are executed. 23 | // It is the minimal number for which V(x) returns true. 24 | var Level = 0 25 | 26 | // Verbose is a boolean type that implements info log methods. See V(). 27 | type Verbose bool 28 | 29 | // V reports whether verbosity at the call site is at least the requested level. 30 | // The returned value is a boolean of type Verbose, which implements Printf. 31 | // This method will write to the log if called. 32 | // Whether an individual call to V generates a log record depends on the setting of Level. 33 | func V(x int) Verbose { 34 | return Level >= x 35 | } 36 | 37 | // Printf is equivalent to log.Printf, guarded by the value of v. 38 | func (v Verbose) Printf(format string, values ...interface{}) { 39 | if v { 40 | log.Printf(format, values...) 41 | } 42 | } 43 | --------------------------------------------------------------------------------