diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 0000000000..f9a59a1983 --- /dev/null +++ b/.bazelrc @@ -0,0 +1,4 @@ +startup --batch + +build --protocopt=--include_source_info +build --protocopt=--experimental_allow_proto3_optional diff --git a/BUILD.bazel b/BUILD.bazel index 7574fb74b9..9ffa59e6cb 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,3 +1,5 @@ +package(default_visibility = ["//visibility:public"]) + load( "//:gapic_generator_java.bzl", "google_java_format", @@ -16,75 +18,6 @@ TEST_SRCS = [ ] # ============= Proto wrappers ================= -java_proto_library( - name = "annotations_java_proto", - visibility = ["//:__subpackages__"], - deps = [ - "@com_google_googleapis//google/api:annotations_proto", - ], -) - -java_proto_library( - name = "client_java_proto", - visibility = [ - "//src/main/java/com/google/api/generator:__subpackages__", - "//src/test/java/com/google/api/generator:__subpackages__", - ], - deps = [ - "@com_google_googleapis//google/api:client_proto", - ], -) - -java_proto_library( - name = "field_behavior_java_proto", - visibility = [ - "//src/main/java/com/google/api/generator:__subpackages__", - "//src/test/java/com/google/api/generator:__subpackages__", - ], - deps = [ - "@com_google_googleapis//google/api:field_behavior_proto", - ], -) - -java_proto_library( - name = "resource_java_proto", - visibility = [ - "//src/main/java/com/google/api/generator:__subpackages__", - "//src/test/java/com/google/api/generator:__subpackages__", - ], - deps = [ - "@com_google_googleapis//google/api:resource_proto", - ], -) - -java_proto_library( - name = "longrunning_java_proto", - visibility = [ - "//src/main/java/com/google/api/generator:__subpackages__", - "//src/test/java/com/google/api/generator:__subpackages__", - ], - deps = [ - "@com_google_googleapis//google/longrunning:operations_proto", - ], -) - -java_proto_library( - name = "monitored_resource_java_proto", - visibility = ["//:__subpackages__"], - deps = [ - "@com_google_googleapis//google/api:monitored_resource_proto", - ], -) - -java_proto_library( - name = "rpc_java_proto", - visibility = ["//:__subpackages__"], - deps = [ - "@com_google_googleapis//google/rpc:code_proto", - "@com_google_googleapis//google/rpc:error_details_proto", - "@com_google_googleapis//google/rpc:status_proto", - ], -) java_proto_library( name = "service_config_java_proto", @@ -97,19 +30,16 @@ java_proto_library( # ============= Binary targets ================ java_binary( - name = "protoc-gen-gapic-java", + name = "protoc-gen-java_gapic", srcs = [ "//src/main/java/com/google/api/generator:generator_files", ], main_class = "com.google.api.generator.Main", deps = [ - ":annotations_java_proto", - ":client_java_proto", - ":field_behavior_java_proto", - ":longrunning_java_proto", - ":resource_java_proto", "//src/main/java/com/google/api/generator", "//src/main/java/com/google/api/generator/gapic", + "@com_google_googleapis//google/api:api_java_proto", + "@com_google_googleapis//google/longrunning:longrunning_java_proto", "@com_google_guava_guava", "@com_google_protobuf//:protobuf_java", ], diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 3bebe8b197..80a3ab67d5 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -35,7 +35,7 @@ below are temporary and better ones will be coming. 4. Build this plugin. ```sh - bazel build :protoc-gen-gapic-java + bazel build :protoc-gen-java_gapic ``` 5. Run the plugin. At this stage, it will not do anything except write @@ -43,7 +43,7 @@ below are temporary and better ones will be coming. ``` protoc -I=${PROTOC_INCLUDE_DIR} -I=${GOOGLEAPIS_DIR} -I=${YOUR_PROTO_DIR} \ - --plugin=bazel-bin/protoc-gen-gapic-java ~/dev/googleapis/google/showcase/v1test/*.proto \ + --plugin=bazel-bin/protoc-gen-java_gapic ~/dev/googleapis/google/showcase/v1test/*.proto \ --gapic-java_out=/tmp/test ``` diff --git a/WORKSPACE b/WORKSPACE index 9dc131d2f1..162b2b5777 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,4 +1,4 @@ -workspace(name = "com_google_api_codegen") +workspace(name = "com_google_api_generator") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") @@ -14,36 +14,63 @@ http_archive( ], ) -load("//:repository_rules.bzl", "com_google_api_codegen_properties") +load("//:repository_rules.bzl", "com_google_api_generator_properties") -com_google_api_codegen_properties( - name = "com_google_api_codegen_properties", +com_google_api_generator_properties( + name = "com_google_api_generator_properties", file = "//:dependencies.properties", ) -load("//:repositories.bzl", "com_google_api_codegen_repositories") +load("//:repositories.bzl", "com_google_api_generator_repositories") -com_google_api_codegen_repositories() +com_google_api_generator_repositories() # protobuf load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") protobuf_deps() -# gRPC. -load("@io_grpc_java//:repositories.bzl", "grpc_java_repositories") - -grpc_java_repositories() - -# Resource names plugin. -load( - "@com_google_protoc_java_resource_names_plugin//:repositories.bzl", - "com_google_protoc_java_resource_names_plugin_repositories", +# Java dependencies. +# Import the monolith so we can transitively use its gapic rules for googleapis. +http_archive( + name = "com_google_api_codegen", + strip_prefix = "gapic-generator-2.4.6", + urls = ["https://github.com/googleapis/gapic-generator/archive/v2.4.6.zip"], ) + load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language") switched_rules_by_language( name = "com_google_googleapis_imports", + gapic = True, + grpc = True, + java = True, +) + +# TODO(miraleung): When the gax-java Bazel build PRs are submitted, do the following: +# - Rename the next rule. +# - Use these rules in build files: +# - "@com_google_api_gax_java//gax", +# - "@com_google_api_gax_java//gax-grpc:gax_grpc", +_gax_java_version = "1.58.2" + +http_archive( + name = "com_google_api_gax_java_temp", + strip_prefix = "gax-java-%s" % _gax_java_version, + urls = ["https://github.com/googleapis/gax-java/archive/v%s.zip" % _gax_java_version], +) + +load("@com_google_api_gax_java_temp//:repository_rules.bzl", "com_google_api_gax_java_properties") + +com_google_api_gax_java_properties( + name = "com_google_api_gax_java_properties", + file = "@com_google_api_gax_java_temp//:dependencies.properties", ) -com_google_protoc_java_resource_names_plugin_repositories(omit_com_google_protobuf = True) +load("@com_google_api_gax_java_temp//:repositories.bzl", "com_google_api_gax_java_repositories") + +com_google_api_gax_java_repositories() + +load("@io_grpc_grpc_java//:repositories.bzl", "grpc_java_repositories") + +grpc_java_repositories() diff --git a/dependencies.properties b/dependencies.properties index 05ca128d8f..feeea4cce5 100644 --- a/dependencies.properties +++ b/dependencies.properties @@ -16,11 +16,12 @@ version.io_grpc_java=1.30.2 # Common deps. maven.com_google_guava_guava=com.google.guava:guava:26.0-jre -maven.javax_validation_javax_validation_api=javax.validation:validation-api:2.0.1.Final maven.com_google_code_findbugs_jsr305=com.google.code.findbugs:jsr305:3.0.0 maven.com_google_auto_value_auto_value=com.google.auto.value:auto-value:1.7.2 maven.com_google_auto_value_auto_value_annotations=com.google.auto.value:auto-value-annotations:1.7.2 maven.com_google_protobuf_protobuf_java=com.google.protobuf:protobuf-java:3.12.2 +maven.javax_annotation_api=javax.annotation:javax.annotation-api:1.3.2 +maven.javax_validation_javax_validation_api=javax.validation:validation-api:2.0.1.Final # Gapic YAML parsing for batching settings. maven.org_yaml_snakeyaml=org.yaml:snakeyaml:1.26 diff --git a/repositories.bzl b/repositories.bzl index cf0a3fa7db..3c207aae8d 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -15,9 +15,9 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:jvm.bzl", "jvm_maven_import_external") -load("@com_google_api_codegen_properties//:dependencies.properties.bzl", "PROPERTIES") +load("@com_google_api_generator_properties//:dependencies.properties.bzl", "PROPERTIES") -def com_google_api_codegen_repositories(): +def com_google_api_generator_repositories(): # Import dependencies shared between Gradle and Bazel (i.e. maven dependencies) for name, artifact in PROPERTIES.items(): _maybe( @@ -32,7 +32,6 @@ def com_google_api_codegen_repositories(): # Import Bazel-only dependencies (Gradle version will import maven artifacts of same # version, while Bazel will depend on Bazel workspaces). The versions are shared in the # properties file. - _protobuf_version = PROPERTIES["version.com_google_protobuf"] _maybe( http_archive, @@ -49,13 +48,6 @@ def com_google_api_codegen_repositories(): licenses = ["notice", "reciprocal"], ) - _maybe( - http_archive, - name = "com_google_protoc_java_resource_names_plugin", - strip_prefix = "protoc-java-resource-names-plugin-3fb2ec9b778f62646c05a7b960c893464c7791c0", - urls = ["https://github.com/googleapis/protoc-java-resource-names-plugin/archive/3fb2ec9b778f62646c05a7b960c893464c7791c0.zip"], - ) - _maybe( http_archive, name = "bazel_skylib", @@ -107,6 +99,7 @@ def com_google_api_codegen_repositories(): server_urls = ["https://repo.maven.apache.org/maven2/"], ) + # TODO(miraleung): Remove these gax imports when gax-java's Bazel build PRs have been submitted. _gax_java_version = PROPERTIES["version.com_google_gax_java"] # Use the Maven artifact because a full bazel-build requires pulling in many transitive deps. @@ -124,15 +117,6 @@ def com_google_api_codegen_repositories(): server_urls = ["https://repo.maven.apache.org/maven2/"], ) - # gRPC. - _io_grpc_version = PROPERTIES["version.io_grpc_java"] - _maybe( - http_archive, - name = "io_grpc_java", - urls = ["https://github.com/grpc/grpc-java/archive/v%s.zip" % _io_grpc_version], - strip_prefix = "grpc-java-%s" % _io_grpc_version, - ) - # grpc-proto doesn't have releases, so we use hashes instead. _io_grpc_proto_prefix = "0020624375a8ee4c7dd9b3e513e443b90bc28990" # Aug. 20, 2020. _maybe( diff --git a/repository_rules.bzl b/repository_rules.bzl index cb625aefa1..f5b8a6444c 100644 --- a/repository_rules.bzl +++ b/repository_rules.bzl @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -def _com_google_api_codegen_properties_impl(ctx): +def _com_google_api_generator_properties_impl(ctx): props_path = ctx.path(ctx.attr.file) result = ctx.execute(["cat", props_path]) @@ -36,13 +36,12 @@ PROPERTIES = {props_as_map} """.format( properties_file = props_name, props_as_map = str(props_as_map), - ) + ) ctx.file("BUILD.bazel", "") ctx.file("%s.bzl" % props_name, dependencies_bzl) - -com_google_api_codegen_properties = repository_rule( - implementation = _com_google_api_codegen_properties_impl, +com_google_api_generator_properties = repository_rule( + implementation = _com_google_api_generator_properties_impl, attrs = { "file": attr.label(), }, diff --git a/rules_java_gapic/BUILD.bazel b/rules_java_gapic/BUILD.bazel new file mode 100644 index 0000000000..e69de29bb2 diff --git a/rules_java_gapic/java_gapic.bzl b/rules_java_gapic/java_gapic.bzl new file mode 100644 index 0000000000..6bdb1a437d --- /dev/null +++ b/rules_java_gapic/java_gapic.bzl @@ -0,0 +1,55 @@ +# Copyright 2019 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@com_google_api_codegen//rules_gapic:gapic.bzl", "proto_custom_library", "unzipped_srcjar") + +def java_gapic_library( + name, + srcs, + package = None, + service_yaml = None, + grpc_service_config = None, + gapic_yaml = None, + deps = [], + test_deps = [], + **kwargs): + file_args_dict = {} + + if grpc_service_config: + file_args_dict[grpc_service_config] = "grpc-service-config" + + if gapic_yaml: + file_args_dict[gapic_yaml] = "gapic-config" + + # Currently a no-op. + if service_yaml: + file_args_dict[service_yaml] = "gapic-service-config" + + #file_args = ["%s=%s" % (k, v) for k, v in file_args_dict.items()] + + srcjar_name = name + "_srcjar" + raw_srcjar_name = srcjar_name + "_raw" + output_suffix = ".srcjar" + + _java_generator_name = "java_gapic" + proto_custom_library( + name = raw_srcjar_name, + deps = srcs, + plugin = Label("@com_google_api_generator//:protoc-gen-%s" % _java_generator_name), + plugin_file_args = {}, + opt_file_args = file_args_dict, + output_type = _java_generator_name, + output_suffix = output_suffix, + **kwargs + ) diff --git a/run.sh b/run.sh index 46572fe76c..6adb1f4771 100755 --- a/run.sh +++ b/run.sh @@ -59,10 +59,10 @@ then fi # Build if needed. -if [[ "${FLAGS_use_cached}" == 0 ]] || [[ ! -f bazel-bin/protoc-gen-gapic-java ]] +if [[ "${FLAGS_use_cached}" == 0 ]] || [[ ! -f bazel-bin/protoc-gen-java_gapic ]] then echo_success "Rebuilding the microgenerator..." - bazel build :protoc-gen-gapic-java + bazel build :protoc-gen-java_gapic if [[ $? -ne 0 ]] then echo_error "Build failed." @@ -72,12 +72,25 @@ then echo_success "Done" fi +# Key values are synced to rules_java_gapic/java_gapic.bzl. +SERVICE_CONFIG_OPT="" +if [ -n "$FLAGS_service_config" ] +then + SERVICE_CONFIG_OPT="grpc-service-config=$FLAGS_service_config" +fi +GAPIC_CONFIG_OPT="" +if [ -n "$FLAGS_gapic_config" ] +then + GAPIC_CONFIG_OPT="gapic-config=$FLAGS_gapic_config" +fi + # Run protoc. protoc -I="${PROTOC_INCLUDE_DIR}" -I="${FLAGS_googleapis}" -I="${FLAGS_protos}" \ -I="${FLAGS_googleapis}/google/longrunning" \ - --plugin=bazel-bin/protoc-gen-gapic-java ${FLAGS_protos}/*.proto \ - --gapic-java_out="${FLAGS_out}" \ - --gapic-java_opt="${FLAGS_service_config},${FLAGS_gapic_config}" \ + --include_source_info \ + --plugin=bazel-bin/protoc-gen-java_gapic ${FLAGS_protos}/*.proto \ + --java_gapic_out="${FLAGS_out}" \ + --java_gapic_opt="${SERVICE_CONFIG_OPT},${GAPIC_CONFIG_OPT}" \ --experimental_allow_proto3_optional echo_success "Output files written to ${FLAGS_out}" diff --git a/src/main/java/com/google/api/generator/BUILD.bazel b/src/main/java/com/google/api/generator/BUILD.bazel index a27e2694f8..864fdfcf6f 100644 --- a/src/main/java/com/google/api/generator/BUILD.bazel +++ b/src/main/java/com/google/api/generator/BUILD.bazel @@ -31,15 +31,12 @@ java_library( ":generator_files", ], deps = [ - "//:annotations_java_proto", - "//:client_java_proto", - "//:field_behavior_java_proto", - "//:longrunning_java_proto", - "//:resource_java_proto", "//src/main/java/com/google/api/generator/engine", "//src/main/java/com/google/api/generator/engine/ast", "//src/main/java/com/google/api/generator/gapic", "//src/main/java/com/google/api/generator/gapic/model", + "@com_google_googleapis//google/api:api_java_proto", + "@com_google_googleapis//google/longrunning:longrunning_java_proto", "@com_google_guava_guava//jar", "@com_google_protobuf//:protobuf_java", ], diff --git a/src/main/java/com/google/api/generator/Main.java b/src/main/java/com/google/api/generator/Main.java index a1db4e4ab4..0e1e985e2f 100644 --- a/src/main/java/com/google/api/generator/Main.java +++ b/src/main/java/com/google/api/generator/Main.java @@ -32,8 +32,7 @@ public static void main(String[] args) ExtensionRegistry registry = ExtensionRegistry.newInstance(); registerAllExtensions(registry); CodeGeneratorRequest request = CodeGeneratorRequest.parseFrom(System.in, registry); - String outputFilePath = "temp-gen.srcjar"; - CodeGeneratorResponse response = Generator.generateGapic(request, outputFilePath); + CodeGeneratorResponse response = Generator.generateGapic(request); response.writeTo(System.out); } diff --git a/src/main/java/com/google/api/generator/engine/ast/MethodInvocationExpr.java b/src/main/java/com/google/api/generator/engine/ast/MethodInvocationExpr.java index 45b1c34ab4..eb1e216134 100644 --- a/src/main/java/com/google/api/generator/engine/ast/MethodInvocationExpr.java +++ b/src/main/java/com/google/api/generator/engine/ast/MethodInvocationExpr.java @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; import javax.annotation.Nullable; @AutoValue @@ -116,6 +117,12 @@ public MethodInvocationExpr build() { || methodInvocationExpr.staticReferenceType() == null, "Only the expression reference or the static reference can be set, not both"); + Preconditions.checkState( + methodInvocationExpr.arguments().stream().allMatch(e -> !Objects.isNull(e)), + String.format( + "Found null expression in arguments for %s", + methodInvocationExpr.methodIdentifier().name())); + return methodInvocationExpr; } } diff --git a/src/main/java/com/google/api/generator/engine/ast/NewObjectExpr.java b/src/main/java/com/google/api/generator/engine/ast/NewObjectExpr.java index fa8c4929cf..40e5275f92 100644 --- a/src/main/java/com/google/api/generator/engine/ast/NewObjectExpr.java +++ b/src/main/java/com/google/api/generator/engine/ast/NewObjectExpr.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; @AutoValue public abstract class NewObjectExpr implements Expr { @@ -56,16 +57,24 @@ public Builder setArguments(Expr... arguments) { public abstract Builder setIsGeneric(boolean isGeneric); - // Private accessor. + // Private accessors. abstract TypeNode type(); - // Private accessor. + abstract boolean isGeneric(); + abstract ImmutableList arguments(); + abstract NewObjectExpr autoBuild(); public NewObjectExpr build() { Preconditions.checkState( TypeNode.isReferenceType(type()), "New object expression should be reference types."); + + Preconditions.checkState( + arguments().stream().allMatch(e -> !Objects.isNull(e)), + String.format( + "Found null argument for the \"new\" constructor of %s", type().reference().name())); + // Only the case where generics() is empty and isGeneric() is false, we set isGeneric() to // false. Otherwise, isGeneric() should be true. setIsGeneric(isGeneric() || !type().reference().generics().isEmpty()); diff --git a/src/main/java/com/google/api/generator/engine/ast/ReferenceConstructorExpr.java b/src/main/java/com/google/api/generator/engine/ast/ReferenceConstructorExpr.java index f3b2d516be..405712c905 100644 --- a/src/main/java/com/google/api/generator/engine/ast/ReferenceConstructorExpr.java +++ b/src/main/java/com/google/api/generator/engine/ast/ReferenceConstructorExpr.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; @AutoValue public abstract class ReferenceConstructorExpr implements Expr { @@ -64,6 +65,10 @@ public Builder setArguments(Expr... arguments) { // private. abstract Builder setKeywordKind(KeywordKind keywordKind); + abstract TypeNode type(); + + abstract ImmutableList arguments(); + abstract ReferenceConstructorExpr autoBuild(); public ReferenceConstructorExpr build() { @@ -71,6 +76,13 @@ public ReferenceConstructorExpr build() { Preconditions.checkState( referenceConstructorExpr.type().isReferenceType(referenceConstructorExpr.type()), "A this/super constructor must have a reference type."); + + Preconditions.checkState( + arguments().stream().allMatch(e -> !Objects.isNull(e)), + String.format( + "Found null argumentfor in the \"this/super\" initialization of %s", + type().reference().name())); + return referenceConstructorExpr; } } diff --git a/src/main/java/com/google/api/generator/gapic/Generator.java b/src/main/java/com/google/api/generator/gapic/Generator.java index 2cab599ff1..80b3e93636 100644 --- a/src/main/java/com/google/api/generator/gapic/Generator.java +++ b/src/main/java/com/google/api/generator/gapic/Generator.java @@ -24,11 +24,11 @@ import java.util.List; public class Generator { - public static CodeGeneratorResponse generateGapic( - CodeGeneratorRequest request, String outputFilePath) { + public static CodeGeneratorResponse generateGapic(CodeGeneratorRequest request) { GapicContext context = Parser.parse(request); List clazzes = Composer.composeServiceClasses(context); - CodeGeneratorResponse response = Writer.writeCode(clazzes, outputFilePath); + String outputFilename = "temp-codegen.srcjar"; + CodeGeneratorResponse response = Writer.writeCode(clazzes, outputFilename); return response; } } diff --git a/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel index c9be270e28..af94a71b49 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel +++ b/src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel @@ -11,9 +11,6 @@ java_library( ":composer_files", ], deps = [ - "//:longrunning_java_proto", - "//:monitored_resource_java_proto", - "//:rpc_java_proto", "//:service_config_java_proto", "//src/main/java/com/google/api/generator/engine/ast", "//src/main/java/com/google/api/generator/gapic:status_java_proto", @@ -23,13 +20,17 @@ java_library( "@com_google_api_gax_grpc//jar", "@com_google_api_gax_java//jar", "@com_google_code_findbugs_jsr305//jar", + "@com_google_googleapis//google/api:api_java_proto", + "@com_google_googleapis//google/longrunning:longrunning_java_proto", + "@com_google_googleapis//google/rpc:rpc_java_proto", "@com_google_guava_guava//jar", "@com_google_protobuf//:protobuf_java", "@com_google_protobuf//:protobuf_java_util", "@com_google_protobuf//java/core", - "@io_grpc_java//api", - "@io_grpc_java//protobuf", - "@io_grpc_java//stub", + "@io_grpc_grpc_java//api", + "@io_grpc_grpc_java//protobuf", + "@io_grpc_grpc_java//stub", + "@javax_annotation_api//jar", "@junit_junit//jar", "@org_threeten_threetenbp//jar", ], diff --git a/src/main/java/com/google/api/generator/gapic/composer/ResourceNameHelperClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ResourceNameHelperClassComposer.java index 249a4c4252..84d2ac35ab 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ResourceNameHelperClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ResourceNameHelperClassComposer.java @@ -1082,13 +1082,19 @@ private static MethodDefinition createToStringMethod( if (!hasVariants) { String token = getTokenSet(tokenHierarchies).stream().collect(Collectors.toList()).get(0); String javaTokenVarName = JavaStyle.toLowerCamelCase(token); + Preconditions.checkNotNull( + patternTokenVarExprs.get(token), + String.format( + "No expression found for token %s amongst values %s", + javaTokenVarName, patternTokenVarExprs.toString())); + MethodInvocationExpr returnInstantiateExpr = MethodInvocationExpr.builder() .setExprReferenceExpr(templateFinalVarExprs.get(0)) .setMethodName("instantiate") .setArguments( ValueExpr.withValue(StringObjectValue.withValue(token)), - patternTokenVarExprs.get(javaTokenVarName)) + patternTokenVarExprs.get(token)) .setReturnType(TypeNode.STRING) .build(); return MethodDefinition.builder() diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java index c3893fee8d..6927c87518 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java @@ -194,6 +194,7 @@ private static List createStaticCreatorMethods( MethodDefinition createMethodOne = MethodDefinition.builder() + .setHeaderCommentStatements(ServiceClientCommentComposer.CREATE_METHOD_NO_ARG_COMMENT) .setScope(ScopeNode.PUBLIC) .setIsStatic(true) .setIsFinal(true) @@ -211,6 +212,8 @@ private static List createStaticCreatorMethods( methods.add( MethodDefinition.builder() + .setHeaderCommentStatements( + ServiceClientCommentComposer.CREATE_METHOD_SETTINGS_ARG_COMMENT) .setScope(ScopeNode.PUBLIC) .setIsStatic(true) .setIsFinal(true) @@ -240,6 +243,9 @@ private static List createStaticCreatorMethods( .build(); methods.add( MethodDefinition.builder() + .setHeaderCommentStatements( + ServiceClientCommentComposer.createCreateMethodStubArgComment( + settingsVarExpr.type())) .setAnnotations(Arrays.asList(betaAnnotation)) .setScope(ScopeNode.PUBLIC) .setIsStatic(true) @@ -327,6 +333,8 @@ private static List createConstructorMethods( methods.add( MethodDefinition.constructorBuilder() + .setHeaderCommentStatements( + ServiceClientCommentComposer.PROTECTED_CONSTRUCTOR_SETTINGS_ARG_COMMENT) .setScope(ScopeNode.PROTECTED) .setReturnType(thisClassType) .setArguments(settingsVarExpr.toBuilder().setIsDecl(true).build()) @@ -376,8 +384,9 @@ private static List createGetterMethods( Map methodNameToTypes = new LinkedHashMap<>(); methodNameToTypes.put("getSettings", types.get(String.format("%sSettings", service.name()))); methodNameToTypes.put("getStub", types.get(String.format("%sStub", service.name()))); + String getOperationsClientMethodName = "getOperationsClient"; if (hasLroClient) { - methodNameToTypes.put("getOperationsClient", types.get("OperationsClient")); + methodNameToTypes.put(getOperationsClientMethodName, types.get("OperationsClient")); } AnnotationNode betaStubAnnotation = AnnotationNode.builder() @@ -392,7 +401,13 @@ private static List createGetterMethods( String methodName = e.getKey(); TypeNode methodReturnType = e.getValue(); String returnVariableName = JavaStyle.toLowerCamelCase(methodName.substring(3)); - return MethodDefinition.builder() + MethodDefinition.Builder methodBuilder = MethodDefinition.builder(); + if (methodName.equals(getOperationsClientMethodName)) { + methodBuilder = + methodBuilder.setHeaderCommentStatements( + ServiceClientCommentComposer.GET_OPERATIONS_CLIENT_METHOD_COMMENT); + } + return methodBuilder .setAnnotations( methodName.equals("getStub") ? Arrays.asList(betaStubAnnotation) diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientCommentComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientCommentComposer.java new file mode 100644 index 0000000000..3ace86e832 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientCommentComposer.java @@ -0,0 +1,56 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer; + +import com.google.api.generator.engine.ast.CommentStatement; +import com.google.api.generator.engine.ast.JavaDocComment; +import com.google.api.generator.engine.ast.TypeNode; + +class ServiceClientCommentComposer { + private static final String COLON = ":"; + + private static final String CREATE_METHOD_STUB_ARG_PATTERN = + "Constructs an instance of EchoClient, using the given stub for making calls. This is for" + + " advanced usage - prefer using create(%s)."; + + static final CommentStatement CREATE_METHOD_NO_ARG_COMMENT = + toSimpleComment("Constructs an instance of EchoClient with default settings."); + + static final CommentStatement CREATE_METHOD_SETTINGS_ARG_COMMENT = + toSimpleComment( + "Constructs an instance of EchoClient, using the given settings. The channels are" + + " created based on the settings passed in, or defaults for any settings that are" + + " not set."); + + static final CommentStatement PROTECTED_CONSTRUCTOR_SETTINGS_ARG_COMMENT = + toSimpleComment( + "Constructs an instance of EchoClient, using the given settings. This is protected so" + + " that it is easy to make a subclass, but otherwise, the static factory methods" + + " should be preferred."); + + static final CommentStatement GET_OPERATIONS_CLIENT_METHOD_COMMENT = + toSimpleComment( + "Returns the OperationsClient that can be used to query the status of a long-running" + + " operation returned by another API method call."); + + static CommentStatement createCreateMethodStubArgComment(TypeNode settingsType) { + return toSimpleComment( + String.format(CREATE_METHOD_STUB_ARG_PATTERN, settingsType.reference().name())); + } + + private static CommentStatement toSimpleComment(String comment) { + return CommentStatement.withComment(JavaDocComment.withComment(comment)); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposer.java index 9e80c622c9..c6166e6e40 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposer.java @@ -108,6 +108,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import javax.annotation.Generated; +import javax.annotation.Nullable; import org.threeten.bp.Duration; // TODO(miraleung): Refactor ClassComposer's interface. @@ -153,7 +154,10 @@ public static ServiceStubSettingsClassComposer instance() { } public GapicClass generate( - Service service, GapicServiceConfig serviceConfig, Map messageTypes) { + Service service, + @Nullable GapicServiceConfig serviceConfig, + Map messageTypes) { + // TODO(miraleung): Robustify this against a null serviceConfig. String pakkage = String.format("%s.stub", service.pakkage()); Map types = createDynamicTypes(service, pakkage); Map methodSettingsMemberVarExprs = @@ -215,7 +219,8 @@ private static Map createMethodSettingsClassMemberVarExprs // Creates class variables Settings, e.g. echoSettings. // TODO(miraleung): Handle batching here. for (Method method : service.methods()) { - boolean hasBatchingSettings = serviceConfig.hasBatchingSetting(service, method); + boolean hasBatchingSettings = + !Objects.isNull(serviceConfig) && serviceConfig.hasBatchingSetting(service, method); TypeNode settingsType = getCallSettingsType(method, types, hasBatchingSettings, isNestedClass); String varName = JavaStyle.toLowerCamelCase(String.format("%sSettings", method.name())); @@ -304,7 +309,9 @@ private static List createClassStatements( for (Method method : service.methods()) { Optional batchingSettingOpt = - serviceConfig.getBatchingSetting(service, method); + Objects.isNull(serviceConfig) + ? Optional.empty() + : serviceConfig.getBatchingSetting(service, method); if (batchingSettingOpt.isPresent()) { statements.add( exprToStatementFn.apply( @@ -1125,7 +1132,8 @@ private static MethodDefinition createClassConstructor( } private static ClassDefinition createNestedBuilderClass( - Service service, GapicServiceConfig serviceConfig, Map types) { + Service service, @Nullable GapicServiceConfig serviceConfig, Map types) { + // TODO(miraleung): Robustify this against a null serviceConfig. String thisClassName = getThisClassName(service.name()); TypeNode outerThisClassType = types.get(thisClassName); @@ -1235,7 +1243,8 @@ private static List createNestedClassMethods( } private static MethodDefinition createNestedClassInitDefaultsMethod( - Service service, GapicServiceConfig serviceConfig, Map types) { + Service service, @Nullable GapicServiceConfig serviceConfig, Map types) { + // TODO(miraleung): Robustify this against a null serviceConfig. TypeNode builderType = types.get(NESTED_BUILDER_CLASS_NAME); VariableExpr builderVarExpr = VariableExpr.withVariable( @@ -1248,7 +1257,7 @@ private static MethodDefinition createNestedClassInitDefaultsMethod( if (streamKind.equals(Method.Stream.CLIENT) || streamKind.equals(Method.Stream.BIDI)) { continue; } - if (serviceConfig.hasBatchingSetting(service, method)) { + if (!Objects.isNull(serviceConfig) && serviceConfig.hasBatchingSetting(service, method)) { Optional batchingSettingOpt = serviceConfig.getBatchingSetting(service, method); Preconditions.checkState( diff --git a/src/main/java/com/google/api/generator/gapic/model/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/model/BUILD.bazel index e883369a61..53be89cb6f 100644 --- a/src/main/java/com/google/api/generator/gapic/model/BUILD.bazel +++ b/src/main/java/com/google/api/generator/gapic/model/BUILD.bazel @@ -11,7 +11,6 @@ java_library( ":model_files", ], deps = [ - "//:rpc_java_proto", "//:service_config_java_proto", "//src/main/java/com/google/api/generator:autovalue", "//src/main/java/com/google/api/generator/engine/ast", @@ -19,6 +18,7 @@ java_library( "@com_google_auto_value_auto_value//jar", "@com_google_auto_value_auto_value_annotations//jar", "@com_google_code_findbugs_jsr305//jar", + "@com_google_googleapis//google/rpc:rpc_java_proto", "@com_google_guava_guava//jar", "@com_google_protobuf//:protobuf_java", ], diff --git a/src/main/java/com/google/api/generator/gapic/protoparser/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/protoparser/BUILD.bazel index 412a924667..e1cb8a9ad7 100644 --- a/src/main/java/com/google/api/generator/gapic/protoparser/BUILD.bazel +++ b/src/main/java/com/google/api/generator/gapic/protoparser/BUILD.bazel @@ -19,16 +19,14 @@ java_library( ":protoparser_files", ], deps = [ - "//:annotations_java_proto", - "//:client_java_proto", - "//:longrunning_java_proto", - "//:resource_java_proto", "//:service_config_java_proto", "//src/main/java/com/google/api/generator/engine/ast", "//src/main/java/com/google/api/generator/gapic/model", "//src/main/java/com/google/api/generator/gapic/utils", "@com_google_api_api_common//jar", "@com_google_code_findbugs_jsr305//jar", + "@com_google_googleapis//google/api:api_java_proto", + "@com_google_googleapis//google/longrunning:longrunning_java_proto", "@com_google_guava_guava//jar", "@com_google_protobuf//:protobuf_java", "@com_google_protobuf//:protobuf_java_util", diff --git a/src/main/java/com/google/api/generator/gapic/protoparser/PluginArgumentParser.java b/src/main/java/com/google/api/generator/gapic/protoparser/PluginArgumentParser.java index d5e325e3bb..784a9ae496 100644 --- a/src/main/java/com/google/api/generator/gapic/protoparser/PluginArgumentParser.java +++ b/src/main/java/com/google/api/generator/gapic/protoparser/PluginArgumentParser.java @@ -22,36 +22,48 @@ // Parses the arguments from the protoc plugin. public class PluginArgumentParser { private static final String COMMA = ","; + private static final String EQUALS = "="; + + // Synced to rules_java_gapic/java_gapic.bzl. + @VisibleForTesting static final String KEY_GRPC_SERVICE_CONFIG = "grpc-service-config"; + @VisibleForTesting static final String KEY_GAPIC_CONFIG = "gapic-config"; + private static final String JSON_FILE_ENDING = "grpc_service_config.json"; private static final String GAPIC_YAML_FILE_ENDING = "gapic.yaml"; - public static Optional parseJsonConfigPath(CodeGeneratorRequest request) { + static Optional parseJsonConfigPath(CodeGeneratorRequest request) { return parseJsonConfigPath(request.getParameter()); } - public static Optional parseGapicYamlConfigPath(CodeGeneratorRequest request) { + static Optional parseGapicYamlConfigPath(CodeGeneratorRequest request) { return parseGapicYamlConfigPath(request.getParameter()); } /** Expects a comma-separated list of file paths. */ @VisibleForTesting static Optional parseJsonConfigPath(String pluginProtocArgument) { - return parseArgument(pluginProtocArgument, JSON_FILE_ENDING); + return parseArgument(pluginProtocArgument, KEY_GRPC_SERVICE_CONFIG, JSON_FILE_ENDING); } @VisibleForTesting static Optional parseGapicYamlConfigPath(String pluginProtocArgument) { - return parseArgument(pluginProtocArgument, GAPIC_YAML_FILE_ENDING); + return parseArgument(pluginProtocArgument, KEY_GAPIC_CONFIG, GAPIC_YAML_FILE_ENDING); } - private static Optional parseArgument(String pluginProtocArgument, String fileEnding) { + private static Optional parseArgument( + String pluginProtocArgument, String key, String fileEnding) { if (Strings.isNullOrEmpty(pluginProtocArgument)) { return Optional.empty(); } - for (String rawPath : pluginProtocArgument.split(COMMA)) { - String path = rawPath.trim(); - if (path.endsWith(fileEnding)) { - return Optional.of(path); + for (String argComponent : pluginProtocArgument.split(COMMA)) { + String[] args = argComponent.trim().split(EQUALS); + if (args.length < 2) { + continue; + } + String keyVal = args[0]; + String valueVal = args[1]; + if (keyVal.equals(key) && valueVal.endsWith(fileEnding)) { + return Optional.of(valueVal); } } return Optional.empty(); diff --git a/src/test/java/com/google/api/generator/engine/ast/MethodInvocationExprTest.java b/src/test/java/com/google/api/generator/engine/ast/MethodInvocationExprTest.java index 54faa4edfe..eed99da9b7 100644 --- a/src/test/java/com/google/api/generator/engine/ast/MethodInvocationExprTest.java +++ b/src/test/java/com/google/api/generator/engine/ast/MethodInvocationExprTest.java @@ -36,6 +36,28 @@ public void validBuildMethodInvocationExpr() { // No exception thrown, we're good. } + @Test + public void validBuildMethodInvocationExpr_hasArguments() { + Reference stringRef = ConcreteReference.withClazz(String.class); + TypeNode returnType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(ArrayList.class) + .setGenerics(Arrays.asList(stringRef)) + .build()); + + MethodInvocationExpr.builder() + .setMethodName("addNumbers") + .setArguments( + ValueExpr.withValue( + PrimitiveValue.builder().setType(TypeNode.INT).setValue("1").build()), + ValueExpr.withValue( + PrimitiveValue.builder().setType(TypeNode.INT).setValue("2").build())) + .setReturnType(returnType) + .build(); + // No exception thrown, we're good. + } + @Test public void validBuildMethodInvocationExpr_staticReference() { TypeNode someType = @@ -86,4 +108,27 @@ public void invalidBuildMethodInvocationExpr_staticAndExprBoth() { .build(); }); } + + @Test + public void invalidBuildMethodInvocationExpr_nullArgument() { + Reference stringRef = ConcreteReference.withClazz(String.class); + TypeNode returnType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(ArrayList.class) + .setGenerics(Arrays.asList(stringRef)) + .build()); + + assertThrows( + IllegalStateException.class, + () -> + MethodInvocationExpr.builder() + .setMethodName("addNumbers") + .setArguments( + ValueExpr.withValue( + PrimitiveValue.builder().setType(TypeNode.INT).setValue("1").build()), + null) + .setReturnType(returnType) + .build()); + } } diff --git a/src/test/java/com/google/api/generator/engine/ast/NewObjectExprTest.java b/src/test/java/com/google/api/generator/engine/ast/NewObjectExprTest.java index 202d39394e..1bc2c48cd6 100644 --- a/src/test/java/com/google/api/generator/engine/ast/NewObjectExprTest.java +++ b/src/test/java/com/google/api/generator/engine/ast/NewObjectExprTest.java @@ -39,6 +39,24 @@ public void validNewObjectValue_basic() { assertEquals(newObjectExpr.isGeneric(), true); } + @Test + public void validNewObjectValue_hasArgument() { + VaporReference ref = + VaporReference.builder() + .setName("Student") + .setPakkage("com.google.example.examples.v1") + .build(); + TypeNode type = TypeNode.withReference(ref); + NewObjectExpr.builder() + .setType(type) + .setArguments( + ValueExpr.withValue(StringObjectValue.withValue("Stu Dent")), + ValueExpr.withValue( + PrimitiveValue.builder().setType(TypeNode.INT).setValue("12345678").build())) + .build(); + // No exception thrown, so we succeeded. + } + @Test public void validNewObjectExpr_edgeCase() { // isGeneric() is false, but generics() is not empty. @@ -130,4 +148,21 @@ public void invalidNewObjectExpr_nullType() { NewObjectExpr.builder().setIsGeneric(false).setType(TypeNode.NULL).build(); }); } + + @Test + public void invalidNewObjectValue_nullArgument() { + VaporReference ref = + VaporReference.builder() + .setName("Student") + .setPakkage("com.google.example.examples.v1") + .build(); + TypeNode type = TypeNode.withReference(ref); + assertThrows( + NullPointerException.class, + () -> + NewObjectExpr.builder() + .setType(type) + .setArguments(ValueExpr.withValue(StringObjectValue.withValue("Stu Dent")), null) + .build()); + } } diff --git a/src/test/java/com/google/api/generator/engine/ast/ReferenceConstructorExprTest.java b/src/test/java/com/google/api/generator/engine/ast/ReferenceConstructorExprTest.java index c2a98d6c64..8ba47c8ac6 100644 --- a/src/test/java/com/google/api/generator/engine/ast/ReferenceConstructorExprTest.java +++ b/src/test/java/com/google/api/generator/engine/ast/ReferenceConstructorExprTest.java @@ -32,6 +32,24 @@ public void validReferenceConstructorExpr_thisConstructorBasic() { // No exception thrown, so we succeeded. } + @Test + public void validReferenceConstructorExpr_hasArguments() { + VaporReference ref = + VaporReference.builder() + .setName("Student") + .setPakkage("com.google.example.examples.v1") + .build(); + TypeNode typeNode = TypeNode.withReference(ref); + ReferenceConstructorExpr.thisBuilder() + .setType(typeNode) + .setArguments( + ValueExpr.withValue(StringObjectValue.withValue("Stu Dent")), + ValueExpr.withValue( + PrimitiveValue.builder().setType(TypeNode.INT).setValue("12345678").build())) + .build(); + // No exception thrown, so we succeeded. + } + @Test public void validReferenceConstructorExpr_superConstructorBasic() { VaporReference ref = @@ -61,4 +79,21 @@ public void invalidReferenceConstructorExpr_nullType() { ReferenceConstructorExpr.superBuilder().setType(TypeNode.NULL).build(); }); } + + @Test + public void invalidReferenceConstructorExpr_nullArgument() { + VaporReference ref = + VaporReference.builder() + .setName("Student") + .setPakkage("com.google.example.examples.v1") + .build(); + TypeNode typeNode = TypeNode.withReference(ref); + assertThrows( + NullPointerException.class, + () -> + ReferenceConstructorExpr.thisBuilder() + .setType(typeNode) + .setArguments(ValueExpr.withValue(StringObjectValue.withValue("Stu Dent")), null) + .build()); + } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/BUILD.bazel index 740ba1b5f2..e1601e6536 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/composer/BUILD.bazel @@ -21,13 +21,6 @@ filegroup( srcs = ["{0}.java".format(f) for f in TESTS], ) -java_proto_library( - name = "logging_java_proto", - deps = [ - "@com_google_googleapis//google/logging/v2:logging_proto", - ], -) - java_proto_library( name = "pubsub_java_proto", deps = [ @@ -52,9 +45,6 @@ java_proto_library( test_class = "com.google.api.generator.gapic.composer.{0}".format(test_name), deps = [ ":common_resources_java_proto", - ":logging_java_proto", - ":pubsub_java_proto", - "//:rpc_java_proto", "//:service_config_java_proto", "//src/main/java/com/google/api/generator/engine/ast", "//src/main/java/com/google/api/generator/engine/writer", @@ -63,6 +53,9 @@ java_proto_library( "//src/main/java/com/google/api/generator/gapic/protoparser", "//src/test/java/com/google/api/generator/gapic/testdata:showcase_java_proto", "@com_google_api_gax_java//jar", + "@com_google_googleapis//google/logging/v2:logging_java_proto", + "@com_google_googleapis//google/pubsub/v1:pubsub_java_proto", + "@com_google_googleapis//google/rpc:rpc_java_proto", "@com_google_protobuf//:protobuf_java", "@com_google_truth_truth//jar", "@junit_junit//jar", diff --git a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/ServiceClientClassComposerTest.java index c5df016a51..8fbe2d911e 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/ServiceClientClassComposerTest.java @@ -90,20 +90,37 @@ public void generateServiceClasses() { + " private final EchoStub stub;\n" + " private final OperationsClient operationsClient;\n" + "\n" + + " /** Constructs an instance of EchoClient with default settings. */\n" + " public static final EchoClient create() throws IOException {\n" + " return create(EchoSettings.newBuilder().build());\n" + " }\n" + "\n" + + " /**\n" + + " * Constructs an instance of EchoClient, using the given settings. The channels are" + + " created based\n" + + " * on the settings passed in, or defaults for any settings that are not set.\n" + + " */\n" + " public static final EchoClient create(EchoSettings settings) throws IOException {\n" + " return new EchoClient(settings);\n" + " }\n" + "\n" + + " /**\n" + + " * Constructs an instance of EchoClient, using the given stub for making calls." + + " This is for\n" + + " * advanced usage - prefer using create(EchoSettings).\n" + + " */\n" + " @BetaApi(\"A restructuring of stub classes is planned, so this may break in the" + " future\")\n" + " public static final EchoClient create(EchoStub stub) {\n" + " return new EchoClient(stub);\n" + " }\n" + "\n" + + " /**\n" + + " * Constructs an instance of EchoClient, using the given settings. This is" + + " protected so that it is\n" + + " * easy to make a subclass, but otherwise, the static factory methods should be" + + " preferred.\n" + + " */\n" + " protected EchoClient(EchoSettings settings) throws IOException {\n" + " this.settings = settings;\n" + " this.stub = ((EchoStubSettings) settings.getStubSettings()).createStub();\n" @@ -128,6 +145,11 @@ public void generateServiceClasses() { + " return stub;\n" + " }\n" + "\n" + + " /**\n" + + " * Returns the OperationsClient that can be used to query the status of a" + + " long-running operation\n" + + " * returned by another API method call.\n" + + " */\n" + " public final OperationsClient getOperationsClient() {\n" + " return operationsClient;\n" + " }\n" diff --git a/src/test/java/com/google/api/generator/gapic/model/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/model/BUILD.bazel index 637631b3f0..705c6b9cc7 100644 --- a/src/test/java/com/google/api/generator/gapic/model/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/model/BUILD.bazel @@ -18,12 +18,12 @@ filegroup( ], test_class = "com.google.api.generator.gapic.model.{0}".format(test_name), deps = [ - "//:rpc_java_proto", "//:service_config_java_proto", "//src/main/java/com/google/api/generator:autovalue", "//src/main/java/com/google/api/generator/gapic/model", "//src/main/java/com/google/api/generator/gapic/protoparser", "//src/test/java/com/google/api/generator/gapic/testdata:showcase_java_proto", + "@com_google_googleapis//google/rpc:rpc_java_proto", "@com_google_protobuf//:protobuf_java", "@com_google_protobuf//:protobuf_java_util", "@com_google_truth_truth//jar", diff --git a/src/test/java/com/google/api/generator/gapic/protoparser/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/protoparser/BUILD.bazel index 30dbd181fe..d8bacd3937 100644 --- a/src/test/java/com/google/api/generator/gapic/protoparser/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/protoparser/BUILD.bazel @@ -24,7 +24,6 @@ filegroup( ], test_class = "com.google.api.generator.gapic.protoparser.{0}".format(test_name), deps = [ - "//:rpc_java_proto", "//:service_config_java_proto", "//src/main/java/com/google/api/generator:autovalue", "//src/main/java/com/google/api/generator/engine/ast", @@ -34,6 +33,7 @@ filegroup( "//src/main/java/com/google/api/generator/gapic/utils", "//src/test/java/com/google/api/generator/gapic/testdata:showcase_java_proto", "//src/test/java/com/google/api/generator/gapic/testdata:testgapic_java_proto", + "@com_google_googleapis//google/rpc:rpc_java_proto", "@com_google_protobuf//:protobuf_java", "@com_google_protobuf//:protobuf_java_util", "@com_google_truth_truth//jar", diff --git a/src/test/java/com/google/api/generator/gapic/protoparser/PluginArgumentParserTest.java b/src/test/java/com/google/api/generator/gapic/protoparser/PluginArgumentParserTest.java index c17c3c101d..e8bbd21de9 100644 --- a/src/test/java/com/google/api/generator/gapic/protoparser/PluginArgumentParserTest.java +++ b/src/test/java/com/google/api/generator/gapic/protoparser/PluginArgumentParserTest.java @@ -21,10 +21,28 @@ import org.junit.Test; public class PluginArgumentParserTest { + @Test public void parseJsonPath_onlyOnePresent() { String jsonPath = "/tmp/grpc_service_config.json"; - assertEquals(jsonPath, PluginArgumentParser.parseJsonConfigPath(jsonPath).get()); + assertEquals( + jsonPath, + PluginArgumentParser.parseJsonConfigPath(createGrpcServiceConfig(jsonPath)).get()); + } + + @Test + public void parseJsonPath_returnsFirstOneFound() { + String jsonPathOne = "/tmp/foobar_grpc_service_config.json"; + String jsonPathTwo = "/tmp/some_other_grpc_service_config.json"; + assertEquals( + jsonPathOne, + PluginArgumentParser.parseJsonConfigPath( + String.join( + ",", + Arrays.asList( + createGrpcServiceConfig(jsonPathOne), + createGrpcServiceConfig(jsonPathTwo)))) + .get()); } @Test @@ -35,11 +53,11 @@ public void parseJsonPath_similarFileAppearsFirst() { String.join( ",", Arrays.asList( - gapicPath, - "/tmp/something.json", - "/tmp/some_grpc_service_configjson", - jsonPath, - gapicPath)); + createGapicConfig(gapicPath), + createGrpcServiceConfig("/tmp/something.json"), + createGrpcServiceConfig("/tmp/some_grpc_service_configjson"), + createGrpcServiceConfig(jsonPath), + createGapicConfig(gapicPath))); assertEquals(jsonPath, PluginArgumentParser.parseJsonConfigPath(rawArgument).get()); } @@ -51,11 +69,11 @@ public void parseJsonPath_argumentHasSpaces() { String.join( " , ", Arrays.asList( - gapicPath, - "/tmp/something.json", - "/tmp/some_grpc_service_configjson", - jsonPath, - gapicPath)); + createGapicConfig(gapicPath), + createGrpcServiceConfig("/tmp/something.json"), + createGrpcServiceConfig("/tmp/some_grpc_service_configjson"), + createGrpcServiceConfig(jsonPath), + createGapicConfig(gapicPath))); assertEquals(jsonPath, PluginArgumentParser.parseJsonConfigPath(rawArgument).get()); } @@ -63,7 +81,8 @@ public void parseJsonPath_argumentHasSpaces() { public void parseJsonPath_restAreEmpty() { String jsonPath = "/tmp/foobar_grpc_service_config.json"; String gapicPath = ""; - String rawArgument = String.join(",", Arrays.asList(gapicPath, jsonPath, gapicPath)); + String rawArgument = + String.join(",", Arrays.asList(gapicPath, createGrpcServiceConfig(jsonPath), gapicPath)); assertEquals(jsonPath, PluginArgumentParser.parseJsonConfigPath(rawArgument).get()); } @@ -77,7 +96,23 @@ public void parseJsonPath_noneFound() { @Test public void parseGapicYamlPath_onlyOnePresent() { String gapicPath = "/tmp/something_gapic.yaml"; - assertEquals(gapicPath, PluginArgumentParser.parseGapicYamlConfigPath(gapicPath).get()); + assertEquals( + gapicPath, + PluginArgumentParser.parseGapicYamlConfigPath(createGapicConfig(gapicPath)).get()); + } + + @Test + public void parseGapicYamlPath_returnsFirstOneFound() { + String gapicPathOne = "/tmp/something_gapic.yaml"; + String gapicPathTwo = "/tmp/other_gapic.yaml"; + assertEquals( + gapicPathOne, + PluginArgumentParser.parseGapicYamlConfigPath( + String.join( + ",", + Arrays.asList( + createGapicConfig(gapicPathOne), createGapicConfig(gapicPathTwo)))) + .get()); } @Test @@ -86,7 +121,12 @@ public void parseGapicYamlPath_similarFileAppearsFirst() { String gapicPath = "/tmp/something_gapic.yaml"; String rawArgument = String.join( - ",", Arrays.asList(jsonPath, "/tmp/something.yaml", "/tmp/some_gapicyaml", gapicPath)); + ",", + Arrays.asList( + createGrpcServiceConfig(jsonPath), + createGapicConfig("/tmp/something.yaml"), + createGapicConfig("/tmp/some_gapicyaml"), + createGapicConfig(gapicPath))); assertEquals(gapicPath, PluginArgumentParser.parseGapicYamlConfigPath(rawArgument).get()); } @@ -94,7 +134,8 @@ public void parseGapicYamlPath_similarFileAppearsFirst() { public void parseGapicYamlPath_restAreEmpty() { String jsonPath = ""; String gapicPath = "/tmp/something_gapic.yaml"; - String rawArgument = String.join(",", Arrays.asList(jsonPath, gapicPath, jsonPath)); + String rawArgument = + String.join(",", Arrays.asList(jsonPath, createGapicConfig(gapicPath), jsonPath)); assertEquals(gapicPath, PluginArgumentParser.parseGapicYamlConfigPath(rawArgument).get()); } @@ -102,7 +143,16 @@ public void parseGapicYamlPath_restAreEmpty() { public void parseGapicYamlPath_noneFound() { String jsonPath = "/tmp/foo_grpc_service_config.json"; String gapicPath = ""; - String rawArgument = String.join(",", Arrays.asList(jsonPath, gapicPath)); + String rawArgument = + String.join(",", Arrays.asList(createGrpcServiceConfig(jsonPath), gapicPath)); assertFalse(PluginArgumentParser.parseGapicYamlConfigPath(rawArgument).isPresent()); } + + private static String createGrpcServiceConfig(String path) { + return String.format("%s=%s", PluginArgumentParser.KEY_GRPC_SERVICE_CONFIG, path); + } + + private static String createGapicConfig(String path) { + return String.format("%s=%s", PluginArgumentParser.KEY_GAPIC_CONFIG, path); + } }