diff --git a/src/config/config.cc b/src/config/config.cc index 8dc801e5..6fb1dfcc 100644 --- a/src/config/config.cc +++ b/src/config/config.cc @@ -89,7 +89,8 @@ bool diagram::should_include(const std::string &name_) const return false; } -bool diagram::should_include(const model::class_diagram::scope_t scope) const +bool diagram::should_include( + const clanguml::class_diagram::model::scope_t scope) const { for (const auto &s : exclude.scopes) { if (s == scope) @@ -127,13 +128,13 @@ bool class_diagram::has_class(std::string clazz) } namespace YAML { +using clanguml::class_diagram::model::scope_t; using clanguml::config::class_diagram; using clanguml::config::config; using clanguml::config::filter; using clanguml::config::plantuml; using clanguml::config::sequence_diagram; using clanguml::config::source_location; -using clanguml::model::class_diagram::scope_t; template <> struct convert { static bool decode(const Node &node, scope_t &rhs) { diff --git a/src/config/config.h b/src/config/config.h index 6ed9ff3f..13c7c4ac 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -17,7 +17,8 @@ */ #pragma once -#include "uml/class_diagram_model.h" +#include "uml/class_diagram/model/diagram.h" +#include "uml/class_diagram/model/enums.h" #include "util/util.h" #include @@ -55,7 +56,7 @@ struct filter { // E.g.: // - public // - private - std::vector scopes; + std::vector scopes; }; struct diagram { @@ -76,7 +77,7 @@ struct diagram { bool should_include(const std::string &name_) const; - bool should_include(const model::class_diagram::scope_t scope) const; + bool should_include(const class_diagram::model::scope_t scope) const; }; struct source_location { diff --git a/src/cx/type.h b/src/cx/type.h index ae32dabf..2856e47a 100644 --- a/src/cx/type.h +++ b/src/cx/type.h @@ -22,7 +22,6 @@ #include #include "cx/util.h" -#include "uml/class_diagram_model.h" #include "util/util.h" namespace clanguml { diff --git a/src/main.cc b/src/main.cc index f58014e8..114f9045 100644 --- a/src/main.cc +++ b/src/main.cc @@ -22,7 +22,7 @@ #include "cx/compilation_database.h" #include "puml/class_diagram_generator.h" #include "puml/sequence_diagram_generator.h" -#include "uml/class_diagram_model.h" +#include "uml/class_diagram/model/diagram.h" #include "uml/class_diagram_visitor.h" #include "uml/sequence_diagram_visitor.h" #include "util/util.h" diff --git a/src/puml/class_diagram_generator.cc b/src/puml/class_diagram_generator.cc index 9fb29eec..b637edf5 100644 --- a/src/puml/class_diagram_generator.cc +++ b/src/puml/class_diagram_generator.cc @@ -18,6 +18,8 @@ #include "class_diagram_generator.h" +#include "util/error.h" + namespace clanguml::generators::class_diagram { namespace puml { @@ -414,12 +416,12 @@ std::ostream &operator<<(std::ostream &os, const generator &g) } } // namespace puml -clanguml::model::class_diagram::diagram generate( +clanguml::class_diagram::model::diagram generate( cppast::libclang_compilation_database &db, const std::string &name, clanguml::config::class_diagram &diagram) { spdlog::info("Generating diagram {}.puml", name); - clanguml::model::class_diagram::diagram d; + clanguml::class_diagram::model::diagram d; d.set_name(name); // Get all translation units matching the glob from diagram diff --git a/src/puml/class_diagram_generator.h b/src/puml/class_diagram_generator.h index 8ead962c..71645cb7 100644 --- a/src/puml/class_diagram_generator.h +++ b/src/puml/class_diagram_generator.h @@ -19,7 +19,10 @@ #include "config/config.h" #include "cx/compilation_database.h" -#include "uml/class_diagram_model.h" +#include "uml/class_diagram/model/class.h" +#include "uml/class_diagram/model/class_relationship.h" +#include "uml/class_diagram/model/diagram.h" +#include "uml/class_diagram/model/enum.h" #include "uml/class_diagram_visitor.h" #include "util/util.h" @@ -37,12 +40,12 @@ namespace generators { namespace class_diagram { namespace puml { -using diagram_config = clanguml::config::class_diagram::diagram; -using diagram_model = clanguml::model::class_diagram::diagram; -using clanguml::model::class_diagram::class_; -using clanguml::model::class_diagram::enum_; -using clanguml::model::class_diagram::relationship_t; -using clanguml::model::class_diagram::scope_t; +using diagram_config = clanguml::class_diagram::model::diagram; +using diagram_model = clanguml::class_diagram::model::diagram; +using clanguml::class_diagram::model::class_; +using clanguml::class_diagram::model::enum_; +using clanguml::class_diagram::model::relationship_t; +using clanguml::class_diagram::model::scope_t; using namespace clanguml::util; std::string relative_to(std::string n, std::string c); @@ -76,7 +79,7 @@ private: } -clanguml::model::class_diagram::diagram generate( +clanguml::class_diagram::model::diagram generate( cppast::libclang_compilation_database &db, const std::string &name, clanguml::config::class_diagram &diagram); diff --git a/src/uml/class_diagram/model/class.cc b/src/uml/class_diagram/model/class.cc new file mode 100644 index 00000000..a669e077 --- /dev/null +++ b/src/uml/class_diagram/model/class.cc @@ -0,0 +1,143 @@ +/** + * src/uml/class_diagram/model/class.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "class.h" + +#include "util/util.h" + +#include + +namespace clanguml::class_diagram::model { + +class_::class_(const std::vector &using_namespaces) + : element{using_namespaces} +{ +} + +bool class_::is_struct() const { return is_struct_; } + +void class_::is_struct(bool is_struct) { is_struct_ = is_struct; } + +bool class_::is_template() const { return is_template_; } + +void class_::is_template(bool is_template) { is_template_ = is_template; } + +bool class_::is_template_instantiation() const +{ + return is_template_instantiation_; +} + +void class_::is_template_instantiation(bool is_template_instantiation) +{ + is_template_instantiation_ = is_template_instantiation; +} + +void class_::add_member(class_member &&member) +{ + members_.emplace_back(std::move(member)); +} + +void class_::add_method(class_method &&method) +{ + methods_.emplace_back(std::move(method)); +} + +void class_::add_parent(class_parent &&parent) +{ + bases_.emplace_back(std::move(parent)); +} + +void class_::add_template(class_template &&tmplt) +{ + templates_.emplace_back(std::move(tmplt)); +} + +const std::vector &class_::members() const { return members_; } + +const std::vector &class_::methods() const { return methods_; } + +const std::vector &class_::parents() const { return bases_; } + +const std::vector &class_::templates() const +{ + return templates_; +} + +void class_::set_base_template(const std::string &full_name) +{ + base_template_full_name_ = full_name; +} + +std::string class_::base_template() const { return base_template_full_name_; } + +bool operator==(const class_ &l, const class_ &r) +{ + return l.full_name() == r.full_name(); +} + +void class_::add_type_alias(type_alias &&ta) +{ + LOG_DBG("Adding class alias: {} -> {}", ta.alias(), ta.underlying_type()); + type_aliases_[ta.alias()] = std::move(ta); +} + +std::string class_::full_name(bool relative) const +{ + using namespace clanguml::util; + + std::ostringstream ostr; + if (relative) + ostr << ns_relative(using_namespaces(), name()); + else + ostr << name(); + + if (!templates_.empty()) { + std::vector tnames; + std::transform(templates_.cbegin(), templates_.cend(), + std::back_inserter(tnames), [this](const auto &tmplt) { + std::vector res; + + if (!tmplt.type().empty()) + res.push_back( + ns_relative(using_namespaces(), tmplt.type())); + + if (!tmplt.name().empty()) + res.push_back( + ns_relative(using_namespaces(), tmplt.name())); + + if (!tmplt.default_value().empty()) { + res.push_back("="); + res.push_back(tmplt.default_value()); + } + + return fmt::format("{}", fmt::join(res, " ")); + }); + ostr << fmt::format("<{}>", fmt::join(tnames, ",")); + } + + return ostr.str(); +} + +bool class_::is_abstract() const +{ + // TODO check if all base abstract methods are overriden + // with non-abstract methods + return std::any_of(methods_.begin(), methods_.end(), + [](const auto &method) { return method.is_pure_virtual(); }); +} +} diff --git a/src/uml/class_diagram/model/class.h b/src/uml/class_diagram/model/class.h new file mode 100644 index 00000000..87717769 --- /dev/null +++ b/src/uml/class_diagram/model/class.h @@ -0,0 +1,82 @@ +/** + * src/uml/class_diagram/model/class.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include "class_member.h" +#include "class_method.h" +#include "class_parent.h" +#include "class_template.h" +#include "element.h" +#include "enums.h" +#include "stylable_element.h" +#include "type_alias.h" + +#include +#include + +namespace clanguml::class_diagram::model { + +class class_ : public element, public stylable_element { +public: + class_(const std::vector &using_namespaces); + + bool is_struct() const; + void is_struct(bool is_struct); + + bool is_template() const; + void is_template(bool is_template); + + bool is_template_instantiation() const; + void is_template_instantiation(bool is_template_instantiation); + + void add_member(class_member &&member); + void add_method(class_method &&method); + void add_parent(class_parent &&parent); + void add_template(class_template &&tmplt); + + const std::vector &members() const; + const std::vector &methods() const; + const std::vector &parents() const; + const std::vector &templates() const; + + void set_base_template(const std::string &full_name); + std::string base_template() const; + + friend bool operator==(const class_ &l, const class_ &r); + + void add_type_alias(type_alias &&ta); + + std::string full_name(bool relative = true) const override; + + bool is_abstract() const; + +private: + bool is_struct_{false}; + bool is_template_{false}; + bool is_template_instantiation_{false}; + std::vector members_; + std::vector methods_; + std::vector bases_; + std::vector templates_; + std::string base_template_full_name_; + std::map type_aliases_; + + std::string full_name_; +}; + +} diff --git a/src/uml/class_diagram/model/class_element.cc b/src/uml/class_diagram/model/class_element.cc new file mode 100644 index 00000000..4f598f0f --- /dev/null +++ b/src/uml/class_diagram/model/class_element.cc @@ -0,0 +1,37 @@ +/** + * src/uml/class_diagram/model/class_element.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "class_element.h" + +namespace clanguml::class_diagram::model { + +class_element::class_element( + scope_t scope, const std::string &name, const std::string &type) + : scope_{scope} + , name_{name} + , type_{type} +{ +} + +scope_t class_element::scope() const { return scope_; } + +std::string class_element::name() const { return name_; } + +std::string class_element::type() const { return type_; } + +} diff --git a/src/uml/class_diagram/model/class_element.h b/src/uml/class_diagram/model/class_element.h new file mode 100644 index 00000000..8e03e9bf --- /dev/null +++ b/src/uml/class_diagram/model/class_element.h @@ -0,0 +1,42 @@ +/** + * src/uml/class_diagram/model/class_element.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include "decorated_element.h" +#include "enums.h" + +#include + +namespace clanguml::class_diagram::model { + +class class_element : public decorated_element { +public: + class_element( + scope_t scope, const std::string &name, const std::string &type); + + scope_t scope() const; + std::string name() const; + std::string type() const; + +private: + scope_t scope_; + std::string name_; + std::string type_; +}; + +} diff --git a/src/uml/class_diagram/model/class_member.cc b/src/uml/class_diagram/model/class_member.cc new file mode 100644 index 00000000..14a3a19e --- /dev/null +++ b/src/uml/class_diagram/model/class_member.cc @@ -0,0 +1,40 @@ +/** + * src/uml/class_diagram/model/class_member.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "class_member.h" + +namespace clanguml::class_diagram::model { + +class_member::class_member( + scope_t scope, const std::string &name, const std::string &type) + : class_element{scope, name, type} +{ +} + +bool class_member::is_relationship() const { return is_relationship_; } + +void class_member::is_relationship(bool is_relationship) +{ + is_relationship_ = is_relationship; +} + +bool class_member::is_static() const { return is_static_; } + +void class_member::is_static(bool is_static) { is_static_ = is_static; } + +} diff --git a/src/uml/class_diagram/model/class_member.h b/src/uml/class_diagram/model/class_member.h new file mode 100644 index 00000000..98a0033c --- /dev/null +++ b/src/uml/class_diagram/model/class_member.h @@ -0,0 +1,43 @@ +/** + * src/uml/class_diagram/model/class_member.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include "class_element.h" +#include "enums.h" + +#include + +namespace clanguml::class_diagram::model { + +class class_member : public class_element { +public: + class_member( + scope_t scope, const std::string &name, const std::string &type); + + bool is_relationship() const; + void is_relationship(bool is_relationship); + + bool is_static() const; + void is_static(bool is_static); + +private: + bool is_relationship_{false}; + bool is_static_{false}; +}; + +} diff --git a/src/uml/class_diagram/model/class_method.cc b/src/uml/class_diagram/model/class_method.cc new file mode 100644 index 00000000..0351b1aa --- /dev/null +++ b/src/uml/class_diagram/model/class_method.cc @@ -0,0 +1,64 @@ +/** + * src/uml/class_diagram/model/class_method.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "class_method.h" + +namespace clanguml::class_diagram::model { + +class_method::class_method( + scope_t scope, const std::string &name, const std::string &type) + : class_element{scope, name, type} +{ +} + +bool class_method::is_pure_virtual() const { return is_pure_virtual_; } + +void class_method::is_pure_virtual(bool is_pure_virtual) +{ + is_pure_virtual_ = is_pure_virtual; +} + +bool class_method::is_virtual() const { return is_virtual_; } + +void class_method::is_virtual(bool is_virtual) { is_virtual_ = is_virtual; } + +bool class_method::is_const() const { return is_const_; } + +void class_method::is_const(bool is_const) { is_const_ = is_const; } + +bool class_method::is_defaulted() const { return is_defaulted_; } + +void class_method::is_defaulted(bool is_defaulted) +{ + is_defaulted_ = is_defaulted; +} + +bool class_method::is_static() const { return is_static_; } + +void class_method::is_static(bool is_static) { is_static_ = is_static; } + +const std::vector &class_method::parameters() const +{ + return parameters_; +} + +void class_method::add_parameter(method_parameter &¶meter) +{ + parameters_.emplace_back(std::move(parameter)); +} +} diff --git a/src/uml/class_diagram/model/class_method.h b/src/uml/class_diagram/model/class_method.h new file mode 100644 index 00000000..d250a889 --- /dev/null +++ b/src/uml/class_diagram/model/class_method.h @@ -0,0 +1,60 @@ +/** + * src/uml/class_diagram/model/class_method.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include "class_element.h" +#include "enums.h" +#include "method_parameter.h" + +#include +#include + +namespace clanguml::class_diagram::model { + +class class_method : public class_element { +public: + class_method( + scope_t scope, const std::string &name, const std::string &type); + + bool is_pure_virtual() const; + void is_pure_virtual(bool is_pure_virtual); + + bool is_virtual() const; + void is_virtual(bool is_virtual); + + bool is_const() const; + void is_const(bool is_const); + + bool is_defaulted() const; + void is_defaulted(bool is_defaulted); + + bool is_static() const; + void is_static(bool is_static); + + const std::vector ¶meters() const; + void add_parameter(method_parameter &¶meter); + +private: + std::vector parameters_; + bool is_pure_virtual_{false}; + bool is_virtual_{false}; + bool is_const_{false}; + bool is_defaulted_{false}; + bool is_static_{false}; +}; +} diff --git a/src/uml/class_diagram/model/class_parent.cc b/src/uml/class_diagram/model/class_parent.cc new file mode 100644 index 00000000..d5ae2593 --- /dev/null +++ b/src/uml/class_diagram/model/class_parent.cc @@ -0,0 +1,35 @@ +/** + * src/uml/class_diagram/model/class_parent.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "class_parent.h" + +namespace clanguml::class_diagram::model { + +void class_parent::set_name(const std::string &name) { name_ = name; } + +std::string class_parent::name() const { return name_; } + +void class_parent::is_virtual(bool is_virtual) { is_virtual_ = is_virtual; } + +bool class_parent::is_virtual() const { return is_virtual_; } + +void class_parent::set_access(access_t access) { access_ = access; } + +access_t class_parent::access() const { return access_; } + +} diff --git a/src/uml/class_diagram/model/class_parent.h b/src/uml/class_diagram/model/class_parent.h new file mode 100644 index 00000000..82520d12 --- /dev/null +++ b/src/uml/class_diagram/model/class_parent.h @@ -0,0 +1,42 @@ +/** + * src/uml/class_diagram/model/class_parent.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include "enums.h" + +#include + +namespace clanguml::class_diagram::model { + +class class_parent { +public: + void set_name(const std::string &name); + std::string name() const; + + void is_virtual(bool is_virtual); + bool is_virtual() const; + + void set_access(access_t access); + access_t access() const; + +private: + std::string name_; + bool is_virtual_{false}; + access_t access_; +}; +} diff --git a/src/uml/class_diagram/model/class_relationship.cc b/src/uml/class_diagram/model/class_relationship.cc new file mode 100644 index 00000000..dae9c76f --- /dev/null +++ b/src/uml/class_diagram/model/class_relationship.cc @@ -0,0 +1,113 @@ +/** + * src/uml/class_diagram/model/class_relationship.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "class_relationship.h" + +namespace clanguml::class_diagram::model { + +std::string to_string(relationship_t r) +{ + switch (r) { + case relationship_t::kNone: + return "none"; + case relationship_t::kExtension: + return "extension"; + case relationship_t::kComposition: + return "composition"; + case relationship_t::kAggregation: + return "aggregation"; + case relationship_t::kContainment: + return "containment"; + case relationship_t::kOwnership: + return "ownership"; + case relationship_t::kAssociation: + return "association"; + case relationship_t::kInstantiation: + return "instantiation"; + case relationship_t::kFriendship: + return "frendship"; + case relationship_t::kDependency: + return "dependency"; + default: + return "invalid"; + } +} + +class_relationship::class_relationship(relationship_t type, + const std::string &destination, scope_t scope, const std::string &label, + const std::string &multiplicity_source, + const std::string &multiplicity_destination) + : type_{type} + , destination_{destination} + , scope_{scope} + , label_{label} + , multiplicity_source_{multiplicity_source} + , multiplicity_destination_{multiplicity_destination} +{ +} + +void class_relationship::set_type(relationship_t type) noexcept +{ + type_ = type; +} + +relationship_t class_relationship::type() const noexcept { return type_; } + +void class_relationship::set_destination(const std::string &destination) +{ + destination_ = destination; +} + +std::string class_relationship::destination() const { return destination_; } + +void class_relationship::set_multiplicity_source( + const std::string &multiplicity_source) +{ + multiplicity_source_ = multiplicity_source; +} + +std::string class_relationship::multiplicity_source() const +{ + return multiplicity_source_; +} + +void class_relationship::set_multiplicity_destination( + const std::string &multiplicity_destination) +{ + multiplicity_destination_ = multiplicity_destination; +} + +std::string class_relationship::multiplicity_destination() const +{ + return multiplicity_destination_; +} + +void class_relationship::set_label(const std::string &label) { label_ = label; } + +std::string class_relationship::label() const { return label_; } + +void class_relationship::set_scope(scope_t scope) noexcept { scope_ = scope; } + +scope_t class_relationship::scope() const noexcept { return scope_; } + +bool operator==(const class_relationship &l, const class_relationship &r) +{ + return l.type() == r.type() && l.destination() == r.destination() && + l.label() == r.label(); +} +} diff --git a/src/uml/class_diagram/model/class_relationship.h b/src/uml/class_diagram/model/class_relationship.h new file mode 100644 index 00000000..22743d0e --- /dev/null +++ b/src/uml/class_diagram/model/class_relationship.h @@ -0,0 +1,69 @@ +/** + * src/uml/class_diagram/model/class_relationship.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include "decorated_element.h" +#include "enums.h" +#include "stylable_element.h" + +#include + +namespace clanguml::class_diagram::model { + +std::string to_string(relationship_t r); + +class class_relationship : public decorated_element, public stylable_element { +public: + class_relationship(relationship_t type, const std::string &destination, + scope_t scope = scope_t::kNone, const std::string &label = "", + const std::string &multiplicity_source = "", + const std::string &multiplicity_destination = ""); + + virtual ~class_relationship() = default; + + void set_type(relationship_t type) noexcept; + relationship_t type() const noexcept; + + void set_destination(const std::string &destination); + std::string destination() const; + + void set_multiplicity_source(const std::string &multiplicity_source); + std::string multiplicity_source() const; + + void set_multiplicity_destination( + const std::string &multiplicity_destination); + std::string multiplicity_destination() const; + + void set_label(const std::string &label); + std::string label() const; + + void set_scope(scope_t scope) noexcept; + scope_t scope() const noexcept; + + friend bool operator==( + const class_relationship &l, const class_relationship &r); + +private: + relationship_t type_{relationship_t::kAssociation}; + std::string destination_; + std::string multiplicity_source_; + std::string multiplicity_destination_; + std::string label_; + scope_t scope_{scope_t::kNone}; +}; +} diff --git a/src/uml/class_diagram/model/class_template.cc b/src/uml/class_diagram/model/class_template.cc new file mode 100644 index 00000000..00ca0e4d --- /dev/null +++ b/src/uml/class_diagram/model/class_template.cc @@ -0,0 +1,60 @@ +/** + * src/uml/class_diagram/model/class_template.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "class_template.h" + +namespace clanguml::class_diagram::model { + +class_template::class_template(const std::string &type, const std::string &name, + const std::string &default_value, bool is_variadic) + : type_{type} + , name_{name} + , default_value_{default_value} + , is_variadic_{is_variadic} +{ + if (is_variadic) + name_ = name_ + "..."; +} + +void class_template::set_type(const std::string &type) { type_ = type; } + +std::string class_template::type() const { return type_; } + +void class_template::set_name(const std::string &name) { name_ = name; } + +std::string class_template::name() const { return name_; } + +void class_template::set_default_value(const std::string &value) +{ + default_value_ = value; +} + +std::string class_template::default_value() const { return default_value_; } + +void class_template::is_variadic(bool is_variadic) noexcept +{ + is_variadic_ = is_variadic; +} + +bool class_template::is_variadic() const noexcept { return is_variadic_; } + +bool operator==(const class_template &l, const class_template &r) +{ + return (l.name() == r.name()) && (l.type() == r.type()); +} +} diff --git a/src/uml/class_diagram/model/class_template.h b/src/uml/class_diagram/model/class_template.h new file mode 100644 index 00000000..ebaa83e3 --- /dev/null +++ b/src/uml/class_diagram/model/class_template.h @@ -0,0 +1,50 @@ +/** + * src/uml/class_diagram/model/class_template.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include +#include + +namespace clanguml::class_diagram::model { + +class class_template { +public: + class_template(const std::string &type = "", const std::string &name = "", + const std::string &default_value = "", bool is_variadic = false); + + void set_type(const std::string &type); + std::string type() const; + + void set_name(const std::string &name); + std::string name() const; + + void set_default_value(const std::string &value); + std::string default_value() const; + + void is_variadic(bool is_variadic) noexcept; + bool is_variadic() const noexcept; + + friend bool operator==(const class_template &l, const class_template &r); + +private: + std::string type_; + std::string name_; + std::string default_value_; + bool is_variadic_{false}; +}; +} diff --git a/src/uml/class_diagram/model/decorated_element.cc b/src/uml/class_diagram/model/decorated_element.cc new file mode 100644 index 00000000..34c4d149 --- /dev/null +++ b/src/uml/class_diagram/model/decorated_element.cc @@ -0,0 +1,82 @@ +/** + * src/uml/class_diagram/model/decorated_element.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "decorated_element.h" + +namespace clanguml::class_diagram::model { + +bool decorated_element::skip() const +{ + for (auto d : decorators_) + if (std::dynamic_pointer_cast(d)) + return true; + + return false; +} + +bool decorated_element::skip_relationship() const +{ + for (auto d : decorators_) + if (std::dynamic_pointer_cast(d)) + return true; + + return false; +} + +std::pair decorated_element::relationship() const +{ + for (auto &d : decorators_) + if (std::dynamic_pointer_cast(d)) + return {relationship_t::kAssociation, + std::dynamic_pointer_cast(d) + ->multiplicity}; + else if (std::dynamic_pointer_cast(d)) + return {relationship_t::kAggregation, + std::dynamic_pointer_cast(d) + ->multiplicity}; + else if (std::dynamic_pointer_cast(d)) + return {relationship_t::kComposition, + std::dynamic_pointer_cast(d) + ->multiplicity}; + + return {relationship_t::kNone, ""}; +} + +std::string decorated_element::style_spec() +{ + for (auto d : decorators_) + if (std::dynamic_pointer_cast(d)) + return std::dynamic_pointer_cast(d)->spec; + + return ""; +} + +const std::vector> & +decorated_element::decorators() const +{ + return decorators_; +} + +void decorated_element::add_decorators( + const std::vector> &decorators) +{ + for (auto d : decorators) { + decorators_.push_back(d); + } +} +} diff --git a/src/uml/class_diagram/model/decorated_element.h b/src/uml/class_diagram/model/decorated_element.h new file mode 100644 index 00000000..0158ee7a --- /dev/null +++ b/src/uml/class_diagram/model/decorated_element.h @@ -0,0 +1,50 @@ +/** + * src/uml/class_diagram/model/decorated_element.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include "enums.h" + +#include "uml/decorators.h" + +#include +#include +#include + +namespace clanguml::class_diagram::model { + +class decorated_element { +public: + bool skip() const; + + bool skip_relationship() const; + + std::pair relationship() const; + + std::string style_spec(); + + const std::vector> & + decorators() const; + + void add_decorators( + const std::vector> &decorators); + +private: + std::vector> decorators_; +}; + +} diff --git a/src/uml/class_diagram/model/diagram.cc b/src/uml/class_diagram/model/diagram.cc new file mode 100644 index 00000000..7a1c0639 --- /dev/null +++ b/src/uml/class_diagram/model/diagram.cc @@ -0,0 +1,85 @@ +/** + * src/uml/class_diagram/model/diagram.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "diagram.h" + +#include "util/error.h" +#include "util/util.h" + +namespace clanguml::class_diagram::model { + +std::string diagram::name() const { return name_; } + +void diagram::set_name(const std::string &name) { name_ = name; } + +const std::vector diagram::classes() const { return classes_; } + +const std::vector diagram::enums() const { return enums_; } + +bool diagram::has_class(const class_ &c) const +{ + return std::any_of(classes_.cbegin(), classes_.cend(), + [&c](const auto &cc) { return cc.full_name() == c.full_name(); }); +} + +void diagram::add_type_alias(type_alias &&ta) +{ + LOG_DBG("Adding global alias: {} -> {}", ta.alias(), ta.underlying_type()); + + type_aliases_[ta.alias()] = std::move(ta); +} + +void diagram::add_class(class_ &&c) +{ + LOG_DBG("Adding class: {}, {}", c.name(), c.full_name()); + if (!has_class(c)) + classes_.emplace_back(std::move(c)); + else + LOG_DBG("Class {} ({}) already in the model", c.name(), c.full_name()); +} + +void diagram::add_enum(enum_ &&e) +{ + LOG_DBG("Adding enum: {}", e.name()); + auto it = std::find(enums_.begin(), enums_.end(), e); + if (it == enums_.end()) + enums_.emplace_back(std::move(e)); + else + LOG_DBG("Enum {} already in the model", e.name()); +} + +std::string diagram::to_alias(const std::string &full_name) const +{ + LOG_DBG("Looking for alias for {}", full_name); + + for (const auto &c : classes_) { + if (c.full_name() == full_name) { + return c.alias(); + } + } + + for (const auto &e : enums_) { + if (e.full_name() == full_name) { + return e.alias(); + } + } + + throw error::uml_alias_missing( + fmt::format("Missing alias for {}", full_name)); +} +} diff --git a/src/uml/class_diagram/model/diagram.h b/src/uml/class_diagram/model/diagram.h new file mode 100644 index 00000000..955dfebc --- /dev/null +++ b/src/uml/class_diagram/model/diagram.h @@ -0,0 +1,55 @@ +/** + * src/uml/class_diagram/model/diagram.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include "class.h" +#include "enum.h" +#include "type_alias.h" + +#include +#include + +namespace clanguml::class_diagram::model { + +class diagram { +public: + std::string name() const; + + void set_name(const std::string &name); + + const std::vector classes() const; + + const std::vector enums() const; + + bool has_class(const class_ &c) const; + + void add_type_alias(type_alias &&ta); + + void add_class(class_ &&c); + + void add_enum(enum_ &&e); + + std::string to_alias(const std::string &full_name) const; + +private: + std::string name_; + std::vector classes_; + std::vector enums_; + std::map type_aliases_; +}; +} diff --git a/src/uml/class_diagram/model/element.cc b/src/uml/class_diagram/model/element.cc new file mode 100644 index 00000000..5bb1ec91 --- /dev/null +++ b/src/uml/class_diagram/model/element.cc @@ -0,0 +1,68 @@ +/** + * src/uml/class_diagram/model/element.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "element.h" + +#include "util/util.h" + +namespace clanguml::class_diagram::model { + +std::atomic_uint64_t element::m_nextId = 1; + +element::element(const std::vector &using_namespaces) + : using_namespaces_{using_namespaces} + , m_id{m_nextId++} +{ +} + +std::string element::alias() const { return fmt::format("C_{:010}", m_id); } + +void element::add_relationship(class_relationship &&cr) +{ + if (cr.destination().empty()) { + LOG_WARN("Skipping relationship '{}' - {} - '{}' due empty " + "destination", + cr.destination(), to_string(cr.type()), full_name(true)); + return; + } + + auto it = std::find(relationships_.begin(), relationships_.end(), cr); + if (it == relationships_.end()) + relationships_.emplace_back(std::move(cr)); +} + +void element::set_using_namespaces(const std::vector &un) +{ + using_namespaces_ = un; +} + +const std::vector &element::using_namespaces() const +{ + return using_namespaces_; +} + +std::vector &element::relationships() +{ + return relationships_; +} + +const std::vector &element::relationships() const +{ + return relationships_; +} +} diff --git a/src/uml/class_diagram/model/element.h b/src/uml/class_diagram/model/element.h new file mode 100644 index 00000000..b1989ffd --- /dev/null +++ b/src/uml/class_diagram/model/element.h @@ -0,0 +1,67 @@ +/** + * src/uml/class_diagram/model/element.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include "class_relationship.h" +#include "decorated_element.h" +#include "enums.h" + +#include +#include +#include + +namespace clanguml::class_diagram::model { + +class element : public decorated_element { +public: + element(const std::vector &using_namespaces); + + std::string alias() const; + + void set_name(const std::string &name) { name_ = name; } + + std::string name() const { return name_; } + + void set_namespace(const std::vector &ns) { namespace_ = ns; } + + std::vector get_namespace() const { return namespace_; } + + virtual std::string full_name(bool relative) const { return name(); } + + void set_using_namespaces(const std::vector &un); + + const std::vector &using_namespaces() const; + + std::vector &relationships(); + + const std::vector &relationships() const; + + void add_relationship(class_relationship &&cr); + +protected: + const uint64_t m_id{0}; + +private: + std::string name_; + std::vector namespace_; + std::vector using_namespaces_; + std::vector relationships_; + + static std::atomic_uint64_t m_nextId; +}; +} diff --git a/src/uml/class_diagram/model/enum.cc b/src/uml/class_diagram/model/enum.cc new file mode 100644 index 00000000..8effe506 --- /dev/null +++ b/src/uml/class_diagram/model/enum.cc @@ -0,0 +1,51 @@ +/** + * src/uml/class_diagram/model/enum.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "enum.h" + +#include "util/util.h" + +#include + +namespace clanguml::class_diagram::model { + +enum_::enum_(const std::vector &using_namespaces) + : element{using_namespaces} +{ +} + +bool operator==(const enum_ &l, const enum_ &r) { return l.name() == r.name(); } + +std::string enum_::full_name(bool relative) const +{ + using namespace clanguml::util; + + std::ostringstream ostr; + if (relative) + ostr << ns_relative(using_namespaces(), name()); + else + ostr << name(); + + return ostr.str(); +} + +std::vector &enum_::constants() { return constants_; } + +const std::vector &enum_::constants() const { return constants_; } + +} diff --git a/src/uml/class_diagram/model/enum.h b/src/uml/class_diagram/model/enum.h new file mode 100644 index 00000000..4eb52bcd --- /dev/null +++ b/src/uml/class_diagram/model/enum.h @@ -0,0 +1,43 @@ +/** + * src/uml/class_diagram/model/enum.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include "class.h" + +#include +#include + +namespace clanguml::class_diagram::model { + +class enum_ : public element, public stylable_element { +public: + enum_(const std::vector &using_namespaces); + + friend bool operator==(const enum_ &l, const enum_ &r); + + std::string full_name(bool relative = true) const override; + + std::vector &constants(); + + const std::vector &constants() const; + +private: + std::vector constants_; +}; + +} diff --git a/src/uml/class_diagram/model/enums.h b/src/uml/class_diagram/model/enums.h new file mode 100644 index 00000000..19f34a53 --- /dev/null +++ b/src/uml/class_diagram/model/enums.h @@ -0,0 +1,39 @@ +/** + * src/uml/class_diagram/model/enums.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +namespace clanguml::class_diagram::model { + +enum class access_t { kPublic, kProtected, kPrivate }; + +enum class scope_t { kPublic, kProtected, kPrivate, kNone }; + +enum class relationship_t { + kNone, + kExtension, + kComposition, + kAggregation, + kContainment, + kOwnership, + kAssociation, + kInstantiation, + kFriendship, + kDependency +}; + +} diff --git a/src/uml/class_diagram/model/method_parameter.cc b/src/uml/class_diagram/model/method_parameter.cc new file mode 100644 index 00000000..0fda0d50 --- /dev/null +++ b/src/uml/class_diagram/model/method_parameter.cc @@ -0,0 +1,53 @@ +/** + * src/uml/class_diagram/model/method_parameter.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "method_parameter.h" + +#include "util/util.h" + +#include + +namespace clanguml::class_diagram::model { + +void method_parameter::set_type(const std::string &type) { type_ = type; } + +std::string method_parameter::type() const { return type_; } + +void method_parameter::set_name(const std::string &name) { name_ = name; } + +std::string method_parameter::name() const { return name_; } + +void method_parameter::set_default_value(const std::string &value) +{ + default_value_ = value; +} + +std::string method_parameter::default_value() const { return default_value_; } + +std::string method_parameter::to_string( + const std::vector &using_namespaces) const +{ + using namespace clanguml::util; + auto t = ns_relative(using_namespaces, type()); + if (default_value().empty()) + return fmt::format("{} {}", t, name()); + + return fmt::format("{} {} = {}", t, name(), default_value()); +} + +} diff --git a/src/uml/class_diagram/model/method_parameter.h b/src/uml/class_diagram/model/method_parameter.h new file mode 100644 index 00000000..4cb752b7 --- /dev/null +++ b/src/uml/class_diagram/model/method_parameter.h @@ -0,0 +1,48 @@ +/** + * src/uml/class_diagram/model/method_parameter.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include "decorated_element.h" +#include "enums.h" + +#include +#include + +namespace clanguml::class_diagram::model { + +class method_parameter : public decorated_element { +public: + void set_type(const std::string &type); + std::string type() const; + + void set_name(const std::string &name); + std::string name() const; + + void set_default_value(const std::string &value); + std::string default_value() const; + + std::string to_string( + const std::vector &using_namespaces) const; + +private: + std::string type_; + std::string name_; + std::string default_value_; +}; + +} diff --git a/src/uml/class_diagram/model/stylable_element.cc b/src/uml/class_diagram/model/stylable_element.cc new file mode 100644 index 00000000..20eb488c --- /dev/null +++ b/src/uml/class_diagram/model/stylable_element.cc @@ -0,0 +1,27 @@ +/** + * src/uml/class_diagram/model/stylable_element.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "stylable_element.h" + +namespace clanguml::class_diagram::model { + +void stylable_element::set_style(const std::string &style) { style_ = style; } + +std::string stylable_element::style() const { return style_; } + +} diff --git a/src/uml/class_diagram/model/stylable_element.h b/src/uml/class_diagram/model/stylable_element.h new file mode 100644 index 00000000..46505cd4 --- /dev/null +++ b/src/uml/class_diagram/model/stylable_element.h @@ -0,0 +1,33 @@ +/** + * src/uml/class_diagram/model/stylable_element.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include + +namespace clanguml::class_diagram::model { + +class stylable_element { +public: + void set_style(const std::string &style); + std::string style() const; + +private: + std::string style_; +}; + +} diff --git a/src/uml/class_diagram/model/type_alias.cc b/src/uml/class_diagram/model/type_alias.cc new file mode 100644 index 00000000..23c75dab --- /dev/null +++ b/src/uml/class_diagram/model/type_alias.cc @@ -0,0 +1,34 @@ +/** + * src/uml/class_diagram/model/type_alias.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ + +#include "type_alias.h" + +namespace clanguml::class_diagram::model { + +void type_alias::set_alias(const std::string &alias) { alias_ = alias; } + +std::string type_alias::alias() const { return alias_; } + +void type_alias::set_underlying_type(const std::string &type) +{ + underlying_type_ = type; +} + +std::string type_alias::underlying_type() const { return underlying_type_; } + +} diff --git a/src/uml/class_diagram/model/type_alias.h b/src/uml/class_diagram/model/type_alias.h new file mode 100644 index 00000000..47a78f35 --- /dev/null +++ b/src/uml/class_diagram/model/type_alias.h @@ -0,0 +1,37 @@ +/** + * src/uml/class_diagram/model/type_alias.h + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed 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. + */ +#pragma once + +#include + +namespace clanguml::class_diagram::model { + +class type_alias { +public: + void set_alias(const std::string &alias); + std::string alias() const; + + void set_underlying_type(const std::string &type); + std::string underlying_type() const; + +private: + std::string alias_; + std::string underlying_type_; +}; + +} diff --git a/src/uml/class_diagram_model.cc b/src/uml/class_diagram_model.cc deleted file mode 100644 index 4d20df51..00000000 --- a/src/uml/class_diagram_model.cc +++ /dev/null @@ -1,633 +0,0 @@ -/** - * src/uml/class_diagram_model.cc - * - * Copyright (c) 2021 Bartek Kryza - * - * Licensed 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. - */ - -#include "class_diagram_model.h" - -namespace clanguml { -namespace model { -namespace class_diagram { -std::atomic_uint64_t element::m_nextId = 1; - -std::string to_string(relationship_t r) -{ - switch (r) { - case relationship_t::kNone: - return "none"; - case relationship_t::kExtension: - return "extension"; - case relationship_t::kComposition: - return "composition"; - case relationship_t::kAggregation: - return "aggregation"; - case relationship_t::kContainment: - return "containment"; - case relationship_t::kOwnership: - return "ownership"; - case relationship_t::kAssociation: - return "association"; - case relationship_t::kInstantiation: - return "instantiation"; - case relationship_t::kFriendship: - return "frendship"; - case relationship_t::kDependency: - return "dependency"; - default: - return "invalid"; - } -} - -// -// stylable_element -// -void stylable_element::set_style(const std::string &style) { style_ = style; } - -std::string stylable_element::style() const { return style_; } - -// -// decorated_element -// - -bool decorated_element::skip() const -{ - for (auto d : decorators_) - if (std::dynamic_pointer_cast(d)) - return true; - - return false; -} - -bool decorated_element::skip_relationship() const -{ - for (auto d : decorators_) - if (std::dynamic_pointer_cast(d)) - return true; - - return false; -} - -std::pair decorated_element::relationship() const -{ - for (auto &d : decorators_) - if (std::dynamic_pointer_cast(d)) - return {relationship_t::kAssociation, - std::dynamic_pointer_cast(d) - ->multiplicity}; - else if (std::dynamic_pointer_cast(d)) - return {relationship_t::kAggregation, - std::dynamic_pointer_cast(d) - ->multiplicity}; - else if (std::dynamic_pointer_cast(d)) - return {relationship_t::kComposition, - std::dynamic_pointer_cast(d) - ->multiplicity}; - - return {relationship_t::kNone, ""}; -} - -std::string decorated_element::style_spec() -{ - for (auto d : decorators_) - if (std::dynamic_pointer_cast(d)) - return std::dynamic_pointer_cast(d)->spec; - - return ""; -} - -const std::vector> & -decorated_element::decorators() const -{ - return decorators_; -} - -void decorated_element::add_decorators( - const std::vector> &decorators) -{ - for (auto d : decorators) { - decorators_.push_back(d); - } -} - -// -// class_element -// -class_element::class_element( - scope_t scope, const std::string &name, const std::string &type) - : scope_{scope} - , name_{name} - , type_{type} -{ -} - -scope_t class_element::scope() const { return scope_; } - -std::string class_element::name() const { return name_; } - -std::string class_element::type() const { return type_; } - -// -// class_member -// -class_member::class_member( - scope_t scope, const std::string &name, const std::string &type) - : class_element{scope, name, type} -{ -} - -bool class_member::is_relationship() const { return is_relationship_; } - -void class_member::is_relationship(bool is_relationship) -{ - is_relationship_ = is_relationship; -} - -bool class_member::is_static() const { return is_static_; } - -void class_member::is_static(bool is_static) { is_static_ = is_static; } - -// -// element -// - -element::element(const std::vector &using_namespaces) - : using_namespaces_{using_namespaces} - , m_id{m_nextId++} -{ -} - -std::string element::alias() const { return fmt::format("C_{:010}", m_id); } - -void element::add_relationship(class_relationship &&cr) -{ - if (cr.destination().empty()) { - LOG_WARN("Skipping relationship '{}' - {} - '{}' due empty " - "destination", - cr.destination(), to_string(cr.type()), full_name(true)); - return; - } - - auto it = std::find(relationships_.begin(), relationships_.end(), cr); - if (it == relationships_.end()) - relationships_.emplace_back(std::move(cr)); -} - -void element::set_using_namespaces(const std::vector &un) -{ - using_namespaces_ = un; -} - -const std::vector &element::using_namespaces() const -{ - return using_namespaces_; -} - -std::vector &element::relationships() -{ - return relationships_; -} - -const std::vector &element::relationships() const -{ - return relationships_; -} - -// -// method_parameter -// -void method_parameter::set_type(const std::string &type) { type_ = type; } - -std::string method_parameter::type() const { return type_; } - -void method_parameter::set_name(const std::string &name) { name_ = name; } - -std::string method_parameter::name() const { return name_; } - -void method_parameter::set_default_value(const std::string &value) -{ - default_value_ = value; -} - -std::string method_parameter::default_value() const { return default_value_; } - -std::string method_parameter::to_string( - const std::vector &using_namespaces) const -{ - using namespace clanguml::util; - auto t = ns_relative(using_namespaces, type()); - if (default_value().empty()) - return fmt::format("{} {}", t, name()); - - return fmt::format("{} {} = {}", t, name(), default_value()); -} - -// -// class_method -// -class_method::class_method( - scope_t scope, const std::string &name, const std::string &type) - : class_element{scope, name, type} -{ -} - -bool class_method::is_pure_virtual() const { return is_pure_virtual_; } - -void class_method::is_pure_virtual(bool is_pure_virtual) -{ - is_pure_virtual_ = is_pure_virtual; -} - -bool class_method::is_virtual() const { return is_virtual_; } - -void class_method::is_virtual(bool is_virtual) { is_virtual_ = is_virtual; } - -bool class_method::is_const() const { return is_const_; } - -void class_method::is_const(bool is_const) { is_const_ = is_const; } - -bool class_method::is_defaulted() const { return is_defaulted_; } - -void class_method::is_defaulted(bool is_defaulted) -{ - is_defaulted_ = is_defaulted; -} - -bool class_method::is_static() const { return is_static_; } - -void class_method::is_static(bool is_static) { is_static_ = is_static; } - -const std::vector &class_method::parameters() const -{ - return parameters_; -} - -void class_method::add_parameter(method_parameter &¶meter) -{ - parameters_.emplace_back(std::move(parameter)); -} - -// -// class_parent -// -void class_parent::set_name(const std::string &name) { name_ = name; } - -std::string class_parent::name() const { return name_; } - -void class_parent::is_virtual(bool is_virtual) { is_virtual_ = is_virtual; } - -bool class_parent::is_virtual() const { return is_virtual_; } - -void class_parent::set_access(class_parent::access_t access) -{ - access_ = access; -} - -class_parent::access_t class_parent::access() const { return access_; } - -// -// class_relationship -// -class_relationship::class_relationship(relationship_t type, - const std::string &destination, scope_t scope, const std::string &label, - const std::string &multiplicity_source, - const std::string &multiplicity_destination) - : type_{type} - , destination_{destination} - , scope_{scope} - , label_{label} - , multiplicity_source_{multiplicity_source} - , multiplicity_destination_{multiplicity_destination} -{ -} - -void class_relationship::set_type(relationship_t type) noexcept -{ - type_ = type; -} - -relationship_t class_relationship::type() const noexcept { return type_; } - -void class_relationship::set_destination(const std::string &destination) -{ - destination_ = destination; -} - -std::string class_relationship::destination() const { return destination_; } - -void class_relationship::set_multiplicity_source( - const std::string &multiplicity_source) -{ - multiplicity_source_ = multiplicity_source; -} - -std::string class_relationship::multiplicity_source() const -{ - return multiplicity_source_; -} - -void class_relationship::set_multiplicity_destination( - const std::string &multiplicity_destination) -{ - multiplicity_destination_ = multiplicity_destination; -} - -std::string class_relationship::multiplicity_destination() const -{ - return multiplicity_destination_; -} - -void class_relationship::set_label(const std::string &label) { label_ = label; } - -std::string class_relationship::label() const { return label_; } - -void class_relationship::set_scope(scope_t scope) noexcept { scope_ = scope; } - -scope_t class_relationship::scope() const noexcept { return scope_; } - -bool operator==(const class_relationship &l, const class_relationship &r) -{ - return l.type() == r.type() && l.destination() == r.destination() && - l.label() == r.label(); -} - -// -// class_template -// -class_template::class_template(const std::string &type, const std::string &name, - const std::string &default_value, bool is_variadic) - : type_{type} - , name_{name} - , default_value_{default_value} - , is_variadic_{is_variadic} -{ - if (is_variadic) - name_ = name_ + "..."; -} - -void class_template::set_type(const std::string &type) { type_ = type; } - -std::string class_template::type() const { return type_; } - -void class_template::set_name(const std::string &name) { name_ = name; } - -std::string class_template::name() const { return name_; } - -void class_template::set_default_value(const std::string &value) -{ - default_value_ = value; -} - -std::string class_template::default_value() const { return default_value_; } - -void class_template::is_variadic(bool is_variadic) noexcept -{ - is_variadic_ = is_variadic; -} - -bool class_template::is_variadic() const noexcept { return is_variadic_; } - -bool operator==(const class_template &l, const class_template &r) -{ - return (l.name() == r.name()) && (l.type() == r.type()); -} - -// -// type_alias -// -void type_alias::set_alias(const std::string &alias) { alias_ = alias; } - -std::string type_alias::alias() const { return alias_; } - -void type_alias::set_underlying_type(const std::string &type) -{ - underlying_type_ = type; -} - -std::string type_alias::underlying_type() const { return underlying_type_; } - -// -// class_ -// -class_::class_(const std::vector &using_namespaces) - : element{using_namespaces} -{ -} - -bool class_::is_struct() const { return is_struct_; } - -void class_::is_struct(bool is_struct) { is_struct_ = is_struct; } - -bool class_::is_template() const { return is_template_; } - -void class_::is_template(bool is_template) { is_template_ = is_template; } - -bool class_::is_template_instantiation() const -{ - return is_template_instantiation_; -} - -void class_::is_template_instantiation(bool is_template_instantiation) -{ - is_template_instantiation_ = is_template_instantiation; -} - -void class_::add_member(class_member &&member) -{ - members_.emplace_back(std::move(member)); -} - -void class_::add_method(class_method &&method) -{ - methods_.emplace_back(std::move(method)); -} - -void class_::add_parent(class_parent &&parent) -{ - bases_.emplace_back(std::move(parent)); -} - -void class_::add_template(class_template &&tmplt) -{ - templates_.emplace_back(std::move(tmplt)); -} - -const std::vector &class_::members() const { return members_; } - -const std::vector &class_::methods() const { return methods_; } - -const std::vector &class_::parents() const { return bases_; } - -const std::vector &class_::templates() const -{ - return templates_; -} - -void class_::set_base_template(const std::string &full_name) -{ - base_template_full_name_ = full_name; -} - -std::string class_::base_template() const { return base_template_full_name_; } - -bool operator==(const class_ &l, const class_ &r) -{ - return l.full_name() == r.full_name(); -} - -void class_::add_type_alias(type_alias &&ta) -{ - LOG_DBG("Adding class alias: {} -> {}", ta.alias(), ta.underlying_type()); - type_aliases_[ta.alias()] = std::move(ta); -} - -std::string class_::full_name(bool relative) const -{ - using namespace clanguml::util; - - std::ostringstream ostr; - if (relative) - ostr << ns_relative(using_namespaces(), name()); - else - ostr << name(); - - if (!templates_.empty()) { - std::vector tnames; - std::transform(templates_.cbegin(), templates_.cend(), - std::back_inserter(tnames), [this](const auto &tmplt) { - std::vector res; - - if (!tmplt.type().empty()) - res.push_back( - ns_relative(using_namespaces(), tmplt.type())); - - if (!tmplt.name().empty()) - res.push_back( - ns_relative(using_namespaces(), tmplt.name())); - - if (!tmplt.default_value().empty()) { - res.push_back("="); - res.push_back(tmplt.default_value()); - } - - return fmt::format("{}", fmt::join(res, " ")); - }); - ostr << fmt::format("<{}>", fmt::join(tnames, ",")); - } - - return ostr.str(); -} - -bool class_::is_abstract() const -{ - // TODO check if all base abstract methods are overriden - // with non-abstract methods - return std::any_of(methods_.begin(), methods_.end(), - [](const auto &method) { return method.is_pure_virtual(); }); -} - -// -// enum_ -// -enum_::enum_(const std::vector &using_namespaces) - : element{using_namespaces} -{ -} - -bool operator==(const enum_ &l, const enum_ &r) { return l.name() == r.name(); } - -std::string enum_::full_name(bool relative) const -{ - using namespace clanguml::util; - - std::ostringstream ostr; - if (relative) - ostr << ns_relative(using_namespaces(), name()); - else - ostr << name(); - - return ostr.str(); -} - -std::vector &enum_::constants() { return constants_; } - -const std::vector &enum_::constants() const { return constants_; } - -// -// diagram -// -std::string diagram::name() const { return name_; } - -void diagram::set_name(const std::string &name) { name_ = name; } - -const std::vector diagram::classes() const { return classes_; } - -const std::vector diagram::enums() const { return enums_; } - -bool diagram::has_class(const class_ &c) const -{ - return std::any_of(classes_.cbegin(), classes_.cend(), - [&c](const auto &cc) { return cc.full_name() == c.full_name(); }); -} - -void diagram::add_type_alias(type_alias &&ta) -{ - LOG_DBG("Adding global alias: {} -> {}", ta.alias(), ta.underlying_type()); - - type_aliases_[ta.alias()] = std::move(ta); -} - -void diagram::add_class(class_ &&c) -{ - LOG_DBG("Adding class: {}, {}", c.name(), c.full_name()); - if (!has_class(c)) - classes_.emplace_back(std::move(c)); - else - LOG_DBG("Class {} ({}) already in the model", c.name(), c.full_name()); -} - -void diagram::add_enum(enum_ &&e) -{ - LOG_DBG("Adding enum: {}", e.name()); - auto it = std::find(enums_.begin(), enums_.end(), e); - if (it == enums_.end()) - enums_.emplace_back(std::move(e)); - else - LOG_DBG("Enum {} already in the model", e.name()); -} - -std::string diagram::to_alias(const std::string &full_name) const -{ - LOG_DBG("Looking for alias for {}", full_name); - - for (const auto &c : classes_) { - if (c.full_name() == full_name) { - return c.alias(); - } - } - - for (const auto &e : enums_) { - if (e.full_name() == full_name) { - return e.alias(); - } - } - - throw error::uml_alias_missing( - fmt::format("Missing alias for {}", full_name)); -} - -} -} -} diff --git a/src/uml/class_diagram_model.h b/src/uml/class_diagram_model.h deleted file mode 100644 index 6918dff5..00000000 --- a/src/uml/class_diagram_model.h +++ /dev/null @@ -1,397 +0,0 @@ -/** - * src/uml/class_diagram_model.h - * - * Copyright (c) 2021 Bartek Kryza - * - * Licensed 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. - */ -#pragma once - -#include "decorators.h" -#include "util/error.h" -#include "util/util.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace clanguml { -namespace model { -namespace class_diagram { - -enum class scope_t { kPublic, kProtected, kPrivate, kNone }; - -enum class relationship_t { - kNone, - kExtension, - kComposition, - kAggregation, - kContainment, - kOwnership, - kAssociation, - kInstantiation, - kFriendship, - kDependency -}; - -std::string to_string(relationship_t r); - -class stylable_element { -public: - void set_style(const std::string &style); - std::string style() const; - -private: - std::string style_; -}; - -class decorated_element { -public: - bool skip() const; - - bool skip_relationship() const; - - std::pair relationship() const; - - std::string style_spec(); - - const std::vector> & - decorators() const; - - void add_decorators( - const std::vector> &decorators); - -private: - std::vector> decorators_; -}; - -class class_element : public decorated_element { -public: - class_element( - scope_t scope, const std::string &name, const std::string &type); - - scope_t scope() const; - std::string name() const; - std::string type() const; - -private: - scope_t scope_; - std::string name_; - std::string type_; -}; - -class class_member : public class_element { -public: - class_member( - scope_t scope, const std::string &name, const std::string &type); - - bool is_relationship() const; - void is_relationship(bool is_relationship); - - bool is_static() const; - void is_static(bool is_static); - -private: - bool is_relationship_{false}; - bool is_static_{false}; -}; - -class method_parameter : public decorated_element { -public: - void set_type(const std::string &type); - std::string type() const; - - void set_name(const std::string &name); - std::string name() const; - - void set_default_value(const std::string &value); - std::string default_value() const; - - std::string to_string( - const std::vector &using_namespaces) const; - -private: - std::string type_; - std::string name_; - std::string default_value_; -}; - -class class_method : public class_element { -public: - class_method( - scope_t scope, const std::string &name, const std::string &type); - - bool is_pure_virtual() const; - void is_pure_virtual(bool is_pure_virtual); - - bool is_virtual() const; - void is_virtual(bool is_virtual); - - bool is_const() const; - void is_const(bool is_const); - - bool is_defaulted() const; - void is_defaulted(bool is_defaulted); - - bool is_static() const; - void is_static(bool is_static); - - const std::vector ¶meters() const; - void add_parameter(method_parameter &¶meter); - -private: - std::vector parameters_; - bool is_pure_virtual_{false}; - bool is_virtual_{false}; - bool is_const_{false}; - bool is_defaulted_{false}; - bool is_static_{false}; -}; - -class class_parent { -public: - enum class access_t { kPublic, kProtected, kPrivate }; - - void set_name(const std::string &name); - std::string name() const; - - void is_virtual(bool is_virtual); - bool is_virtual() const; - - void set_access(access_t access); - access_t access() const; - -private: - std::string name_; - bool is_virtual_{false}; - access_t access_; -}; - -class class_relationship : public decorated_element, public stylable_element { -public: - class_relationship(relationship_t type, const std::string &destination, - scope_t scope = scope_t::kNone, const std::string &label = "", - const std::string &multiplicity_source = "", - const std::string &multiplicity_destination = ""); - - virtual ~class_relationship() = default; - - void set_type(relationship_t type) noexcept; - relationship_t type() const noexcept; - - void set_destination(const std::string &destination); - std::string destination() const; - - void set_multiplicity_source(const std::string &multiplicity_source); - std::string multiplicity_source() const; - - void set_multiplicity_destination( - const std::string &multiplicity_destination); - std::string multiplicity_destination() const; - - void set_label(const std::string &label); - std::string label() const; - - void set_scope(scope_t scope) noexcept; - scope_t scope() const noexcept; - - friend bool operator==( - const class_relationship &l, const class_relationship &r); - -private: - relationship_t type_{relationship_t::kAssociation}; - std::string destination_; - std::string multiplicity_source_; - std::string multiplicity_destination_; - std::string label_; - scope_t scope_{scope_t::kNone}; -}; - -class class_template { -public: - class_template(const std::string &type = "", const std::string &name = "", - const std::string &default_value = "", bool is_variadic = false); - - void set_type(const std::string &type); - std::string type() const; - - void set_name(const std::string &name); - std::string name() const; - - void set_default_value(const std::string &value); - std::string default_value() const; - - void is_variadic(bool is_variadic) noexcept; - bool is_variadic() const noexcept; - - friend bool operator==(const class_template &l, const class_template &r); - -private: - std::string type_; - std::string name_; - std::string default_value_; - bool is_variadic_{false}; -}; - -class element : public decorated_element { -public: - element(const std::vector &using_namespaces); - - std::string alias() const; - - void set_name(const std::string &name) { name_ = name; } - - std::string name() const { return name_; } - - void set_namespace(const std::vector &ns) { namespace_ = ns; } - - std::vector get_namespace() const { return namespace_; } - - virtual std::string full_name(bool relative) const { return name(); } - - void set_using_namespaces(const std::vector &un); - - const std::vector &using_namespaces() const; - - std::vector &relationships(); - - const std::vector &relationships() const; - - void add_relationship(class_relationship &&cr); - -protected: - const uint64_t m_id{0}; - -private: - std::string name_; - std::vector namespace_; - std::vector using_namespaces_; - std::vector relationships_; - - static std::atomic_uint64_t m_nextId; -}; - -class type_alias { -public: - void set_alias(const std::string &alias); - std::string alias() const; - - void set_underlying_type(const std::string &type); - std::string underlying_type() const; - -private: - std::string alias_; - std::string underlying_type_; -}; - -class class_ : public element, public stylable_element { -public: - class_(const std::vector &using_namespaces); - - bool is_struct() const; - void is_struct(bool is_struct); - - bool is_template() const; - void is_template(bool is_template); - - bool is_template_instantiation() const; - void is_template_instantiation(bool is_template_instantiation); - - void add_member(class_member &&member); - void add_method(class_method &&method); - void add_parent(class_parent &&parent); - void add_template(class_template &&tmplt); - - const std::vector &members() const; - const std::vector &methods() const; - const std::vector &parents() const; - const std::vector &templates() const; - - void set_base_template(const std::string &full_name); - std::string base_template() const; - - friend bool operator==(const class_ &l, const class_ &r); - - void add_type_alias(type_alias &&ta); - - std::string full_name(bool relative = true) const override; - - bool is_abstract() const; - -private: - bool is_struct_{false}; - bool is_template_{false}; - bool is_template_instantiation_{false}; - std::vector members_; - std::vector methods_; - std::vector bases_; - std::vector templates_; - std::string base_template_full_name_; - std::map type_aliases_; - - std::string full_name_; -}; - -struct enum_ : public element, public stylable_element { -public: - enum_(const std::vector &using_namespaces); - - friend bool operator==(const enum_ &l, const enum_ &r); - - std::string full_name(bool relative = true) const override; - - std::vector &constants(); - - const std::vector &constants() const; - -private: - std::vector constants_; -}; - -class diagram { -public: - std::string name() const; - - void set_name(const std::string &name); - - const std::vector classes() const; - - const std::vector enums() const; - - bool has_class(const class_ &c) const; - - void add_type_alias(type_alias &&ta); - - void add_class(class_ &&c); - - void add_enum(enum_ &&e); - - std::string to_alias(const std::string &full_name) const; - -private: - std::string name_; - std::vector classes_; - std::vector enums_; - std::map type_aliases_; -}; -} -} -} diff --git a/src/uml/class_diagram_visitor.cc b/src/uml/class_diagram_visitor.cc index 7fd68029..3303f108 100644 --- a/src/uml/class_diagram_visitor.cc +++ b/src/uml/class_diagram_visitor.cc @@ -37,18 +37,19 @@ namespace clanguml { namespace visitor { namespace class_diagram { -using clanguml::model::class_diagram::class_; -using clanguml::model::class_diagram::class_member; -using clanguml::model::class_diagram::class_method; -using clanguml::model::class_diagram::class_parent; -using clanguml::model::class_diagram::class_relationship; -using clanguml::model::class_diagram::class_template; -using clanguml::model::class_diagram::diagram; -using clanguml::model::class_diagram::enum_; -using clanguml::model::class_diagram::method_parameter; -using clanguml::model::class_diagram::relationship_t; -using clanguml::model::class_diagram::scope_t; -using clanguml::model::class_diagram::type_alias; +using clanguml::class_diagram::model::access_t; +using clanguml::class_diagram::model::class_; +using clanguml::class_diagram::model::class_member; +using clanguml::class_diagram::model::class_method; +using clanguml::class_diagram::model::class_parent; +using clanguml::class_diagram::model::class_relationship; +using clanguml::class_diagram::model::class_template; +using clanguml::class_diagram::model::diagram; +using clanguml::class_diagram::model::enum_; +using clanguml::class_diagram::model::method_parameter; +using clanguml::class_diagram::model::relationship_t; +using clanguml::class_diagram::model::scope_t; +using clanguml::class_diagram::model::type_alias; namespace detail { scope_t cpp_access_specifier_to_scope(cppast::cpp_access_specifier_kind as) @@ -76,7 +77,7 @@ scope_t cpp_access_specifier_to_scope(cppast::cpp_access_specifier_kind as) // tu_context // tu_context::tu_context(cppast::cpp_entity_index &idx, - clanguml::model::class_diagram::diagram &d_, + clanguml::class_diagram::model::diagram &d_, const clanguml::config::class_diagram &config_) : entity_index{idx} , d{d_} @@ -152,7 +153,7 @@ tu_context::get_type_alias_template(const std::string &full_name) const // template element_visitor_context::element_visitor_context( - clanguml::model::class_diagram::diagram &d_, T &e) + clanguml::class_diagram::model::diagram &d_, T &e) : element(e) , d{d_} { @@ -163,7 +164,7 @@ element_visitor_context::element_visitor_context( // tu_visitor::tu_visitor(cppast::cpp_entity_index &idx_, - clanguml::model::class_diagram::diagram &d_, + clanguml::class_diagram::model::diagram &d_, const clanguml::config::class_diagram &config_) : ctx{idx_, d_, config_} { @@ -421,16 +422,16 @@ void tu_visitor::process_class_declaration(const cppast::cpp_class &cls, switch (base.access_specifier()) { case cppast::cpp_access_specifier_kind::cpp_private: - cp.set_access(class_parent::access_t::kPrivate); + cp.set_access(access_t::kPrivate); break; case cppast::cpp_access_specifier_kind::cpp_public: - cp.set_access(class_parent::access_t::kPublic); + cp.set_access(access_t::kPublic); break; case cppast::cpp_access_specifier_kind::cpp_protected: - cp.set_access(class_parent::access_t::kProtected); + cp.set_access(access_t::kProtected); break; default: - cp.set_access(class_parent::access_t::kPublic); + cp.set_access(access_t::kPublic); } LOG_DBG("Found base class {} for class {}", cp.name(), c.name()); @@ -631,8 +632,9 @@ bool tu_visitor::process_field_with_template_instantiation( if (ctx.config.should_include(tinst.name())) { LOG_DBG("Adding field instantiation relationship {} {} {} : {}", - rr.destination(), model::class_diagram::to_string(rr.type()), - c.full_name(), rr.label()); + rr.destination(), + clanguml::class_diagram::model::to_string(rr.type()), c.full_name(), + rr.label()); c.add_relationship(std::move(rr)); @@ -708,7 +710,8 @@ void tu_visitor::process_field(const cppast::cpp_member_variable &mv, class_ &c, } LOG_DBG("Adding field relationship {} {} {} : {}", - r.destination(), model::class_diagram::to_string(r.type()), + r.destination(), + clanguml::class_diagram::model::to_string(r.type()), c.full_name(), r.label()); c.add_relationship(std::move(r)); @@ -932,7 +935,8 @@ void tu_visitor::process_function_parameter( class_relationship r{relationship_t::kDependency, type}; LOG_DBG("Adding field relationship {} {} {} : {}", - r.destination(), model::class_diagram::to_string(r.type()), + r.destination(), + clanguml::class_diagram::model::to_string(r.type()), c.full_name(), r.label()); c.add_relationship(std::move(r)); @@ -988,7 +992,8 @@ void tu_visitor::process_function_parameter( "{} {} {} " ": {}", rr.destination(), - model::class_diagram::to_string(rr.type()), + clanguml::class_diagram::model::to_string( + rr.type()), c.full_name(), rr.label()); c.add_relationship(std::move(rr)); } @@ -1003,7 +1008,8 @@ void tu_visitor::process_function_parameter( LOG_DBG("Adding field dependency relationship {} {} {} " ": {}", rr.destination(), - model::class_diagram::to_string(rr.type()), + clanguml::class_diagram::model::to_string( + rr.type()), c.full_name(), rr.label()); c.add_relationship(std::move(rr)); @@ -1241,7 +1247,7 @@ bool tu_visitor::find_relationships(const cppast::cpp_type &t_, class_ tu_visitor::build_template_instantiation( const cppast::cpp_template_instantiation_type &t, - std::optional parent) + std::optional parent) { class_ tinst{ctx.config.using_namespace}; std::string full_template_name; @@ -1477,7 +1483,7 @@ class_ tu_visitor::build_template_instantiation( "Adding template argument '{}' as base class", ct.type()); class_parent cp; - cp.set_access(class_parent::access_t::kPublic); + cp.set_access(access_t::kPublic); cp.set_name(ct.type()); tinst.add_parent(std::move(cp)); diff --git a/src/uml/class_diagram_visitor.h b/src/uml/class_diagram_visitor.h index 53d9c782..b0660d47 100644 --- a/src/uml/class_diagram_visitor.h +++ b/src/uml/class_diagram_visitor.h @@ -17,9 +17,9 @@ */ #pragma once -#include "class_diagram_model.h" #include "config/config.h" #include "cx/cursor.h" +#include "uml/class_diagram/model/diagram.h" #include #include @@ -43,7 +43,7 @@ namespace class_diagram { struct tu_context { tu_context(cppast::cpp_entity_index &idx, - clanguml::model::class_diagram::diagram &d_, + clanguml::class_diagram::model::diagram &d_, const clanguml::config::class_diagram &config_); bool has_type_alias(const std::string &full_name) const; @@ -67,7 +67,7 @@ struct tu_context { std::vector namespace_; cppast::cpp_entity_index &entity_index; - clanguml::model::class_diagram::diagram &d; + clanguml::class_diagram::model::diagram &d; const clanguml::config::class_diagram &config; std::map> alias_index; @@ -76,19 +76,19 @@ struct tu_context { }; template struct element_visitor_context { - element_visitor_context(clanguml::model::class_diagram::diagram &d_, T &e); + element_visitor_context(clanguml::class_diagram::model::diagram &d_, T &e); tu_context *ctx; T &element; - clanguml::model::class_diagram::class_ *parent_class{}; - clanguml::model::class_diagram::diagram &d; + clanguml::class_diagram::model::class_ *parent_class{}; + clanguml::class_diagram::model::diagram &d; }; class tu_visitor { public: tu_visitor(cppast::cpp_entity_index &idx_, - clanguml::model::class_diagram::diagram &d_, + clanguml::class_diagram::model::diagram &d_, const clanguml::config::class_diagram &config_); void operator()(const cppast::cpp_entity &file); @@ -100,73 +100,73 @@ public: void process_enum_declaration(const cppast::cpp_enum &enm); void process_anonymous_enum(const cppast::cpp_enum &en, - clanguml::model::class_diagram::class_ &c, + clanguml::class_diagram::model::class_ &c, cppast::cpp_access_specifier_kind as); void process_field(const cppast::cpp_member_variable &mv, - clanguml::model::class_diagram::class_ &c, + clanguml::class_diagram::model::class_ &c, cppast::cpp_access_specifier_kind as); bool process_field_with_template_instantiation( const cppast::cpp_member_variable &mv, const cppast::cpp_type &tr, - clanguml::model::class_diagram::class_ &c, - clanguml::model::class_diagram::class_member &m, + clanguml::class_diagram::model::class_ &c, + clanguml::class_diagram::model::class_member &m, cppast::cpp_access_specifier_kind as); void process_static_field(const cppast::cpp_variable &mv, - clanguml::model::class_diagram::class_ &c, + clanguml::class_diagram::model::class_ &c, cppast::cpp_access_specifier_kind as); void process_method(const cppast::cpp_member_function &mf, - clanguml::model::class_diagram::class_ &c, + clanguml::class_diagram::model::class_ &c, cppast::cpp_access_specifier_kind as); void process_template_method(const cppast::cpp_function_template &mf, - clanguml::model::class_diagram::class_ &c, + clanguml::class_diagram::model::class_ &c, cppast::cpp_access_specifier_kind as); void process_static_method(const cppast::cpp_function &mf, - clanguml::model::class_diagram::class_ &c, + clanguml::class_diagram::model::class_ &c, cppast::cpp_access_specifier_kind as); void process_constructor(const cppast::cpp_constructor &mf, - clanguml::model::class_diagram::class_ &c, + clanguml::class_diagram::model::class_ &c, cppast::cpp_access_specifier_kind as); void process_destructor(const cppast::cpp_destructor &mf, - clanguml::model::class_diagram::class_ &c, + clanguml::class_diagram::model::class_ &c, cppast::cpp_access_specifier_kind as); void process_function_parameter(const cppast::cpp_function_parameter ¶m, - clanguml::model::class_diagram::class_method &m, - clanguml::model::class_diagram::class_ &c, + clanguml::class_diagram::model::class_method &m, + clanguml::class_diagram::model::class_ &c, const std::set &template_parameter_names = {}); bool find_relationships(const cppast::cpp_type &t, std::vector> &relationships, - clanguml::model::class_diagram::relationship_t relationship_hint = - clanguml::model::class_diagram::relationship_t::kNone); + clanguml::class_diagram::model::relationship_t>> &relationships, + clanguml::class_diagram::model::relationship_t relationship_hint = + clanguml::class_diagram::model::relationship_t::kNone); void process_template_type_parameter( const cppast::cpp_template_type_parameter &t, - clanguml::model::class_diagram::class_ &parent); + clanguml::class_diagram::model::class_ &parent); void process_template_nontype_parameter( const cppast::cpp_non_type_template_parameter &t, - clanguml::model::class_diagram::class_ &parent); + clanguml::class_diagram::model::class_ &parent); void process_template_template_parameter( const cppast::cpp_template_template_parameter &t, - clanguml::model::class_diagram::class_ &parent); + clanguml::class_diagram::model::class_ &parent); void process_friend(const cppast::cpp_friend &t, - clanguml::model::class_diagram::class_ &parent); + clanguml::class_diagram::model::class_ &parent); private: - clanguml::model::class_diagram::class_ build_template_instantiation( + clanguml::class_diagram::model::class_ build_template_instantiation( const cppast::cpp_template_instantiation_type &t, - std::optional parent = {}); + std::optional parent = {}); const cppast::cpp_type &resolve_alias(const cppast::cpp_type &t); diff --git a/tests/test_cases.cc b/tests/test_cases.cc index bde5c0c8..10771830 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -51,7 +51,7 @@ clanguml::model::sequence_diagram::diagram generate_sequence_diagram( return diagram_model; } -clanguml::model::class_diagram::diagram generate_class_diagram( +clanguml::class_diagram::model::diagram generate_class_diagram( cppast::libclang_compilation_database &db, std::shared_ptr diagram) { @@ -78,7 +78,7 @@ std::string generate_sequence_puml( std::string generate_class_puml( std::shared_ptr config, - clanguml::model::class_diagram::diagram &model) + clanguml::class_diagram::model::diagram &model) { using namespace clanguml::generators::class_diagram::puml; diff --git a/tests/test_cases.h b/tests/test_cases.h index ddfd54b3..717795d3 100644 --- a/tests/test_cases.h +++ b/tests/test_cases.h @@ -23,7 +23,7 @@ #include "cx/compilation_database.h" #include "puml/class_diagram_generator.h" #include "puml/sequence_diagram_generator.h" -#include "uml/class_diagram_model.h" +#include "uml/class_diagram/model/diagram.h" #include "uml/class_diagram_visitor.h" #include "uml/sequence_diagram_visitor.h" #include "util/util.h" @@ -52,7 +52,7 @@ clanguml::model::sequence_diagram::diagram generate_sequence_diagram( compilation_database &db, std::shared_ptr diagram); -clanguml::model::class_diagram::diagram generate_class_diagram( +clanguml::class_diagram::model::diagram generate_class_diagram( compilation_database &db, std::shared_ptr diagram); @@ -62,7 +62,7 @@ std::string generate_sequence_puml( std::string generate_class_puml( std::shared_ptr config, - clanguml::model::class_diagram::diagram &model); + clanguml::class_diagram::model::diagram &model); void save_puml(const std::string &path, const std::string &puml);