diff options
Diffstat (limited to 'chromeos-dbus-bindings')
-rw-r--r-- | chromeos-dbus-bindings/adaptor_generator.cc | 55 | ||||
-rw-r--r-- | chromeos-dbus-bindings/adaptor_generator.h | 3 | ||||
-rw-r--r-- | chromeos-dbus-bindings/chromeos-dbus-bindings.gyp | 2 | ||||
-rw-r--r-- | chromeos-dbus-bindings/header_generator.cc | 32 | ||||
-rw-r--r-- | chromeos-dbus-bindings/header_generator.h | 13 | ||||
-rw-r--r-- | chromeos-dbus-bindings/method_name_generator.cc | 7 | ||||
-rw-r--r-- | chromeos-dbus-bindings/name_parser.cc | 95 | ||||
-rw-r--r-- | chromeos-dbus-bindings/name_parser.h | 63 | ||||
-rw-r--r-- | chromeos-dbus-bindings/name_parser_unittest.cc | 113 | ||||
-rw-r--r-- | chromeos-dbus-bindings/proxy_generator.cc | 29 |
10 files changed, 308 insertions, 104 deletions
diff --git a/chromeos-dbus-bindings/adaptor_generator.cc b/chromeos-dbus-bindings/adaptor_generator.cc index 8576907..deb26b1 100644 --- a/chromeos-dbus-bindings/adaptor_generator.cc +++ b/chromeos-dbus-bindings/adaptor_generator.cc @@ -14,6 +14,7 @@ #include "chromeos-dbus-bindings/dbus_signature.h" #include "chromeos-dbus-bindings/indented_text.h" #include "chromeos-dbus-bindings/interface.h" +#include "chromeos-dbus-bindings/name_parser.h" using base::StringPrintf; using std::string; @@ -59,17 +60,13 @@ bool AdaptorGenerator::GenerateAdaptors( void AdaptorGenerator::GenerateInterfaceAdaptor( const Interface& interface, IndentedText *text) { - vector<string> namespaces; - string itf_name; - CHECK(GetNamespacesAndClassName(interface.name, &namespaces, &itf_name)); - string class_name = itf_name + "Adaptor"; - string full_itf_name = GetFullClassName(namespaces, itf_name); - itf_name += "Interface"; + NameParser parser{interface.name}; + string itf_name = parser.MakeInterfaceName(false); + string class_name = parser.MakeAdaptorName(false); + string full_itf_name = parser.MakeFullCppName(); text->AddBlankLine(); - for (const auto& ns : namespaces) { - text->AddLine(StringPrintf("namespace %s {", ns.c_str())); - } + parser.AddOpenNamespaces(text, false); text->AddBlankLine(); text->AddLine(StringPrintf("// Interface definition for %s.", @@ -121,9 +118,7 @@ void AdaptorGenerator::GenerateInterfaceAdaptor( text->AddLine("};"); text->AddBlankLine(); - for (auto it = namespaces.rbegin(); it != namespaces.rend(); ++it) { - text->AddLine(StringPrintf("} // namespace %s", it->c_str())); - } + parser.AddCloseNamespaces(text, false); } // static @@ -200,7 +195,7 @@ void AdaptorGenerator::RegisterInterface(const string& itf_name, if (!interface.properties.empty()) text->AddBlankLine(); for (const auto& property : interface.properties) { - string variable_name = GetPropertyVariableName(property.name); + string variable_name = NameParser{property.name}.MakeVariableName(); text->AddLine(StringPrintf("itf->AddProperty(\"%s\", &%s_);", property.name.c_str(), variable_name.c_str())); } @@ -264,9 +259,7 @@ void AdaptorGenerator::AddInterfaceMethods(const Interface& interface, for (const auto& argument : input_arguments_copy) { string param_type; CHECK(signature.Parse(argument.type, ¶m_type)); - if (!IsIntegralType(param_type)) { - param_type = StringPrintf("const %s&", param_type.c_str()); - } + MakeConstReferenceIfNeeded(¶m_type); string param_name = GetArgName("in", argument.name, ++index); method_params.push_back(param_type + ' ' + param_name); } @@ -314,9 +307,7 @@ void AdaptorGenerator::AddSendSignalMethods( for (const auto& argument : signal.arguments) { string param_type; CHECK(signature.Parse(argument.type, ¶m_type)); - if (!IsIntegralType(param_type)) { - param_type = StringPrintf("const %s&", param_type.c_str()); - } + MakeConstReferenceIfNeeded(¶m_type); string param_name = GetArgName("in", argument.name, ++index); param_names.push_back(param_name); method_params.push_back(param_type + ' ' + param_name); @@ -395,7 +386,7 @@ void AdaptorGenerator::AddPropertyMethodImplementation( block.AddBlankLine(); string type; CHECK(signature.Parse(property.type, &type)); - string variable_name = GetPropertyVariableName(property.name); + string variable_name = NameParser{property.name}.MakeVariableName(); // Getter method. block.AddComments(property.doc_string); @@ -410,8 +401,7 @@ void AdaptorGenerator::AddPropertyMethodImplementation( block.AddLine("}"); // Setter method. - if (!IsIntegralType(type)) - type = StringPrintf("const %s&", type.c_str()); + MakeConstReferenceIfNeeded(&type); block.AddLine(StringPrintf("void Set%s(%s %s) {", property.name.c_str(), type.c_str(), @@ -435,7 +425,7 @@ void AdaptorGenerator::AddPropertyDataMembers(const Interface& interface, for (const auto& property : interface.properties) { string type; CHECK(signature.Parse(property.type, &type)); - string variable_name = GetPropertyVariableName(property.name); + string variable_name = NameParser{property.name}.MakeVariableName(); block.AddLine( StringPrintf("chromeos::dbus_utils::ExportedProperty<%s> %s_;", @@ -447,23 +437,4 @@ void AdaptorGenerator::AddPropertyDataMembers(const Interface& interface, text->AddBlock(block); } -// static -string AdaptorGenerator::GetPropertyVariableName(const string& property_name) { - // Convert CamelCase property name to google_style variable name. - string result; - for (size_t i = 0; i < property_name.length(); i++) { - char c = property_name[i]; - if (c < 'A' || c > 'Z') { - result += c; - continue; - } - - if (i != 0) { - result += '_'; - } - result += base::ToLowerASCII(c); - } - return result; -} - } // namespace chromeos_dbus_bindings diff --git a/chromeos-dbus-bindings/adaptor_generator.h b/chromeos-dbus-bindings/adaptor_generator.h index 87e1b26..57e2bf5 100644 --- a/chromeos-dbus-bindings/adaptor_generator.h +++ b/chromeos-dbus-bindings/adaptor_generator.h @@ -71,9 +71,6 @@ class AdaptorGenerator : public HeaderGenerator { static void AddPropertyDataMembers(const Interface& interface, IndentedText *text); - // Return a variable name based on the given property name. - static std::string GetPropertyVariableName(const std::string& property_name); - DISALLOW_COPY_AND_ASSIGN(AdaptorGenerator); }; diff --git a/chromeos-dbus-bindings/chromeos-dbus-bindings.gyp b/chromeos-dbus-bindings/chromeos-dbus-bindings.gyp index 5b729d4..79468c1 100644 --- a/chromeos-dbus-bindings/chromeos-dbus-bindings.gyp +++ b/chromeos-dbus-bindings/chromeos-dbus-bindings.gyp @@ -29,6 +29,7 @@ 'header_generator.cc', 'indented_text.cc', 'method_name_generator.cc', + 'name_parser.cc', 'proxy_generator.cc', 'xml_interface_parser.cc', ], @@ -79,6 +80,7 @@ 'dbus_signature_unittest.cc', 'indented_text_unittest.cc', 'method_name_generator_unittest.cc', + 'name_parser_unittest.cc', 'proxy_generator_unittest.cc', 'xml_interface_parser_unittest.cc', ], diff --git a/chromeos-dbus-bindings/header_generator.cc b/chromeos-dbus-bindings/header_generator.cc index 41d7e1b..d08131d 100644 --- a/chromeos-dbus-bindings/header_generator.cc +++ b/chromeos-dbus-bindings/header_generator.cc @@ -8,7 +8,6 @@ #include <base/file_util.h> #include <base/files/file_path.h> -#include <base/strings/string_split.h> #include <base/strings/string_util.h> #include <base/strings/stringprintf.h> #include <chromeos/strings/string_utils.h> @@ -36,34 +35,15 @@ string HeaderGenerator::GenerateHeaderGuard( } // static -bool HeaderGenerator::GetNamespacesAndClassName( - const string& interface_name, - vector<string>* namespaces, - string* class_name) { - vector<string> split_namespaces; - base::SplitString(interface_name, '.', &split_namespaces); - if (split_namespaces.size() < 2) { - LOG(ERROR) << "Interface name must have both a domain and object part " - << "separated by '.'. Got " << interface_name << " instead."; - return false; - } - *class_name = split_namespaces.back(); - split_namespaces.pop_back(); - namespaces->swap(split_namespaces); - return true; -} - -std::string HeaderGenerator::GetFullClassName( - const std::vector<std::string>& namespaces, - const std::string& class_name) { - std::vector<std::string> parts = namespaces; - parts.push_back(class_name); - return chromeos::string_utils::Join("::", parts); +bool HeaderGenerator::IsIntegralType(const string& type) { + return type.find("::") == std::string::npos; } // static -bool HeaderGenerator::IsIntegralType(const string& type) { - return type.find("::") == std::string::npos; +void HeaderGenerator::MakeConstReferenceIfNeeded(std::string* type) { + if (!IsIntegralType(*type)) { + *type = base::StringPrintf("const %s&", type->c_str()); + } } // static diff --git a/chromeos-dbus-bindings/header_generator.h b/chromeos-dbus-bindings/header_generator.h index 938e93b..55b1265 100644 --- a/chromeos-dbus-bindings/header_generator.h +++ b/chromeos-dbus-bindings/header_generator.h @@ -30,19 +30,12 @@ class HeaderGenerator { // Create a unique header guard string to protect multiple includes of header. static std::string GenerateHeaderGuard(const base::FilePath& output_file); - // Returns a vector of nesting namespaces. - static bool GetNamespacesAndClassName(const std::string& interface_name, - std::vector<std::string>* namespaces, - std::string* class_name); - - // Returns a fully-qualified class name like "ns1::ns2::class_name". - static std::string GetFullClassName( - const std::vector<std::string>& namespaces, - const std::string& class_name); - // Used to decide whether the argument should be a const reference. static bool IsIntegralType(const std::string& type); + // If |type| is a non-integral type, converts it into a const reference. + static void MakeConstReferenceIfNeeded(std::string* type); + // Writes indented text to a file. static bool WriteTextToFile(const base::FilePath& output_file, const IndentedText& text); diff --git a/chromeos-dbus-bindings/method_name_generator.cc b/chromeos-dbus-bindings/method_name_generator.cc index d35f058..5332660 100644 --- a/chromeos-dbus-bindings/method_name_generator.cc +++ b/chromeos-dbus-bindings/method_name_generator.cc @@ -9,6 +9,7 @@ #include "chromeos-dbus-bindings/indented_text.h" #include "chromeos-dbus-bindings/interface.h" +#include "chromeos-dbus-bindings/name_parser.h" using std::string; using std::vector; @@ -29,15 +30,15 @@ bool MethodNameGenerator::GenerateMethodNames( IndentedText text; for (const auto& interface : interfaces) { text.AddBlankLine(); - text.AddLine(base::StringPrintf("namespace %s {", interface.name.c_str())); + NameParser parser{interface.name}; + parser.AddOpenNamespaces(&text, true); for (const auto& method : interface.methods) { text.AddLine( base::StringPrintf("const char %s[] = \"%s\";", GenerateMethodNameConstant(method.name).c_str(), method.name.c_str())); } - text.AddLine(base::StringPrintf("} // namespace %s", - interface.name.c_str())); + parser.AddCloseNamespaces(&text, true); } return HeaderGenerator::WriteTextToFile(output_file, text); } diff --git a/chromeos-dbus-bindings/name_parser.cc b/chromeos-dbus-bindings/name_parser.cc new file mode 100644 index 0000000..33584d9 --- /dev/null +++ b/chromeos-dbus-bindings/name_parser.cc @@ -0,0 +1,95 @@ +// Copyright 2014 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos-dbus-bindings/name_parser.h" + +#include <string> + +#include <base/strings/string_util.h> +#include <base/strings/stringprintf.h> +#include <chromeos/strings/string_utils.h> + +#include "chromeos-dbus-bindings/indented_text.h" + +namespace chromeos_dbus_bindings { + +namespace { + +void AddOpenNamespace(IndentedText *text, const std::string& name) { + text->AddLine(base::StringPrintf("namespace %s {", name.c_str())); +} + +void AddCloseNamespace(IndentedText *text, const std::string& name) { + text->AddLine(base::StringPrintf("} // namespace %s", name.c_str())); +} + +} // anonymous namespace + +NameParser::NameParser(const std::string& name) + : namespaces{chromeos::string_utils::Split(name, '.')} { + CHECK(!namespaces.empty()) << "Empty name specified"; + type_name = namespaces.back(); + namespaces.pop_back(); +} + +std::string NameParser::MakeFullyQualified(const std::string& name) const { + std::vector<std::string> parts = namespaces; + parts.push_back(name); + return chromeos::string_utils::Join("::", parts); +} + +std::string NameParser::MakeFullCppName() const { + return MakeFullyQualified(type_name); +} + +std::string NameParser::MakeVariableName() const { + // Convert CamelCase name to google_style variable name. + std::string result; + for (char c : type_name) { + if (isupper(c)) { + if (!result.empty()) + result += '_'; + c = base::ToLowerASCII(c); + } + result.push_back(c); + } + return result; +} + +std::string NameParser::MakeInterfaceName(bool fully_qualified) const { + std::string interface_name = type_name + "Interface"; + return fully_qualified ? MakeFullyQualified(interface_name) : interface_name; +} + +std::string NameParser::MakeProxyName(bool fully_qualified) const { + std::string proxy_name = type_name + "Proxy"; + return fully_qualified ? MakeFullyQualified(proxy_name) : proxy_name; +} + +std::string NameParser::MakeAdaptorName(bool fully_qualified) const { + std::string adaptor_name = type_name + "Adaptor"; + return fully_qualified ? MakeFullyQualified(adaptor_name) : adaptor_name; +} + +void NameParser::AddOpenNamespaces(IndentedText *text, + bool add_main_type) const { + for (const auto& ns : namespaces) { + AddOpenNamespace(text, ns); + } + + if (add_main_type) + AddOpenNamespace(text, type_name); +} + +void NameParser::AddCloseNamespaces(IndentedText *text, + bool add_main_type) const { + if (add_main_type) + AddCloseNamespace(text, type_name); + + for (auto it = namespaces.rbegin(); it != namespaces.rend(); ++it) { + AddCloseNamespace(text, *it); + } +} + +} // namespace chromeos_dbus_bindings diff --git a/chromeos-dbus-bindings/name_parser.h b/chromeos-dbus-bindings/name_parser.h new file mode 100644 index 0000000..0282819 --- /dev/null +++ b/chromeos-dbus-bindings/name_parser.h @@ -0,0 +1,63 @@ +// Copyright 2014 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_DBUS_BINDINGS_NAME_PARSER_H_ +#define CHROMEOS_DBUS_BINDINGS_NAME_PARSER_H_ + +#include <string> +#include <vector> + +#include <base/macros.h> + +namespace chromeos_dbus_bindings { + +struct Interface; +class IndentedText; + +// A helper class that allows to decompose D-Bus name strings such as +// "org.chromium.TestInterface" into components and be able to construct the +// corresponding C++ identifiers, namespaces, variable names, etc. +class NameParser { + public: + explicit NameParser(const std::string& name); + + // Returns fully-qualified C++ type name for the current D-Bus name + // for example "org::chromium::TestInterface". + std::string MakeFullCppName() const; + + // Returns a variable name suitable for object of this type. + // For example "test_interface". + std::string MakeVariableName() const; + + // Returns a name of an interface for the given type, optionally qualifying + // it with the C++ namespaces. + std::string MakeInterfaceName(bool fully_qualified) const; + + // Returns a name of a proxy class for the given type, optionally qualifying + // it with the C++ namespaces. + std::string MakeProxyName(bool fully_qualified) const; + + // Returns a name of an adaptor class for the given type, optionally + // qualifying it with the C++ namespaces. + std::string MakeAdaptorName(bool fully_qualified) const; + + // Adds opening "namespace ... {" statements to |text|. + // If |add_main_type| is true, adds the main type name as a namespace as well. + void AddOpenNamespaces(IndentedText *text, bool add_main_type) const; + + // Adds closing "} // namespace ..." statements to |text|. + // If |add_main_type| is true, adds the main type name as a namespace as well. + void AddCloseNamespaces(IndentedText *text, bool add_main_type) const; + + std::string type_name; // e.g. "TestInterface". + std::vector<std::string> namespaces; // e.g. {"org", "chromium"}. + + private: + // Helper function to prepend the C++ namespaces to the |name|. + std::string MakeFullyQualified(const std::string& name) const; +}; + +} // namespace chromeos_dbus_bindings + +#endif // CHROMEOS_DBUS_BINDINGS_NAME_PARSER_H_ diff --git a/chromeos-dbus-bindings/name_parser_unittest.cc b/chromeos-dbus-bindings/name_parser_unittest.cc new file mode 100644 index 0000000..62de4fe --- /dev/null +++ b/chromeos-dbus-bindings/name_parser_unittest.cc @@ -0,0 +1,113 @@ +// Copyright 2014 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos-dbus-bindings/name_parser.h" + +#include <map> +#include <string> + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include "chromeos-dbus-bindings/indented_text.h" + +namespace chromeos_dbus_bindings { + +TEST(NameParser, Parsing_Empty) { + EXPECT_DEATH(NameParser{""}, "Empty name specified"); +} + +TEST(NameParser, Parsing_NoNamespaces) { + NameParser parser{"foo"}; + EXPECT_EQ("foo", parser.type_name); + EXPECT_TRUE(parser.namespaces.empty()); +} + +TEST(NameParser, Parsing_FullyQualified) { + NameParser parser{"foo.bar.FooBar"}; + EXPECT_EQ("FooBar", parser.type_name); + EXPECT_THAT(parser.namespaces, testing::ElementsAre("foo", "bar")); +} + +TEST(NameParser, MakeFullCppName) { + NameParser parser{"foo.bar.FooBar"}; + EXPECT_EQ("foo::bar::FooBar", parser.MakeFullCppName()); +} + +TEST(NameParser, MakeVariableName) { + NameParser parser{"foo.bar.FooBar"}; + EXPECT_EQ("foo_bar", parser.MakeVariableName()); +} + +TEST(NameParser, MakeVariableName_NoCapitals) { + NameParser parser{"foo"}; + EXPECT_EQ("foo", parser.MakeVariableName()); +} + +TEST(NameParser, MakeVariableName_NoInitialCapital) { + NameParser parser{"fooBarBaz"}; + EXPECT_EQ("foo_bar_baz", parser.MakeVariableName()); +} + +TEST(NameParser, MakeInterfaceName) { + NameParser parser{"foo.bar.FooBar"}; + EXPECT_EQ("FooBarInterface", parser.MakeInterfaceName(false)); + EXPECT_EQ("foo::bar::FooBarInterface", parser.MakeInterfaceName(true)); +} + +TEST(NameParser, MakeProxyName) { + NameParser parser{"foo.bar.FooBar"}; + EXPECT_EQ("FooBarProxy", parser.MakeProxyName(false)); + EXPECT_EQ("foo::bar::FooBarProxy", parser.MakeProxyName(true)); +} + +TEST(NameParser, MakeAdaptorName) { + NameParser parser{"foo.bar.FooBar"}; + EXPECT_EQ("FooBarAdaptor", parser.MakeAdaptorName(false)); + EXPECT_EQ("foo::bar::FooBarAdaptor", parser.MakeAdaptorName(true)); +} + +TEST(NameParser, AddOpenNamespaces) { + std::string expected = + "namespace foo {\n" + "namespace bar {\n"; + NameParser parser{"foo.bar.FooBar"}; + IndentedText text; + parser.AddOpenNamespaces(&text, false); + EXPECT_EQ(expected, text.GetContents()); +} + +TEST(NameParser, AddOpenNamespaces_WithMainType) { + std::string expected = + "namespace foo {\n" + "namespace bar {\n" + "namespace FooBar {\n"; + NameParser parser{"foo.bar.FooBar"}; + IndentedText text; + parser.AddOpenNamespaces(&text, true); + EXPECT_EQ(expected, text.GetContents()); +} + +TEST(NameParser, AddCloseNamespaces) { + std::string expected = + "} // namespace bar\n" + "} // namespace foo\n"; + NameParser parser{"foo.bar.FooBar"}; + IndentedText text; + parser.AddCloseNamespaces(&text, false); + EXPECT_EQ(expected, text.GetContents()); +} + +TEST(NameParser, AddCloseNamespaces_WithMainType) { + std::string expected = + "} // namespace FooBar\n" + "} // namespace bar\n" + "} // namespace foo\n"; + NameParser parser{"foo.bar.FooBar"}; + IndentedText text; + parser.AddCloseNamespaces(&text, true); + EXPECT_EQ(expected, text.GetContents()); +} + +} // namespace chromeos_dbus_bindings diff --git a/chromeos-dbus-bindings/proxy_generator.cc b/chromeos-dbus-bindings/proxy_generator.cc index 01f2a75..1c09f33 100644 --- a/chromeos-dbus-bindings/proxy_generator.cc +++ b/chromeos-dbus-bindings/proxy_generator.cc @@ -12,6 +12,7 @@ #include "chromeos-dbus-bindings/dbus_signature.h" #include "chromeos-dbus-bindings/indented_text.h" +#include "chromeos-dbus-bindings/name_parser.h" using base::StringPrintf; using std::pair; @@ -72,20 +73,14 @@ bool ProxyGenerator::GenerateProxies( void ProxyGenerator::GenerateInterfaceProxy(const ServiceConfig& config, const Interface& interface, IndentedText* text) { - vector<string> namespaces; - string itf_name; - CHECK(GetNamespacesAndClassName(interface.name, - &namespaces, - &itf_name)); - string proxy_name = itf_name + "Proxy"; - - for (const auto& space : namespaces) { - text->AddLine(StringPrintf("namespace %s {", space.c_str())); - } + NameParser parser{interface.name}; + string proxy_name = parser.MakeProxyName(false); + + parser.AddOpenNamespaces(text, false); text->AddBlankLine(); text->AddLine(StringPrintf("// Interface proxy for %s.", - GetFullClassName(namespaces, itf_name).c_str())); + parser.MakeFullCppName().c_str())); text->AddComments(interface.doc_string); text->AddLine(StringPrintf("class %s final {", proxy_name.c_str())); text->AddLineWithOffset("public:", kScopeOffset); @@ -127,9 +122,7 @@ void ProxyGenerator::GenerateInterfaceProxy(const ServiceConfig& config, text->AddBlankLine(); - for (auto it = namespaces.rbegin(); it != namespaces.rend(); ++it) { - text->AddLine(StringPrintf("} // namespace %s", it->c_str())); - } + parser.AddCloseNamespaces(text, false); text->AddBlankLine(); } @@ -294,9 +287,7 @@ void ProxyGenerator::AddSignalReceiver(const Interface& interface, block.AddLine(StringPrintf("%s,", last_argument.c_str())); } CHECK(signature.Parse(argument.type, &last_argument)); - if (!IsIntegralType(last_argument)) { - last_argument = StringPrintf("const %s&", last_argument.c_str()); - } + MakeConstReferenceIfNeeded(&last_argument); if (!argument.name.empty()) { last_argument += ' '; last_argument += argument.name; @@ -326,9 +317,7 @@ void ProxyGenerator::AddMethodProxy(const Interface::Method& method, for (const auto& argument : method.input_arguments) { string argument_type; CHECK(signature.Parse(argument.type, &argument_type)); - if (!IsIntegralType(argument_type)) { - argument_type = StringPrintf("const %s&", argument_type.c_str()); - } + MakeConstReferenceIfNeeded(&argument_type); string argument_name = GetArgName("in", argument.name, ++argument_number); argument_names.push_back(argument_name); block.AddLine(StringPrintf( |