THRIFT-3027 Go compiler does not ensure common initialisms have consistent case
Client: Go
Patch: Magrath <paul@paulmagrath.com>
This closes #394
diff --git a/compiler/cpp/src/generate/t_go_generator.cc b/compiler/cpp/src/generate/t_go_generator.cc
index 74960da..4826114 100644
--- a/compiler/cpp/src/generate/t_go_generator.cc
+++ b/compiler/cpp/src/generate/t_go_generator.cc
@@ -35,6 +35,7 @@
#include <sys/types.h>
#include <sstream>
#include <algorithm>
+#include <clocale>
#include "t_generator.h"
#include "platform.h"
#include "version.h"
@@ -292,6 +293,7 @@
std::string package_name_;
std::string package_dir_;
+ static std::string camelcase(const std::string& value);
static std::string publicize(const std::string& value, bool is_args_or_result = false);
static std::string new_prefix(const std::string& value);
static std::string privatize(const std::string& value);
@@ -406,6 +408,34 @@
throw "INVALID TYPE IN type_to_go_type: " + type->get_name();
}
+// This set is taken from https://github.com/golang/lint/blob/master/lint.go#L692
+const std::set<std::string> commonInitialisms = {"API", "ASCII", "CPU", "CSS",
+"DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "LHS",
+"QPS", "RAM", "RHS", "RPC", "SLA", "SMTP", "SSH", "TCP", "TLS", "TTL", "UDP",
+"UI", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XSRF", "XSS",};
+
+std::string t_go_generator::camelcase(const std::string& value) {
+
+ std::string value2(value);
+ std::setlocale(LC_ALL, "C"); // set locale to classic
+
+ // as long as we are changing things, let's change _ followed by lowercase to capital and fix common initialisms
+ for (std::string::size_type i = 1; i < value2.size() - 1; ++i) {
+ if (value2[i] == '_'){
+ if (islower(value2[i + 1])) {
+ value2.replace(i, 2, 1, toupper(value2[i + 1]));
+ }
+ std::string word = value2.substr(i,value2.find('_', i));
+ std::transform(word.begin(), word.end(), word.begin(), ::toupper);
+ if (commonInitialisms.find(word) != commonInitialisms.end()) {
+ value2.replace(i, word.length(), word);
+ }
+ }
+ }
+
+ return value2;
+}
+
std::string t_go_generator::publicize(const std::string& value, bool is_args_or_result) {
if (value.size() <= 0) {
return value;
@@ -423,12 +453,7 @@
value2[0] = toupper(value2[0]);
}
- // as long as we are changing things, let's change _ followed by lowercase to capital
- for (string::size_type i = 1; i < value2.size() - 1; ++i) {
- if (value2[i] == '_' && islower(value2[i + 1])) {
- value2.replace(i, 2, 1, toupper(value2[i + 1]));
- }
- }
+ value2 = camelcase(value2);
// final length before further checks, the string may become longer
size_t len_before = value2.length();
@@ -477,12 +502,7 @@
value2[0] = tolower(value2[0]);
}
- // as long as we are changing things, let's change _ followed by lowercase to capital
- for (string::size_type i = 1; i < value2.size() - 1; ++i) {
- if (value2[i] == '_' && isalpha(value2[i + 1])) {
- value2.replace(i, 2, 1, toupper(value2[i + 1]));
- }
- }
+ value2 = camelcase(value2);
return value2;
}
diff --git a/lib/go/test/InitialismsTest.thrift b/lib/go/test/InitialismsTest.thrift
new file mode 100644
index 0000000..68b6350
--- /dev/null
+++ b/lib/go/test/InitialismsTest.thrift
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+
+struct InitialismsTest {
+ 1: string user_id,
+ 2: string server_url,
+}
diff --git a/lib/go/test/Makefile.am b/lib/go/test/Makefile.am
index f34b577..ef61249 100644
--- a/lib/go/test/Makefile.am
+++ b/lib/go/test/Makefile.am
@@ -32,7 +32,8 @@
TypedefFieldTest.thrift \
RefAnnotationFieldsTest.thrift \
ErrorTest.thrift \
- NamesTest.thrift
+ NamesTest.thrift \
+ InitialismsTest.thrift
mkdir -p gopath/src
grep -v list.*map.*list.*map $(THRIFTTEST) | grep -v 'set<Insanity>' > ThriftTest.thrift
$(THRIFT) -r IncludesTest.thrift
@@ -46,6 +47,7 @@
$(THRIFT) RefAnnotationFieldsTest.thrift
$(THRIFT) ErrorTest.thrift
$(THRIFT) NamesTest.thrift
+ $(THRIFT) InitialismsTest.thrift
GOPATH=`pwd`/gopath $(GO) get code.google.com/p/gomock/gomock
ln -nfs ../../../thrift gopath/src/thrift
ln -nfs ../../tests gopath/src/tests
@@ -59,7 +61,8 @@
typedeffieldtest \
refannotationfieldstest \
errortest \
- namestest
+ namestest \
+ initialismstest
GOPATH=`pwd`/gopath $(GO) test thrift tests
clean-local:
@@ -81,4 +84,5 @@
ServicesTest.thrift \
TypedefFieldTest.thrift \
ErrorTest.thrift \
- NamesTest.thrift
+ NamesTest.thrift \
+ InitialismsTest.thrift
diff --git a/lib/go/test/tests/initialisms_test.go b/lib/go/test/tests/initialisms_test.go
new file mode 100644
index 0000000..1d13b97
--- /dev/null
+++ b/lib/go/test/tests/initialisms_test.go
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 tests
+
+import (
+ "initialismstest"
+ "reflect"
+ "testing"
+)
+
+func TestThatCommonInitialismsAreFixed(t *testing.T) {
+ s := initialismstest.InitialismsTest{}
+ st := reflect.TypeOf(s)
+ _, ok := st.FieldByName("UserID")
+ if !ok {
+ t.Error("UserID attribute is missing!")
+ }
+ _, ok = st.FieldByName("ServerURL")
+ if !ok {
+ t.Error("ServerURL attribute is missing!")
+ }
+}