Repository: go-kratos/kratos
Pull request #2101 (2022-06-14 06:46:22)

fix:fix proto add underscore problem
<!--
🎉 Thanks for sending a pull request to Kratos! Here are some tips for you:

1. If this is your first time contributing to Kratos, please read our contribution guide: https://go-kratos.dev/en/docs/community/contribution/
2. Ensure you have added or ran the appropriate tests and lint for your PR, please use `make lint` and `make test` before filing your PR, use `make clean` to tidy your go mod.
3. If the PR is unfinished, you may need to mark it as a WIP(Work In Progress) PR or draft PR
4. Please use a semantic commits format title, such as `<type>[optional scope]: <description>`, see: https://go-kratos.dev/docs/community/contribution#type
5. at the same time, please note that similar work should be submitted in one PR as far as possible to reduce the workload of reviewers. Do not split a work into multiple PR unless it should.
-->

<!--
🎉 感谢您向 Kratos 发送 PR 请求！以下是一些提示：
如果这是你第一次为 Kratos 贡献，请阅读我们的贡献指南：https://go-kratos.dev/en/docs/community/contribution/
2、确保您已经为您的 PR 添加或运行了适当的测试和lint，请在提交PR之前使用“make lint”和“make test”，使用“make clean”整理您的 go.mod。
3、如果请购单未完成，您可能需要将其标记为 WIP（在制品）PR 或 draft PR
4、请使用语义提交格式标题，如“<类型>[可选范围]：<说明>`，请参阅：https://go-kratos.dev/docs/community/contribution#type
5. 同时请注意，同类的工作请尽量在一个PR中提交，以减轻 review 者的工作负担，不要把一项工作拆分成很多个PR，除非它应该这样做。
-->

<!--
-->

#### Description (what this PR does / why we need it):
<!--
* The description should include the motivation for this PR or contrast this with previous behavior
-->


#### Which issue(s) this PR fixes (resolves / be part of):
<!--
* Automatically closes linked issue when PR is merged.
* If your PR is not fully resolved the issue, please use `part of #<issue number>` instead.

Usage: `fixes/resolves #<issue number>`, or `fixes/resolves (paste link of issue)`.
-->


#### Other special notes for the reviewers:
<!--
* Somethings that need extra attention for the reviewers
* Some additional notes, TODO list, etc.
-->


fix: #2089 

`kratos proto add hello/hello_world.proto`

```protobuf
syntax = "proto3";

package hello;

option go_package = "/hello;hello";
option java_multiple_files = true;
option java_package = "hello";

service HelloWorld {
	rpc CreateHelloWorld (CreateHelloWorldRequest) returns (CreateHelloWorldReply);
	rpc UpdateHelloWorld (UpdateHelloWorldRequest) returns (UpdateHelloWorldReply);
	rpc DeleteHelloWorld (DeleteHelloWorldRequest) returns (DeleteHelloWorldReply);
	rpc GetHelloWorld (GetHelloWorldRequest) returns (GetHelloWorldReply);
	rpc ListHelloWorld (ListHelloWorldRequest) returns (ListHelloWorldReply);
}

message CreateHelloWorldRequest {}
message CreateHelloWorldReply {}

message UpdateHelloWorldRequest {}
message UpdateHelloWorldReply {}

message DeleteHelloWorldRequest {}
message DeleteHelloWorldReply {}

message GetHelloWorldRequest {}
message GetHelloWorldReply {}

message ListHelloWorldRequest {}
message ListHelloWorldReply {}
```




codecov-commenter: # [Codecov](https://codecov.io/gh/go-kratos/kratos/pull/2101?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) Report
> Merging [#2101](https://codecov.io/gh/go-kratos/kratos/pull/2101?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) (543ed94) into [main](https://codecov.io/gh/go-kratos/kratos/commit/123fc1e6c81a92d0cb9512904382b4e2c3993653?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) (123fc1e) will **decrease** coverage by `0.05%`.
> The diff coverage is `n/a`.

```diff
@@            Coverage Diff             @@
##             main    #2101      +/-   ##
==========================================
- Coverage   79.09%   79.03%   -0.06%     
==========================================
  Files          84       84              
  Lines        3683     3683              
==========================================
- Hits         2913     2911       -2     
- Misses        559      561       +2     
  Partials      211      211              
```


| [Impacted Files](https://codecov.io/gh/go-kratos/kratos/pull/2101?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) | Coverage Δ | |
|---|---|---|
| [internal/context/context.go](https://codecov.io/gh/go-kratos/kratos/pull/2101/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos#diff-aW50ZXJuYWwvY29udGV4dC9jb250ZXh0Lmdv) | `97.01% <0.00%> (-2.99%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/go-kratos/kratos/pull/2101?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/go-kratos/kratos/pull/2101?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos). Last update [123fc1e...543ed94](https://codecov.io/gh/go-kratos/kratos/pull/2101?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos).


Patch:
diff --git a/cmd/kratos/internal/proto/add/add.go b/cmd/kratos/internal/proto/add/add.go
index 5173e6d1..626b5db2 100644
--- a/cmd/kratos/internal/proto/add/add.go
+++ b/cmd/kratos/internal/proto/add/add.go
@@ -7,6 +7,8 @@ import (
 
 	"github.com/spf13/cobra"
 	"golang.org/x/mod/modfile"
+	"golang.org/x/text/cases"
+	"golang.org/x/text/language"
 )
 
 // CmdAdd represents the add command.
@@ -63,7 +65,11 @@ func javaPackage(name string) string {
 }
 
 func serviceName(name string) string {
-	return export(strings.Split(name, ".")[0])
+	return toUpperCamelCase(strings.Split(name, ".")[0])
 }
 
-func export(s string) string { return strings.ToUpper(s[:1]) + s[1:] }
+func toUpperCamelCase(s string) string {
+	s = strings.ReplaceAll(s, "_", " ")
+	s = cases.Title(language.Und, cases.NoLower).String(s)
+	return strings.ReplaceAll(s, " ", "")
+}
diff --git a/cmd/kratos/internal/proto/server/server.go b/cmd/kratos/internal/proto/server/server.go
index 0ac7355f..dcc19790 100644
--- a/cmd/kratos/internal/proto/server/server.go
+++ b/cmd/kratos/internal/proto/server/server.go
@@ -7,15 +7,10 @@ import (
 	"path"
 	"strings"
 
-	"golang.org/x/text/cases"
-	"golang.org/x/text/language"
-
 	"github.com/emicklei/proto"
 	"github.com/spf13/cobra"
 )
 
-var caser = cases.Title(language.English)
-
 // CmdServer the service command.
 var CmdServer = &cobra.Command{
 	Use:   "server",
@@ -67,7 +62,7 @@ func run(cmd *cobra.Command, args []string) {
 					continue
 				}
 				cs.Methods = append(cs.Methods, &Method{
-					Service: s.Name, Name: caser.String(r.Name), Request: r.RequestType,
+					Service: s.Name, Name: ucFirst(r.Name), Request: r.RequestType,
 					Reply: r.ReturnsType, Type: getMethodType(r.StreamsRequest, r.StreamsReturns),
 				})
 			}
@@ -107,3 +102,11 @@ func getMethodType(streamsRequest, streamsReturns bool) MethodType {
 	}
 	return unaryType
 }
+
+func ucFirst(str string) string {
+	if str == "" {
+		return ""
+	}
+
+	return strings.ToUpper(str[:1]) + str[1:]
+}


Test patch:
diff --git a/cmd/kratos/internal/proto/add/add_test.go b/cmd/kratos/internal/proto/add/add_test.go
new file mode 100644
index 00000000..eda6b414
--- /dev/null
+++ b/cmd/kratos/internal/proto/add/add_test.go
@@ -0,0 +1,38 @@
+package add
+
+import "testing"
+
+func TestUnderscoreToUpperCamelCase(t *testing.T) {
+	tests := []struct {
+		name string
+		want string
+	}{
+		{
+			name: "hello_world",
+			want: "HelloWorld",
+		},
+		{
+			name: "v2_kratos_dev",
+			want: "V2KratosDev",
+		},
+		{
+			name: "www_Google_com",
+			want: "WwwGoogleCom",
+		},
+		{
+			name: "wwwBaidu_com",
+			want: "WwwBaiduCom",
+		},
+		{
+			name: "HelloWorld",
+			want: "HelloWorld",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := toUpperCamelCase(tt.name); got != tt.want {
+				t.Errorf("toUpperCamelCase() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/cmd/kratos/internal/proto/server/server_test.go b/cmd/kratos/internal/proto/server/server_test.go
new file mode 100644
index 00000000..a2cbeee6
--- /dev/null
+++ b/cmd/kratos/internal/proto/server/server_test.go
@@ -0,0 +1,52 @@
+package server
+
+import "testing"
+
+func Test_ucFirst(t *testing.T) {
+	type args struct {
+		str string
+	}
+	tests := []struct {
+		name string
+		args args
+		want string
+	}{
+		{
+			name: "ucFirst on lowercase words",
+			args: args{str: "helloworld"},
+			want: "Helloworld",
+		},
+		{
+			name: "ucFirst on uppercase words",
+			args: args{str: "HELLOWORLD"},
+			want: "HELLOWORLD",
+		},
+		{
+			name: "ucFirst on lowercase words with spaces",
+			args: args{str: "hello world"},
+			want: "Hello world",
+		},
+		{
+			name: "ucFirst on uppercase words with spaces",
+			args: args{str: "HELLO WORLD"},
+			want: "HELLO WORLD",
+		},
+		{
+			name: "ucFirst on Lower Camel Case words",
+			args: args{str: "helloWorld"},
+			want: "HelloWorld",
+		},
+		{
+			name: "ucFirst on Upper Camel Case words",
+			args: args{str: "HelloWorld"},
+			want: "HelloWorld",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := ucFirst(tt.args.str); got != tt.want {
+				t.Errorf("ucFirst() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}