llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.24k stars 11.66k forks source link

clang-format indents protobuf incorrectly when an option has a composite value #39707

Open llvmbot opened 5 years ago

llvmbot commented 5 years ago
Bugzilla Link 40360
Version 8.0
OS All
Reporter LLVM Bugzilla Contributor

Extended Description

I'm using clang-format on OS X to format protocol buffer sources.


$ clang-format --version clang-format version 8.0.0 (tags/google/stable/2018-12-18)

I have a few proto source files that get improperly formatted. The indentation is wrong: the formatter un-indents one too many after composite option value ends.

Example protobuf code (test.proto):

syntax = "proto3";

package fullstory.users.v1;

import "google/api/annotations.proto"; import "google/protobuf/empty.proto"; import "protoc-gen-swagger/options/annotations.proto";

option go_package = "users";

service Foo { rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty) { option (google.api.http).get = "/foo/bar"; option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = { summary: "Query for foobar", description: "Query for a bar using a foo"; }; } rpc Baz(google.protobuf.Empty) returns (google.protobuf.Empty) { option (google.api.http).delete = "/foo/baz"; option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = { summary: "Initiates a baz process", description: "Start processing a given baz"; }; } }

The above is actually what I would expect the output of the formatter to be. So if I run it through clang-format, I would expect no change. Instead, the last several lines of the service get incorrectly un-indented.


$ clang-format '-style={BasedOnStyle: google, ColumnLimit: 150, IndentWidth: 4, SpacesBeforeTrailingComments: 1, PenaltyBreakComment: 10}' < test.proto

syntax = "proto3";

package fullstory.users.v1;

import "google/api/annotations.proto"; import "google/protobuf/empty.proto"; import "protoc-gen-swagger/options/annotations.proto";

option go_package = "users";

service Foo { rpc Bar(google.protobuf.Empty) returns(google.protobuf.Empty) { option(google.api.http).get = "/foo/bar"; option(grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = { summary : "Query for foobar", description : "Query for a bar using a foo"; }; } rpc Baz(google.protobuf.Empty) returns(google.protobuf.Empty) { option(google.api.http).delete = "/foo/baz"; option(grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = { summary : "Initiates a baz process", description : "Start processing a given baz"; }; } }

noel-yap commented 2 years ago

Likewise, I'm seeing the following diff from the reformatting:

 option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
-  info: {
-    title: "grpc gateway helloworld sample";
-    version: "1.0.0";
-  };
-};
+  info: { title: "grpc gateway helloworld sample";
+version: "1.0.0";
+}
+;
+}
+;

 service FirstService {
   option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_tag) = {
@@ -23,12 +24,12 @@
   rpc SayHello(SayHelloRequest) returns (SayHelloResponse) {
     option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
       description: "Says Hello";
-    };
-    option (google.api.http) = {
-      post: "/examplegrpc.proto.v1.FirstService.SayHello"
-      body: "*"
-    };
-  }
+  };
+  option (google.api.http) = {
+    post: "/examplegrpc.proto.v1.FirstService.SayHello"
+    body: "*"
+  };
+}
 }