Skip to content

Commit 9a0eab3

Browse files
committed
Fix invalid character handling in proto file names
1 parent bb7274c commit 9a0eab3

File tree

9 files changed

+142
-7
lines changed

9 files changed

+142
-7
lines changed

jprotoc-test/src/test/java/com/salesforce/jprotoc/ProtoGenerationPresenceTest.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ public void nestedGrpc8Exists() {
3737

3838
@Test
3939
public void currentTimeGrpc8Exists() {
40-
assertThat(CurrentTimeGrpc8.class).isNotNull();
40+
assertThat(com.salesforce.invalid.dollar.CurrentTimeGrpc8.class).isNotNull();
41+
assertThat(com.salesforce.invalid.plus.CurrentTimeGrpc8.class).isNotNull();
42+
assertThat(com.salesforce.invalid.dot.CurrentTimeGrpc8.class).isNotNull();
43+
assertThat(com.salesforce.invalid.number.CurrentTimeGrpc8.class).isNotNull();
44+
assertThat(com.salesforce.invalid.dash.CurrentTimeGrpc8.class).isNotNull();
45+
assertThat(com.salesforce.invalid.underscore.CurrentTimeGrpc8.class).isNotNull();
46+
assertThat(com.salesforce.invalid.enye.CurrentTimeGrpc8.class).isNotNull();
4147
}
4248
}

jprotoc-test/src/test/proto/weylandyutani.proto renamed to jprotoc-test/src/test/proto/invalidClassNames/weyland$yutani.proto

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
syntax = "proto3";
22

3+
package com.salesforce.invalid.dollar;
4+
35
import "google/protobuf/empty.proto";
46
import "google/protobuf/timestamp.proto";
57

6-
option java_package = "com.salesforce.jprotoc";
7-
88
// The time - as a service.
99
service CurrentTime {
1010
// Sends the current time
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
syntax = "proto3";
2+
3+
package com.salesforce.invalid.plus;
4+
5+
import "google/protobuf/empty.proto";
6+
import "google/protobuf/timestamp.proto";
7+
8+
// The time - as a service.
9+
service CurrentTime {
10+
// Sends the current time
11+
rpc SayTime (google.protobuf.Empty) returns (TimeResponse) {}
12+
}
13+
14+
// The response message containing the time
15+
message TimeResponse {
16+
google.protobuf.Timestamp time = 1;
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
syntax = "proto3";
2+
3+
package com.salesforce.invalid.dash;
4+
5+
import "google/protobuf/empty.proto";
6+
import "google/protobuf/timestamp.proto";
7+
8+
// The time - as a service.
9+
service CurrentTime {
10+
// Sends the current time
11+
rpc SayTime (google.protobuf.Empty) returns (TimeResponse) {}
12+
}
13+
14+
// The response message containing the time
15+
message TimeResponse {
16+
google.protobuf.Timestamp time = 1;
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
syntax = "proto3";
2+
3+
package com.salesforce.invalid.dot;
4+
5+
import "google/protobuf/empty.proto";
6+
import "google/protobuf/timestamp.proto";
7+
8+
// The time - as a service.
9+
service CurrentTime {
10+
// Sends the current time
11+
rpc SayTime (google.protobuf.Empty) returns (TimeResponse) {}
12+
}
13+
14+
// The response message containing the time
15+
message TimeResponse {
16+
google.protobuf.Timestamp time = 1;
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
syntax = "proto3";
2+
3+
package com.salesforce.invalid.number;
4+
5+
import "google/protobuf/empty.proto";
6+
import "google/protobuf/timestamp.proto";
7+
8+
// The time - as a service.
9+
service CurrentTime {
10+
// Sends the current time
11+
rpc SayTime (google.protobuf.Empty) returns (TimeResponse) {}
12+
}
13+
14+
// The response message containing the time
15+
message TimeResponse {
16+
google.protobuf.Timestamp time = 1;
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
syntax = "proto3";
2+
3+
package com.salesforce.invalid.underscore;
4+
5+
import "google/protobuf/empty.proto";
6+
import "google/protobuf/timestamp.proto";
7+
8+
// The time - as a service.
9+
service CurrentTime {
10+
// Sends the current time
11+
rpc SayTime (google.protobuf.Empty) returns (TimeResponse) {}
12+
}
13+
14+
// The response message containing the time
15+
message TimeResponse {
16+
google.protobuf.Timestamp time = 1;
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
syntax = "proto3";
2+
3+
package com.salesforce.invalid.enye;
4+
5+
import "google/protobuf/empty.proto";
6+
import "google/protobuf/timestamp.proto";
7+
8+
// The time - as a service.
9+
service CurrentTime {
10+
// Sends the current time
11+
rpc SayTime (google.protobuf.Empty) returns (TimeResponse) {}
12+
}
13+
14+
// The response message containing the time
15+
message TimeResponse {
16+
google.protobuf.Timestamp time = 1;
17+
}

jprotoc/src/main/java/com/salesforce/jprotoc/ProtoTypeMap.java

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@
77

88
package com.salesforce.jprotoc;
99

10-
import com.google.common.base.CaseFormat;
11-
import com.google.common.base.Joiner;
12-
import com.google.common.base.Preconditions;
13-
import com.google.common.base.Strings;
10+
import com.google.common.base.*;
1411
import com.google.common.collect.ImmutableMap;
1512
import com.google.protobuf.DescriptorProtos;
1613

@@ -142,7 +139,9 @@ private static String getJavaOuterClassname(
142139
filename = filename.substring(filename.lastIndexOf('/') + 1);
143140
}
144141

142+
filename = makeInvalidCharactersUnderscores(filename);
145143
filename = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, filename);
144+
filename = upcaseAfterNumber(filename);
146145
filename = appendOuterClassSuffix(filename, fileDescriptor);
147146
return filename;
148147
}
@@ -160,4 +159,32 @@ private static String appendOuterClassSuffix(final String enclosingClassName, De
160159
return enclosingClassName;
161160
}
162161
}
162+
163+
/**
164+
* Replace invalid proto identifier characters with an underscore, so they will be dropped and camel cases below.
165+
* https://developers.google.com/protocol-buffers/docs/reference/proto3-spec
166+
*/
167+
private static String makeInvalidCharactersUnderscores(String filename) {
168+
char[] filechars = filename.toCharArray();
169+
for (int i = 0; i < filechars.length; i++) {
170+
char c = filechars[i];
171+
if (!CharMatcher.inRange('0', '9').or(CharMatcher.inRange('A', 'Z')).or(CharMatcher.inRange('a', 'z')).matches(c)) {
172+
filechars[i] = '_';
173+
}
174+
}
175+
return new String(filechars);
176+
}
177+
178+
/**
179+
* Upper case characters after numbers, like {@code Weyland9Yutani}.
180+
*/
181+
private static String upcaseAfterNumber(String filename) {
182+
char[] filechars = filename.toCharArray();
183+
for (int i = 1; i < filechars.length; i++) {
184+
if (CharMatcher.inRange('0', '9').matches(filechars[i - 1])) {
185+
filechars[i] = Character.toUpperCase(filechars[i]);
186+
}
187+
}
188+
return new String(filechars);
189+
}
163190
}

0 commit comments

Comments
 (0)