pax_global_header00006660000000000000000000000064130763515700014521gustar00rootroot0000000000000052 comment=3ca972edaa20d8e54d6e600087f8a01e442c3be0 injeqt-1.2.0/000077500000000000000000000000001307635157000130135ustar00rootroot00000000000000injeqt-1.2.0/.gitignore000066400000000000000000000004141307635157000150020ustar00rootroot00000000000000# Compiled Object files *.slo *.lo *.o *.obj # Compiled Dynamic libraries *.so *.dylib *.dll # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app # Build directory build # Generated documentation docs # KDevelop4 files *.kdev4 .kdev* injeqt-1.2.0/.travis.yml000066400000000000000000000003641307635157000151270ustar00rootroot00000000000000dist: trusty language: cpp before_install: - sudo apt-get update -qq - sudo apt-get install qtbase5-dev-tools qtbase5-dev libqt5core5a cmake script: - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Debug .. - make - make test injeqt-1.2.0/AUTHORS000066400000000000000000000001061307635157000140600ustar00rootroot00000000000000Rafał Przemysław Malinowski injeqt-1.2.0/CMakeLists.txt000066400000000000000000000050731307635157000155600ustar00rootroot00000000000000# # %injeqt copyright begin% # Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) # %injeqt copyright end% # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # project (injeqt) cmake_minimum_required (VERSION 2.8) set (INJEQT_SOVERSION "1") set (INJEQT_VERSION "1.2") option (DISABLE_TESTS "Do not build tests" OFF) option (DISABLE_EXAMPLES "Do not build examples" OFF) find_package (Qt5Core 5.2 REQUIRED) # do not link with qtmain on windows if (POLICY CMP0020) cmake_policy (SET CMP0020 OLD) endif () if (POLICY CMP0043) cmake_policy (SET CMP0043 NEW) endif () set (WARNINGS "-Werror -W -Wall -Wextra -Wundef -Wunused -Wuninitialized -Wcast-align -Wpointer-arith -Woverloaded-virtual -Wnon-virtual-dtor -fno-common") set (VISIBILITY "-fvisibility=hidden -fvisibility-inlines-hidden") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${WARNINGS} ${VISIBILITY}") set (CMAKE_AUTOMOC TRUE) set (CMAKE_INCLUDE_CURRENT_DIR ON) include_directories ( ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src/internal ) add_subdirectory (src) if (NOT DISABLE_EXAMPLES) add_subdirectory (examples) endif (NOT DISABLE_EXAMPLES) if (NOT CMAKE_BUILD_TYPE MATCHES RELEASE AND NOT DISABLE_TESTS) enable_testing () add_subdirectory (test) endif (NOT CMAKE_BUILD_TYPE MATCHES RELEASE AND NOT DISABLE_TESTS) if (NOT DEFINED CMAKE_INSTALL_LIBDIR) set (CMAKE_INSTALL_LIBDIR lib) endif (NOT DEFINED CMAKE_INSTALL_LIBDIR) set (prefix ${CMAKE_INSTALL_PREFIX}) set (exec_prefix ${CMAKE_INSTALL_PREFIX}) set (libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) set (includedir ${CMAKE_INSTALL_PREFIX}/include) set (LIBS "-lQt5Core") configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/injeqt.pc.in ${CMAKE_CURRENT_BINARY_DIR}/injeqt.pc @ONLY ) install (DIRECTORY include/injeqt DESTINATION include ) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/injeqt.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) injeqt-1.2.0/ChangeLog000066400000000000000000000030011307635157000145570ustar00rootroot000000000000002016-07-21 Rafał Przemysław Malinowski * 1.1: released 2016-02-01 Rafał Przemysław Malinowski * 1.1: replaced INJEQT_INSTANCE_* with INJEQT_TYPE_ROLE macros * 1.1: add instantiate_all_with_type_role method to injector 2016-01-30 Rafał Przemysław Malinowski * 1.1: allow for duplicate dependencies 2016-01-07 Rafał Przemysław Malinowski * 1.1: add INJEQT_SET macro as alias to INJEQT_SETTER * 1.1: add INJEQT_INIT methods called after all setters * 1.1: add INJEQT_DONE methods called before injector destruction * 1.1: add INJEQT_INSTANCE_ON_DEMAND macro to mark class as on-demand * 1.1: add INJEQT_INSTANCE_IMMEDIATE macro to mark class as immediate 2015-04-09 Rafał Przemysław Malinowski * 1.1: added subinjectors functionality 2015-03-07 Rafał Przemysław Malinowski * 1.1: added injector::inject_into(QObject *) method 2015-03-07 Rafał Przemysław Malinowski * tests: tests now compile properly on 32bit platforms * 1.0.1: released 2014-12-02 Rafał Przemysław Malinowski * windows: allow windows mingw build * 0.9.1: windows bugfix release 2014-11-23 Rafał Przemysław Malinowski * 0.9.0: initial release injeqt-1.2.0/Doxyfile000066400000000000000000000115521307635157000145250ustar00rootroot00000000000000DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "Injeqt" PROJECT_NUMBER = "0.1" PROJECT_BRIEF = "Dependency injection framework for Qt5" OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ALWAYS_DETAILED_SEC = YES INLINE_INHERITED_MEMB = YES FULL_PATH_NAMES = YES SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 4 MARKDOWN_SUPPORT = YES AUTOLINK_SUPPORT = YES SUBGROUPING = YES LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- SORT_BRIEF_DOCS = YES SORT_MEMBERS_CTORS_1ST = YES SORT_GROUP_NAMES = YES SORT_BY_SCOPE_NAME = YES SHOW_NAMESPACES = YES SHOW_FILES = YES HIDE_IN_BODY_DOCS = YES EXTRACT_ALL = YES EXTRACT_PRIVATE = YES EXTRACT_STATIC = YES HIDE_SCOPE_NAMES = YES #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- RECURSIVE = YES EXCLUDE = EXCLUDE_PATTERNS = */test/* */build/* */examples/* EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = EXAMPLE_RECURSIVE = NO IMAGE_PATH = USE_MDFILE_AS_MAINPAGE = README.md CLANG_ASSISTED_PARSING = YES #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES REFERENCES_LINK_SOURCE = YES SOURCE_TOOLTIPS = YES VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = injeqt injeqt::v1 injeqt::internal #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = docs/html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = YES HTML_DYNAMIC_SECTIONS = NO HTML_INDEX_NUM_ENTRIES = 100 DISABLE_INDEX = NO GENERATE_TREEVIEW = NO ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES #--------------------------------------------------------------------------- # Configuration options related to the Latex output #--------------------------------------------------------------------------- GENERATE_LATEX = NO #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES MSCGEN_PATH = DIA_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = YES DOT_NUM_THREADS = 0 DOT_FONTNAME = Helvetica DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = NO COLLABORATION_GRAPH = NO GROUP_GRAPHS = NO UML_LOOK = YES UML_LIMIT_NUM_FIELDS = 10 TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = NO INCLUDED_BY_GRAPH = NO CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = NO DIRECTORY_GRAPH = NO DOT_IMAGE_FORMAT = svg INTERACTIVE_SVG = NO DOTFILE_DIRS = MSCFILE_DIRS = DIAFILE_DIRS = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = YES DOT_MULTI_TARGETS = YES GENERATE_LEGEND = YES DOT_CLEANUP = YES injeqt-1.2.0/LICENSE000066400000000000000000000635121307635157000140270ustar00rootroot00000000000000GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. (This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.) Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {description} Copyright (C) {year} {fullname} This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. {signature of Ty Coon}, 1 April 1990 Ty Coon, President of Vice That's all there is to it!injeqt-1.2.0/README.md000066400000000000000000000103121307635157000142670ustar00rootroot00000000000000injeqt ====== Simple dependency injection framework for Qt Documentation ------------- Documentation available at [github](https://github.com/vogel/injeqt/wiki). Example ------- Here is example of what can be done using injeqt: #include #include #include #include #include #include class hello_service : public QObject { Q_OBJECT public: hello_service() {} virtual ~hello_service() {} std::string say_hello() const { return {"Hello"}; } }; class world_service : public QObject { Q_OBJECT public: world_service() {} virtual ~world_service() {} std::string say_world() const { return {"World"}; } }; class hello_factory : public QObject { Q_OBJECT public: Q_INVOKABLE hello_factory() {} virtual ~hello_factory() {} Q_INVOKABLE hello_service * create_service() { return new hello_service{}; } }; class hello_client : public QObject { Q_OBJECT public: Q_INVOKABLE hello_client() : _s{nullptr}, _w{nullptr} {} virtual ~hello_client() {} std::string say() const { return _s->say_hello() + " " + _w->say_world() + "!"; } private slots: INJEQT_INIT void init() { std::cerr << "all services set" << std::endl; } INJEQT_DONE void done() { std::cerr << "ready for destruction" << std::endl; } INJEQT_SET void set_hello_service(hello_service *s) { _s = s; } INJEQT_SET void set_world_service(world_service *w) { _w = w; } private: hello_service *_s; world_service *_w; }; class module : public injeqt::module { public: explicit module() { _w = std::unique_ptr{new world_service{}}; add_type(); add_type(); add_factory(); add_ready_object(_w.get()); } virtual ~module() {} private: std::unique_ptr _w; }; int main() { auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new module{}}); auto injector = injeqt::injector{std::move(modules)}; auto client = injector.get(); auto hello = client->say(); std::cout << hello << std::endl; } #include "hello-world.moc" In that example we can see two main services names `hello_service` and `world_service`. There is also client of these names `hello_client`. In `module` class we configure how we create and access these instances. `hello_client` is added using `add_type` function. It means that injeqt will try to create it using default constructor. We provide that by declaration of `Q_INVOKABLE hello_client()` (`Q_INVOKABLE` is requires by Qt's meta object system). `hello_service` is added using `add_factory` function. It means that injeqt will first try to create a `hello_factory` object, then it will look for a method of that objet that returns `hello_service` object. It will find `Q_INVOKABLE hello_service * create_service()` and use it. To be able to create `hello_factory` injeqt must know about it, so we also add it using `add_type` method. Last, `world_service`, is added as a ready object - provided from outside of injeqt scope. In `main` method list of conifguration modules are passed to newly created `injector` instance. From that moment, we can use `injector` to create and manage our services. Just one line below an `hello_client` instance is required. This is what happens next: * injeqt looks for dependencies of `hello_client` and found that it first needs to create `hello_factory` * injeqt creates `hello_factory` without problems, as it does not have dependencies of its own * injeqt adds new instance to object pool * injeqt calls `hello_factory::create_service()` methods and ads its result to object pool * now all dependencies of `hello_client` are available, so new instance of it is created with default constructor and its added to objec tpool * all methods of `hello_client` marked with `INJEQT_SET` are called with proper objects from pool * all methods of `hello_client` marked with `INJEQT_INIT` are called * this instance is returned to caller * before injector is destructed, all methods of `hello_client` marked with `INJEQT_DONE` are called injeqt-1.2.0/examples/000077500000000000000000000000001307635157000146315ustar00rootroot00000000000000injeqt-1.2.0/examples/CMakeLists.txt000066400000000000000000000026571307635157000174030ustar00rootroot00000000000000# # %injeqt copyright begin% # Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) # %injeqt copyright end% # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # find_package(Qt5Test 5.2 REQUIRED) include_directories( ${CMAKE_SOURCE_DIR}/src ) function (injeqt_add_example name_) file (RELATIVE_PATH sourcePath "${CMAKE_SOURCE_DIR}/examples" "${CMAKE_CURRENT_SOURCE_DIR}") get_filename_component (exeDir "${CMAKE_CURRENT_BINARY_DIR}/${name_}" PATH) file (MAKE_DIRECTORY "${exeDir}") add_executable (${name_} ${ARGN}) target_link_libraries (${name_} injeqt) set_property (TARGET ${name_} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-error") qt5_use_modules (${name_} Core) endfunction () injeqt_add_example(hello-world-example hello-world.cpp) injeqt-1.2.0/examples/hello-world.cpp000066400000000000000000000054661307635157000176000ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include class hello_service : public QObject { Q_OBJECT public: hello_service() {} virtual ~hello_service() {} std::string say_hello() const { return {"Hello"}; } }; class world_service : public QObject { Q_OBJECT public: world_service() {} virtual ~world_service() {} std::string say_world() const { return {"World"}; } }; class hello_factory : public QObject { Q_OBJECT public: Q_INVOKABLE hello_factory() {} virtual ~hello_factory() {} Q_INVOKABLE hello_service * create_service() { return new hello_service{}; } }; class hello_client : public QObject { Q_OBJECT public: Q_INVOKABLE hello_client() : _s{nullptr}, _w{nullptr} {} virtual ~hello_client() {} std::string say() const { return _s->say_hello() + " " + _w->say_world() + "!"; } private slots: INJEQT_INIT void init() { std::cerr << "all services set" << std::endl; } INJEQT_DONE void done() { std::cerr << "ready for destruction" << std::endl; } INJEQT_SET void set_hello_service(hello_service *s) { _s = s; } INJEQT_SET void set_world_service(world_service *w) { _w = w; } private: hello_service *_s; world_service *_w; }; class module : public injeqt::module { public: explicit module() { _w = std::unique_ptr{new world_service{}}; add_type(); add_type(); add_factory(); add_ready_object(_w.get()); } virtual ~module() {} private: std::unique_ptr _w; }; int main() { auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new module{}}); auto injector = injeqt::injector{std::move(modules)}; auto client = injector.get(); auto hello = client->say(); std::cout << hello << std::endl; } #include "hello-world.moc" injeqt-1.2.0/include/000077500000000000000000000000001307635157000144365ustar00rootroot00000000000000injeqt-1.2.0/include/injeqt/000077500000000000000000000000001307635157000157305ustar00rootroot00000000000000injeqt-1.2.0/include/injeqt/exception/000077500000000000000000000000001307635157000177265ustar00rootroot00000000000000injeqt-1.2.0/include/injeqt/exception/ambiguous-types.h000066400000000000000000000025161307635157000232400ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when some ambiguous types were configured in injector * @todo check what happens when typeA: typeP and typeB: typeP are configured, but some dependency requires typeP */ class INJEQT_API ambiguous_types : public exception { public: explicit ambiguous_types(std::string what = std::string{}); virtual ~ambiguous_types(); }; }}} injeqt-1.2.0/include/injeqt/exception/default-constructor-not-found.h000066400000000000000000000024621307635157000260210ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when type without default constructor tagged with Q_INVOKABLE was passed to module::add_type() */ class INJEQT_API default_constructor_not_found : public exception { public: explicit default_constructor_not_found(std::string what = std::string{}); virtual ~default_constructor_not_found(); }; }}} injeqt-1.2.0/include/injeqt/exception/dependency-duplicated.h000066400000000000000000000023771307635157000243420ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception is not thrown in Injeqt 1.1. * @todo Remove in Injeqt 2.0 */ class INJEQT_API dependency_duplicated : public invalid_dependency { public: explicit dependency_duplicated(std::string what = std::string{}); virtual ~dependency_duplicated(); }; }}} injeqt-1.2.0/include/injeqt/exception/dependency-on-self.h000066400000000000000000000023371307635157000235630ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when a type depends on itself */ class INJEQT_API dependency_on_self : public invalid_dependency { public: explicit dependency_on_self(std::string what = std::string{}); virtual ~dependency_on_self(); }; }}} injeqt-1.2.0/include/injeqt/exception/dependency-on-subtype.h000066400000000000000000000023551307635157000243250ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when a type depends on own subtype */ class INJEQT_API dependency_on_subtype : public invalid_dependency { public: explicit dependency_on_subtype(std::string what = std::string{}); virtual ~dependency_on_subtype(); }; }}} injeqt-1.2.0/include/injeqt/exception/dependency-on-supertype.h000066400000000000000000000023651307635157000246730ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when a type depends on own supertype */ class INJEQT_API dependency_on_supertype : public invalid_dependency { public: explicit dependency_on_supertype(std::string what = std::string{}); virtual ~dependency_on_supertype(); }; }}} injeqt-1.2.0/include/injeqt/exception/empty-type.h000066400000000000000000000023131307635157000222130ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when an empty type object was passed to a function. */ class INJEQT_API empty_type : public exception { public: explicit empty_type(std::string what = std::string{}); virtual ~empty_type(); }; }}} injeqt-1.2.0/include/injeqt/exception/exception.h000066400000000000000000000023471307635157000221030ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include namespace injeqt { namespace v1 { namespace exception { class INJEQT_API exception : public std::exception { public: explicit exception(std::string what = std::string{}); virtual ~exception(); virtual const char * what() const noexcept override; private: std::string _what; }; }}} injeqt-1.2.0/include/injeqt/exception/instantiation-failed.h000066400000000000000000000023321307635157000242050ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when instantiation of a type failed. */ class INJEQT_API instantiation_failed : public exception { public: explicit instantiation_failed(std::string what = std::string{}); virtual ~instantiation_failed(); }; }}} injeqt-1.2.0/include/injeqt/exception/interface-not-implemented.h000066400000000000000000000024171307635157000251420ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when a QObject that does not implement specified was passed to a function. */ class INJEQT_API interface_not_implemented : public exception { public: explicit interface_not_implemented(std::string what = std::string{}); virtual ~interface_not_implemented(); }; }}} injeqt-1.2.0/include/injeqt/exception/invalid-action.h000066400000000000000000000024201307635157000227760ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when action with bad number of arguments or with bad argument was found with INJEQT_INIT or INJEQT_DONE tag. */ class INJEQT_API invalid_action : public exception { public: explicit invalid_action(std::string what = std::string{}); virtual ~invalid_action(); }; }}} injeqt-1.2.0/include/injeqt/exception/invalid-dependency.h000066400000000000000000000023241307635157000236420ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when an invalid dependency is found. */ class INJEQT_API invalid_dependency : public exception { public: explicit invalid_dependency(std::string what = std::string{}); virtual ~invalid_dependency(); }; }}} injeqt-1.2.0/include/injeqt/exception/invalid-qobject.h000066400000000000000000000023301307635157000231500ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when an invalid QObject was passed to a function. */ class INJEQT_API invalid_qobject : public exception { public: explicit invalid_qobject(std::string what = std::string{}); virtual ~invalid_qobject(); }; }}} injeqt-1.2.0/include/injeqt/exception/invalid-setter.h000066400000000000000000000024001307635157000230250ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when setter with bad number of arguments or with bad argument was found with INJEQT_SET tag. */ class INJEQT_API invalid_setter : public exception { public: explicit invalid_setter(std::string what = std::string{}); virtual ~invalid_setter(); }; }}} injeqt-1.2.0/include/injeqt/exception/qobject-type.h000066400000000000000000000023221307635157000225040ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when a qobject type object was passed to a function. */ class INJEQT_API qobject_type : public exception { public: explicit qobject_type(std::string what = std::string{}); virtual ~qobject_type(); }; }}} injeqt-1.2.0/include/injeqt/exception/unavailable-required-types.h000066400000000000000000000024241307635157000253440ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when an injector is configured with provider that requires unavailable type. */ class INJEQT_API unavailable_required_types : public exception { public: explicit unavailable_required_types(std::string what = std::string{}); virtual ~unavailable_required_types(); }; }}} injeqt-1.2.0/include/injeqt/exception/unique-factory-method-not-found.h000066400000000000000000000024621307635157000262430ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception thrown when type F does not have unique factory method for T in module::add_factory() call. */ class INJEQT_API unique_factory_method_not_found : public exception { public: explicit unique_factory_method_not_found(std::string what = std::string{}); virtual ~unique_factory_method_not_found(); }; }}} injeqt-1.2.0/include/injeqt/exception/unknown-type.h000066400000000000000000000023331307635157000225560ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when type that was not configured was requested from injector */ class INJEQT_API unknown_type : public exception { public: explicit unknown_type(std::string what = std::string{}); virtual ~unknown_type(); }; }}} injeqt-1.2.0/include/injeqt/exception/unresolvable-dependencies.h000066400000000000000000000024041307635157000252240ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace injeqt { namespace v1 { namespace exception { /** * @brief Exception throw when injector is configured with some dependnecies unresolable. */ class INJEQT_API unresolvable_dependencies : public exception { public: explicit unresolvable_dependencies(std::string what = std::string{}); virtual ~unresolvable_dependencies(); }; }}} injeqt-1.2.0/include/injeqt/injector.h000066400000000000000000000233521307635157000177230ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include #include #include /** * @file * @brief Contains classes and functions for creating injectors. */ namespace injeqt { namespace internal { class injector_impl; }} namespace injeqt { namespace v1 { class module; /** * @brief Injector is created from set of modules that contains injectable types. * * Injector is constructed from set of modules that contains groups of related types. * Then it can be used to get instances of configured types that have their dependencies * resolved and set - there is no need to manually wire services and factories. * * If two or more modules have the same type configured an exception is thrown during construction. * Otherwise, from all types in modules a set of available types is computed. Each type directly * added to modules is added to it. Then all unique super types are added to this set. This means * that two types with common ancestor can be used in injection. Note that Qt meta object system * only supports single inheritance. * * Injector takes ownership of modules passed to it. Also all objects created inside injector * (using default constructor - configured with module::add_type(), or factory - configured * with module::add_factory()) are under its ownership. Lifetime of objects added as ready * objects (configured with module::add_ready_object(QObject *) is not managed by injector. * For clarity ready objects can be stored in module instances as unique pointers. Injector will own * then as it own modules. */ class INJEQT_API injector final { public: /** * @brief Create empty injector with no types configured. * * Empty injector will not be able to produce any object of any type. */ injector(); /** * @brief Create new injector from provided modules. * @param modules list of modules * @throw ambiguous_types if one or more types in @p modules is ambiguous * @throw unresolvable_dependencies if a type with unresolvable dependency is found in @p modules * @throw dependency_on_self when type depends on self * @throw dependency_on_subtype when type depends on own supertype * @throw dependency_on_subtype when type depends on own subtype * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has other number of parameters than one * * Creates injector with all types from modules configured. If combined configuration * of all modules is invalid an exception is thrown. Configuration is invalid when: * * any type is configured in more than one module * * a dependency exists with type that is non configured in any module * * a cycle of factories is found (currently does not throw an exception) */ explicit injector(std::vector> modules); /** * @brief Create new injector from provided modules with set of parent injectors. * @param super_injectors list of injectors providing types for this one to use * @param modules list of modules * @throw ambiguous_types if one or more types in @p modules is ambiguous * @throw unresolvable_dependencies if a type with unresolvable dependency is found in @p modules * @throw dependency_on_self when type depends on self * @throw dependency_on_subtype when type depends on own supertype * @throw dependency_on_subtype when type depends on own subtype * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has other number of parameters than one * * Creates injector with all types from modules configured. Also a virtual module consisting of all * provided types from @p super_injectors is added to module set. If combined configuration * of all modules is invalid an exception is thrown. Configuration is invalid when: * * any type is configured in more than one module * * a dependency exists with type that is non configured in any module * * a cycle of factories is found (currently does not throw an exception) */ explicit injector(std::vector super_injectors, std::vector> modules); injector(injector &&x); ~injector(); injector & operator = (injector &&x); /** * @brief Instantiates object of given type @tparam T * @tparam T type of object to instantiate * @throw unknown_type if @@tparam T was not configured in injector * @throw instantiation_failed if instantiation of one of required types failed * * When object of given type is instantiated by instantiate() method, injector first check if T is in set of * available types. If not, an exception is thrown. Next an unique configured type U that implements T * is found. If object of type U was already created, method returns. If not, it is created with all * dependencies it requires. Depending on configuration of U it can be created directly by U default * constructor or it can be created by factory that is assigned to that type (note: injector will * create itself all required factories with the same alghoritm). After U with all its dependencies * is created all dependency setters are called with proper arguments. Then U object is added to cache. */ template void instantiate() { instantiate(make_type()); } /** * @brief Returns pointer to object of given type T. * @tparam T type of object to return * @throw qobject_type if T is QObject * @throw unknown_type if @p interface_type was not configured in injector * @throw instantiation_failed if instantiation of one of required types failed * * When object of given type is requested by get<T>() method, injector first check if T is in set of * available types. If not, an exception is thrown. Next an unique configured type U that implements T * is found. If object of type U was already created, it is returned. If not, it is created with all * dependencies it requires. Depending on configuration of U it can be created directly by U default * constructor or it can be created by factory that is assigned to that type (note: injector will * create itself all required factories with the same alghoritm). After U with all its dependencies * is created all dependency setters are called with proper arguments. Then U object is added to cache * and is itself returned. */ template T * get() { return qobject_cast(get(make_type())); } /** * @brief Returns all objects with given @p type_role. * @throw instantiation_failed if instantiation of one of found types failed */ std::vector get_all_with_type_role(const std::string &type_role); /** * @brief Instantiates object of given type @p interface_type * @param interface_type type of object to return * @throw empty_type if interface_type is empty * @throw qobject_type if interface_type represents QObject * @throw unknown_type if @p interface_type was not configured in injector * @throw instantiation_failed if instantiation of one of required types failed */ void instantiate(const type &interface_type); /** * @brief Instantiate all objects with given @p type_role. * @throw instantiation_failed if instantiation of one of found types failed */ void instantiate_all_with_type_role(const std::string &type_role); /** * @brief Returns pointer to object of given type interface_type. * @param interface_type type of object to return * @throw empty_type if interface_type is empty * @throw qobject_type if interface_type represents QObject * @throw unknown_type if @p interface_type was not configured in injector * @throw instantiation_failed if instantiation of one of required types failed * * @see T * get() */ QObject * get(const type &interface_type); /** * @brief Inject dependencies into @p object. * @param object object to inject dependencies into. * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject-derived pointer of not configured type * @throw invalid_setter if any tagged setter has other number of parameters than one * @pre object != nullptr * * This method looks for invokable setters tagged with INJEQT_SET in @p object. If any of setter is not valid * dependency injector setter or its parameter is of type not configured in injector an exception is thrown. * If all setters are valid, they are called with proper objects (which may be already available in injector * or created on demand). */ void inject_into(QObject *object); private: std::unique_ptr _pimpl; }; }} injeqt-1.2.0/include/injeqt/injeqt.h000066400000000000000000000025401307635157000173740ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #ifdef injeqt_EXPORTS #define INJEQT_API Q_DECL_EXPORT #else #define INJEQT_API Q_DECL_IMPORT #endif #ifndef Q_MOC_RUN # define INJEQT_INIT # define INJEQT_DONE # define INJEQT_SET // depreceated, use INJEQT_SET instead # define INJEQT_SETTER #endif #define INJEQT_TYPE_ROLE_CLASSINFO_NAME "injeqt.type-role" #define INJEQT_TYPE_ROLE(N) Q_CLASSINFO(INJEQT_TYPE_ROLE_CLASSINFO_NAME, N) namespace injeqt { namespace v1 { } using namespace v1; } injeqt-1.2.0/include/injeqt/module.h000066400000000000000000000215011307635157000173650ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include /** * @file * @brief Contains classes and functions for creating modules. */ namespace injeqt { namespace internal { class injector_impl; class module_impl; }} namespace injeqt { namespace v1 { /** * @brief Module represents set of types and objects that can be injected and that can use injections. * * Injector is normally constructed from set of modules, each one contains * group of related types. * * Modules are move-only types and cannot by copied. * * To add a module to system one must inherit from it and configure it in constructor and * then pass instance of it to created injector class. * * Set of types in given module does not have to fully satify each one dependencies - it * is only required for a group of modules passed into injector. * * Module configuration is done by calling any of add_* method. Currently implemnted are: * add_ready_object, add_type, add_factory. */ class INJEQT_API module { public: module(); virtual ~module(); protected: /** * @brief Add already constructed object to module. * @tparam T type of added object (must be inherited from QObject). * @param object added object * @throw qobject_type when passed type @p T represents QObject * @throw invalid_qobject when passed @p object is nullptr or does not have valid QMetaObject * @throw interface_not_implemented when passed @p object does not implements type @p T * * It has to be fully constructed and must not expect any injection to take place on it * (even if it has INJEQT_SET methods). However this object could be injected into other * ones as it if is of type T. * * Real type of object must be same as T or descend from it. In other cases an exception * will be thrown. * * Module class does not take ownership of this object. Either subclass of module must do * it in any way or calee must ensure that object will be destroyed after module is destroyed. * * Example usage: * * class injectable : public QObject * { * Q_OBJECT * }; * * class ready_module : public module * { * ready_module() * { * _ready_object = std::make_unique(); * add_ready_object(_ready_object.get()); * } * }; * * class ready_module2 : public module * { * ready_module2(injectable *ready_object) * { * add_ready_object(ready_object); * } * }; * * In second example responsibility for ready_object's lifetime lies on ready_module2 object * creator. * * When injector object is created with any of these modules this code will lead to return * the same object thas was passed to add_ready_object method: * * auto o = injector.get(); */ template void add_ready_object(QObject *object) { add_ready_object(make_type(), object); } /** * @brief Add type that can be default-constructed to module. * @tparam T type added to module (must be inherited from QObject). * @throw qobject_type when passed type @p T represents QObject * @throw default_constructor_not_found is @p T does not have default constructor tagged with Q_INVOKABLE * * When an object of that type (or one of inherited types) is requested from injector or * as a dependency to other objects then default constructor of T is invoked to create it. * This constructor must be marked with Q_INVOKABLE macro and must not have any parameters * (even with default values). In other cases this method will throw an exception. * * After object of type T is created it will be injected will all required dependencies * and it will remain in cache until owning injector object exists. Onle one instance of * T will exist at one time inside injector (this may change when in future scope abstraction * will be added to library, but it won't affect default behavior). Injector takes ownership * of created T object. * * Example usage: * * class injectable : public QObject * { * Q_OBJECT * public: * Q_INVOKABLE injectable() {} * }; * * class type_module : public module * { * type_module() * { * add_type(); * } * }; * * When injector object is created with that modules this code will lead to creation of new object * of type injectable (for o1) and return it and (for o2) to return it again. * * auto o1 = injector.get(); * auto o2 = injector.get(); */ template void add_type() { add_type(make_type()); } /** * @brief Add type that can be created by factory to module. * @tparam T type added to module (must be inherited from QObject). * @tparam F factory type (must be inherited from QObject). * @throw qobject_type when passed type @p T represents QObject * @throw qobject_type when passed type @p F represents QObject * @throw unique_factory_method_not_found when type F does not have unique factory method for T * * When an object of that type (or one of inherited types) is requested from injector or * as a dependency to other objects then object of type F is requted first and its method * returning pointer to T* and not accepting any arguments if called to create T object. * Type F must be registered in any of injector modules. * * Type F must contain exactly one method marked with Q_INVOKABLE macro that returns object * of type T* and does not have any arguments. In other case an exception will be thrown. * Qt meta-object system unfortunately does not allow us to require returned type to be * std::unique_ptr which would make object ownership clear in code. * * After object of type T is created it will be injected will all required dependencies * and it will remain in cache until owning injector object exists. Onle one instance of * T will exist at one time inside injector (this may change when in future scope abstraction * will be added to library, but it won't affect default behavior). Injector takes ownership * of created T object. * * Example usage: * * class injectable : public QObject * { * Q_OBJECT * public: * injectable(int arg) { (void)arg; } * }; * * class injectable_factory : public QObject * { * Q_OBJECT * public: * Q_INVOKABLE injectable_factory() {} * Q_INVOKABLE injectable * create() * { return new injectable{2}; } * }; * * class type_module : public module * { * type_module() * { * add_type(); * add_factory(); * } * }; * * Note that injectable constructor does not have to be maked with Q_INVOKABLE. Also note that * injectable_factory had to be added itself to module (it could be added in another module * that would have to be included into final injector). * * When injector object is created with that modules this code will lead to creation of new object * of type injectable_factory (for o1) and then in call of injectable_factory::create(). Second line * will lead to return of cached object (the same as o1) without any additional calls. * * auto o1 = injector.get(); * auto o2 = injector.get(); */ template void add_factory() { add_factory(make_type(), make_type()); } private: friend class ::injeqt::internal::injector_impl; std::unique_ptr _pimpl; /** * @see add_ready_object(QObject *); * @pre !t.is_empty() */ void add_ready_object(type t, QObject *object); /** * @see add_type(); * @pre !t.is_empty() */ void add_type(type t); /** * @see add_factory(); * @pre !t.is_empty() * @pre !f.is_empty() */ void add_factory(type t, type f); }; }} injeqt-1.2.0/include/injeqt/type.h000066400000000000000000000076351307635157000170750ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include /** * @file * @brief Contains classes and functions for abstractions of C++ types. */ class QMetaObject; class QObject; /** * @brief */ namespace injeqt { /** * @brief */ namespace v1 { /** * @brief Abstraction of C++ type. * * Represents a C++ type. Currently only types inheriting from QObject class can * be represented. Type can be empty if created with default constructor or if * passed QMetaObject is nullptr - use is_empty() to check for that. Type can be * also qobject if passed QMetaObject designates QObject - use is_qobject() to check * for that. Most Injeqt code requires type that is !is_empty() && !is_qobject(). * * Direct instantiations of this class should not be needed in user code. * * Use convienance free function make_type<T> that also registers type T * in Qt meta-type that is required for Injeqt to function properly. * * Type name can be retrieived by name() member. Original QMetaObject can be read * using meta_object() member. * * Behavior for all methods is undefined if theirs preconditions are not met. */ class INJEQT_API type final { public: /** * @brief Create empty type */ type(); /** * @param meta_object QMetaObject representing QObject-based type.
* New object does not take ownership of meta_object. QMetaObject * pointers in Qt are usually pointers to static members. * * Create new type instance. If passed meta_object is nullptr or designates * QObject class, then new type is invalid. */ explicit type(const QMetaObject * meta_object); /** * @return true, if type is empty */ bool is_empty() const; /** * @pre !is_empty() * @return true, if type is qobject */ bool is_qobject() const; /** * @pre !is_empty() * @return unique name of type */ std::string name() const; /** * Return base QMetaObject type. If type is not valid, result may be nullptr. */ const QMetaObject * meta_object() const; private: const QMetaObject * _meta_object; }; INJEQT_API bool operator == (const type &x, const type &y); INJEQT_API bool operator != (const type &x, const type &y); INJEQT_API bool operator < (const type &x, const type &y); INJEQT_API bool operator > (const type &x, const type &y); INJEQT_API bool operator <= (const type &x, const type &y); INJEQT_API bool operator >= (const type &x, const type &y); /** * @brief Create instance of type class. * @tparam T type to be represented by new object * * Call to create type object abstracting T. If T is not a class based on * QObject with Q_OBJECT macro defined the result object is invalid. * * This function registers T in Qt meta type systems, because sometimes automatic * registration does not occur as soon as it is required by Injeqt. * * Example usage: * * class injectable : public QObject * { * Q_OBJECT * }; * * auto injectable_type = make_type(); */ template inline type make_type() { return type{&T::staticMetaObject}; } } } injeqt-1.2.0/injeqt.pc.in000066400000000000000000000004201307635157000152320ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: injeqt Description: Dependency injection library for Qt5 Version: @INJEQT_VERSION@ Libs: -L${libdir} -linjeqt@INJEQT_MAJOR@@INJEQT_MINOR@ Libs.private: @LIBS@ Cflags: -I${includedir} injeqt-1.2.0/src/000077500000000000000000000000001307635157000136025ustar00rootroot00000000000000injeqt-1.2.0/src/CMakeLists.txt000066400000000000000000000066541307635157000163550ustar00rootroot00000000000000# # %injeqt copyright begin% # Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) # %injeqt copyright end% # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # set (INJEQT_SRCS injector.cpp module.cpp type.cpp exception/ambiguous-types.cpp exception/default-constructor-not-found.cpp exception/dependency-duplicated.cpp exception/dependency-on-self.cpp exception/dependency-on-subtype.cpp exception/dependency-on-supertype.cpp exception/empty-type.cpp exception/exception.cpp exception/instantiation-failed.cpp exception/interface-not-implemented.cpp exception/invalid-action.cpp exception/invalid-dependency.cpp exception/invalid-qobject.cpp exception/invalid-setter.cpp exception/qobject-type.cpp exception/unavailable-required-types.cpp exception/unknown-type.cpp exception/unique-factory-method-not-found.cpp exception/unresolvable-dependencies.cpp internal/action-method.cpp internal/default-constructor-method.cpp internal/dependencies.cpp internal/dependency.cpp internal/factory-method.cpp internal/implementation.cpp internal/implemented-by.cpp internal/injector-core.cpp internal/injector-impl.cpp internal/interfaces-utils.cpp internal/module-impl.cpp internal/provided-object.cpp internal/provider-by-default-constructor.cpp internal/provider-by-default-constructor-configuration.cpp internal/provider-by-factory.cpp internal/provider-by-factory-configuration.cpp internal/provider-by-parent-injector.cpp internal/provider-by-parent-injector-configuration.cpp internal/provider-ready.cpp internal/provider-ready-configuration.cpp internal/required-to-satisfy.cpp internal/resolved-dependency.cpp internal/resolve-dependencies.cpp internal/setter-method.cpp internal/type-dependencies.cpp internal/type-relations.cpp internal/type-role.cpp internal/types-by-name.cpp internal/types-model.cpp ) add_definitions (-Dinjeqt_EXPORTS) if (NOT CMAKE_BUILD_TYPE MATCHES RELEASE AND NOT DISABLE_TESTS) add_definitions (-Dinjeqt_INTERNAL_EXPORTS) if (NOT DISABLE_COVERAGE) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fprofile-arcs -ftest-coverage -O0") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fprofile-arcs -ftest-coverage -O0") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -O0") endif (NOT DISABLE_COVERAGE) endif (NOT CMAKE_BUILD_TYPE MATCHES RELEASE AND NOT DISABLE_TESTS) add_library ( injeqt SHARED ${INJEQT_SRCS} ) qt5_use_modules (injeqt LINK_PUBLIC Core ) set_target_properties (injeqt PROPERTIES SOVERSION "${INJEQT_SOVERSION}" VERSION "${INJEQT_VERSION}" ) if (NOT WIN32) include (GNUInstallDirs) endif () install (TARGETS injeqt RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) injeqt-1.2.0/src/exception/000077500000000000000000000000001307635157000156005ustar00rootroot00000000000000injeqt-1.2.0/src/exception/ambiguous-types.cpp000066400000000000000000000021351307635157000214420ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { ambiguous_types::ambiguous_types(std::string what) : exception{std::move(what)} { } ambiguous_types::~ambiguous_types() { } }}} injeqt-1.2.0/src/exception/default-constructor-not-found.cpp000066400000000000000000000022431307635157000242230ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { default_constructor_not_found::default_constructor_not_found(std::string what) : exception{std::move(what)} { } default_constructor_not_found::~default_constructor_not_found() { } }}} injeqt-1.2.0/src/exception/dependency-duplicated.cpp000066400000000000000000000022041307635157000225340ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { dependency_duplicated::dependency_duplicated(std::string what) : invalid_dependency{std::move(what)} { } dependency_duplicated::~dependency_duplicated() { } }}} injeqt-1.2.0/src/exception/dependency-on-self.cpp000066400000000000000000000021651307635157000217670ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { dependency_on_self::dependency_on_self(std::string what) : invalid_dependency{std::move(what)} { } dependency_on_self::~dependency_on_self() { } }}} injeqt-1.2.0/src/exception/dependency-on-subtype.cpp000066400000000000000000000022041307635157000225230ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { dependency_on_subtype::dependency_on_subtype(std::string what) : invalid_dependency{std::move(what)} { } dependency_on_subtype::~dependency_on_subtype() { } }}} injeqt-1.2.0/src/exception/dependency-on-supertype.cpp000066400000000000000000000022161307635157000230730ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { dependency_on_supertype::dependency_on_supertype(std::string what) : invalid_dependency{std::move(what)} { } dependency_on_supertype::~dependency_on_supertype() { } }}} injeqt-1.2.0/src/exception/empty-type.cpp000066400000000000000000000021041307635157000204160ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { empty_type::empty_type(std::string what) : exception{std::move(what)} { } empty_type::~empty_type() { } }}} injeqt-1.2.0/src/exception/exception.cpp000066400000000000000000000022051307635157000203010ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { exception::exception(std::string what) : _what{std::move(what)} { } exception::~exception() { } const char * exception::what() const noexcept { return _what.c_str(); } }}} injeqt-1.2.0/src/exception/instantiation-failed.cpp000066400000000000000000000021661307635157000224170ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { instantiation_failed::instantiation_failed(std::string what) : exception{std::move(what)} { } instantiation_failed::~instantiation_failed() { } }}} injeqt-1.2.0/src/exception/interface-not-implemented.cpp000066400000000000000000000022171307635157000233450ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { interface_not_implemented::interface_not_implemented(std::string what) : exception{std::move(what)} { } interface_not_implemented::~interface_not_implemented() { } }}} injeqt-1.2.0/src/exception/invalid-action.cpp000066400000000000000000000021301307635157000212010ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { invalid_action::invalid_action(std::string what) : exception{std::move(what)} { } invalid_action::~invalid_action() { } }}} injeqt-1.2.0/src/exception/invalid-dependency.cpp000066400000000000000000000021541307635157000220500ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { invalid_dependency::invalid_dependency(std::string what) : exception{std::move(what)} { } invalid_dependency::~invalid_dependency() { } }}} injeqt-1.2.0/src/exception/invalid-qobject.cpp000066400000000000000000000021351307635157000213600ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { invalid_qobject::invalid_qobject(std::string what) : exception{std::move(what)} { } invalid_qobject::~invalid_qobject() { } }}} injeqt-1.2.0/src/exception/invalid-setter.cpp000066400000000000000000000021301307635157000212320ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { invalid_setter::invalid_setter(std::string what) : exception{std::move(what)} { } invalid_setter::~invalid_setter() { } }}} injeqt-1.2.0/src/exception/qobject-type.cpp000066400000000000000000000021161307635157000207120ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { qobject_type::qobject_type(std::string what) : exception{std::move(what)} { } qobject_type::~qobject_type() { } }}} injeqt-1.2.0/src/exception/unavailable-required-types.cpp000066400000000000000000000022241307635157000235470ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { unavailable_required_types::unavailable_required_types(std::string what) : exception{std::move(what)} { } unavailable_required_types::~unavailable_required_types() { } }}} injeqt-1.2.0/src/exception/unique-factory-method-not-found.cpp000066400000000000000000000022551307635157000244500ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { unique_factory_method_not_found::unique_factory_method_not_found(std::string what) : exception{std::move(what)} { } unique_factory_method_not_found::~unique_factory_method_not_found() { } }}} injeqt-1.2.0/src/exception/unknown-type.cpp000066400000000000000000000021161307635157000207620ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { unknown_type::unknown_type(std::string what) : exception{std::move(what)} { } unknown_type::~unknown_type() { } }}} injeqt-1.2.0/src/exception/unresolvable-dependencies.cpp000066400000000000000000000022171307635157000234330ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace injeqt { namespace v1 { namespace exception { unresolvable_dependencies::unresolvable_dependencies(std::string what) : exception{std::move(what)} { } unresolvable_dependencies::~unresolvable_dependencies() { } }}} injeqt-1.2.0/src/injector.cpp000066400000000000000000000052651307635157000161330ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include "containers.h" #include "injector-impl.h" #include "module-impl.h" #include "provider.h" #include using namespace injeqt::internal; namespace injeqt { namespace v1 { injector::injector() : _pimpl{new ::injeqt::internal::injector_impl{}} { } injector::injector(std::vector> modules) : _pimpl{new ::injeqt::internal::injector_impl{std::move(modules)}} { } injector::injector(std::vector super_injectors, std::vector> modules) { auto extract_impl = std::function([](injector *i){ return i->_pimpl.get(); }); _pimpl.reset(new ::injeqt::internal::injector_impl{transform(super_injectors, extract_impl), std::move(modules)}); } injector::injector(injector &&x) : _pimpl{std::move(x._pimpl)} { } injector::~injector() { } injector & injector::operator = (injector &&x) { _pimpl = std::move(x._pimpl); return *this; } void injector::instantiate(const type &interface_type) { assert(!interface_type.is_empty()); if (interface_type.is_qobject()) throw exception::qobject_type{}; _pimpl->instantiate(interface_type); } void injector::instantiate_all_with_type_role(const std::string &type_role) { _pimpl->instantiate_all_with_type_role(type_role); } QObject * injector::get(const type &interface_type) { assert(!interface_type.is_empty()); if (interface_type.is_qobject()) throw exception::qobject_type{}; return _pimpl->get(interface_type); } std::vector injector::get_all_with_type_role(const std::string &type_role) { return _pimpl->get_all_with_type_role(type_role); } void injector::inject_into(QObject *object) { assert(object); _pimpl->inject_into(object); } }} injeqt-1.2.0/src/internal/000077500000000000000000000000001307635157000154165ustar00rootroot00000000000000injeqt-1.2.0/src/internal/action-method.cpp000066400000000000000000000072031307635157000206570ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "action-method.h" #include #include #include "internal/interfaces-utils.h" #include namespace injeqt { namespace internal { bool action_method::is_action_init_tag(const std::string& tag) { return tag == "INJEQT_INIT"; } bool action_method::is_action_done_tag(const std::string& tag) { return tag == "INJEQT_DONE"; } bool action_method::validate_action_method(const QMetaMethod &meta_method) { auto meta_object = meta_method.enclosingMetaObject(); if (!meta_object) throw exception::invalid_action{std::string{"action does not have enclosing meta object: "} + "?::" + meta_method.methodSignature().data()}; if (meta_method.methodType() == QMetaMethod::Signal) throw exception::invalid_action{std::string{"action is signal: "} + meta_object->className() + "::" + meta_method.methodSignature().data()}; if (meta_method.methodType() == QMetaMethod::Constructor) throw exception::invalid_action{std::string{"action is constructor: "} + meta_object->className() + "::" + meta_method.methodSignature().data()}; if (!is_action_init_tag(meta_method.tag()) && !is_action_done_tag(meta_method.tag())) throw exception::invalid_action{std::string{"action does not have valid tag: "} + meta_object->className() + "::" + meta_method.methodSignature().data()}; if (meta_method.parameterCount() != 0) throw exception::invalid_action{std::string{"invalid parameter count: "} + meta_object->className() + "::" + meta_method.methodSignature().data()}; return true; } action_method::action_method() { } action_method::action_method(QMetaMethod meta_method) : _object_type{meta_method.enclosingMetaObject()}, _meta_method{std::move(meta_method)} { assert(validate_action_method(meta_method)); } bool action_method::is_empty() const { return !_meta_method.isValid(); } const type & action_method::object_type() const { return _object_type; } bool action_method::invoke(QObject *on) const { assert(!is_empty()); assert(on != nullptr); assert(implements(type{on->metaObject()}, _object_type)); return _meta_method.invoke(on); } action_method make_action_method(const QMetaMethod &meta_method) { action_method::validate_action_method(meta_method); return action_method{meta_method}; } std::vector extract_actions(const std::string &action_tag, const type &for_type) { assert(!for_type.is_empty()); auto result = std::vector{}; auto meta_object = for_type.meta_object(); auto method_count = meta_object->methodCount(); for (decltype(method_count) i = 0; i < method_count; i++) { auto probably_action = meta_object->method(i); auto method_tag = std::string{probably_action.tag()}; if (action_tag == method_tag) result.emplace_back(make_action_method(probably_action)); } return result; } }} injeqt-1.2.0/src/internal/action-method.h000066400000000000000000000104621307635157000203250ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include "internal.h" #include #include #include #include #include /** * @file * @brief Contains classes and functions for representing setter methods. */ namespace injeqt { namespace internal { /** * @brief Abstraction of setter method. * * This class is used for defining setter based dependencies and for invoking these setter methods * to resolve dependencies. Setter method is crated from Qt type QMetaMethod. As Qt only creates QMetaMethod * objects for slots, signals and all methods marked with Q_INVOKABLE tag and Injeqt requires * all its setter methods to be tagged with INJEQT_SET - setter method must be a slot. This method should return * void is allowed to have only one parameter of pointer to type inherited from QObject. This type must * be also configured in one of module to be able to be resolved. * * Example of valid setter method: * * class set_object : public QObject * { * Q_OBJECT * }; * * class with_setter : public QObject * { * Q_OBJECT * public slots: * INJEQT_SET void setter(set_object *obj) { ... } * }; * * Object with setter method must not take ownership of passed object. */ class INJEQT_INTERNAL_API action_method final { public: static bool is_action_init_tag(const std::string &tag); static bool is_action_done_tag(const std::string &tag); static bool validate_action_method(const QMetaMethod &meta_method); /** * @brief Create empty action_method. */ action_method(); /** * @brief Create object from QMetaMethod definition. * @param parameter_type Type of parameter of setter @p meta_method * @param meta_method Qt meta method that should be a setter method * @note Qt QMetaType system limitations with plugins disallow use of QMetaType to retreive parameter type from QMetaMethod. * @pre meta_method.methodType() == QMetaMethod::Slot * @pre meta_method.parameterCount() == 1 * @pre meta_method.enclosingMetaObject() != nullptr * @pre !parameter_type.is_empty() * @pre parameter_type.name() + "*" == std::string{meta_method.parameterTypes()[0].data()} */ explicit action_method(QMetaMethod meta_method); /** * @return true if action_method is empty and does not represent valie setter method */ bool is_empty() const; /** * @return Type of objects that owns this setter method. * * May return invalid type if QMetaMethod passed in constructor was invalid. */ const type & object_type() const; /** * @param on object to call this method on * @param parameter parmeter to be passed in invocation * @return true if invoke was successfull * @pre !is_empty() * @pre on != nullptr * @pre type{on->metaObject()} == object_type() * @pre parameter != nullptr * @pre !type{parameter->metaObject()}.is_empty() * @pre implements(type{parameter->metaObject()}, _parameter_type) * * This method can be only called on valid objects with @p on parameter being * the same type as object_type() returns and @p parameter of type that implements parameter_type(). * * Calling this on invalid object with result in undefined behavior. */ bool invoke(QObject *on) const; private: type _object_type; QMetaMethod _meta_method; }; INJEQT_INTERNAL_API action_method make_action_method(const QMetaMethod &meta_method); std::vector extract_actions(const std::string &action_tag, const type &for_type); }} injeqt-1.2.0/src/internal/containers.h000066400000000000000000000037571307635157000177500ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include "internal.h" #include #include /** * @file * @brief Helper functions for containers. */ namespace injeqt { namespace internal { /** * @brief Functional interface to std::transform. * @tparam S type of source items * @tparam T type of result items * @param source source data * @param f transforming function */ template inline std::vector transform(const std::vector &source, std::function f) { auto result = std::vector{}; std::transform(std::begin(source), std::end(source), std::back_inserter(result), f); return result; } /** * @brief Extract data from multiple vectors into one vector. * @tparam S type of source items * @tparam T type of result items * @param f function returning vector for each item in source */ template inline std::vector extract(const std::vector &sources, std::function(const S &)> f) { auto result = std::vector{}; for (auto &&source : sources) { auto v = f(source); std::copy(std::begin(v), std::end(v), std::back_inserter(result)); } return result; } }} injeqt-1.2.0/src/internal/default-constructor-method.cpp000066400000000000000000000052601307635157000234120ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "default-constructor-method.h" #include namespace injeqt { namespace internal { default_constructor_method::default_constructor_method() { } default_constructor_method::default_constructor_method(QMetaMethod meta_method) : _object_type{meta_method.enclosingMetaObject()}, _meta_method{std::move(meta_method)} { assert(meta_method.methodType() == QMetaMethod::Constructor); assert(meta_method.parameterCount() == 0); assert(meta_method.enclosingMetaObject() != nullptr); } bool default_constructor_method::is_empty() const { return !_meta_method.isValid(); } const type & default_constructor_method::object_type() const { return _object_type; } const QMetaMethod & default_constructor_method::meta_method() const { return _meta_method; } std::unique_ptr default_constructor_method::invoke() const { assert(!is_empty()); return std::unique_ptr{_meta_method.enclosingMetaObject()->newInstance()}; } bool operator == (const default_constructor_method &x, const default_constructor_method &y) { if (x.object_type() != y.object_type()) return false; assert(x.meta_method() == y.meta_method()); return true; } bool operator != (const default_constructor_method &x, const default_constructor_method &y) { return !(x == y); } default_constructor_method make_default_constructor_method(const type &t) { assert(!t.is_empty()); assert(!t.is_qobject()); auto meta_object = t.meta_object(); auto constructor_count = meta_object->constructorCount(); for (decltype(constructor_count) i = 0; i < constructor_count; i++) { auto constructor = meta_object->constructor(i); if (constructor.methodType() != QMetaMethod::Constructor) continue; if (constructor.parameterCount() != 0) continue; return default_constructor_method{constructor}; } return default_constructor_method{}; } }} injeqt-1.2.0/src/internal/default-constructor-method.h000066400000000000000000000074441307635157000230650ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include "internal.h" #include #include #include #include #include /** * @file * @brief Contains classes and functions for representing default constructors. */ class QObject; namespace injeqt { namespace internal { /** * @brief Abstraction of default constructor. * * This class is used for creating objects of types configured with module::add_type(). * Default constructor is crated from Qt type QMetaMethod. As Qt only creates QMetaMethod * objects for slots, signals and all methods marked with Q_INVOKABLE tag - Injeqt * requires that default constructor is also marked with that tag. It is also not allowed * to have any parameters without default values. * * Example of valid default constructor: * * class with_default_constructor : public QObject * { * Q_OBJECT * public: * Q_INVOKABLE with_default_constructor(QObject * parent = nullptr) {} * }; * * To extract constructor from a type call make_default_constructor_method(). */ class INJEQT_INTERNAL_API default_constructor_method final { public: /** * @brief Create empty default_constructor_method. */ default_constructor_method(); /** * @brief Create object from QMetaMethod definition. * @param meta_method Qt meta method that should be a default constructor * @pre meta_method.methodType() == QMetaMethod::Constructor * @pre meta_method.parameterCount() == 0 * @pre meta_method.enclosingMetaObject() != nullptr */ explicit default_constructor_method(QMetaMethod meta_method); /** * @return true if default_constructor_method is empty and does not represent constructor */ bool is_empty() const; /** * @return Type of objects created by default constructor. */ const type & object_type() const; /** * @return Qt representation of default constructor. * * May return empty value if object is empty. */ const QMetaMethod & meta_method() const; /** * @return New instance of type of default constructor. * @pre !is_empty() */ std::unique_ptr invoke() const; private: type _object_type; QMetaMethod _meta_method; }; INJEQT_INTERNAL_API bool operator == (const default_constructor_method &x, const default_constructor_method &y); INJEQT_INTERNAL_API bool operator != (const default_constructor_method &x, const default_constructor_method &y); /** * @brief Extract default constructor method from given type T. * @tparam t type to extract constructor from * @pre !t.is_empty() && !t.is_qobject() * * This method looks for all constructors of type t tagged with Q_INVOKABLE and returns * default_constructor_method based on one without any parameters or with all parameters * with default values. If no such constructor is found - empty default_constructor_method * is returned. */ INJEQT_INTERNAL_API default_constructor_method make_default_constructor_method(const type &t); }} injeqt-1.2.0/src/internal/dependencies.cpp000066400000000000000000000057121307635157000205550ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "dependencies.h" #include #include #include #include #include #include #include #include "dependency.h" #include "interfaces-utils.h" #include "setter-method.h" #include "type-relations.h" #include #include #include #include namespace injeqt { namespace internal { namespace { std::vector extract_setters(const types_by_name &known_types, const type &for_type) { assert(!for_type.is_empty()); auto result = std::vector{}; auto meta_object = for_type.meta_object(); auto method_count = meta_object->methodCount(); for (decltype(method_count) i = 0; i < method_count; i++) { auto maybe_setter = meta_object->method(i); if (setter_method::is_setter_tag(maybe_setter.tag())) result.emplace_back(make_setter_method(known_types, maybe_setter)); } return result; } } dependencies extract_dependencies(const types_by_name &known_types, const type &for_type) { assert(!for_type.is_empty()); auto interfaces = extract_interfaces(for_type); auto setters = extract_setters(known_types, for_type); for (auto &&setter : setters) { auto parameter_type = setter.parameter_type(); if (parameter_type == for_type) throw exception::dependency_on_self{}; if (std::find(std::begin(interfaces), std::end(interfaces), parameter_type) != std::end(interfaces)) throw exception::dependency_on_supertype{}; auto parameter_interfaces = extract_interfaces(parameter_type); if (std::find(std::begin(parameter_interfaces), std::end(parameter_interfaces), for_type) != std::end(parameter_interfaces)) throw exception::dependency_on_subtype{}; } auto result = std::vector{}; std::transform(std::begin(setters), std::end(setters), std::back_inserter(result), [](const setter_method &setter){ return dependency{setter}; } ); return dependencies{result}; } }} injeqt-1.2.0/src/internal/dependencies.h000066400000000000000000000060471307635157000202240ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "dependency.h" #include "internal.h" #include "types-by-name.h" /** * @file * @brief Contains classes and functions for representing set of Injeqt dependencies. */ namespace injeqt { namespace internal { /** * @brief Extract type from dependency for storting purposes. * @brief Identity function. */ inline type type_from_dependency(const dependency &d) { return d.required_type(); } /** * @brief Identity function. */ inline dependency dependency_from_dependency(const dependency &d) { return d; } /** * @brief Abstraction of Injeqt set of dependencies. * * This set is used to represent all dependencies of one class. It is not possible * to store two dependnecies with the same dependency::required_type() values in it. * Set is sorted by dependency::required_type() and it can be matched with other * type based sets (like implementations) using match() function. * * The best way to create instance of this type is to call make_validated_dependencies(const type &). */ using dependencies = sorted_unique_vector; /** * @brief Extract set of dependencies from type. * @param for_type type to extract dependencies from. * @pre !for_type.is_empty() * @throw dependency_on_self when type depends on self. * @throw dependency_on_subtype when type depends on own supertype. * @throw dependency_on_subtype when type depends on own subtype. * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has other number of parameters than one * * This function computes and returns set of all dependencies of a given type. All slots methods tagged * with INJEQT_SET are describing dependnecies. If all dependnecies are valid, there is no duplication, * and type does not depends on self, subtype or supertype, a result is returned. Otherwise one of many * exceptions can be thrown. */ INJEQT_INTERNAL_API dependencies extract_dependencies(const types_by_name &known_types, const type &for_type); }} injeqt-1.2.0/src/internal/dependency.cpp000066400000000000000000000035701307635157000202450ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "dependency.h" #include namespace injeqt { namespace internal { dependency::dependency(setter_method setter) : _setter{std::move(setter)} { assert(!_setter.is_empty()); } const type & dependency::required_type() const { return _setter.parameter_type(); } const setter_method & dependency::setter() const { return _setter; } bool operator == (const dependency &x, const dependency &y) { if (x.setter() != y.setter()) return false; return true; } bool operator != (const dependency &x, const dependency &y) { return !(x == y); } bool operator < (const dependency &x, const dependency &y) { if (x.required_type() < y.required_type()) return true; if (x.required_type() > y.required_type()) return false; return x.setter() < y.setter(); } bool operator > (const dependency &x, const dependency &y) { return y < x; } bool operator <= (const dependency &x, const dependency &y) { return !(y < x); } bool operator >= (const dependency &x, const dependency &y) { return !(x < y); } }} injeqt-1.2.0/src/internal/dependency.h000066400000000000000000000055401307635157000177110ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "internal.h" #include "setter-method.h" /** * @file * @brief Contains classes and functions for abstractions of Injeqt dependencies. */ namespace injeqt { namespace internal { /** * @brief Abstraction of Injeqt dependency. * * Current version of Injeqt supports only setter-based dependencies between classes. * Dependency is based on setter_method class - it contains one object of setter_method * type to represent method used to resolve dependency. It also has helper function * required_type() to get a type that of object can be accepted as a dependency. * * Objects of this type are valid only when backing setter_method is valid. */ class INJEQT_INTERNAL_API dependency final { public: /** * @brief Create dependency instance that uses setter method to be resolved. * @param setter setter method used to resolve dependency * @pre !setter.is_empty() */ explicit dependency(setter_method setter); /** * @return type that is required to resolve dependency * * Objects that resolve must be either of type returned by this method or * of type that derives from it. This type is the same as setter().parameter_type(). */ const type & required_type() const; /** * @return setter method that must be used to resolve dependency * * Returned method can be invoked on object that is of type that contains this * dependency to resolve it. */ const setter_method & setter() const; private: setter_method _setter; }; INJEQT_INTERNAL_API bool operator == (const dependency &x, const dependency &y); INJEQT_INTERNAL_API bool operator != (const dependency &x, const dependency &y); INJEQT_INTERNAL_API bool operator < (const dependency &x, const dependency &y); INJEQT_INTERNAL_API bool operator > (const dependency &x, const dependency &y); INJEQT_INTERNAL_API bool operator <= (const dependency &x, const dependency &y); INJEQT_INTERNAL_API bool operator >= (const dependency &x, const dependency &y); }} injeqt-1.2.0/src/internal/factory-method.cpp000066400000000000000000000065251307635157000210570ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "factory-method.h" #include "interfaces-utils.h" #include namespace injeqt { namespace internal { factory_method::factory_method() { } factory_method::factory_method(type result_type, QMetaMethod meta_method) : _object_type{meta_method.enclosingMetaObject()}, _result_type{std::move(result_type)}, _meta_method{std::move(meta_method)} { assert(meta_method.methodType() == QMetaMethod::Method || meta_method.methodType() == QMetaMethod::Slot); assert(meta_method.parameterCount() == 0); assert(meta_method.enclosingMetaObject() != nullptr); assert(!_result_type.is_empty()); assert(_result_type.name() + "*" == std::string{meta_method.typeName()}); } bool factory_method::is_empty() const { return !_meta_method.isValid(); } const type & factory_method::object_type() const { return _object_type; } const type & factory_method::result_type() const { return _result_type; } const QMetaMethod & factory_method::meta_method() const { return _meta_method; } std::unique_ptr factory_method::invoke(QObject *on) const { assert(!is_empty()); assert(on != nullptr); assert(meta_method().enclosingMetaObject() == on->metaObject()); QObject *result = nullptr; _meta_method.invoke(on, QReturnArgument((_result_type.name() + "*").c_str(), result)); // TODO: check for false result return std::unique_ptr{result}; } bool operator == (const factory_method &x, const factory_method &y) { if (x.object_type() != y.object_type()) return false; if (x.result_type() != y.result_type()) return false; return true; } bool operator != (const factory_method &x, const factory_method &y) { return !(x == y); } factory_method make_factory_method(const types_by_name &known_types, const type &t, const type &f) { assert(!t.is_empty()); assert(!t.is_qobject()); assert(!f.is_empty()); assert(!f.is_qobject()); auto meta_object = f.meta_object(); auto method_count = meta_object->methodCount(); auto factory_methods = std::vector{}; for (decltype(method_count) i = 0; i < method_count; i++) { auto method = meta_object->method(i); if (method.parameterCount() != 0) continue; auto return_type = type_by_pointer(known_types, method.typeName()); if (return_type.is_empty()) continue; auto interfaces = extract_interfaces(return_type); if (interfaces.contains(t)) factory_methods.emplace_back(return_type, method); } if (factory_methods.size() == 1) return factory_methods.front(); else return factory_method{}; } }} injeqt-1.2.0/src/internal/factory-method.h000066400000000000000000000121121307635157000205110ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include #include "internal.h" #include "types-by-name.h" #include #include /** * @file * @brief Contains classes and functions for representing factory methods. */ class QObject; namespace injeqt { namespace internal { /** * @brief Abstraction of factory method. * * This class is used for creating objects of types configured with module::add_factory(). * Factory method is created from Qt type QMetaMethod. As Qt only creates QMetaMethod * objects for slots, signals and all methods marked with Q_INVOKABLE tag - Injeqt * requires that factory method is marked with that tag or is a slot. This method must return * pointer of type inherited from QObject and is not allowed only to have parameters with * default values. * * Example of valid factory method: * * class created_object : public QObject * { * Q_OBJECT * }; * * class with_factory_method : public QObject * { * Q_OBJECT * public: * Q_INVOKABLE created_object * create() { ... } * }; * * To extract constructor from a type call make_factory_method(). * For above example a call to make_factory_method() * would return valid object. * * Note that in Injeqt factory should not own created object - invoking * injector own lifetime of it. Method invoke(QObject *) call factory method * and immediately wraps returned QObject * in a std::unique_ptr that it later * returns. */ class INJEQT_INTERNAL_API factory_method final { public: /** * @brief Create empty factory_method. */ factory_method(); /** * @brief Create object from QMetaMethod definition. * @param parameter_type Type of retrun value of @p meta_method * @param meta_method Qt meta method that should be a factory method * @note Qt QMetaType system limitations with plugins disallow use of QMetaType to retreive return type from QMetaMethod * @pre meta_method.methodType() == QMetaMethod::Method || meta_method.methodType() == QMetaMethod::Slot * @pre meta_method.parameterCount() == 0 * @pre meta_method.enclosingMetaObject() != nullptr * @pre !result_type.is_empty() * @pre result_type.name() + "*" == std::string{result_type.typeName()} */ explicit factory_method(type result_type, QMetaMethod meta_method); /** * @return true if factory_method is empty and does not represent method */ bool is_empty() const; /** * @return Type of objects that owns this factory method. */ const type & object_type() const; /** * @return Type of objects created by factory method. */ const type & result_type() const; /** * @return Qt representation of factory method. * * May return empty value if is_empty() */ const QMetaMethod & meta_method() const; /** * @param on object to call this method on * @return Result on factory method called on given object. * @pre !is_empty() * @pre on != nullptr * @pre meta_method().enclosingMetaObject() is equal to @p on type * * This method can be only called on valid objects with @p on parameter being * the same type as object_type() returns. Invalid invocation with result * in undefined behavior. */ std::unique_ptr invoke(QObject *on) const; private: type _object_type; type _result_type; QMetaMethod _meta_method; }; INJEQT_INTERNAL_API bool operator == (const factory_method &x, const factory_method &y); INJEQT_INTERNAL_API bool operator != (const factory_method &x, const factory_method &y); /** * @brief Extract factory method from given type F that returns pointers to T. * @tparam t factory method must return T * * @tparam f type to extract constructor from * @pre !t.is_empty() && !t.is_qobject() * @pre !f.is_empty() && !f.is_qobject() * * This function looks for all methods of type F that are tagged with Q_INVOKABLE, does not * accepts argumetns and returns T* or pointer to type derived from T. If only one such method * is found it is wrapped in factory_method type and returned. In other cases an empty * factory_method is returned. */ INJEQT_INTERNAL_API factory_method make_factory_method(const types_by_name &known_types, const type &t, const type &f); }} injeqt-1.2.0/src/internal/implementation.cpp000066400000000000000000000057351307635157000211610ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "implementation.h" #include #include #include #include #include "interfaces-utils.h" #include #include namespace injeqt { namespace internal { implementation::implementation(type interface_type, QObject *object) : _interface_type{std::move(interface_type)}, _object{object} { assert(!_interface_type.is_empty()); assert(!_interface_type.is_qobject()); assert(_object != nullptr); assert(_object->metaObject() != nullptr); assert(extract_interfaces(type{_object->metaObject()}).contains(_interface_type)); } const type & implementation::interface_type() const { return _interface_type; } QObject * implementation::object() const { return _object; } bool operator == (const implementation &x, const implementation &y) { if (x.interface_type() != y.interface_type()) return false; if (x.object() != y.object()) return false; return true; } bool operator != (const implementation &x, const implementation &y) { return !(x == y); } bool operator < (const implementation &x, const implementation &y) { if (x.interface_type() < y.interface_type()) return true; if (x.interface_type() > y.interface_type()) return false; return x.object() < y.object(); } bool operator > (const implementation &x, const implementation &y) { return y < x; } bool operator <= (const implementation &x, const implementation &y) { return !(y < x); } bool operator >= (const implementation &x, const implementation &y) { return !(x < y); } implementation make_implementation(type interface_type, QObject *object) { if (interface_type.is_empty()) throw exception::empty_type{}; if (interface_type.is_qobject()) throw exception::qobject_type(); if (!object || !object->metaObject()) throw exception::invalid_qobject{}; if (!implements(type{object->metaObject()}, interface_type)) throw exception::interface_not_implemented{type{object->metaObject()}.name() + ": " + interface_type.name()}; return implementation{interface_type, object}; } }} injeqt-1.2.0/src/internal/implementation.h000066400000000000000000000065151307635157000206230ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "internal.h" /** * @file * @brief Contains classes and functions for defining implementation of type. */ class QObject; namespace injeqt { namespace internal { /** * @brief Connects type with object that implements it. * * This class is used to connect type with object that implements that type. * * This class is mostly used in internal code to store objects in cache and to pass * them as resolved dependencies. The only place where this class is created from outside * data is module::add_ready_object(QObject *) where a validation is used to ensure * that user passed valid data. */ class INJEQT_INTERNAL_API implementation final { public: /** * @brief Create new instance. * @param interface_type type that object implements * @param object object that should implement interface_type * @pre !interface_type.is_empty() * @pre !interface_type.is_qobject() * @pre object != nullptr * @pre object->metaObject() != nullptr * @pre extract_interfaces(type{object->metaObject()}).contains(interface_type) */ explicit implementation(type interface_type, QObject *object); const type & interface_type() const; QObject * object() const; private: type _interface_type; QObject *_object; }; INJEQT_INTERNAL_API bool operator == (const implementation &x, const implementation &y); INJEQT_INTERNAL_API bool operator != (const implementation &x, const implementation &y); INJEQT_INTERNAL_API bool operator < (const implementation &x, const implementation &y); INJEQT_INTERNAL_API bool operator > (const implementation &x, const implementation &y); INJEQT_INTERNAL_API bool operator <= (const implementation &x, const implementation &y); INJEQT_INTERNAL_API bool operator >= (const implementation &x, const implementation &y); /** * @brief Check if @p interface_type and @p object met implementation preconditions and return new instance if true * @param interface_type type that object implements * @param object object that should implement interface_type * @throw empty_type when passed type @p interface_type is an empty type * @throw qobject_type when passed type @p interface_type represents QObject * @throw invalid_qobject when passed @p object is nullptr or does not have valid QMetaObject * @throw interface_not_implemented when passed @p object does not implements type @p interface_type */ INJEQT_INTERNAL_API implementation make_implementation(type interface_type, QObject *object); }} injeqt-1.2.0/src/internal/implementations.h000066400000000000000000000036561307635157000210110ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "implementation.h" #include "sorted-unique-vector.h" /** * @file * @brief Contains classes and functions for representing set of Injeqt implementation objects. */ namespace injeqt { namespace internal { /** * @brief Extract type from implementation for storting purposes. */ inline type type_from_implementation(const implementation &i) { return i.interface_type(); } /** * @brief Abstraction of Injeqt set of implementation objects. * * This set is used to represent all currently available implementations. Implementations are sorted * by types and this class only allows one implementation of given type to exists. Set is sorted * by implementation::interface_type() and it can be matched with other type based sets (like dependencies) * using match() function. * * This class is mostly used by injector_core to store objects created by injector or provided to it * by module::add_ready_object(QObject *). */ using implementations = sorted_unique_vector; }} injeqt-1.2.0/src/internal/implemented-by-mapping.h000066400000000000000000000037311307635157000221370ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "implemented-by.h" #include "sorted-unique-vector.h" /** * @file * @brief Contains classes and functions for representing set of Injeqt implemented_by objects. */ namespace injeqt { namespace internal { /** * @brief Extract interface type from implemented_by for storting purposes. */ inline type type_from_implemented_by(const implemented_by &i) { return i.interface_type(); } /** * @brief Abstraction of Injeqt set of implemented_by objects. * * This set is used to represent all currently available types and its mapping to configured types. * All available types are interfaces that are implemented by configured type and are not conflicting * (interfaces are conflicting when two or more configured types implements them). Only types in * this class are available for injector to return objects of. Relations object are sorted by * interface types that are unique. * * This class is mostly used in type_relations to store all available types. */ using implemented_by_mapping = sorted_unique_vector; }} injeqt-1.2.0/src/internal/implemented-by.cpp000066400000000000000000000034501307635157000210370ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "implemented-by.h" #include #include "interfaces-utils.h" #include namespace injeqt { namespace internal { implemented_by::implemented_by(type interface_type, type implementation_type) : _interface_type{std::move(interface_type)}, _implementation_type{std::move(implementation_type)} { assert(!_interface_type.is_empty()); assert(!_implementation_type.is_empty()); assert(implements(_implementation_type, _interface_type)); } type implemented_by::interface_type() const { return _interface_type; } type implemented_by::implementation_type() const { return _implementation_type; } bool operator == (const implemented_by &x, const implemented_by &y) { if (x.interface_type() != y.interface_type()) return false; if (x.implementation_type() != y.implementation_type()) return false; return true; } bool operator != (const implemented_by &x, const implemented_by &y) { return !(x == y); } }} injeqt-1.2.0/src/internal/implemented-by.h000066400000000000000000000047241307635157000205110ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "internal.h" /** * @file * @brief Contains classes and functions for representing "interface is implemented by type" relations. */ namespace injeqt { namespace internal { /** * @brief Represents "interface is implemented by type" relations. * * In Injeqt dependencies between objects are described by types. When an object of some type * T is added to injector using module class then it can be passed as a dependency of type * T or any of T supertypes - excluding only supertypes common with other configured objects. * This class represens such relation. It is mostly used in implemnted_by_mapping set to * represents all types that injector knows and can handle. */ class INJEQT_INTERNAL_API implemented_by final { public: /** * @brief Create new instance of implemented_by. * @param interface_type type of available interface * @param implementation_type type of object implementing interface * @pre !interface_type.is_empty() * @pre !implementation_type.is_empty() * @pre implements(implementation_type, interface_type) */ explicit implemented_by(type interface_type, type implementation_type); /** * @return type of available interface. */ type interface_type() const; /** * @return type of object implementing interface. */ type implementation_type() const; private: type _interface_type; type _implementation_type; }; INJEQT_INTERNAL_API bool operator == (const implemented_by &x, const implemented_by &y); INJEQT_INTERNAL_API bool operator != (const implemented_by &x, const implemented_by &y); }} injeqt-1.2.0/src/internal/injector-core.cpp000066400000000000000000000237011307635157000206700ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "injector-core.h" #include #include #include #include #include "action-method.h" #include "containers.h" #include "interfaces-utils.h" #include "provided-object.h" #include "provider-by-default-constructor.h" #include "provider-ready.h" #include "provider.h" #include "module-impl.h" #include "required-to-satisfy.h" #include "resolve-dependencies.h" #include "resolved-dependency.h" #include "type-role.h" #include namespace injeqt { namespace internal { injector_core::injector_core() { } injector_core::injector_core(types_by_name known_types, std::vector> &&all_providers) : _known_types{std::move(known_types)} { auto all_providers_size = all_providers.size(); _available_providers = providers{std::move(all_providers)}; // some types were removed, because of duplication if (_available_providers.size() != all_providers_size) throw exception::ambiguous_types{}; // TODO: find a way to extract type names _types_model = create_types_model(); auto required_types = std::vector{}; for (auto &&p : _available_providers) for (auto &&r : p->required_types()) required_types.push_back(r); auto unavailable_required_types = match(types{required_types}, _types_model.available_types()).unmatched_1; if (!unavailable_required_types.empty()) { auto message = std::string{}; for (auto &&t : unavailable_required_types) { message.append(t.name()); message.append("\n"); } throw exception::unavailable_required_types{message}; } } injector_core::~injector_core() { for (auto &&resolved_object : _resolved_objects) call_done_methods(resolved_object.object()); } types_model injector_core::create_types_model() const { auto all_types = std::vector{}; auto need_dependencies = std::vector{}; for (auto &&p : _available_providers) { all_types.push_back(p->provided_type()); if (p->require_resolving()) { auto interfaces = extract_interfaces(p->provided_type()); std::copy(std::begin(interfaces), std::end(interfaces), std::back_inserter(need_dependencies)); } } return make_types_model(_known_types, all_types, need_dependencies); } std::vector injector_core::provided_types() const { auto result = std::vector{}; std::transform(std::begin(_available_providers), std::end(_available_providers), std::back_inserter(result), type_from_provider); return result; } void injector_core::instantiate(const type &interface_type) { assert(!interface_type.is_empty()); assert(!interface_type.is_qobject()); auto object_it = _objects.get(interface_type); if (object_it == end(_objects)) instantiate_interface(interface_type); } void injector_core::instantiate_all_with_type_role(const std::string &type_role) { for (auto &&provider : _available_providers) { auto type = provider->provided_type(); if (has_type_role(type, type_role)) instantiate_interface(type); } } QObject * injector_core::get(const type &interface_type) { assert(!interface_type.is_empty()); assert(!interface_type.is_qobject()); instantiate(interface_type); return _objects.get(interface_type)->object(); } std::vector injector_core::get_all_with_type_role(const std::string &type_role) { auto result = std::vector{}; for (auto &&provider : _available_providers) { auto type = provider->provided_type(); if (has_type_role(type, type_role)) result.push_back(get(type)); } return result; } void injector_core::instantiate_interface(const type &interface_type) { assert(!interface_type.is_empty()); assert(!interface_type.is_qobject()); instantiate_implementation(implementation_for(interface_type)); } type injector_core::implementation_for(const type &interface_type) const { assert(!interface_type.is_empty()); assert(!interface_type.is_qobject()); auto implementation_type_it = _types_model.available_types().get(interface_type); if (implementation_type_it == end(_types_model.available_types())) throw exception::unknown_type{interface_type.name()}; return implementation_type_it->implementation_type(); } void injector_core::instantiate_implementation(const type &implementation_type) { assert(!implementation_type.is_empty()); assert(!implementation_type.is_qobject()); auto types_to_instantiate = required_to_satisfy(implementation_type_dependencies(implementation_type), _types_model, _objects); types_to_instantiate.add(implementation_type); instantiate_all(types_to_instantiate); } dependencies injector_core::implementation_type_dependencies(const type &implementation_type) const { assert(!implementation_type.is_empty()); assert(!implementation_type.is_qobject()); return _types_model.mapped_dependencies().contains_key(implementation_type) ? _types_model.mapped_dependencies().get(implementation_type)->dependency_list() : dependencies{}; } void injector_core::instantiate_all(const types &interface_types) { instantiate_required_types_for(interface_types); auto provided_objects = provide_objects(providers_for(non_instantiated(interface_types))); _objects.merge(implementations{objects_to_store(extract_implementations(provided_objects))}); resolve_objects(objects_to_resolve(provided_objects)); } void injector_core::instantiate_required_types_for(const types &types_to_instantiate) { for (auto &&provider : providers_for(types_to_instantiate)) for (auto &&required_type : provider->required_types()) instantiate_interface(required_type); } std::vector injector_core::non_instantiated(const types &to_filter) const { auto result = std::vector{}; result.reserve(to_filter.size()); for (auto &&type : to_filter) if (_objects.get(type) == end(_objects)) result.push_back(type); return result; } std::vector injector_core::provide_objects(const std::vector &providers) { auto result = std::vector{}; result.reserve(providers.size()); for (auto &&provider : providers) { auto instance = provider->provide(*this); auto i = make_implementation(provider->provided_type(), instance); result.push_back(provided_object{provider, i}); } return result; } std::vector injector_core::objects_to_resolve(const std::vector &provided_objects) const { auto result = std::vector{}; result.reserve(provided_objects.size()); for (auto &&provided_object : provided_objects) if (provided_object.provided_by()->require_resolving()) result.push_back(provided_object.object()); return result; } std::vector injector_core::extract_implementations(const std::vector &provided_objects) const { auto result = std::vector{}; result.reserve(provided_objects.size()); for (auto &&provided_object : provided_objects) result.push_back(provided_object.object()); return result; } std::vector injector_core::objects_to_store(const std::vector &objects) const { auto result = std::vector{}; for (auto &&object : objects) { auto interfaces = extract_interfaces(object.interface_type()); auto matched = match(interfaces, _types_model.available_types()).matched; for (auto &&m : matched) { auto i = implementation{m.first, object.object()}; // no need to check preconditions again with make_implementation result.emplace_back(i); } } return result; } void injector_core::resolve_objects(const std::vector &objects) { for (auto &&object : objects) resolve_object(object); for (auto &&object : objects) call_init_methods(object.object()); _resolved_objects.merge(implementations{objects}); } void injector_core::resolve_object(const implementation &object) const { auto object_dependencies = implementation_type_dependencies(object.interface_type()); resolve_object(object_dependencies, object); } void injector_core::resolve_object(const dependencies &object_dependencies, const implementation &object) const { auto resolved_dependencies = resolve_dependencies(object_dependencies, _objects); assert(resolved_dependencies.unresolved.empty()); for (auto &&resolved : resolved_dependencies.resolved) { assert(implements(object.interface_type(), resolved.setter().object_type())); resolved.apply_on(object.object()); } } void injector_core::inject_into(QObject *object) { auto object_implementation = implementation{type{object->metaObject()}, object}; auto dependencies = extract_dependencies(_known_types, object_implementation.interface_type()); auto types_to_instantiate = required_to_satisfy(dependencies, _types_model, _objects); instantiate_all(types_to_instantiate); resolve_object(dependencies, object_implementation); call_init_methods(object); } void injector_core::call_init_methods(QObject *object) const { for (auto action : extract_actions("INJEQT_INIT", type{object->metaObject()})) action.invoke(object); } void injector_core::call_done_methods(QObject *object) const { auto done_actions = extract_actions("INJEQT_DONE", type{object->metaObject()}); for (auto i = done_actions.rbegin(), e = done_actions.rend(); i != e; ++i) i->invoke(object); } }} injeqt-1.2.0/src/internal/injector-core.h000066400000000000000000000274021307635157000203370ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "implementations.h" #include "providers.h" #include "types-by-name.h" #include "types-model.h" #include #include /** * @file * @brief Contains classes and functions for implementation of injector core. */ namespace injeqt { namespace internal { class provided_object; /** * @brief Implementation of injector class. * @see injector * @see injector_impl * * This class is core of Injeqt library. * * Its main purpose is to gather configuration from set of providers and construct objects with * resolved dependencies. * * Injector keeps list of all configured providers and of all already created objects. * Two methods objects_with(implementations, const type &) and objects_with(implementations, const types &) * are used to update list of already created objects with new ones. */ class INJEQT_API injector_core final { public: /** * @brief Create empty injector_core with no configuration. * * Injector with empty configuration will not be able to return any objects. Each call * to get(const type &) will result in type_not_configured */ injector_core(); /** * @brief Create injector configured with set of providers. * @param all_providers set of all providers available to injector * @see injector::injector(std::vector>) * @throw ambiguous_types if one or more types in @p providers is ambiguous * @throw unresolvable_dependencies if a type with unresolvable dependency is found in @p providers * @throw dependency_on_self when type depends on self * @throw dependency_on_subtype when type depends on own supertype * @throw dependency_on_subtype when type depends on own subtype * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject-derived pointer of not configured type * @throw invalid_setter if any tagged setter has other number of parameters than one * * This constructor creates types_model object to get all required information from providers. This object * takes ownership of passed providers. */ explicit injector_core(types_by_name known_types, std::vector> &&all_providers); injector_core(const injector_core &) = delete; injector_core(injector_core &&) = default; injector_core & operator = (const injector_core &) = delete; injector_core & operator = (injector_core &&) = default; /** * @brief Destroy injector_core. * * TODO: add note about INJEQT_DONE */ ~injector_core(); /** * @brief Returns list of all configured types. * * Result contians only types explicitely configured in modules, not supertypes of these. It also includes * results of provided_types() calls from all added parent injectors. */ std::vector provided_types() const; /** * @brief Instantiates object of given type @p interface_type * @param interface_type type of object to instantiate. * @throw unknown_type if @p interface_type was not configured in injector * @throw instantiation_failed if instantiation of one of required types failed * @pre !interface_type.is_empty() * @pre !interface_type.is_qobject() * @see injector::get() */ void instantiate(const type &interface_type); /** * @brief Instantiate all objects with given @p type_role. * @throw instantiation_failed if instantiation of one of found types failed */ void instantiate_all_with_type_role(const std::string &type_role); /** * @brief Returns pointer to object of given type @p interface_type * @param interface_type type of object to return. * @throw unknown_type if @p interface_type was not configured in injector * @throw instantiation_failed if instantiation of one of required types failed * @pre !interface_type.is_empty() * @pre !interface_type.is_qobject() * @see injector::get() */ QObject * get(const type &interface_type); /** * @brief Returns all objects with given @p type_role. * @throw instantiation_failed if instantiation of one of found types failed */ std::vector get_all_with_type_role(const std::string &type_role); /** * @brief Inject dependencies into @p object. * @param object object to inject dependencies into. * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject-derived pointer of not configured type * @throw invalid_setter if any tagged setter has other number of parameters than one * @pre object != nullptr * * This method looks for invokable setters tagged with INJEQT_SET in @p object. If any of setter is not valid * dependency injector setter or its parameter is of type not configured in injector an exception is thrown. * If all setters are valid, they are called with proper objects (which may be already available in injector * or created on demand). */ void inject_into(QObject *object); private: types_by_name _known_types; providers _available_providers; implementations _objects; implementations _resolved_objects; types_model _types_model; /** * @brief Extract all provided types and makes a types_model from them. * @throw ambiguous_types if one or more types in @p all_providers is ambiguous * @throw unresolvable_dependencies if a type with unresolvable dependency is found in @p all_providers * @throw dependency_on_self when type depends on self * @throw dependency_on_subtype when type depends on own supertype * @throw dependency_on_subtype when type depends on own subtype * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has other number of parameters than one */ types_model create_types_model() const; /** * @brief Return type that implements @p interface_type. * @throw unknown_type if @p interface_type does not have corresponding implementation */ type implementation_for(const type &interface_type) const; /** * @brief Instantiate class of interface type @p interface_type and makes it available for use. * @param interface_type type of interface of object to create * @throw instantiation_failed if instantiation of one of required types failed * @throw unknown_type if @p interface_type does not have corresponding implementation * * Instantiate class of interface type @p interface_type with all of its dependencies, then resolves them and * calls INJEQT_INIT slots. */ void instantiate_interface(const type &interface_type); /** * @brief Instantiate class of type @p implementation_type and makes it available for use. * @param interface_type type of interface of object to create * @throw instantiation_failed if instantiation of one of required types failed * * Instantiate class of exact type @p implementation_type with all of its dependencies, then resolves them and * calls INJEQT_INIT slots. */ void instantiate_implementation(const type &implementation_type); /** * @brief Return all dependencies for @p implementation_type. */ dependencies implementation_type_dependencies(const type &implementation_type) const; /** * @brief Instantiate classes of interface types from @p interface_types and makes them available for use. * @param interface_types types of interfaces of objects to create * @throw instantiation_failed if instantiation of one of required types failed * @pre No class from @p interface_types contains dependency that is not already resolved or not in @p interface_types * * Instantiate all classes of interface type @p interface_types without looking for dependencies. */ void instantiate_all(const types &interface_types); /** * @brief Instantiate classes that are required before instantiating any of @p types_to_instantiate. * @param types_to_instantiate types that are checked for list of required types * @throw instantiation_failed if instantiation of one of required types failed * * Instantiate all classes that are returned from @see provider::required_type() methods of any provider * for these types. */ void instantiate_required_types_for(const types &types_to_instantiate); /** * @brief Return list of providers required to instantiate types from @p for_types. */ template std::vector providers_for(const T &for_types) const { auto result = std::vector{}; result.reserve(for_types.size()); for (auto &&for_type : for_types) { auto provider_it = _available_providers.get(for_type); assert(provider_it != end(_available_providers)); result.push_back(provider_it->get()); } return result; } /** * @brief Filter list of types from @p to_filter to include only non already instantiated types. */ std::vector non_instantiated(const types &to_filter) const; /** * @brief Instantiate types with @p providers. */ std::vector provide_objects(const std::vector &providers); /** * @brief Return objects that needs resolving from @p provided_objects. * @see provider::require_resolving() */ std::vector objects_to_resolve(const std::vector &provided_objects) const; /** * @brief Extract implementations from vector of @p provided_object. */ std::vector extract_implementations(const std::vector &provided_objects) const; /** * @brief Return objects to store in list of instantiated objects. * * Each implementation object is returned with set of @see implementation instances that contains all unique inferfaces * for that object, so it is later avaialble under all types it implements. */ std::vector objects_to_store(const std::vector &objects) const; /** * @brief Resolve all @p objects dependencies, call all INJEQT_INIT slots and add types to list of resolved objects. * * This method assumes that all object dependencies are already instantiated. */ void resolve_objects(const std::vector &objects); /** * @brief Resolve all @p object dependencies. * * This method assumes that all object dependencies are already instantiated. */ void resolve_object(const implementation &object) const; /** * @brief Resolve all @p object dependencies with @p object_dependencies. */ void resolve_object(const dependencies &object_dependencies, const implementation &object) const; /** * @brief Call all INJEQT_INIT methods on given object in proper order. */ void call_init_methods(QObject *object) const; /** * @brief Call all INJEQT_DONE methods on given object in proper order. */ void call_done_methods(QObject *object) const; }; }} injeqt-1.2.0/src/internal/injector-impl.cpp000066400000000000000000000104171307635157000207010ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "injector-impl.h" #include #include #include "containers.h" #include "interfaces-utils.h" #include "provider-by-default-constructor.h" #include "provider-by-parent-injector-configuration.h" #include "provider-ready.h" #include "provider.h" #include "module-impl.h" #include "required-to-satisfy.h" #include "resolve-dependencies.h" #include "resolved-dependency.h" #include namespace injeqt { namespace internal { injector_impl::injector_impl() { } injector_impl::injector_impl(std::vector> modules) : // modules are only stored because these can own objects used by injector _modules{std::move(modules)} { init(std::vector{}); } injector_impl::injector_impl(std::vector super_injectors, std::vector> modules) : // modules are only stored because these can own objects used by injector _modules{std::move(modules)} { init(super_injectors); } void injector_impl::init(std::vector super_injectors) { auto extract_provider_configurations_lambda = [](const std::unique_ptr &m){ return m->_pimpl->provider_configurations(); }; auto extract_provider_configurations = std::function>(const std::unique_ptr &)>{extract_provider_configurations_lambda}; auto provider_configurations = extract(_modules, extract_provider_configurations); for (auto &&super_injector : super_injectors) for (auto &&provided_type : super_injector->provided_types()) provider_configurations.push_back(std::make_shared(super_injector, provided_type)); auto extract_types_lamdba = [](const std::shared_ptr &pc){ auto result = std::vector{}; for (auto &&t : pc->types()) { auto interfaces = extract_interfaces(t); std::copy(std::begin(interfaces), std::end(interfaces), std::back_inserter(result)); } return result; }; auto extract_types = std::function(const std::shared_ptr &)>{extract_types_lamdba}; auto known_types = types_by_name{extract(provider_configurations, extract_types)}; auto create_provider_lambda = [&known_types](const std::shared_ptr &pc){ return pc->create_provider(known_types); }; auto create_provider = std::function(std::shared_ptr)>{create_provider_lambda}; auto providers = transform(provider_configurations, create_provider); _core = injector_core{known_types, std::move(providers)}; } std::vector injector_impl::provided_types() const { return _core.provided_types(); } void injector_impl::instantiate(const type &interface_type) { assert(!interface_type.is_empty()); assert(!interface_type.is_qobject()); _core.instantiate(interface_type); } void injector_impl::instantiate_all_with_type_role(const std::string &type_role) { _core.instantiate_all_with_type_role(type_role); } QObject * injector_impl::get(const type &interface_type) { assert(!interface_type.is_empty()); assert(!interface_type.is_qobject()); return _core.get(interface_type); } std::vector injector_impl::get_all_with_type_role(const std::string &type_role) { return _core.get_all_with_type_role(type_role); } void injector_impl::inject_into(QObject *object) { assert(object); _core.inject_into(object); } }} injeqt-1.2.0/src/internal/injector-impl.h000066400000000000000000000154331307635157000203510ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "implementations.h" #include "injector-core.h" #include "providers.h" #include "types-by-name.h" #include #include /** * @file * @brief Contains classes and functions for implementation of injector. */ namespace injeqt { namespace v1 { class module; }} namespace injeqt { namespace internal { /** * @brief Implementation of injector class. * @see injector * @see injector_core * * Its main purpose is to own all modules passed to injector constructor and to pass everthing else * to injector_core class. */ class INJEQT_API injector_impl final { public: /** * @brief Create empty injector_impl with no configuration. * * Injector with empty configuration will not be able to return any objects. Each call * to get(const type &) will result in type_not_configured */ injector_impl(); /** * @brief Create injector configured with set of modules. * @param modules set of modules containing configuration of injector * @see injector::injector(std::vector>) * @throw ambiguous_types if one or more types in @p modules is ambiguous * @throw unresolvable_dependencies if a type with unresolvable dependency is found in @p modules * @throw dependency_on_self when type depends on self * @throw dependency_on_subtype when type depends on own supertype * @throw dependency_on_subtype when type depends on own subtype * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject-derived pointer of not configured type * @throw invalid_setter if any tagged setter has other number of parameters than one * * This constructor extract all providers from all modules and creates injector_core object * with these providers. */ explicit injector_impl(std::vector> modules); /** * @brief Create injector configured with set of modules. * @param super_injectors list of injectors providing types for this one to use * @param modules set of modules containing configuration of injector * @see injector::injector(std::vector>) * @throw ambiguous_types if one or more types in @p modules is ambiguous * @throw unresolvable_dependencies if a type with unresolvable dependency is found in @p modules * @throw dependency_on_self when type depends on self * @throw dependency_on_subtype when type depends on own supertype * @throw dependency_on_subtype when type depends on own subtype * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject-derived pointer of not configured type * @throw invalid_setter if any tagged setter has other number of parameters than one * * This constructor extract all providers from all modules and creates injector_core object * with these providers. */ explicit injector_impl(std::vector super_injectors, std::vector> modules); /** * @brief Returns list of all configured types. * * Result contians only types explicitely configured in modules, not supertypes of these. It also includes * results of provided_types() calls from all added parent injectors. */ std::vector provided_types() const; /** * @brief Instantiates object of given type @p interface_type * @param interface_type type of object to instantiate. * @throw unknown_type if @p interface_type was not configured in instantiate * @throw instantiation_failed if instantiation of one of required types failed * @pre !interface_type.is_empty() * @pre !interface_type.is_qobject() * @see injector::get() */ void instantiate(const type &interface_type); /** * @brief Instantiate all objects with given @p type_role. * @throw instantiation_failed if instantiation of one of found types failed */ void instantiate_all_with_type_role(const std::string &type_role); /** * @brief Returns pointer to object of given type @p interface_type * @param interface_type type of object to return. * @throw unknown_type if @p interface_type was not configured in injector * @throw instantiation_failed if instantiation of one of required types failed * @pre !interface_type.is_empty() * @pre !interface_type.is_qobject() * @see injector::get() */ QObject * get(const type &interface_type); /** * @brief Returns all objects with given @p type_role. * @throw instantiation_failed if instantiation of one of found types failed */ std::vector get_all_with_type_role(const std::string &type_role); /** * @brief Inject dependencies into @p object. * @param object object to inject dependencies into. * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject-derived pointer of not configured type * @throw invalid_setter if any tagged setter has other number of parameters than one * @pre object != nullptr * * This method looks for invokable setters tagged with INJEQT_SET in @p object. If any of setter is not valid * dependency injector setter or its parameter is of type not configured in injector an exception is thrown. * If all setters are valid, they are called with proper objects (which may be already available in injector * or created on demand). */ void inject_into(QObject *object); private: std::vector> _modules; injector_core _core; void init(std::vector super_injectors); }; }} injeqt-1.2.0/src/internal/interfaces-utils.cpp000066400000000000000000000033441307635157000214070ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "interfaces-utils.h" #include #include #include namespace injeqt { namespace internal { namespace { bool is_qobject(const QMetaObject * const meta_object) { return !meta_object->superClass(); } } types extract_interfaces(const type &for_type) { assert(!for_type.is_empty()); auto result = std::vector{}; auto meta_object = for_type.meta_object(); while (meta_object && !is_qobject(meta_object)) { result.emplace_back(meta_object); meta_object = meta_object->superClass(); } return types{result}; } bool implements(const type &implementation, const type &interface) { assert(!implementation.is_empty()); assert(!interface.is_empty()); auto interfaces = extract_interfaces(implementation); return std::find(std::begin(interfaces), std::end(interfaces), interface) != std::end(interfaces); } }} injeqt-1.2.0/src/internal/interfaces-utils.h000066400000000000000000000033751307635157000210600ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "internal.h" #include "types.h" /** * @file * @brief Contains functions for extracting and checking interfaces from a type. */ namespace injeqt { namespace internal { /** * @brief Return list of interfaces that given type implements. * @pre !for_type.is_empty() * * QObject meta type system supports only single inheritance. This method * gets all QObject-based ancestors of for_type (including for_type itself, * excluding QObject) and returns it as a types collection. If for_type * object is not valid an empty collection is returned. */ INJEQT_INTERNAL_API types extract_interfaces(const type &for_type); /** * @brief Return true if @p implementation implements @p interface * @pre !implementation.is_empty() * @pre !interface.is_empty() */ INJEQT_INTERNAL_API bool implements(const type &implementation, const type &interface); }} injeqt-1.2.0/src/internal/internal.h000066400000000000000000000017621307635157000174110ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2016 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #ifdef injeqt_INTERNAL_EXPORTS #define INJEQT_INTERNAL_API Q_DECL_EXPORT #else #define INJEQT_INTERNAL_API #endif injeqt-1.2.0/src/internal/module-impl.cpp000066400000000000000000000023471307635157000203540ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "module-impl.h" #include namespace injeqt { namespace internal { void module_impl::add_provider_configuration(std::shared_ptr p) { _provider_configurations.push_back(p); } const std::vector> & module_impl::provider_configurations() { return _provider_configurations; } }} injeqt-1.2.0/src/internal/module-impl.h000066400000000000000000000036601307635157000200200ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "provider-configuration.h" #include /** * @file * @brief Contains classes and functions for implementation of modules. */ namespace injeqt { namespace internal { /** * @brief Implementation of module class. * @see module class * * Main job of this class is to create providers and keep list of pointers to them. All providers * are created using add_ready_object(type, QObject *), add_type(type) and add_factory(type, type) methods. * * List can be retreived using providers() method. Injector that takes the module gets all providers from * that list and move it to itself. */ class INJEQT_API module_impl final { public: const std::vector> & provider_configurations(); /** * @brief Add provider to list * @param p provider to add * @pre p must be valid */ void add_provider_configuration(std::shared_ptr p); private: std::vector> _provider_configurations; }; }} injeqt-1.2.0/src/internal/provided-object.cpp000066400000000000000000000027111307635157000212030ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2016 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "provided-object.h" #include "provider.h" #include namespace injeqt { namespace internal { provided_object::provided_object(provider *provided_by, implementation object) : _provided_by{provided_by}, _object{std::move(object)} { assert(_provided_by); assert(!_provided_by->provided_type().is_empty()); assert(!_provided_by->provided_type().is_qobject()); assert(_provided_by->provided_type() == object.interface_type()); } provider * provided_object::provided_by() const { return _provided_by; } implementation provided_object::object() const { return _object; } }} injeqt-1.2.0/src/internal/provided-object.h000066400000000000000000000034671307635157000206610ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2016 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "implementation.h" #include "internal.h" /** * @file * @brief Contains classes and functions for defining provider/implementation pair. */ class QObject; namespace injeqt { namespace internal { class provider; /** * @brief Connects implementation objet with provider that created it. */ class INJEQT_INTERNAL_API provided_object final { public: /** * @brief Create new instance. * @param interface_type type that object implements * @param object object that should implement interface_type * @pre provider != nullptr * @pre !provider->provided_type().is_empty() * @pre !provider->provided_type().is_qobject() * @pre provider->provided_type() == object->implementation_type() */ explicit provided_object(provider *provided_by, implementation object); provider * provided_by() const; implementation object() const; private: provider *_provided_by; implementation _object; }; }} injeqt-1.2.0/src/internal/provider-by-default-constructor-configuration.cpp000066400000000000000000000037741307635157000272510ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "provider-by-default-constructor-configuration.h" #include #include #include "default-constructor-method.h" #include "provider-by-default-constructor.h" #include namespace injeqt { namespace internal { provider_by_default_constructor_configuration::provider_by_default_constructor_configuration(type object_type) : _object_type{std::move(object_type)} { assert(!_object_type.is_empty()); } provider_by_default_constructor_configuration::~provider_by_default_constructor_configuration() { } std::vector provider_by_default_constructor_configuration::types() const { return {_object_type}; } std::unique_ptr provider_by_default_constructor_configuration::create_provider(const types_by_name &) const { if (_object_type.is_qobject()) throw exception::qobject_type(); auto c = make_default_constructor_method(_object_type); if (c.is_empty()) throw exception::default_constructor_not_found{_object_type.name()}; return std::unique_ptr{new provider_by_default_constructor{std::move(c)}}; } }} injeqt-1.2.0/src/internal/provider-by-default-constructor-configuration.h000066400000000000000000000051011307635157000267000ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "internal.h" #include "provider-configuration.h" /** * @file * @brief Contains classes and functions for representing configuration of provider working on default constructor. */ namespace injeqt { namespace internal { /** * @brief Configuration of provider that returns default-constructed object. * * This provider configuration object will return provider implementation that will * use default constructor to create objects. */ class INJEQT_INTERNAL_API provider_by_default_constructor_configuration : public provider_configuration { public: /** * @brief Create provider configuration instance. * @param object_type type of object that this provider will return * @pre !object_type.is_empty() * * This constructor does not throw even when @p object_type is invalid or does not have deafult * contructor. Factory method create_provider(const types_by_name &) will throw in that case. */ explicit provider_by_default_constructor_configuration(type object_type); virtual ~provider_by_default_constructor_configuration(); /** * @return list consisting of object_type param passed to constructor */ virtual std::vector types() const override; /** * @param known_types list of all types known to injector, not used * @return pointer to new @see provider_by_default_constructor object * @throw exception::qobject_type if object_type passed to constructor was QObject * @throw exception::default_constructor_not_found if object_type passed does not have default constructor */ virtual std::unique_ptr create_provider(const types_by_name &known_types) const override; private: type _object_type; }; }} injeqt-1.2.0/src/internal/provider-by-default-constructor.cpp000066400000000000000000000034631307635157000243770ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "provider-by-default-constructor.h" #include #include namespace injeqt { namespace internal { provider_by_default_constructor::provider_by_default_constructor(default_constructor_method constructor) : _constructor{std::move(constructor)} { assert(!_constructor.is_empty()); } provider_by_default_constructor::~provider_by_default_constructor() { } const type & provider_by_default_constructor::provided_type() const { return _constructor.object_type(); } const default_constructor_method & provider_by_default_constructor::constructor() const { return _constructor; } QObject * provider_by_default_constructor::provide(injector_core &) { if (!_object) { _object = _constructor.invoke(); if (!_object) throw exception::instantiation_failed{provided_type().name()}; } return _object.get(); } bool provider_by_default_constructor::require_resolving() const { return true; } }} injeqt-1.2.0/src/internal/provider-by-default-constructor.h000066400000000000000000000064771307635157000240540ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "internal.h" #include "provider.h" #include "default-constructor-method.h" /** * @file * @brief Contains classes and functions for representing provider working on default constructor. */ namespace injeqt { namespace internal { /** * @brief Provider that returns default-constructed object. * * This provider implementation will return object using default constructor of some type. * Its provided_type() returns type of object that contains passed constructor. Its required_types() * returns empty set of types no other objects are required for construction. * * Once created, object will be stored inside and return on subsequents calls to provide(injector_core &). * This provider has ownershipd over created object and will destroy it at own destruction. */ class INJEQT_INTERNAL_API provider_by_default_constructor final : public provider { public: /** * @brief Create provider instance with default constructor to call. * @param constructor constructor method used to create object * @pre !constructor.is_empty() */ explicit provider_by_default_constructor(default_constructor_method constructor); virtual ~provider_by_default_constructor(); provider_by_default_constructor(provider_by_default_constructor &&x) = delete; provider_by_default_constructor & operator = (provider_by_default_constructor &&x) = delete; /** * @return default_constructor_method::object_type() of object passed to construtor */ virtual const type & provided_type() const override; /** * @return object created by default constructor * @post result != nullptr * @post implements(type{result->metaObject()}, provided_type()) * @throw instantiation_failed if instantiation of provided type failed * * If object was not yet created the constructor() method is called and object is stored * in internal cache. Then object from cache is returned. */ virtual QObject * provide(injector_core &i) override; /** * @return empty set of object - this provider does not require another object to instantiate */ virtual types required_types() const { return types{}; } /** * @return true * * Objects created by injector will have its dependencies resolved. */ virtual bool require_resolving() const; /** * @return constructor object passed in constructor */ const default_constructor_method & constructor() const; private: default_constructor_method _constructor; std::unique_ptr _object; }; }} injeqt-1.2.0/src/internal/provider-by-factory-configuration.cpp000066400000000000000000000041671307635157000247060ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "provider-by-factory-configuration.h" #include #include #include "factory-method.h" #include "provider-by-factory.h" #include namespace injeqt { namespace internal { provider_by_factory_configuration::provider_by_factory_configuration(type object_type, type factory_type) : _object_type{std::move(object_type)}, _factory_type{std::move(factory_type)} { assert(!_object_type.is_empty()); assert(!_factory_type.is_empty()); } provider_by_factory_configuration::~provider_by_factory_configuration() { } std::vector provider_by_factory_configuration::types() const { return {_object_type, _factory_type}; } std::unique_ptr provider_by_factory_configuration::create_provider(const types_by_name &known_types) const { if (_object_type.is_qobject()) throw exception::qobject_type(); if (_factory_type.is_qobject()) throw exception::qobject_type(); auto fm = internal::make_factory_method(known_types, _object_type, _factory_type); if (fm.is_empty()) throw exception::unique_factory_method_not_found{_object_type.name() + " in " + _factory_type.name()}; return std::unique_ptr{new provider_by_factory{std::move(fm)}}; } }} injeqt-1.2.0/src/internal/provider-by-factory-configuration.h000066400000000000000000000056161307635157000243530ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "internal.h" #include "provider-configuration.h" /** * @file * @brief Contains classes and functions for representing configuration of provider working on factory method. */ namespace injeqt { namespace internal { /** * @brief Configuration of provider that returns object created by factory method. * * This provider configuration object will return provider implementation that will * use factory method to create objects. */ class INJEQT_INTERNAL_API provider_by_factory_configuration : public provider_configuration { public: /** * @brief Create provider configuration instance. * @param object_type type of object that this provider will return * @param factory_type type of object that contains factory method that will return object of type @p object_type * @pre !object_type.is_empty() * @pre !factory.is_empty() * * This constructor does not throw even when @p object_type or @p factory_type is invalid or if * @p factory_type does not contain proper factory method. * Factory method create_provider(const types_by_name &) will throw in that case. */ explicit provider_by_factory_configuration(type object_type, type factory_type); virtual ~provider_by_factory_configuration(); /** * @return list consisting of object_type and factory_type params passed to constructor */ virtual std::vector types() const override; /** * @param known_types list of all types known to injector, used to check return types of methods * @return pointer to new @see provider_by_factory object * @throw exception::qobject_type if object_type passed to constructor was QObject * @throw exception::factory_type if object_type passed to constructor was QObject * @throw exception::unique_factory_method_not_found if factory_type does not have unique factory metohod returning object_type */ virtual std::unique_ptr create_provider(const types_by_name &known_types) const override; private: type _object_type; type _factory_type; }; }} injeqt-1.2.0/src/internal/provider-by-factory.cpp000066400000000000000000000034361307635157000220370ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "provider-by-factory.h" #include #include "injector-impl.h" namespace injeqt { namespace internal { provider_by_factory::provider_by_factory(factory_method factory) : _factory{std::move(factory)} { } provider_by_factory::~provider_by_factory() { } const type & provider_by_factory::provided_type() const { return _factory.result_type(); } const factory_method & provider_by_factory::factory() const { return _factory; } QObject * provider_by_factory::provide(injector_core &i) { if (!_object) { auto factory_object = i.get(_factory.object_type()); _object = _factory.invoke(factory_object); if (!_object) throw exception::instantiation_failed{provided_type().name()}; } return _object.get(); } types provider_by_factory::required_types() const { return types{_factory.object_type()}; } bool provider_by_factory::require_resolving() const { return false; } }} injeqt-1.2.0/src/internal/provider-by-factory.h000066400000000000000000000066051307635157000215050ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "factory-method.h" #include "internal.h" #include "provider.h" /** * @file * @brief Contains classes and functions for representing provider working on factory method. */ namespace injeqt { namespace internal { /** * @brief Provider that returns object created by factory. * * This provider implementation will return object using factory method. Its provided_type() returns * type of factory method return type and its required_types() returns type of object of factory method. * On first call of provide(injector_core &) it will ask injector_core for object of type * factory_method::object_method() to be able to invoke this method on that object. * * Once created, object will be stored inside and return on subsequents calls to provide(injector_core &). * This provider has ownershipd over created object and will destroy it at own destruction. */ class INJEQT_INTERNAL_API provider_by_factory final : public provider { public: /** * @brief Create provider instance with factory method to call. * @param factory factory method used to create object */ explicit provider_by_factory(factory_method factory); virtual ~provider_by_factory(); provider_by_factory(provider_by_factory &&x) = delete; provider_by_factory & operator = (provider_by_factory &&x) = delete; /** * @return factory_method::retrun_type() of object passed to construtor */ virtual const type & provided_type() const override; /** * @return object created by factory method * @post result != nullptr * @post implements(type{result->metaObject()}, provided_type()) * @throw instantiation_failed if instantiation of provided type failed * * If object was not yet created the object of type factory_method::object_type() is requested * from @p i and the factory method is called on it to get object and stoe it in internal cache, * Then object from cache is returned. */ virtual QObject * provide(injector_core &i) override; /** * @return factory_method::object_type() from object passed to constructor * * Factory object must be present before factory method can be invoked. */ virtual types required_types() const override; /** * @return false * * Objects creaded by factory should be ready to use and do not require dependency resolving. */ virtual bool require_resolving() const override; /** * @return factory method object passed in constructor */ const factory_method & factory() const; private: factory_method _factory; std::unique_ptr _object; }; }} injeqt-1.2.0/src/internal/provider-by-parent-injector-configuration.cpp000066400000000000000000000033121307635157000263320ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2015 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "provider-by-parent-injector-configuration.h" #include "provider-by-parent-injector.h" #include namespace injeqt { namespace internal { provider_by_parent_injector_configuration::provider_by_parent_injector_configuration(injector_impl *parent_injector, type object_type) : _parent_injector{parent_injector}, _object_type{std::move(object_type)} { assert(_parent_injector); assert(!_object_type.is_empty()); } provider_by_parent_injector_configuration::~provider_by_parent_injector_configuration() { } std::vector provider_by_parent_injector_configuration::types() const { return {_object_type}; } std::unique_ptr provider_by_parent_injector_configuration::create_provider(const types_by_name &) const { return std::unique_ptr{new provider_by_parent_injector{_parent_injector, _object_type}}; } }} injeqt-1.2.0/src/internal/provider-by-parent-injector-configuration.h000066400000000000000000000044671307635157000260130ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2015 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "provider-configuration.h" #include "injector-impl.h" /** * @file * @brief Contains classes and functions for representing configuration of provider that uses different injector. */ namespace injeqt { namespace internal { /** * @brief Configuration of provider that uses different injector. * * This provider configuration object will return provider implementation that will * use different (parent) injector to provide objects. */ class provider_by_parent_injector_configuration : public provider_configuration { public: /** * @brief Create provider configuration instance. * @param parent_injector injector used to get object * @param object_type type to provide * @pre parent_injector != nullptr * @pre !object_type.is_empty() */ explicit provider_by_parent_injector_configuration(injector_impl *parent_injector, type object_type); virtual ~provider_by_parent_injector_configuration(); /** * @return list consisting of object_type param passed to constructor */ virtual std::vector types() const override; /** * @param known_types list of all types known to injector, used to check return types of methods * @return pointer to new @see provider_by_parent_injector_ object */ virtual std::unique_ptr create_provider(const types_by_name &known_types) const override; private: injector_impl *_parent_injector; type _object_type; }; }} injeqt-1.2.0/src/internal/provider-by-parent-injector.cpp000066400000000000000000000027061307635157000234730ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2015 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "provider-by-parent-injector.h" namespace injeqt { namespace internal { provider_by_parent_injector::provider_by_parent_injector(injector_impl *parent_injector, type provided_type) : _parent_injector{parent_injector}, _provided_type{std::move(provided_type)} { assert(_parent_injector); } const type & provider_by_parent_injector::provided_type() const { return _provided_type; } QObject * provider_by_parent_injector::provide(injector_core &) { return _parent_injector->get(_provided_type); } bool provider_by_parent_injector::require_resolving() const { return false; } }} injeqt-1.2.0/src/internal/provider-by-parent-injector.h000066400000000000000000000053751307635157000231450ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2015 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "injector-impl.h" #include "provider.h" /** * @file * @brief Contains classes and functions for representing provider that uses different injector. */ namespace injeqt { namespace internal { /** * @brief Provider that returns object from other (parent) injector. * * This provider implementation will return object from different (parent) injector. * It is basically a proxy. It can be used to implement injectors inside plugins that * use main application injector for getting global services. It can be also used to manager * scopes of object - by creating separate subinjectors for each context. */ class provider_by_parent_injector final : public provider { public: /** * @param parent_injector injector used to get object * @param provided_type type to provide * @pre parent_injector != nullptr */ explicit provider_by_parent_injector(injector_impl *parent_injector, type provided_type); virtual ~provider_by_parent_injector() {} /** * @return provided_type value passed to constructor */ virtual const type & provided_type() const override; /** * @return object returned by parent_injector * @post result != nullptr * @post implements(type{result->metaObject()}, provided_type()) * @throw instantiation_failed if instantiation of provided type failed * * If object was not yet created the constructor() method is called and object is stored * in internal cache. Then object from cache is returned. */ virtual QObject * provide(injector_core &i) override; /** * @return empty set of object - this provider does not require another object to instantiate */ virtual types required_types() const override { return types{}; } /** * @return false * * Parent injector takes care of it. */ virtual bool require_resolving() const override; private: injector_impl *_parent_injector; type _provided_type; }; }} injeqt-1.2.0/src/internal/provider-configuration.h000066400000000000000000000055331307635157000222740ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "internal.h" #include "types-by-name.h" #include /** * @file * @brief Contains classes and functions for representing configuration of object's provider. */ namespace injeqt { namespace internal { class provider; /** * @brief Abstract configuration of object's provider * @see provider * * This object is used to create @see provider objects. Configurations are stored in @see module * and @see module_impl, providers are stored in @see injector_core objects. * * Provider configuration contains only two methods: types() and create_provider(const types_by_name &). * First one is represents list of types that are known to provider (like factory type and created * object type), second one creates provider based on list of all known types. * * This class is reqruied due to Qt limitations of interactions between plugins and QMetaType system. * If QMetaType have worked properly inside plugins it could be used to extract parameter and return * types of invokable methods (using QMetaMethod::returnType() and QMetaMethod::paremeterType() with * QMetaType::metaObjectForType(int). As it does not work, Injeqt stores all known QMetaObject in * common @see types_by_name structure (that can only by computed in @see injector when all modules are known) * and uses QMetaMethod::typeName() and QMetaMethod::returnType()::paramterTypes() to get names of * types, that are mapped using this @see types_by_name. */ class INJEQT_INTERNAL_API provider_configuration { public: explicit provider_configuration() {} virtual ~provider_configuration() {} /** * @return list of all types that this configuration knows (like factory type and created object type) */ virtual std::vector types() const = 0; /** * @param known_types list of all types known to injector * @return new provider object */ virtual std::unique_ptr create_provider(const types_by_name &known_types) const = 0; }; }} injeqt-1.2.0/src/internal/provider-ready-configuration.cpp000066400000000000000000000030741307635157000237270ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "provider-ready-configuration.h" #include "provider-ready.h" #include namespace injeqt { namespace internal { provider_ready_configuration::provider_ready_configuration(type object_type, QObject *object) : _object_type{std::move(object_type)}, _object{object} { assert(!_object_type.is_empty()); } provider_ready_configuration::~provider_ready_configuration() { } std::vector provider_ready_configuration::types() const { return {_object_type}; } std::unique_ptr provider_ready_configuration::create_provider(const types_by_name &) const { auto i = internal::make_implementation(_object_type, _object); return std::unique_ptr{new provider_ready{i}}; } }} injeqt-1.2.0/src/internal/provider-ready-configuration.h000066400000000000000000000055471307635157000234030ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "internal.h" #include "provider-configuration.h" /** * @file * @brief Contains classes and functions for representing configuration of provider working on ready object. */ namespace injeqt { namespace internal { /** * @brief Configuration of provider that always returns the same object. * * This provider configuration object will return provider implementation that will always return the same object. */ class INJEQT_INTERNAL_API provider_ready_configuration : public provider_configuration { public: /** * @brief Create provider configuration instance. * @param object_type type of object that this provider will always return * @param object object that this provider will always return * @pre !object_type.is_empty() * * This constructor does not throw even when @p object_type and @p object combination is invalid. * Factory method create_provider(const types_by_name &) will throw in that case. */ explicit provider_ready_configuration(type object_type, QObject *object); virtual ~provider_ready_configuration(); /** * @return list consisting of object_type param passed to constructor */ virtual std::vector types() const override; /** * @param known_types list of all types known to injector, not used * @return pointer to new @see provider_ready object * @throw exception::empty_type if object_type passed to constructor was empty * @throw exception::qobject_type if object_type passed to constructor was QObject * @throw exception::invalid_qobject if object passed to constructor was nullptr * @throw exception::invalid_qobject if object passed to constructor was nullptr does not have a valid metaObject() * @throw exception::interface_not_implemented if object passed to constructor does not implement object_type interface */ virtual std::unique_ptr create_provider(const types_by_name &known_types) const override; private: type _object_type; QObject *_object; }; }} injeqt-1.2.0/src/internal/provider-ready.cpp000066400000000000000000000026611307635157000210630ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "provider-ready.h" namespace injeqt { namespace internal { provider_ready::provider_ready(implementation ready_implementation) : _ready_implementation{std::move(ready_implementation)} { } const type & provider_ready::provided_type() const { return _ready_implementation.interface_type(); } const implementation & provider_ready::ready_implementation() const { return _ready_implementation; } QObject * provider_ready::provide(injector_core &) { return _ready_implementation.object(); } bool provider_ready::require_resolving() const { return false; } }} injeqt-1.2.0/src/internal/provider-ready.h000066400000000000000000000050001307635157000205160ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "provider.h" #include "implementation.h" #include "internal.h" /** * @file * @brief Contains classes and functions for representing provider working on ready object. */ namespace injeqt { namespace internal { /** * @brief Provider that always returns the same object. * * This provider implementation will always return the same object. Its provided_type() * returns type of object passed to it in constructor. Its required_types() returns * empty set of types. */ class INJEQT_INTERNAL_API provider_ready final : public provider { public: /** * @brief Create provider instance with object to return. * @param ready_implementation object that this provider will always return */ explicit provider_ready(implementation ready_implementation); virtual ~provider_ready() {} /** * @return implementation::interface_type() of object passed to construtor */ virtual const type & provided_type() const override; /** * @return object passed in constructor * @post result != nullptr * @post implements(type{result->metaObject()}, provided_type()) */ virtual QObject * provide(injector_core &i) override; /** * @return empty set of object - this provider already has instance of a type */ virtual types required_types() const override { return types{}; } /** * @return false * * Object should be ready to use and do not require dependency resolving. */ virtual bool require_resolving() const override; /** * @return implementation object passed in constructor */ const implementation & ready_implementation() const; private: implementation _ready_implementation; }; }} injeqt-1.2.0/src/internal/provider.h000066400000000000000000000054621307635157000174300ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "types.h" /** * @file * @brief Contains classes and functions for representing providers of object. */ class QObject; namespace injeqt { namespace internal { class injector_core; /** * @brief Abstract provider of objects. * * Providers are used in injector to create objects of configured types. Objects * can be created in different ways so this is an abstract class with a few * mplementations. * * Provider can require objects of other types to be already available in injector * using required_types() and then provide an object with its provide() object. * Provider may or may no take ownership of a provided object - look for concrete * types for more information. * * Provider return objects that may or may not require dependency resolving. * It can be checked with require_resolving() method. */ class provider { public: explicit provider() {} virtual ~provider() {} /** * @return type of object that this provider provides. */ virtual const type & provided_type() const = 0; /** * @return provided object * @param i injector_core that requests object * @post result != nullptr * @post implements(type{result->metaObject()}, provided_type()) * @throw instantiation_failed if instantiation of provided type failed * * Provider can require some types with required_types() to be already available * in injector_core. Provider may or may no take ownership of a provided object - * look for concrete types for more information. */ virtual QObject * provide(injector_core &i) = 0; /** * @return list of types that must be instantiated in injector_core before calling provide(injector_core) method * * Return value of this method must be the same for whole lifetime of this object. */ virtual types required_types() const = 0; /** * @return true, if provided object require resolving of dependencies */ virtual bool require_resolving() const = 0; }; }} injeqt-1.2.0/src/internal/providers.h000066400000000000000000000034701307635157000176100ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "provider.h" #include "sorted-unique-vector.h" #include /** * @file * @brief Contains classes and functions for representing set of Injeqt providers sorted by provider::provided_type(). */ namespace injeqt { namespace internal { /** * @brief Extract provided_type from pointer to provider for storting purposes. */ inline type type_from_provider(const std::unique_ptr &c) { return c->provided_type(); } /** * @brief Abstraction of Injeqt set of providers. * * As provider is an abstract class it stores set of pointers to it. * * This set is used to represent all providers available to module and injector. It is * not possible to store two providers with the same provider::provided_type() values in it. * Set is sorted by provider::provided_type(). */ using providers = sorted_unique_vector, type_from_provider>; }} injeqt-1.2.0/src/internal/required-to-satisfy.cpp000066400000000000000000000052151307635157000220450ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "required-to-satisfy.h" #include "dependencies.h" #include "implemented-by.h" #include "interfaces-utils.h" #include #include namespace injeqt { namespace internal { types required_to_satisfy(const dependencies &dependencies_to_satisfy, const types_model &model, const implementations &objects) { assert(model.get_unresolvable_dependencies().empty()); auto result = std::vector{}; auto ready = std::set{}; std::transform(std::begin(objects), std::end(objects), std::inserter(ready, std::end(ready)), [](const implementation &i){ return i.interface_type(); }); auto interfaces_to_check = std::vector{}; std::transform(std::begin(dependencies_to_satisfy), std::end(dependencies_to_satisfy), std::back_inserter(interfaces_to_check), [](const dependency &d){ return d.required_type(); }); while (!interfaces_to_check.empty()) { auto current_interface_type = interfaces_to_check.back(); interfaces_to_check.pop_back(); auto current_implementation_type_it = model.available_types().get(current_interface_type); if (current_implementation_type_it == std::end(model.available_types())) continue; auto current_implementation_type = current_implementation_type_it->implementation_type(); if (ready.find(current_implementation_type) != std::end(ready)) continue; ready.insert(current_implementation_type); result.push_back(current_implementation_type); if (model.mapped_dependencies().contains_key(current_implementation_type)) { auto dependencies = model.mapped_dependencies().get(current_implementation_type)->dependency_list(); std::transform(std::begin(dependencies), std::end(dependencies), std::back_inserter(interfaces_to_check), [](const dependency &d){ return d.required_type(); }); } } return types{result}; } }} injeqt-1.2.0/src/internal/required-to-satisfy.h000066400000000000000000000036001307635157000215060ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "implementations.h" #include "internal.h" #include "types-model.h" #include "types.h" /** * @file * @brief Contains functions for computing list of types required to properly satisfy provided dependnecies. */ namespace injeqt { namespace internal { /** * @brief Return list of types required to properly satisfy provided dependnecies. * @param dependencies_to_satisfy list of dependencies to satisfy * @param model model of all types in system, must be valid * @param objects list of available interfaces, must be valid * @pre model.get_unresolvable_dependencies().empty() * * This function computes list of all types that must be instantiated in order to properly resolve all * provided dependencies. It means it recursively traverses dependency tree and returns all nodes that * are not found in @p objects set. */ INJEQT_INTERNAL_API types required_to_satisfy(const dependencies &dependencies_to_satisfy, const types_model &model, const implementations &objects); }} injeqt-1.2.0/src/internal/resolve-dependencies.cpp000066400000000000000000000027601307635157000222320ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "resolve-dependencies.h" #include "dependency.h" #include "implementations.h" #include "resolved-dependency.h" namespace injeqt { namespace internal { resolve_dependencies_result resolve_dependencies(const dependencies &to_resolve, const implementations &resolve_with) { auto match_result = match(to_resolve, resolve_with, type_from_dependency, type_from_implementation, match_increment_mode::left); auto resolved = std::vector{}; for (auto &&match : match_result.matched) resolved.emplace_back(match.second, match.first.setter()); return {dependencies{match_result.unmatched_1}, resolved}; } }} injeqt-1.2.0/src/internal/resolve-dependencies.h000066400000000000000000000046641307635157000217040ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "dependencies.h" #include "implementations.h" #include "internal.h" #include /** * @file * @brief Contains classes and functions for resolving dependencies. */ namespace injeqt { namespace internal { class resolved_dependency; /** * @brief Structure for holding result of resolving dependencies. * */ struct resolve_dependencies_result { /** * @brief All dependencies that were not resolved. */ dependencies unresolved; /** * @brief All dependencies that were resolved. * * There is no need to keep the result in sorted_unique_vector based class - resolve_dependencies * function is guaranteed to return only unique result and that field is not matched against any * other collection. If that condition changes this can be easily turned into sorted_unique_vector. */ std::vector resolved; }; /** * @brief Resolve set of dependencies with set of implementations objects. * * This function matches each dependency with implementation with the same same type. If any dependency does not * have corresponding object - it is added to resolve_dependencies_result::unresolved field. All matching dependency - * implementation pairs are added to resolve_dependencies_result::resolved field. * * This function requires that all items in both sets are valid. In other case its behavior is undefined. * This function returns only valid objects. */ INJEQT_INTERNAL_API resolve_dependencies_result resolve_dependencies(const dependencies &to_resolve, const implementations &resolve_with); }} injeqt-1.2.0/src/internal/resolved-dependency.cpp000066400000000000000000000047141307635157000220670ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "resolved-dependency.h" #include "internal/interfaces-utils.h" #include namespace injeqt { namespace internal { resolved_dependency::resolved_dependency(implementation resolved_with, setter_method setter) : _resolved_with{std::move(resolved_with)}, _setter{std::move(setter)} { assert(!_setter.is_empty()); assert(_resolved_with.interface_type() == _setter.parameter_type()); } const implementation & resolved_dependency::resolved_with() const { return _resolved_with; } const setter_method & resolved_dependency::setter() const { return _setter; } bool resolved_dependency::apply_on(QObject *on) { assert(on != nullptr); assert(implements(type{on->metaObject()}, _setter.object_type())); return _setter.invoke(on, _resolved_with.object()); } bool operator == (const resolved_dependency &x, const resolved_dependency &y) { if (x.resolved_with() != y.resolved_with()) return false; if (x.setter() != y.setter()) return false; return true; } bool operator != (const resolved_dependency &x, const resolved_dependency &y) { return !(x == y); } bool operator < (const resolved_dependency &x, const resolved_dependency &y) { if (x.resolved_with() < y.resolved_with()) return true; if (x.resolved_with() > y.resolved_with()) return false; return x.setter() < y.setter(); } bool operator > (const resolved_dependency &x, const resolved_dependency &y) { return y < x; } bool operator <= (const resolved_dependency &x, const resolved_dependency &y) { return !(y < x); } bool operator >= (const resolved_dependency &x, const resolved_dependency &y) { return !(x < y); } }} injeqt-1.2.0/src/internal/resolved-dependency.h000066400000000000000000000061211307635157000215260ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "implementation.h" #include "internal.h" #include "setter-method.h" /** * @file * @brief Contains classes and functions for resolved dependencies. */ namespace injeqt { namespace internal { /** * @brief Abstraction of Injeqt resolved dependency. * * Resolved dependency consists of implementation and a setter_method. To resolve dependency * on an object call apply_on(QObject *) method. To get instances of resolved_dependency call * resolve_dependencies(const dependencies &, const implementations &). This class is currently * only used in injector_core. */ class INJEQT_INTERNAL_API resolved_dependency final { public: /** * @brief Create new resolved_dependency object. * @param resolved_with object that resolve dependency * @param setter setter_method that can be used to resolve dependency on an object instance * @pre !setter.is_empty() * @pre resolved_with.interface_type() == setter.parameter_type() */ explicit resolved_dependency(implementation resolved_with, setter_method setter); /** * @return object that resolve dependency. */ const implementation & resolved_with() const; /** * @return setter method used to resolve dependency on an object instance. */ const setter_method & setter() const; /** * @brief Apply resolved dependency on an object instance. * @param on object to apply dependency on * @pre on != nullptr * @pre type{on->metaObject()} == setter().object_type() * * This method can only be called on valid resolved_dependency object. */ bool apply_on(QObject *on); private: implementation _resolved_with; setter_method _setter; }; INJEQT_INTERNAL_API bool operator == (const resolved_dependency &x, const resolved_dependency &y); INJEQT_INTERNAL_API bool operator != (const resolved_dependency &x, const resolved_dependency &y); INJEQT_INTERNAL_API bool operator < (const resolved_dependency &x, const resolved_dependency &y); INJEQT_INTERNAL_API bool operator > (const resolved_dependency &x, const resolved_dependency &y); INJEQT_INTERNAL_API bool operator <= (const resolved_dependency &x, const resolved_dependency &y); INJEQT_INTERNAL_API bool operator >= (const resolved_dependency &x, const resolved_dependency &y); }} injeqt-1.2.0/src/internal/setter-method.cpp000066400000000000000000000125141307635157000207110ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "setter-method.h" #include #include #include "interfaces-utils.h" #include namespace injeqt { namespace internal { bool setter_method::is_setter_tag(const std::string &tag) { return tag == "INJEQT_SET" || tag == "INJEQT_SETTER"; } bool setter_method::validate_setter_method(type parameter_type, const QMetaMethod &meta_method) { auto meta_object = meta_method.enclosingMetaObject(); if (!meta_object) throw exception::invalid_setter{std::string{"setter does not have enclosing meta object: "} + "?::" + meta_method.methodSignature().data()}; if (meta_method.methodType() == QMetaMethod::Signal) throw exception::invalid_setter{std::string{"setter is signal: "} + meta_object->className() + "::" + meta_method.methodSignature().data()}; if (meta_method.methodType() == QMetaMethod::Constructor) throw exception::invalid_setter{std::string{"setter is constructor: "} + meta_object->className() + "::" + meta_method.methodSignature().data()}; if (!is_setter_tag(meta_method.tag())) throw exception::invalid_setter{std::string{"setter does not have valid tag: "} + meta_object->className() + "::" + meta_method.methodSignature().data()}; if (meta_method.parameterCount() != 1) throw exception::invalid_setter{std::string{"invalid parameter count: "} + meta_object->className() + "::" + meta_method.methodSignature().data()}; if (parameter_type.is_empty() || parameter_type.is_qobject()) throw exception::invalid_setter{std::string{"invalid parameter (empty): "} + meta_object->className() + "::" + meta_method.methodSignature().data()}; if (parameter_type.is_empty()) throw exception::invalid_setter{std::string{"invalid parameter (qobject): "} + meta_object->className() + "::" + meta_method.methodSignature().data()}; if (parameter_type.name() + "*" != std::string{meta_method.parameterTypes()[0].data()}) throw exception::invalid_setter{std::string{"invalid parameter (type): "} + meta_object->className() + "::" + meta_method.methodSignature().data()}; return true; } setter_method::setter_method() { } setter_method::setter_method(type parameter_type, QMetaMethod meta_method) : _object_type{meta_method.enclosingMetaObject()}, _parameter_type{std::move(parameter_type)}, _meta_method{std::move(meta_method)} { assert(validate_setter_method(parameter_type, meta_method)); } bool setter_method::is_empty() const { return !_meta_method.isValid(); } const type & setter_method::object_type() const { return _object_type; } const type & setter_method::parameter_type() const { return _parameter_type; } const QMetaMethod & setter_method::meta_method() const { return _meta_method; } std::string setter_method::signature() const { return _meta_method.methodSignature().data(); } bool setter_method::invoke(QObject *on, QObject *parameter) const { assert(!is_empty()); assert(on != nullptr); assert(implements(type{on->metaObject()}, _object_type)); assert(parameter != nullptr); assert(!type{parameter->metaObject()}.is_empty()); assert(implements(type{parameter->metaObject()}, _parameter_type)); return _meta_method.invoke(on, Q_ARG(QObject *, parameter)); } bool operator == (const setter_method &x, const setter_method &y) { if (x.object_type() != y.object_type()) return false; if (x.parameter_type() != y.parameter_type()) return false; if (x.meta_method() != y.meta_method()) return false; return true; } bool operator != (const setter_method &x, const setter_method &y) { return !(x == y); } bool operator < (const setter_method &x, const setter_method &y) { if (x.object_type() < y.object_type()) return true; if (x.object_type() > y.object_type()) return false; if (x.parameter_type() < y.parameter_type()) return true; if (x.parameter_type() > y.parameter_type()) return false; return x.meta_method().methodSignature() < y.meta_method().methodSignature(); } bool operator > (const setter_method &x, const setter_method &y) { return y < x; } bool operator <= (const setter_method &x, const setter_method &y) { return !(y < x); } bool operator >= (const setter_method &x, const setter_method &y) { return !(x < y); } setter_method make_setter_method(const types_by_name &known_types, const QMetaMethod &meta_method) { auto parameter_type = meta_method.parameterCount() == 1 ? type_by_pointer(known_types, meta_method.parameterTypes()[0].data()) : type{nullptr}; setter_method::validate_setter_method(parameter_type, meta_method); return setter_method{parameter_type, meta_method}; } }} injeqt-1.2.0/src/internal/setter-method.h000066400000000000000000000125011307635157000203520ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include #include "internal.h" #include "types-by-name.h" #include /** * @file * @brief Contains classes and functions for representing setter methods. */ namespace injeqt { namespace internal { /** * @brief Abstraction of setter method. * * This class is used for defining setter based dependencies and for invoking these setter methods * to resolve dependencies. Setter method is crated from Qt type QMetaMethod. As Qt only creates QMetaMethod * objects for slots, signals and all methods marked with Q_INVOKABLE tag and Injeqt requires * all its setter methods to be tagged with INJEQT_SET - setter method must be a slot. This method should return * void is allowed to have only one parameter of pointer to type inherited from QObject. This type must * be also configured in one of module to be able to be resolved. * * Example of valid setter method: * * class set_object : public QObject * { * Q_OBJECT * }; * * class with_setter : public QObject * { * Q_OBJECT * public slots: * INJEQT_SET void setter(set_object *obj) { ... } * }; * * Object with setter method must not take ownership of passed object. */ class INJEQT_INTERNAL_API setter_method final { public: static bool is_setter_tag(const std::string &tag); static bool validate_setter_method(type parameter_type, const QMetaMethod &meta_method); /** * @brief Create empty setter_method. */ setter_method(); /** * @brief Create object from QMetaMethod definition. * @param parameter_type Type of parameter of setter @p meta_method * @param meta_method Qt meta method that should be a setter method * @note Qt QMetaType system limitations with plugins disallow use of QMetaType to retreive parameter type from QMetaMethod. * @pre meta_method.methodType() == QMetaMethod::Slot * @pre meta_method.parameterCount() == 1 * @pre meta_method.enclosingMetaObject() != nullptr * @pre !parameter_type.is_empty() * @pre parameter_type.name() + "*" == std::string{meta_method.parameterTypes()[0].data()} */ explicit setter_method(type parameter_type, QMetaMethod meta_method); /** * @return true if setter_method is empty and does not represent valie setter method */ bool is_empty() const; /** * @return Type of objects that owns this setter method. * * May return invalid type if QMetaMethod passed in constructor was invalid. */ const type & object_type() const; /** * @return Type of objects parameter accepted by setter method. * * May return invalid type if QMetaMethod passed in constructor was invalid. */ const type & parameter_type() const; /** * @return Qt representation of setter method. * * May return empty value if QMetaMethod passed in constructor was invalid. */ const QMetaMethod & meta_method() const; /** * @return String signature of setter method. * * May return empty value if QMetaMethod passed in constructor was invalid. */ std::string signature() const; /** * @param on object to call this method on * @param parameter parmeter to be passed in invocation * @return true if invoke was successfull * @pre !is_empty() * @pre on != nullptr * @pre type{on->metaObject()} == object_type() * @pre parameter != nullptr * @pre !type{parameter->metaObject()}.is_empty() * @pre implements(type{parameter->metaObject()}, _parameter_type) * * This method can be only called on valid objects with @p on parameter being * the same type as object_type() returns and @p parameter of type that implements parameter_type(). * * Calling this on invalid object with result in undefined behavior. */ bool invoke(QObject *on, QObject *parameter) const; private: type _object_type; type _parameter_type; QMetaMethod _meta_method; }; INJEQT_INTERNAL_API bool operator == (const setter_method &x, const setter_method &y); INJEQT_INTERNAL_API bool operator != (const setter_method &x, const setter_method &y); INJEQT_INTERNAL_API bool operator < (const setter_method &x, const setter_method &y); INJEQT_INTERNAL_API bool operator > (const setter_method &x, const setter_method &y); INJEQT_INTERNAL_API bool operator <= (const setter_method &x, const setter_method &y); INJEQT_INTERNAL_API bool operator >= (const setter_method &x, const setter_method &y); INJEQT_INTERNAL_API setter_method make_setter_method(const types_by_name &known_types, const QMetaMethod &meta_method); }} injeqt-1.2.0/src/internal/sorted-unique-vector.h000066400000000000000000000216571307635157000217060ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * type library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * type library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include #include namespace injeqt { namespace internal { /** * @addtogroup Misc * @{ */ /** * @class sorted_unique_vector * @short Vector that stored only unique values thata are always sorted. * @tparam T type of data * @tparam LessThanComparator comparator used for sorting * @tparam EqualityComparator comparator used for uniqueness testing */ template class sorted_unique_vector { public: using type = sorted_unique_vector; using value_type = V; using key_type = K; using storage_type = std::vector; using const_iterator = typename storage_type::const_iterator; using size_type = typename storage_type::size_type; private: static bool compare_keys(const value_type &v1, const value_type &v2) { auto k1 = KeyExtractor(v1); auto k2 = KeyExtractor(v2); return k1 < k2; } static bool compare_with_key(const value_type &v, const key_type &k) { auto vk = KeyExtractor(v); return vk < k; } static bool keys_equal(const value_type &v1, const value_type &v2) { auto k1 = KeyExtractor(v1); auto k2 = KeyExtractor(v2); return k1 == k2; } public: /** * @short Create empty sorted_unique_vector. */ sorted_unique_vector() {} /** * @short Create sorted_unique_vector from given vector. * @param storage vector to get data from * * Copies content of storage, sorts it and removes duplicates. */ explicit sorted_unique_vector(storage_type storage) : _content{std::move(storage)} { std::stable_sort(std::begin(_content), std::end(_content), compare_keys); ensure_unique(_content); } /** * @short Create sorted_unique_vector from given initialization list. * @param values vector to get data from * * Copies content of storage, sorts it and removes duplicates. */ explicit sorted_unique_vector(std::initializer_list values) : _content{std::move(values)} { std::stable_sort(std::begin(_content), std::end(_content), compare_keys); ensure_unique(_content); } const_iterator begin() const { return std::begin(_content); } const_iterator end() const { return std::end(_content); } /** * @short Add new item to sorted vector. * @param item new item * * Item is added at proper place so vector remains sorted. Item will not be * added if another one that compares equal (using EqualityComparator) * already exists. */ void add(value_type item) { if (_content.empty()) { _content.emplace_back(std::move(item)); return; } auto upperBound = std::upper_bound(std::begin(_content), std::end(_content), item, compare_keys); if (upperBound == std::begin(_content) || !keys_equal(*(upperBound - 1), item)) _content.emplace(upperBound, std::move(item)); } /** * @short Merge with another sorted vector. * @param sorted_vector vector to merge with * * All items from sorted_vector are added at proper places and duplicates are removed. */ void merge(const type &sorted_vector) { auto result = storage_type{}; std::merge(std::begin(_content), std::end(_content), std::begin(sorted_vector._content), std::end(sorted_vector._content), std::back_inserter(result), compare_keys); ensure_unique(result); _content = std::move(result); } /** * @return Data stored in sorted vector. */ const storage_type & content() const { return _content; } /** * @return true if no data is stored */ bool empty() const { return _content.empty(); } /** * @return true if element with value v is found */ bool contains(const value_type &v) const { auto lower_bound = std::lower_bound(begin(), end(), v, compare_keys); if (lower_bound == end()) return false; return *lower_bound == v; } /** * @return true if element with key k is found */ bool contains_key(const key_type &k) const { auto lower_bound = std::lower_bound(begin(), end(), k, compare_with_key); if (lower_bound == end()) return false; return k == KeyExtractor(*lower_bound); } /** * @return item with key k */ const_iterator get(const key_type &k) const { auto lower_bound = std::lower_bound(begin(), end(), k, compare_with_key); if (lower_bound == end()) return lower_bound; auto vk = KeyExtractor(*lower_bound); if (vk == k) return lower_bound; else return end(); } /** * @return number of stored items */ typename storage_type::size_type size() const { return _content.size(); } /** * @short Removes all items from sorted vector. */ void clear() { _content.clear(); } private: storage_type _content; void ensure_unique(storage_type &storage) { storage.erase(std::unique(std::begin(storage), std::end(storage), keys_equal), std::end(storage)); } }; /** * @return begin iterator to content of sorted_unique_vector. */ template typename sorted_unique_vector::const_iterator begin(const sorted_unique_vector &sorted_vector) { return std::begin(sorted_vector.content()); } /** * @return end iterator to content of sorted_unique_vector. */ template typename sorted_unique_vector::const_iterator end(const sorted_unique_vector &sorted_vector) { return std::end(sorted_vector.content()); } template bool operator == (const sorted_unique_vector &x, const sorted_unique_vector &y) { return x.content() == y.content(); } template bool operator != (const sorted_unique_vector &x, const sorted_unique_vector &y) { return !(x == y); } template struct match_result { std::vector> matched; sorted_unique_vector unmatched_1; sorted_unique_vector unmatched_2; }; enum class match_increment_mode { both, left }; template match_result match( const sorted_unique_vector &suv_1, const sorted_unique_vector &suv_2, K(*ke1)(const V1 &), K(*ke2)(const V2 &), match_increment_mode increment_mode = match_increment_mode::both) { auto unmatched_1 = std::vector{}; auto unmatched_2 = std::vector{}; auto matched = std::vector>{}; auto suv_1_it = begin(suv_1); auto suv_1_end = end(suv_1); auto suv_2_it = begin(suv_2); auto suv_2_end = end(suv_2); while (suv_1_it != suv_1_end && suv_2_it != suv_2_end) { auto suv_1_key = ke1(*suv_1_it); auto suv_2_key = ke2(*suv_2_it); if (suv_1_key == suv_2_key) { matched.emplace_back(*suv_1_it, *suv_2_it); switch (increment_mode) { case match_increment_mode::both: ++suv_1_it; ++suv_2_it; break; case match_increment_mode::left: ++suv_1_it; break; } } else if (suv_1_key < suv_2_key) { unmatched_1.emplace_back(*suv_1_it); ++suv_1_it; } else if (suv_2_key < suv_1_key) { unmatched_2.emplace_back(*suv_2_it); ++suv_2_it; } } while (suv_1_it != suv_1_end) { unmatched_1.emplace_back(*suv_1_it); suv_1_it++; } while (suv_2_it != suv_2_end) { unmatched_2.emplace_back(*suv_2_it); suv_2_it++; } return { matched, sorted_unique_vector{unmatched_1}, sorted_unique_vector{unmatched_2} }; } template match_result match(const sorted_unique_vector &suv_1, const sorted_unique_vector &suv_2) { return match(suv_1, suv_2, KeyExtractor1, KeyExtractor2); } /** * @} */ }} injeqt-1.2.0/src/internal/type-dependencies.cpp000066400000000000000000000031551307635157000215330ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "type-dependencies.h" namespace injeqt { namespace internal { type_dependencies::type_dependencies(type dependent_type, dependencies dependency_list) : _dependent_type{std::move(dependent_type)}, _dependency_list{std::move(dependency_list)} { } const type & type_dependencies::dependent_type() const { return _dependent_type; } const dependencies & type_dependencies::dependency_list() const { return _dependency_list; } bool operator == (const type_dependencies &x, const type_dependencies &y) { if (x.dependent_type() != y.dependent_type()) return false; if (x.dependency_list() != y.dependency_list()) return false; return true; } bool operator != (const type_dependencies &x, const type_dependencies &y) { return !(x == y); } }} injeqt-1.2.0/src/internal/type-dependencies.h000066400000000000000000000061601307635157000211770ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "dependencies.h" #include "internal.h" #include /** * @file * @brief Contains classes and functions for representing type and its dependencies. */ namespace injeqt { namespace internal { /** * @brief Type and its dependencies. * * This class is used to represent type with connection of all its dependencies. Instances created * with make_type_dependencies(type) function are guaranteed to be valid. * * Used in model class to store all dependnecies and in injector_core to resolve them. */ class INJEQT_INTERNAL_API type_dependencies final { public: /** * @brief Create new instance of type_dependencies. * @param dependent_type type that contains dependencies described with dependency_list * @param dependency_list list of dependencies of dependent_type */ explicit type_dependencies(type dependent_type, dependencies dependency_list); /** * @return type that contains dependencies described with dependency_list */ const type & dependent_type() const; /** * @return list of dependencies of dependent_type() */ const dependencies & dependency_list() const; private: type _dependent_type; dependencies _dependency_list; }; INJEQT_INTERNAL_API bool operator == (const type_dependencies &x, const type_dependencies &y); INJEQT_INTERNAL_API bool operator != (const type_dependencies &x, const type_dependencies &y); /** * @brief Create valid type_dependencies from given type. * @param dependent_type type to get dependecies from. * @pre !dependent_type.is_empty() * @throw dependency_on_self when type depends on self * @throw dependency_on_subtype when type depends on own supertype * @throw dependency_on_subtype when type depends on own subtype * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has other number of parameters than one */ inline type_dependencies make_type_dependencies(const types_by_name &known_types, type dependent_type) { assert(!dependent_type.is_empty()); return type_dependencies{dependent_type, extract_dependencies(known_types, dependent_type)}; } }} injeqt-1.2.0/src/internal/type-relations.cpp000066400000000000000000000050111307635157000210760ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "type-relations.h" #include #include "interfaces-utils.h" #include namespace injeqt { namespace internal { type_relations::type_relations() { } type_relations::type_relations(implemented_by_mapping unique, types ambiguous) : _unique{std::move(unique)}, _ambiguous{std::move(ambiguous)} { } const implemented_by_mapping & type_relations::unique() const { return _unique; } const types & type_relations::ambiguous() const { return _ambiguous; } type_relations make_type_relations(const std::vector &main_types) { auto type_count = std::map{}; auto implemented_by_type = std::map{}; for (auto &&main_type : main_types) { auto interface_types = extract_interfaces(main_type); for (auto &&interface_type : interface_types) { type_count[interface_type]++; implemented_by_type.insert({interface_type, main_type}); } } auto unique = std::vector{}; auto ambiguous = std::vector{}; for (auto &&counted_type : type_count) if (counted_type.second == 1) unique.push_back(implemented_by{counted_type.first, implemented_by_type.at(counted_type.first)}); else if (counted_type.second > 1) ambiguous.push_back(counted_type.first); return type_relations{implemented_by_mapping{unique}, types{ambiguous}}; } void validate_non_ambiguous(const std::vector &types, const type_relations &relations) { for (auto &&t : types) { auto message = std::string{}; if (relations.ambiguous().contains(t)) { message.append(t.name()); message.append("\n"); } if (!message.empty()) throw exception::ambiguous_types{message}; } } }} injeqt-1.2.0/src/internal/type-relations.h000066400000000000000000000066051307635157000205550ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "implemented-by-mapping.h" #include "internal.h" #include "types.h" /** * @file * @brief Contains classes and functions for defining relations between Injeqt types. */ namespace injeqt { namespace internal { /** * @brief Defines relations between Injeqt types. * @see make_type_relations(const std::vector &) to learn about alghoritm * * This class is used in model to compute relations between all injeqt types and in * make_validated_dependencies(const type &) to check if there is ambiguity between dependencies * of a type. If a type configured in module lands in ambiguous() set then whole injector * conifguration is considered invalid. * * To create object of this type use make_type_relations(const std::vector &) to ensure that * it is valid. */ class INJEQT_INTERNAL_API type_relations final { public: /** * @brief Create empty type_relations object. */ type_relations(); /** * @brief Create new type_relations object. * @param unique unique mappings * @param ambiguous set of ambiguous types * * This constructor does not check for validity of data. Use make_type_relations(const std::vector &) * factory function to ensure that data is valid. */ explicit type_relations(implemented_by_mapping unique, types ambiguous); /** * @return mappings of unique types. */ const implemented_by_mapping & unique() const; /** * @return set of ambiguous types. */ const types & ambiguous() const; private: implemented_by_mapping _unique; types _ambiguous; }; /** * @brief Create valid type_relations from list of types. * @param main_types list of types to create relations from * * Each type T from main_types has set of base types (that can be empty) - it consists of all * base types between T (including) and QObject (excluding). All types that are unique in set * are added to unique() set of result object as implemented_by object with interface_type set * to this base type and implementation_type set to T. All non unique types are added to * ambiguous() set of result object. */ INJEQT_INTERNAL_API type_relations make_type_relations(const std::vector &main_types); /** * @brief Check if relations do not have ambiguous types for provided types. * @param types types to check * @param relations relations to check * @throw ambiguous_types if @p relations contains ambiguous types from set of @p types */ INJEQT_INTERNAL_API void validate_non_ambiguous(const std::vector &types, const type_relations &relations); }} injeqt-1.2.0/src/internal/type-role.cpp000066400000000000000000000027201307635157000200430ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2016 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "type-role.h" #include #include namespace injeqt { namespace internal { bool has_type_role(type for_type, const std::string &role) { auto meta_object = for_type.meta_object(); auto class_info_count = meta_object->classInfoCount(); for (decltype(class_info_count) i = 0; i < class_info_count; i++) { auto class_info = meta_object->classInfo(i); auto name = std::string{class_info.name()}; auto value = std::string{class_info.value()}; if (name == INJEQT_TYPE_ROLE_CLASSINFO_NAME && value == role) return true; } return false; } }} injeqt-1.2.0/src/internal/type-role.h000066400000000000000000000022731307635157000175130ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2016 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "internal.h" #include namespace injeqt { namespace internal { INJEQT_INTERNAL_API bool has_type_role(type for_type, const std::string &role); template inline bool has_type_role(const std::string &role) { return has_type_role(make_type(), role); } }} injeqt-1.2.0/src/internal/types-by-name.cpp000066400000000000000000000024751307635157000206240ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "types-by-name.h" namespace injeqt { namespace internal { type type_by_pointer(const types_by_name &known_types, const std::string &pointer_name) { if (pointer_name.length() < 2) return type{}; if (pointer_name[pointer_name.length() - 1] != '*') return type{}; auto name = pointer_name.substr(0, pointer_name.length() - 1); auto item = known_types.get(name); if (item == std::end(known_types)) return type{}; else return *item; } }} injeqt-1.2.0/src/internal/types-by-name.h000066400000000000000000000024411307635157000202620ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "internal.h" #include "sorted-unique-vector.h" namespace injeqt { namespace internal { inline std::string name_from_type(const type &t) { return t.name(); } using types_by_name = sorted_unique_vector; INJEQT_INTERNAL_API type type_by_pointer(const types_by_name &known_types, const std::string &pointer_name); }} injeqt-1.2.0/src/internal/types-dependencies.h000066400000000000000000000030541307635157000213610ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "sorted-unique-vector.h" #include "type-dependencies.h" /** * @file * @brief Contains classes and functions for representing set of Injeqt type_dependencies objects. */ namespace injeqt { namespace internal { /** * @brief Extract type from type_dependencies for storting purposes. */ inline type type_from_type_dependencies(const type_dependencies &td) { return td.dependent_type(); } /** * @brief Set of type_dependencies objects. * * Used in model and injector_core to do fast lookup of type_dependencies for given type. */ using types_dependencies = sorted_unique_vector; }} injeqt-1.2.0/src/internal/types-model.cpp000066400000000000000000000063241307635157000203710ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "types-model.h" #include #include #include "type-relations.h" #include namespace injeqt { namespace internal { types_model::types_model() { } types_model::types_model(implemented_by_mapping available_types, types_dependencies mapped_dependencies) : _available_types{std::move(available_types)}, _mapped_dependencies{std::move(mapped_dependencies)} { } const implemented_by_mapping & types_model::available_types() const { return _available_types; } const types_dependencies & types_model::mapped_dependencies() const { return _mapped_dependencies; } bool types_model::contains(const type &interface_type) const { return _available_types.get(interface_type) != end(_available_types); } std::vector types_model::get_unresolvable_dependencies() const { auto result = std::vector{}; for (auto &&mapped_type_dependency : _mapped_dependencies) for (auto &&dependency : mapped_type_dependency.dependency_list()) if (!contains(dependency.required_type())) result.push_back(dependency); return result; } types_model make_types_model(const types_by_name &known_types, const std::vector &all_types, const std::vector &need_dependencies) { auto relations = make_type_relations(all_types); validate_non_ambiguous(all_types, relations); auto all_dependencies = std::vector{}; std::transform(std::begin(need_dependencies), std::end(need_dependencies), std::back_inserter(all_dependencies), [&](const type &t){ return make_type_dependencies(known_types, t); }); auto available_types = relations.unique(); auto mapped_dependencies = types_dependencies{all_dependencies}; auto result = types_model(available_types, mapped_dependencies); validate_non_unresolvable(result); return result; } void validate_non_unresolvable(const types_model &model) { auto unresolvable_dependencies = model.get_unresolvable_dependencies(); if (!unresolvable_dependencies.empty()) { auto message = std::string{}; for (auto &&unresolvable_dependency : unresolvable_dependencies) { message.append(unresolvable_dependency.required_type().name()); message.append(": "); message.append(unresolvable_dependency.setter().signature()); message.append("\n"); } throw exception::unresolvable_dependencies{message}; } } }} injeqt-1.2.0/src/internal/types-model.h000066400000000000000000000101641307635157000200330ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "implemented-by-mapping.h" #include "internal.h" #include "types-by-name.h" #include "types-dependencies.h" /** * @file * @brief Contains classes and functions for representing model of Injeqt types. */ namespace injeqt { namespace internal { /** * @brief Model of all types, their dependencies and relations. * * This class is used to represent model of all types, their dependencies and relations. * Basically it consists of implemented_by_mapping and types_dependencies build from * the same set of types. * * Use make_types_model(const std::vector &) to create valid instance of this type * and be informed of any errors in form of exceptions. */ class INJEQT_INTERNAL_API types_model { public: /** * @brief Create empty instance of types_model. */ types_model(); /** * @brief Create new instance of types_model. * @param available_types set of all interfaces in model mapped to implementation types * @param mapped_dependencies set of all dependencies of implementation types * * Both @p available_types and @p mapped_dependencies should be created from the same set of * types for types_model to be usefull. */ explicit types_model(implemented_by_mapping available_types, types_dependencies mapped_dependencies); /** * @return set of all interfaces in model mapped to implementation types. */ const implemented_by_mapping & available_types() const; /** * @return set of all dependencies of implementation types */ const types_dependencies & mapped_dependencies() const; /** * @return true if model contains @p interface_type */ bool contains(const type &interface_type) const; /** * @brief Return all unresolvable dependencies */ std::vector get_unresolvable_dependencies() const; private: implemented_by_mapping _available_types; types_dependencies _mapped_dependencies; }; /** * @brief Create types_model from given set of types. * @param known_types list of all known types * @param all_types set of types to make model from, all types must be valid. * @param need_dependencies list of types that will have dependencies extracted * @post result.get_unresolvable_dependencies().empty() * @throw ambiguous_types if one or more types is ambiguous (@see make_type_relations) * @throw unresolvable_dependencies if a type has a dependency type not in @p all_types set * @throw dependency_on_self when type depends on self * @throw dependency_on_subtype when type depends on own supertype * @throw dependency_on_subtype when type depends on own subtype * @throw invalid_setter if any tagged setter has parameter that is not a QObject-derived pointer * @throw invalid_setter if any tagged setter has parameter that is a QObject pointer * @throw invalid_setter if any tagged setter has other number of parameters than one */ INJEQT_INTERNAL_API types_model make_types_model(const types_by_name &known_types, const std::vector &all_types, const std::vector &need_dependencies); /** * @brief Check if types model do not have unresolvable types. * @param model model to check * @throw unresolvable_dependencies if @p model contains unresolvable types */ INJEQT_INTERNAL_API void validate_non_unresolvable(const types_model &model); }} injeqt-1.2.0/src/internal/types.h000066400000000000000000000024541307635157000167400ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include "sorted-unique-vector.h" /** * @file * @brief Contains classes and functions for representing set of Injeqt types. */ namespace injeqt { namespace internal { /** * @brief Identity function. */ inline type type_from_type(const type &i) { return i; } /** * @brief Set of type objects. */ using types = sorted_unique_vector; }} injeqt-1.2.0/src/module.cpp000066400000000000000000000035231307635157000155760ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "module-impl.h" #include "provider-by-default-constructor-configuration.h" #include "provider-by-factory-configuration.h" #include "provider-ready-configuration.h" #include #include namespace injeqt { namespace v1 { module::module() : _pimpl{new injeqt::internal::module_impl{}} { } module::~module() { } void module::add_ready_object(type t, QObject *object) { assert(!t.is_empty()); _pimpl->add_provider_configuration(std::make_shared(std::move(t), object)); } void module::add_type(type t) { assert(!t.is_empty()); _pimpl->add_provider_configuration(std::make_shared(std::move(t))); } void module::add_factory(type t, type f) { assert(!t.is_empty()); assert(!f.is_empty()); _pimpl->add_provider_configuration(std::make_shared(std::move(t), std::move(f))); } }} injeqt-1.2.0/src/type.cpp000066400000000000000000000036251307635157000152750ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** @file */ #include #include #include namespace injeqt { namespace v1 { type::type() : _meta_object{nullptr} { } type::type(const QMetaObject *meta_object) : _meta_object{meta_object} { } bool type::is_empty() const { return _meta_object == nullptr; } bool type::is_qobject() const { assert(!is_empty()); return _meta_object->superClass() == nullptr; } std::string type::name() const { assert(!is_empty()); return _meta_object->className(); } const QMetaObject * type::meta_object() const { return _meta_object; } bool operator == (const type &x, const type &y) { return x.meta_object() == y.meta_object(); } bool operator != (const type &x, const type &y) { return !(x == y); } bool operator < (const type &x, const type &y) { return x.meta_object() < y.meta_object(); } bool operator > (const type &x, const type &y) { return y < x; } bool operator <= (const type &x, const type &y) { return !(y < x); } bool operator >= (const type &x, const type &y) { return !(x < y); } }} injeqt-1.2.0/test/000077500000000000000000000000001307635157000137725ustar00rootroot00000000000000injeqt-1.2.0/test/CMakeLists.txt000066400000000000000000000066451307635157000165450ustar00rootroot00000000000000# # %injeqt copyright begin% # Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) # %injeqt copyright end% # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # find_package (Qt5Test 5.2 REQUIRED) option (DISABLE_COVERAGE "Do not gather coverage data" OFF) include_directories ( ${CMAKE_SOURCE_DIR}/src ) if (NOT DISABLE_COVERAGE) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fprofile-arcs -ftest-coverage -O0") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fprofile-arcs -ftest-coverage -O0") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -O0") add_custom_target (coverage COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/coverage.sh WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) endif (NOT DISABLE_COVERAGE) function (injeqt_add_test name file) file (RELATIVE_PATH sourcePath "${CMAKE_SOURCE_DIR}/test" "${CMAKE_CURRENT_SOURCE_DIR}") get_filename_component (exeDir "${CMAKE_CURRENT_BINARY_DIR}/${name}" PATH) file (MAKE_DIRECTORY "${exeDir}") add_executable (${name} ${file}) set_property (TARGET ${name} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-error") qt5_use_modules (${name} Core Test) if (NOT DISABLE_COVERAGE) target_link_libraries (${name} gcov) endif (NOT DISABLE_COVERAGE) add_test ("${sourcePath}/${name}" ${name}) endfunction () function (injeqt_add_unit_test name) injeqt_add_test (${name} unit/${name}.cpp) target_link_libraries (${name} injeqt) endfunction () function (injeqt_add_integration_test name) injeqt_add_test (${name} integration/${name}.cpp) target_link_libraries (${name} injeqt) endfunction () set (UNIT_TESTS action-method-test default-constructor-method-test dependencies-test dependency-test factory-method-test implementation-test implemented-by-test injector-core-test injector-test interfaces-utils-test module-impl-test module-test provider-by-default-constructor-test provider-by-default-constructor-configuration-test provider-by-factory-test provider-by-factory-configuration-test provider-ready-test provider-ready-configuration-test required-to-satisfy-test resolved-dependency-test resolve-dependencies-test setter-method-test sorted-unique-vector-test type-dependencies-test type-relations-test type-role-test type-test types-by-name-test types-model-test ) set (INTEGRATION_TESTS default-constructor-behavior-test duplicate-dependencies-test factory-behavior-test get-all-with-type-role-test init-done-test inject-into-behavior-test inject-into-during-init-test instantiate-all-with-type-role-test ready-object-behavior-test super-sub-dependency-test ) foreach (UNIT_TEST ${UNIT_TESTS}) injeqt_add_unit_test (${UNIT_TEST}) endforeach () foreach (INTEGRATION_TEST ${INTEGRATION_TESTS}) injeqt_add_integration_test (${INTEGRATION_TEST}) endforeach () injeqt-1.2.0/test/coverage.sh000077500000000000000000000002741307635157000161270ustar00rootroot00000000000000#!/bin/bash lcov --capture --directory . --output-file coverage.info lcov --directory . --output-file coverage.info --remove coverage.info "/usr/*" "*.moc" "test/*" genhtml coverage.info injeqt-1.2.0/test/integration/000077500000000000000000000000001307635157000163155ustar00rootroot00000000000000injeqt-1.2.0/test/integration/default-constructor-behavior-test.cpp000066400000000000000000000045721307635157000256120ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include class int_container : public QObject { Q_OBJECT public: int_container() {} virtual ~int_container() {} virtual int value() const = 0; }; class nine_container : public int_container { Q_OBJECT public: Q_INVOKABLE nine_container() {} virtual ~nine_container() {} virtual int value() const override { return 9; } }; class base_int_service : public QObject { Q_OBJECT public: Q_INVOKABLE base_int_service() {} int value() const { return _int_container->value(); } private slots: INJEQT_SET void set_int_container(int_container *container) { _int_container = container; } private: QPointer _int_container; }; class int_service : public base_int_service { Q_OBJECT public: Q_INVOKABLE int_service() {} }; class default_constructor_behavior_test : public QObject { Q_OBJECT private slots: void should_create_proper_object_structure(); }; void default_constructor_behavior_test::should_create_proper_object_structure() { class m : public injeqt::module { public: m() { add_type(); add_type(); } virtual ~m() {} }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{}}); auto injector = injeqt::injector{std::move(modules)}; auto service = injector.get(); QCOMPARE(9, service->value()); } QTEST_APPLESS_MAIN(default_constructor_behavior_test) #include "default-constructor-behavior-test.moc" injeqt-1.2.0/test/integration/duplicate-dependencies-test.cpp000066400000000000000000000136311307635157000244000ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2016 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include class injectable_super : public QObject { Q_OBJECT public: Q_INVOKABLE injectable_super() {} virtual ~injectable_super() {} }; class injectable_sub : public injectable_super { Q_OBJECT public: Q_INVOKABLE injectable_sub() {} virtual ~injectable_sub() {} }; class same_duplicate_dependnecies : public QObject { Q_OBJECT public: injectable_super *v1 = nullptr; injectable_super *v2 = nullptr; Q_INVOKABLE same_duplicate_dependnecies() {} virtual ~same_duplicate_dependnecies() {} private slots: INJEQT_SET void set_injectable_super_1(injectable_super *x) { v1 = x; } INJEQT_SET void set_injectable_super_2(injectable_super *x) { v2 = x; } }; class hierarchy_duplicate_dependnecies : public QObject { Q_OBJECT public: injectable_super *v1 = nullptr; injectable_sub *v2 = nullptr; Q_INVOKABLE hierarchy_duplicate_dependnecies() {} virtual ~hierarchy_duplicate_dependnecies() {} private slots: INJEQT_SET void set_injectable_super(injectable_super *x) { v1 = x; } INJEQT_SET void set_injectable_sub(injectable_sub *x) { v2 = x; } }; class same_duplicate_dependnecies_super : public QObject { Q_OBJECT public: injectable_super *v1 = nullptr; Q_INVOKABLE same_duplicate_dependnecies_super() {} virtual ~same_duplicate_dependnecies_super() {} private slots: INJEQT_SET void set_injectable_super(injectable_super *x) { v1 = x; } }; class same_duplicate_dependnecies_sub : public same_duplicate_dependnecies_super { Q_OBJECT public: injectable_super *v2 = nullptr; Q_INVOKABLE same_duplicate_dependnecies_sub() {} virtual ~same_duplicate_dependnecies_sub() {} private slots: INJEQT_SET void set_injectable_super(injectable_super *x) { v2 = x; } }; class hierarchy_duplicate_dependnecies_super : public QObject { Q_OBJECT public: injectable_super *v1 = nullptr; Q_INVOKABLE hierarchy_duplicate_dependnecies_super() {} virtual ~hierarchy_duplicate_dependnecies_super() {} private slots: INJEQT_SET void set_injectable_super(injectable_super *x) { v1 = x; } }; class hierarchy_duplicate_dependnecies_sub : public same_duplicate_dependnecies_super { Q_OBJECT public: injectable_sub *v2 = nullptr; Q_INVOKABLE hierarchy_duplicate_dependnecies_sub() {} virtual ~hierarchy_duplicate_dependnecies_sub() {} private slots: INJEQT_SET void set_injectable_sub(injectable_sub *x) { v2 = x; } }; class duplicate_dependencies_test : public QObject { Q_OBJECT private: injeqt::injector get_injector() const; private slots: void should_set_same_duplicate_dependencies_in_class(); void should_set_hierarchy_duplicate_dependencies_in_class(); void should_set_same_duplicate_dependencies_in_hierarchy(); void should_set_hierarchy_duplicate_dependencies_in_hierarchy(); }; injeqt::injector duplicate_dependencies_test::get_injector() const { class m : public injeqt::module { public: m() { add_type(); add_type(); add_type(); add_type(); add_type(); } virtual ~m() {} }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{}}); return injeqt::injector{std::move(modules)}; } void duplicate_dependencies_test::should_set_same_duplicate_dependencies_in_class() { auto injector = get_injector(); auto c = injector.get(); auto sub = injector.get(); auto super = injector.get(); QVERIFY(c != nullptr); QVERIFY(sub != nullptr); QVERIFY(super != nullptr); QVERIFY(super == sub); QVERIFY(c->v1 == sub); QVERIFY(c->v2 == sub); } void duplicate_dependencies_test::should_set_hierarchy_duplicate_dependencies_in_class() { auto injector = get_injector(); auto c = injector.get(); auto sub = injector.get(); auto super = injector.get(); QVERIFY(c != nullptr); QVERIFY(sub != nullptr); QVERIFY(super != nullptr); QVERIFY(super == sub); QVERIFY(c->v1 == sub); QVERIFY(c->v2 == sub); } void duplicate_dependencies_test::should_set_same_duplicate_dependencies_in_hierarchy() { auto injector = get_injector(); auto c = injector.get(); auto sub = injector.get(); auto super = injector.get(); QVERIFY(c != nullptr); QVERIFY(sub != nullptr); QVERIFY(super != nullptr); QVERIFY(super == sub); QVERIFY(c->v1 == sub); QVERIFY(c->v2 == sub); } void duplicate_dependencies_test::should_set_hierarchy_duplicate_dependencies_in_hierarchy() { auto injector = get_injector(); auto c = injector.get(); auto sub = injector.get(); auto super = injector.get(); QVERIFY(c != nullptr); QVERIFY(sub != nullptr); QVERIFY(super != nullptr); QVERIFY(super == sub); QVERIFY(c->v1 == sub); QVERIFY(c->v2 == sub); } QTEST_APPLESS_MAIN(duplicate_dependencies_test) #include "duplicate-dependencies-test.moc" injeqt-1.2.0/test/integration/factory-behavior-test.cpp000066400000000000000000000134001307635157000232400ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include class default_constructible : public QObject { Q_OBJECT public: Q_INVOKABLE default_constructible() {} }; class int_container : public QObject { Q_OBJECT public: int_container() {} virtual ~int_container() {} virtual int value() const = 0; }; class simple_int_container : public int_container { Q_OBJECT public: simple_int_container(int value) : _value{value} {} virtual ~simple_int_container() {} virtual int value() const override { return _value; } private: int _value; }; class int_container_with_ignored_setter : public int_container { Q_OBJECT public: int_container_with_ignored_setter(int value) : _value{value} {} virtual ~int_container_with_ignored_setter() {} virtual int value() const override { return _value; } default_constructible * object() const { return _object; } private slots: INJEQT_SET void set_default_constructible(default_constructible *object) { _object = object; } private: int _value; QPointer _object; }; class int_service : public QObject { Q_OBJECT public: Q_INVOKABLE int_service() {} int value() const { return _int_container->value(); } private slots: INJEQT_SET void set_int_container(int_container *container) { _int_container = container; } private: QPointer _int_container; }; class int_container_factory : public QObject { Q_OBJECT public: int_container_factory(int value) : _value{value} {} Q_INVOKABLE int_container * create_int_container() const { return new simple_int_container{_value}; } private: int _value; }; class int_container_with_ignored_setter_factory : public QObject { Q_OBJECT public: int_container_with_ignored_setter_factory(int value) : _value{value} {} Q_INVOKABLE int_container * create_int_container() const { return new int_container_with_ignored_setter{_value}; } private: int _value; }; class factory_behavior_test : public QObject { Q_OBJECT private slots: void should_create_proper_object_structure(); void should_ignore_invalid_setters_in_created_by_factory_object(); void should_ignore_valid_setters_in_created_by_factory_object(); }; void factory_behavior_test::should_create_proper_object_structure() { class m : public injeqt::module { public: m(int value) { _factory = std::unique_ptr(new int_container_factory{value}); add_type(); add_factory(); add_ready_object(_factory.get()); } virtual ~m() {} private: std::unique_ptr _factory; }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{9}}); auto injector = injeqt::injector{std::move(modules)}; auto service = injector.get(); QCOMPARE(9, service->value()); } void factory_behavior_test::should_ignore_invalid_setters_in_created_by_factory_object() { class m : public injeqt::module { public: m(int value) { _factory = std::unique_ptr(new int_container_with_ignored_setter_factory{value}); add_type(); add_factory(); add_ready_object(_factory.get()); } virtual ~m() {} private: std::unique_ptr _factory; }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{9}}); auto injector = injeqt::injector{std::move(modules)}; auto service = injector.get(); auto container = qobject_cast(injector.get()); QCOMPARE(9, service->value()); QCOMPARE(static_cast(nullptr), container->object()); } void factory_behavior_test::should_ignore_valid_setters_in_created_by_factory_object() { class m : public injeqt::module { public: m(int value) { _factory = std::unique_ptr(new int_container_with_ignored_setter_factory{value}); add_type(); add_type(); add_factory(); add_ready_object(_factory.get()); } virtual ~m() {} private: std::unique_ptr _factory; }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{9}}); auto injector = injeqt::injector{std::move(modules)}; auto service = injector.get(); auto container = qobject_cast(injector.get()); QCOMPARE(9, service->value()); QCOMPARE(static_cast(nullptr), container->object()); } QTEST_APPLESS_MAIN(factory_behavior_test) #include "factory-behavior-test.moc" injeqt-1.2.0/test/integration/get-all-with-type-role-test.cpp000066400000000000000000000064501307635157000242170ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2016 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include using injeqt::make_type; using injeqt::type; #define ROLE_1 "role1" #define ROLE_2 "role2" class role_1_type_1 : public QObject { Q_OBJECT INJEQT_TYPE_ROLE(ROLE_1) public: Q_INVOKABLE role_1_type_1() { } }; class role_1_type_2 : public QObject { Q_OBJECT INJEQT_TYPE_ROLE(ROLE_1) public: Q_INVOKABLE role_1_type_2() { } }; class role_2_type_1 : public QObject { Q_OBJECT INJEQT_TYPE_ROLE(ROLE_2) public: Q_INVOKABLE role_2_type_1() { } }; class role_2_type_2 : public QObject { Q_OBJECT INJEQT_TYPE_ROLE(ROLE_2) public: Q_INVOKABLE role_2_type_2() { } }; class get_all_with_type_role_test : public QObject { Q_OBJECT private: injeqt::injector create_injector(); private slots: void should_return_all_role_instances(); }; injeqt::injector get_all_with_type_role_test::create_injector() { class m : public injeqt::module { public: m() { add_type(); add_type(); add_type(); add_type(); } virtual ~m() {} }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{}}); return injeqt::injector{std::move(modules)}; } void get_all_with_type_role_test::should_return_all_role_instances() { auto injector = create_injector(); auto role_1_objects = injector.get_all_with_type_role(ROLE_1); QCOMPARE(role_1_objects.size(), size_t{2}); QVERIFY(std::any_of(std::begin(role_1_objects), std::end(role_1_objects), [](QObject *o){ return !!qobject_cast(o); })); QVERIFY(std::any_of(std::begin(role_1_objects), std::end(role_1_objects), [](QObject *o){ return !!qobject_cast(o); })); auto role_2_object = injector.get(); auto role_2_objects = injector.get_all_with_type_role(ROLE_2); QCOMPARE(role_2_objects.size(), size_t{2}); QVERIFY(std::any_of(std::begin(role_2_objects), std::end(role_2_objects), [](QObject *o){ return !!qobject_cast(o); })); QVERIFY(std::any_of(std::begin(role_2_objects), std::end(role_2_objects), [](QObject *o){ return !!qobject_cast(o); })); QVERIFY(std::any_of(std::begin(role_2_objects), std::end(role_2_objects), [role_2_object](QObject *o){ return o == role_2_object; })); } QTEST_APPLESS_MAIN(get_all_with_type_role_test) #include "get-all-with-type-role-test.moc" injeqt-1.2.0/test/integration/init-done-test.cpp000066400000000000000000000133731307635157000216730ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2016 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include class default_object; class ready_object; class factory_object; class by_factory_object; class common_object : public QObject { Q_OBJECT public: common_object() { QVERIFY(!_common_init_called); QVERIFY(!_common_done_called); }; virtual ~common_object() { } protected: bool _common_init_called = false; bool _common_done_called = false; private slots: INJEQT_INIT void init() { QVERIFY(!_common_init_called); QVERIFY(!_common_done_called); _common_init_called = true; } INJEQT_DONE void done() { QVERIFY(_common_init_called); QVERIFY(!_common_done_called); _common_done_called = true; } }; class default_object : public common_object { Q_OBJECT public: Q_INVOKABLE default_object() { QVERIFY(!_init_called); QVERIFY(!_done_called); }; virtual ~default_object() { QVERIFY(_init_called); QVERIFY(_done_called); QVERIFY(_common_init_called); QVERIFY(_common_done_called); } private: QPointer _ready_object; QPointer _by_factory_object; bool _init_called = false; bool _done_called = false; private slots: INJEQT_INIT void init() { QVERIFY(_ready_object); QVERIFY(_by_factory_object); QVERIFY(_common_init_called); QVERIFY(!_common_done_called); QVERIFY(!_init_called); QVERIFY(!_done_called); _init_called = true; } INJEQT_DONE void done() { QVERIFY(_ready_object); QVERIFY(_by_factory_object); QVERIFY(_common_init_called); QVERIFY(!_common_done_called); QVERIFY(_init_called); QVERIFY(!_done_called); _done_called = true; } INJEQT_SET void set_ready_object(ready_object *x) { QVERIFY(!_init_called); QVERIFY(!_done_called); _ready_object = x; } INJEQT_SET void set_by_factory_object(by_factory_object *x) { QVERIFY(!_init_called); QVERIFY(!_done_called); _by_factory_object = x; } }; class by_factory_object : public common_object { Q_OBJECT public: Q_INVOKABLE by_factory_object() { QVERIFY(!_common_init_called); QVERIFY(!_common_done_called); }; virtual ~by_factory_object() { QVERIFY(!_common_init_called); QVERIFY(!_common_done_called); } private slots: INJEQT_INIT void init() { QVERIFY(false); } INJEQT_DONE void done() { QVERIFY(false); } }; class factory : public QObject { Q_OBJECT public: Q_INVOKABLE factory() {} Q_INVOKABLE by_factory_object * create_by_factory_object() const { return new by_factory_object{}; } }; class ready_object : public common_object { Q_OBJECT public: Q_INVOKABLE ready_object() { QVERIFY(!_common_init_called); QVERIFY(!_common_done_called); }; virtual ~ready_object() { QVERIFY(!_common_init_called); QVERIFY(!_common_done_called); } private slots: INJEQT_INIT void init() { QVERIFY(false); } INJEQT_DONE void done() { QVERIFY(false); } }; class injeqt_into_object : public common_object { Q_OBJECT public: Q_INVOKABLE injeqt_into_object() { QVERIFY(!_common_init_called); QVERIFY(!_common_done_called); }; virtual ~injeqt_into_object() { QVERIFY(_init_called); QVERIFY(_common_init_called); QVERIFY(!_common_done_called); } private: QPointer _default_object; QPointer _ready_object; QPointer _by_factory_object; bool _init_called = false; private slots: INJEQT_INIT void init() { QVERIFY(_default_object); QVERIFY(_ready_object); QVERIFY(_by_factory_object); QVERIFY(_common_init_called); QVERIFY(!_common_done_called); _init_called = true; } INJEQT_DONE void done() { QVERIFY(false); } INJEQT_SET void set_default_object(default_object *x) { QVERIFY(!_init_called); QVERIFY(!_common_init_called); _default_object = x; } INJEQT_SET void set_ready_object(ready_object *x) { QVERIFY(!_init_called); QVERIFY(!_common_init_called); _ready_object = x; } INJEQT_SET void set_by_factory_object(by_factory_object *x) { QVERIFY(!_init_called); QVERIFY(!_common_init_called); _by_factory_object = x; } }; class init_done_test : public QObject { Q_OBJECT private slots: void should_properly_call_init_and_done(); }; void init_done_test::should_properly_call_init_and_done() { class m : public injeqt::module { public: m() { _ready_object = std::unique_ptr(new ready_object{}); add_type(); add_type(); add_factory(); add_ready_object(_ready_object.get()); } virtual ~m() {} private: std::unique_ptr _ready_object; }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{}}); auto injector = injeqt::injector{std::move(modules)}; injector.get(); injector.get(); injector.get(); injeqt_into_object object{}; injector.inject_into(&object); } QTEST_APPLESS_MAIN(init_done_test) #include "init-done-test.moc" injeqt-1.2.0/test/integration/inject-into-behavior-test.cpp000066400000000000000000000046301307635157000240210ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2015 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include class int_container : public QObject { Q_OBJECT public: int_container() {} virtual ~int_container() {} virtual int value() const = 0; }; class nine_container : public int_container { Q_OBJECT public: Q_INVOKABLE nine_container() {} virtual ~nine_container() {} virtual int value() const override { return 9; } }; class int_service : public QObject { Q_OBJECT public: Q_INVOKABLE int_service() {} int value() const { return _int_container->value(); } private slots: INJEQT_SET void set_int_container(int_container *container) { _int_container = container; } private: QPointer _int_container; }; class int_sub_service : public int_service { Q_OBJECT public: Q_INVOKABLE int_sub_service() {} }; class inject_into_behavior_test : public QObject { Q_OBJECT private slots: void should_properly_inject_into(); }; void inject_into_behavior_test::should_properly_inject_into() { class m : public injeqt::module { public: m() { add_type(); } virtual ~m() {} }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{}}); auto injector = injeqt::injector{std::move(modules)}; int_service service{}; injector.inject_into(&service); QCOMPARE(9, service.value()); int_sub_service sub_service{}; injector.inject_into(&sub_service); QCOMPARE(9, sub_service.value()); } QTEST_APPLESS_MAIN(inject_into_behavior_test) #include "inject-into-behavior-test.moc" injeqt-1.2.0/test/integration/inject-into-during-init-test.cpp000066400000000000000000000037731307635157000244620ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2015 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include injeqt::injector global_injector; class injectable; class injeqt_into_me : public QObject { Q_OBJECT public: injeqt_into_me() {} virtual ~injeqt_into_me() {} private slots: INJEQT_SET void set_injectable(injectable *) {} }; class injectable : public QObject { Q_OBJECT public: Q_INVOKABLE injectable() {} virtual ~injectable() {} private slots: INJEQT_INIT void init() { injeqt_into_me o; global_injector.inject_into(&o); } }; class inject_into_during_init_test : public QObject { Q_OBJECT private slots: void should_properly_inject_into_during_init(); }; void inject_into_during_init_test::should_properly_inject_into_during_init() { class m : public injeqt::module { public: m() { add_type(); } virtual ~m() {} }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{}}); global_injector = injeqt::injector{std::move(modules)}; global_injector.get(); } QTEST_APPLESS_MAIN(inject_into_during_init_test) #include "inject-into-during-init-test.moc" injeqt-1.2.0/test/integration/instantiate-all-with-type-role-test.cpp000066400000000000000000000056731307635157000257710ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2016 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include using injeqt::make_type; using injeqt::type; #define ROLE_1 "role1" #define ROLE_2 "role2" std::set instantiated_types; class role_1_type : public QObject { Q_OBJECT INJEQT_TYPE_ROLE(ROLE_1) public: Q_INVOKABLE role_1_type() { instantiated_types.insert(make_type()); } }; class no_role_required_by_role_2 : public QObject { Q_OBJECT public: Q_INVOKABLE no_role_required_by_role_2() { instantiated_types.insert(make_type()); } }; class role_2_type : public QObject { Q_OBJECT INJEQT_TYPE_ROLE(ROLE_2) public: Q_INVOKABLE role_2_type() { instantiated_types.insert(make_type()); } private slots: INJEQT_SET void set_no_role_required_by_role_2(no_role_required_by_role_2 *) {} }; class instantiate_all_with_type_role_test : public QObject { Q_OBJECT private: injeqt::injector create_injector(); private slots: void should_create_all_role_instances_with_dependencied_when_requested(); }; injeqt::injector instantiate_all_with_type_role_test::create_injector() { class m : public injeqt::module { public: m() { add_type(); add_type(); add_type(); } virtual ~m() {} }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{}}); return injeqt::injector{std::move(modules)}; } void instantiate_all_with_type_role_test::should_create_all_role_instances_with_dependencied_when_requested() { auto injector = create_injector(); instantiated_types.clear(); injector.instantiate_all_with_type_role(ROLE_2); QCOMPARE(instantiated_types, (std::set{make_type(), make_type()})); instantiated_types.clear(); injector.instantiate_all_with_type_role(ROLE_1); QCOMPARE(instantiated_types, (std::set{make_type()})); } QTEST_APPLESS_MAIN(instantiate_all_with_type_role_test) #include "instantiate-all-with-type-role-test.moc" injeqt-1.2.0/test/integration/ready-object-behavior-test.cpp000066400000000000000000000116011307635157000241420ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include class default_constructible : public QObject { Q_OBJECT public: Q_INVOKABLE default_constructible() {} }; class int_container : public QObject { Q_OBJECT public: int_container() {} virtual ~int_container() {} virtual int value() const = 0; }; class simple_int_container : public int_container { Q_OBJECT public: simple_int_container(int value) : _value{value} {} virtual ~simple_int_container() {} virtual int value() const override { return _value; } private: int _value; }; class int_container_with_ignored_setter : public int_container { Q_OBJECT public: int_container_with_ignored_setter(int value) : _value{value} {} virtual ~int_container_with_ignored_setter() {} virtual int value() const override { return _value; } default_constructible * object() const { return _object; } private slots: INJEQT_SET void set_default_constructible(default_constructible *object) { _object = object; } private: int _value; QPointer _object; }; class int_service : public QObject { Q_OBJECT public: Q_INVOKABLE int_service() {} int value() const { return _int_container->value(); } private slots: INJEQT_SET void set_int_container(int_container *container) { _int_container = container; } private: QPointer _int_container; }; class ready_object_behavior_test : public QObject { Q_OBJECT private slots: void should_create_proper_object_structure(); void should_ignore_invalid_setters_in_ready_object(); void should_ignore_valid_setters_in_ready_object(); }; void ready_object_behavior_test::should_create_proper_object_structure() { class m : public injeqt::module { public: m(int value) { _container = std::unique_ptr(new simple_int_container{value}); add_type(); add_ready_object(_container.get()); } virtual ~m() {} private: std::unique_ptr _container; }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{9}}); auto injector = injeqt::injector{std::move(modules)}; auto service = injector.get(); QCOMPARE(9, service->value()); } void ready_object_behavior_test::should_ignore_invalid_setters_in_ready_object() { class m : public injeqt::module { public: m(int value) { _container = std::unique_ptr(new int_container_with_ignored_setter{value}); add_type(); add_ready_object(_container.get()); } virtual ~m() {} private: std::unique_ptr _container; }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{9}}); auto injector = injeqt::injector{std::move(modules)}; auto service = injector.get(); auto container = injector.get(); QCOMPARE(9, service->value()); QCOMPARE(static_cast(nullptr), container->object()); } void ready_object_behavior_test::should_ignore_valid_setters_in_ready_object() { class m : public injeqt::module { public: m(int value) { _container = std::unique_ptr(new int_container_with_ignored_setter{value}); add_type(); add_type(); add_ready_object(_container.get()); } virtual ~m() {} private: std::unique_ptr _container; }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{9}}); auto injector = injeqt::injector{std::move(modules)}; auto service = injector.get(); auto container = injector.get(); QCOMPARE(9, service->value()); QCOMPARE(static_cast(nullptr), container->object()); } QTEST_APPLESS_MAIN(ready_object_behavior_test) #include "ready-object-behavior-test.moc" injeqt-1.2.0/test/integration/super-sub-dependency-test.cpp000066400000000000000000000062001307635157000240350ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2016 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include class injectable_super : public QObject { Q_OBJECT public: Q_INVOKABLE injectable_super() {} virtual ~injectable_super() {} }; class injectable_sub : public injectable_super { Q_OBJECT public: Q_INVOKABLE injectable_sub() {} virtual ~injectable_sub() {} }; class super_dependnecies : public QObject { Q_OBJECT public: injectable_super *v = nullptr; Q_INVOKABLE super_dependnecies() {} virtual ~super_dependnecies() {} private slots: INJEQT_SET void set_injectable_super(injectable_super *x) { v = x; } }; class sub_dependnecies : public QObject { Q_OBJECT public: injectable_sub *v = nullptr; Q_INVOKABLE sub_dependnecies() {} virtual ~sub_dependnecies() {} private slots: INJEQT_SET void set_injectable_sub(injectable_sub *x) { v = x; } }; class super_sub_dependency_test : public QObject { Q_OBJECT private: injeqt::injector get_injector() const; private slots: void should_set_valid_super_dependencies(); void should_set_valid_sub_dependencies(); }; injeqt::injector super_sub_dependency_test::get_injector() const { class m : public injeqt::module { public: m() { add_type(); add_type(); add_type(); } virtual ~m() {} }; auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr{new m{}}); return injeqt::injector{std::move(modules)}; } void super_sub_dependency_test::should_set_valid_super_dependencies() { auto injector = get_injector(); auto c = injector.get(); auto sub = injector.get(); auto super = injector.get(); QVERIFY(c != nullptr); QVERIFY(sub != nullptr); QVERIFY(super != nullptr); QVERIFY(c->v == super); QVERIFY(c->v == sub); } void super_sub_dependency_test::should_set_valid_sub_dependencies() { auto injector = get_injector(); auto c = injector.get(); auto sub = injector.get(); auto super = injector.get(); QVERIFY(c != nullptr); QVERIFY(sub != nullptr); QVERIFY(super != nullptr); QVERIFY(c->v == super); QVERIFY(c->v == sub); } QTEST_APPLESS_MAIN(super_sub_dependency_test) #include "super-sub-dependency-test.moc" injeqt-1.2.0/test/mocks/000077500000000000000000000000001307635157000151065ustar00rootroot00000000000000injeqt-1.2.0/test/mocks/mocked-provider-configuration.h000066400000000000000000000025211307635157000232160ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include "provider.h" #include "provider-configuration.h" using namespace injeqt::internal; using namespace injeqt::v1; class mocked_provider_configuration : public provider_configuration { public: mocked_provider_configuration() {} virtual ~mocked_provider_configuration() {} virtual std::vector types() const override { return {}; } virtual std::unique_ptr create_provider(const types_by_name &) const override { return nullptr; } }; injeqt-1.2.0/test/mocks/mocked-provider.h000066400000000000000000000041071307635157000203530ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include "provider.h" #include #include using namespace injeqt::internal; using namespace injeqt::v1; class mocked_provider : public provider { public: explicit mocked_provider(type provided_type, types required_types, std::function provide = [](){ return nullptr; }) : _provided_type{std::move(provided_type)}, _required_types{std::move(required_types)}, _provide{std::move(provide)}, _object{nullptr} {} virtual ~mocked_provider() {} virtual const type & provided_type() const override { return _provided_type; }; virtual QObject * provide(injector_core &) override { if (!_object) _object = _provide(); return _object; }; virtual types required_types() const override { return _required_types; }; virtual bool require_resolving() const override { return true; } QObject * object() const { return _object; } private: type _provided_type; types _required_types; std::function _provide; QObject *_object; }; template std::unique_ptr make_mocked_provider() { return std::unique_ptr(new mocked_provider{make_type(), types{make_type()...}, [](){ return new T(); }}); } injeqt-1.2.0/test/unit/000077500000000000000000000000001307635157000147515ustar00rootroot00000000000000injeqt-1.2.0/test/unit/action-method-test.cpp000066400000000000000000000120731307635157000211700ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include #include "internal/action-method.h" #include #ifndef Q_MOC_RUN # define INVALID_ACTION_TAG #endif using namespace injeqt::internal; using namespace injeqt::v1; class test_type : public QObject { Q_OBJECT public: int v = 0; test_type() {} Q_INVOKABLE test_type(int) {} Q_INVOKABLE INJEQT_INIT void tagged_init_action_method() { } Q_INVOKABLE INJEQT_DONE void tagged_done_action_method() { } public slots: INJEQT_INIT void tagged_init_action_slot() { v = 1; } INJEQT_DONE void tagged_done_action_slot() { } INJEQT_INIT void invalid_init_action_arguments(int) { } INJEQT_DONE void invalid_done_action_arguments(int) { } INVALID_ACTION_TAG void invalid_action_invalid_tag() { } void invalid_action_no_tag() { } signals: INJEQT_INIT void invalid_init_action_signal(); INJEQT_DONE void invalid_done_action_signal(); }; class action_method_test : public QObject { Q_OBJECT private slots: void should_create_empty(); void should_create_valid_from_tagged_action_method(); void should_create_valid_from_tagged_action_slot(); void should_invoke_have_results(); void should_throw_when_empty_method(); void should_throw_when_arguments(); void should_throw_when_invalid_tag(); void should_throw_when_no_tag(); void should_throw_when_signal(); void should_throw_when_constructor(); }; void action_method_test::should_create_empty() { auto action = action_method{}; QVERIFY(action.is_empty()); } void action_method_test::should_create_valid_from_tagged_action_method() { auto action = make_action_method(get_method("tagged_init_action_method()")); QVERIFY(!action.is_empty()); QCOMPARE(action.object_type(), make_type()); ;action = make_action_method(get_method("tagged_done_action_method()")); QVERIFY(!action.is_empty()); QCOMPARE(action.object_type(), make_type()); } void action_method_test::should_create_valid_from_tagged_action_slot() { auto action = make_action_method(get_method("tagged_init_action_slot()")); QVERIFY(!action.is_empty()); QCOMPARE(action.object_type(), make_type()); make_action_method(get_method("tagged_done_action_slot()")); QVERIFY(!action.is_empty()); QCOMPARE(action.object_type(), make_type()); } void action_method_test::should_invoke_have_results() { auto action = make_action_method(get_method("tagged_init_action_slot()")); auto on = make_object(); QCOMPARE(0, static_cast(on.get())->v); action.invoke(on.get()); QCOMPARE(1, static_cast(on.get())->v); } void action_method_test::should_throw_when_empty_method() { expect({"action does not have enclosing meta object"}, [&]{ make_action_method(QMetaMethod{}); }); } void action_method_test::should_throw_when_arguments() { expect({"invalid parameter count"}, [&]{ make_action_method(get_method("invalid_init_action_arguments(int)")); }); expect({"invalid parameter count"}, [&]{ make_action_method(get_method("invalid_done_action_arguments(int)")); }); } void action_method_test::should_throw_when_invalid_tag() { expect({"action does not have valid tag"}, [&]{ make_action_method(get_method("invalid_action_invalid_tag()")); }); } void action_method_test::should_throw_when_no_tag() { expect({"action does not have valid tag"}, [&]{ make_action_method(get_method("invalid_action_no_tag()")); }); } void action_method_test::should_throw_when_signal() { expect({"action is signal"}, [&]{ make_action_method(get_method("invalid_init_action_signal()")); }); expect({"action is signal"}, [&]{ make_action_method(get_method("invalid_done_action_signal()")); }); } void action_method_test::should_throw_when_constructor() { expect({"action is constructor"}, [&]{ make_action_method(get_constructor("test_type(int)")); }); } QTEST_APPLESS_MAIN(action_method_test) #include "action-method-test.moc" injeqt-1.2.0/test/unit/default-constructor-method-test.cpp000066400000000000000000000076721307635157000237330ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include "internal/default-constructor-method.h" #include #include using namespace injeqt::internal; using namespace injeqt::v1; class no_default_constructor : public QObject { Q_OBJECT public: Q_INVOKABLE no_default_constructor(int a) { (void)a; } Q_INVOKABLE no_default_constructor(std::string a) { (void)a; } }; class default_not_invokable_constructor : public QObject { Q_OBJECT public: default_not_invokable_constructor() {} }; class default_invokable_constructor : public QObject { Q_OBJECT public: Q_INVOKABLE default_invokable_constructor(QObject *parent = nullptr) : QObject{parent} {} }; class default_invokable_constructor_no_parameters : public QObject { Q_OBJECT public: Q_INVOKABLE default_invokable_constructor_no_parameters() {} }; class default_constructor_method_test : public QObject { Q_OBJECT private slots: void should_return_empty_when_default_constructed(); void should_return_empty_when_created_with_not_default_constructor(); void should_return_empty_when_created_with_not_invokable_constructor(); void should_create_valid_with_invokable_constructor(); void should_create_object_with_default_constructor(); void should_properly_compare(); }; void default_constructor_method_test::should_return_empty_when_default_constructed() { auto c = default_constructor_method{}; QVERIFY(c.is_empty()); } void default_constructor_method_test::should_return_empty_when_created_with_not_default_constructor() { auto c = make_default_constructor_method(make_type()); QVERIFY(c.is_empty()); } void default_constructor_method_test::should_return_empty_when_created_with_not_invokable_constructor() { auto c = make_default_constructor_method(make_type()); QVERIFY(c.is_empty()); } void default_constructor_method_test::should_create_valid_with_invokable_constructor() { auto c = make_default_constructor_method(make_type()); QVERIFY(!c.is_empty()); QCOMPARE(c.object_type(), make_type()); } void default_constructor_method_test::should_create_object_with_default_constructor() { auto c = make_default_constructor_method(make_type()); QVERIFY(!c.is_empty()); auto object = c.invoke(); auto cast = qobject_cast(object.get()); QVERIFY(cast != nullptr); } void default_constructor_method_test::should_properly_compare() { auto c_empty = default_constructor_method{}; auto c1a = make_default_constructor_method(make_type()); auto c1b = make_default_constructor_method(make_type()); auto c2a = make_default_constructor_method(make_type()); auto c2b = make_default_constructor_method(make_type()); test_compare({{c_empty}, {c1a, c1b}, {c2a, c2b}}); } QTEST_APPLESS_MAIN(default_constructor_method_test) #include "default-constructor-method-test.moc" injeqt-1.2.0/test/unit/dependencies-test.cpp000066400000000000000000000275351307635157000210740ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include #include #include #include #include #include "internal/dependencies.h" #include using namespace injeqt::internal; using namespace injeqt::v1; class injectable_type1 : public QObject { Q_OBJECT }; class sub_injectable_type1a : public injectable_type1 { Q_OBJECT }; class sub_injectable_type1b : public injectable_type1 { Q_OBJECT }; class injectable_type2 : public QObject { Q_OBJECT }; class injectable_type3 : public QObject { Q_OBJECT }; class valid_injected_type : public QObject { Q_OBJECT public: Q_INVOKABLE INJEQT_SET void setter_1(injectable_type1 *) {} public slots: INJEQT_SET void setter_2(injectable_type2 *) {} void no_injeqt_setter_1(injectable_type1 *) {} void no_injeqt_setter_2(injectable_type2 *) {} void no_injeqt_setter_3(int) {} }; class inheriting_valid_injected_type : public valid_injected_type { Q_OBJECT public slots: INJEQT_SET void setter_3(injectable_type3 *) {} }; class valid_injected_type_with_common_superclass : public QObject { Q_OBJECT public: Q_INVOKABLE INJEQT_SET void setter_1(sub_injectable_type1a *) {} public slots: INJEQT_SET void setter_2(sub_injectable_type1b *) {} }; class duplicate_dependency_injected_type : public QObject { Q_OBJECT public: Q_INVOKABLE INJEQT_SET void setter_1(injectable_type1 *) {} public slots: INJEQT_SET void setter_2(injectable_type1 *) {} }; class injected_type_with_superclass : public QObject { Q_OBJECT public: Q_INVOKABLE INJEQT_SET void setter_1(injectable_type1 *) {} public slots: INJEQT_SET void setter_2(sub_injectable_type1a *) {} }; class injected_type_with_superclass_inverted : public QObject { Q_OBJECT public: Q_INVOKABLE INJEQT_SET void setter_2(sub_injectable_type1a *) {} public slots: INJEQT_SET void setter_1(injectable_type1 *) {} }; class invalid_injected_type_depends_on_self : public QObject { Q_OBJECT public slots: INJEQT_SET void setter_1(invalid_injected_type_depends_on_self *) {} }; class invalid_injected_type_depends_on_subtype_subtype; class invalid_injected_type_depends_on_subtype : public QObject { Q_OBJECT public slots: INJEQT_SET void setter_1(invalid_injected_type_depends_on_subtype_subtype *) {} }; class invalid_injected_type_depends_on_subtype_subtype : public invalid_injected_type_depends_on_subtype { Q_OBJECT }; class invalid_injected_type_depends_on_supertype_supertype : public QObject { Q_OBJECT }; class invalid_injected_type_depends_on_supertype : public invalid_injected_type_depends_on_supertype_supertype { Q_OBJECT public slots: INJEQT_SET void setter_1(invalid_injected_type_depends_on_supertype_supertype *) {} }; class invalid_setter_empty_type : public QObject { Q_OBJECT public slots: INJEQT_SET void setter_int(int) {}; }; class invalid_setter_qobject_type : public QObject { Q_OBJECT public slots: INJEQT_SET void setter_qobject(QObject *) {}; }; class invalid_setter_no_paremeters : public QObject { Q_OBJECT public slots: INJEQT_SET void setter_no_paremeters() {}; }; class invalid_setter_two_paremters : public QObject { Q_OBJECT public slots: INJEQT_SET void setter_two_parameters(injectable_type1 *, injectable_type2 *) {}; }; class invalid_setter_is_signal: public QObject { Q_OBJECT signals: INJEQT_SET void setter_two_parameters(injectable_type1 *); }; class dependencies_test : public QObject { Q_OBJECT public: dependencies_test(); private slots: void should_find_no_dependnecies_in_qobject(); void should_find_all_valid_dependencies(); void should_find_all_valid_dependencies_in_hierarchy(); void should_find_dependencies_with_common_superclass(); void should_accept_duplicate_dependency(); void should_accept_superclass_dependency(); void should_accept_superclass_inverted_dependency(); void should_fail_when_depends_on_self(); void should_fail_when_depends_on_subtype(); void should_fail_when_depends_on_supertype(); void should_throw_when_setter_with_empty_type(); void should_throw_when_setter_with_qobject_type(); void should_throw_when_setter_with_no_parameters(); void should_throw_when_setter_with_two_parameters(); void should_throw_when_setter_is_signal(); private: types_by_name known_types; void verify_dependency(dependencies list, const dependency &check); }; dependencies_test::dependencies_test() { known_types = types_by_name{std::vector{ make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type() }}; } void dependencies_test::verify_dependency(dependencies list, const dependency &check) { auto iterator = std::find(begin(list), end(list), check); QVERIFY(iterator != end(list)); } void dependencies_test::should_find_no_dependnecies_in_qobject() { auto dependencies = extract_dependencies(known_types, make_type()); QCOMPARE(dependencies.size(), size_t{0}); } void dependencies_test::should_find_all_valid_dependencies() { auto dependencies = extract_dependencies(known_types, make_type()); QCOMPARE(dependencies.size(), size_t{2}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_1(injectable_type1*)")}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_2(injectable_type2*)")}); } void dependencies_test::should_find_all_valid_dependencies_in_hierarchy() { auto dependencies = extract_dependencies(known_types, make_type()); QCOMPARE(dependencies.size(), size_t{3}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_1(injectable_type1*)")}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_2(injectable_type2*)")}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_3(injectable_type3*)")}); } void dependencies_test::should_find_dependencies_with_common_superclass() { auto dependencies = extract_dependencies(known_types, make_type()); QCOMPARE(dependencies.size(), size_t{2}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_1(sub_injectable_type1a*)")}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_2(sub_injectable_type1b*)")}); } void dependencies_test::should_accept_duplicate_dependency() { auto dependencies = extract_dependencies(known_types, make_type()); QCOMPARE(dependencies.size(), size_t{2}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_1(injectable_type1*)")}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_2(injectable_type1*)")}); } void dependencies_test::should_accept_superclass_dependency() { auto dependencies = extract_dependencies(known_types, make_type()); QCOMPARE(dependencies.size(), size_t{2}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_1(injectable_type1*)")}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_2(sub_injectable_type1a*)")}); } void dependencies_test::should_accept_superclass_inverted_dependency() { auto dependencies = extract_dependencies(known_types, make_type()); QCOMPARE(dependencies.size(), size_t{2}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_2(sub_injectable_type1a*)")}); verify_dependency(dependencies, dependency{make_test_setter_method("setter_1(injectable_type1*)")}); } void dependencies_test::should_fail_when_depends_on_self() { expect({}, [&]{ auto dependencies = extract_dependencies(known_types, make_type()); }); } void dependencies_test::should_fail_when_depends_on_subtype() { expect({}, [&]{ auto dependencies = extract_dependencies(known_types, make_type()); }); } void dependencies_test::should_fail_when_depends_on_supertype() { expect({}, [&]{ auto dependencies = extract_dependencies(known_types, make_type()); }); } void dependencies_test::should_throw_when_setter_with_empty_type() { expect({"setter_int"}, [&]{ auto dependencies = extract_dependencies(known_types, make_type()); }); } void dependencies_test::should_throw_when_setter_with_qobject_type() { expect({"setter_qobject"}, [&]{ auto dependencies = extract_dependencies(known_types, make_type()); }); } void dependencies_test::should_throw_when_setter_with_no_parameters() { expect({"invalid parameter count"}, [&]{ auto dependencies = extract_dependencies(known_types, make_type()); }); } void dependencies_test::should_throw_when_setter_with_two_parameters() { expect({"invalid parameter count"}, [&]{ auto dependencies = extract_dependencies(known_types, make_type()); }); } void dependencies_test::should_throw_when_setter_is_signal() { expect({"setter is signal"}, [&]{ auto dependencies = extract_dependencies(known_types, make_type()); }); } QTEST_APPLESS_MAIN(dependencies_test); #include "dependencies-test.moc" injeqt-1.2.0/test/unit/dependency-test.cpp000066400000000000000000000047001307635157000205510ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "utils.h" #include "internal/dependency.h" #include using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT }; class type_2 : public QObject { Q_OBJECT }; class type_with_dependency : public QObject { Q_OBJECT public slots: INJEQT_SET void setter_1(type_1 *) { } INJEQT_SET void setter_1b(type_1 *) { } INJEQT_SET void setter_2(type_2 *) { } }; class dependency_test : public QObject { Q_OBJECT private slots: void should_create_valid_dependency(); void should_properly_compare(); }; void dependency_test::should_create_valid_dependency() { auto s = make_test_setter_method("setter_1(type_1*)"); auto d = dependency{s}; QCOMPARE(d.required_type(), make_type()); QCOMPARE(d.setter(), s); } void dependency_test::should_properly_compare() { auto s1a = dependency{make_test_setter_method("setter_1(type_1*)")}; auto s1b = dependency{make_test_setter_method("setter_1(type_1*)")}; auto s2a = dependency{make_test_setter_method("setter_1b(type_1*)")}; auto s2b = dependency{make_test_setter_method("setter_1b(type_1*)")}; auto s3a = dependency{make_test_setter_method("setter_2(type_2*)")}; auto s3b = dependency{make_test_setter_method("setter_2(type_2*)")}; test_compare({{s1a, s1b}, {s2a, s2b}, {s3a, s3b}}); } QTEST_APPLESS_MAIN(dependency_test) #include "dependency-test.moc" injeqt-1.2.0/test/unit/expect.h000066400000000000000000000031661307635157000164200ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include template void expect(const std::vector &contents, std::function call) { try { call(); QFAIL("Exception not thrown"); } catch (E &e) { for (auto &&content : contents) if (std::string(e.what()).find(content) == std::string::npos) QFAIL(qPrintable(QString{"Expected string '%1' not found in exception message '%2'"} .arg(content.c_str()) .arg(e.what()))); } catch (std::exception &e) { QFAIL(qPrintable(QString{"Unexpected exception thrown: %1 %2"} .arg(typeid(e).name()) .arg(e.what()))); } catch (...) { QFAIL("Unexpected exception thrown"); } } template void expect(std::function call) { expect({}, call); } injeqt-1.2.0/test/unit/factory-method-test.cpp000066400000000000000000000163521307635157000213660ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include #include "internal/factory-method.h" #include #include using namespace injeqt::internal; using namespace injeqt::v1; class result_object : public QObject { Q_OBJECT }; class other_object : public QObject { Q_OBJECT }; class factory_not_invokable : public QObject { Q_OBJECT public: result_object * create_result_object() { return nullptr; } }; class non_unique_factory : public QObject { Q_OBJECT public: Q_INVOKABLE result_object * create_result_object_1() { return nullptr; } Q_INVOKABLE result_object * create_result_object_2() { return nullptr; } }; class valid_factory : public QObject { Q_OBJECT public slots: Q_INVOKABLE result_object * create_result_object() { return new result_object{}; } }; class valid_factory_subtype : public valid_factory { Q_OBJECT }; class valid_multi_factory : public QObject { Q_OBJECT public slots: Q_INVOKABLE result_object * create_result_object() { return new result_object{}; } Q_INVOKABLE other_object * create_other_object() { return new other_object{}; } }; class valid_factory_with_default_parameter : public QObject { Q_OBJECT public slots: Q_INVOKABLE result_object * create_result_object(int a = 0) { (void)a; return new result_object{}; } }; class invalid_factory : public QObject { Q_OBJECT public slots: Q_INVOKABLE result_object * create_result_object(int) { return new result_object{}; } }; class factory_method_test : public QObject { Q_OBJECT public: factory_method_test(); private slots: void should_return_empty_when_created_with_not_invokable_factory_method(); void should_return_empty_when_created_with_non_unique_factory_method(); void should_return_empty_when_created_with_different_type_factory_method(); void should_return_empty_when_created_with_invalid_factory_method(); void should_create_empty(); void should_create_valid_with_invokable_factory_method(); void should_create_valid_subtype_with_invokable_factory_method(); void should_create_valid_with_invokable_factory_with_default_parameter_method(); void should_create_object_with_factory_method(); void should_properly_compare(); private: types_by_name known_types; }; factory_method_test::factory_method_test() { known_types = types_by_name{std::vector{ make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type() }}; } void factory_method_test::should_return_empty_when_created_with_not_invokable_factory_method() { auto f = make_factory_method(known_types, make_type(), make_type()); QVERIFY(f.is_empty()); } void factory_method_test::should_return_empty_when_created_with_non_unique_factory_method() { auto f = make_factory_method(known_types, make_type(), make_type()); QVERIFY(f.is_empty()); } void factory_method_test::should_return_empty_when_created_with_different_type_factory_method() { auto f = make_factory_method(known_types, make_type(), make_type()); QVERIFY(f.is_empty()); } void factory_method_test::should_return_empty_when_created_with_invalid_factory_method() { auto f = make_factory_method(known_types, make_type(), make_type()); QVERIFY(f.is_empty()); } void factory_method_test::should_create_empty() { auto f = factory_method{}; QVERIFY(f.is_empty()); } void factory_method_test::should_create_valid_with_invokable_factory_method() { auto f1 = factory_method{make_type(), make_method("create_result_object()")}; QVERIFY(!f1.is_empty()); QCOMPARE(f1.object_type(), make_type()); QCOMPARE(f1.result_type(), make_type()); auto f2 = make_factory_method(known_types, make_type(), make_type()); QVERIFY(!f2.is_empty()); QCOMPARE(f2.object_type(), make_type()); QCOMPARE(f2.result_type(), make_type()); QCOMPARE(f1, f2); } void factory_method_test::should_create_valid_subtype_with_invokable_factory_method() { auto f1 = factory_method{make_type(), make_method("create_result_object()")}; QVERIFY(!f1.is_empty()); QCOMPARE(f1.object_type(), make_type()); QCOMPARE(f1.result_type(), make_type()); auto f2 = make_factory_method(known_types, make_type(), make_type()); QVERIFY(!f2.is_empty()); QCOMPARE(f2.object_type(), make_type()); QCOMPARE(f2.result_type(), make_type()); QCOMPARE(f1, f2); } void factory_method_test::should_create_valid_with_invokable_factory_with_default_parameter_method() { auto f = make_factory_method(known_types, make_type(), make_type()); QVERIFY(!f.is_empty()); QCOMPARE(f.object_type(), make_type()); QCOMPARE(f.result_type(), make_type()); } void factory_method_test::should_create_object_with_factory_method() { auto f = make_factory_method(known_types, make_type(), make_type()); auto factory_object = make_object(); auto object = f.invoke(factory_object.get()); auto cast = qobject_cast(object.get()); QVERIFY(cast != nullptr); } void factory_method_test::should_properly_compare() { auto fm_empty = factory_method{}; auto fm1a = make_factory_method(known_types, make_type(), make_type()); auto fm1b = make_factory_method(known_types, make_type(), make_type()); auto fm2a = make_factory_method(known_types, make_type(), make_type()); auto fm2b = make_factory_method(known_types, make_type(), make_type()); auto fm3a = make_factory_method(known_types, make_type(), make_type()); auto fm3b = make_factory_method(known_types, make_type(), make_type()); test_compare({{fm_empty}, {fm1a, fm1b}, {fm2a, fm2b}, {fm3a, fm3b}}); } QTEST_APPLESS_MAIN(factory_method_test) #include "factory-method-test.moc" injeqt-1.2.0/test/unit/implementation-test.cpp000066400000000000000000000106461307635157000214660ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include #include #include #include #include "internal/implementation.h" #include using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT }; class type_2 : public QObject { Q_OBJECT }; class type_1_subtype_1 : public type_1 { Q_OBJECT }; class type_1_subtype_1_subtype_1 : public type_1_subtype_1 { Q_OBJECT }; class implementation_test : public QObject { Q_OBJECT private slots: void should_throw_when_type_is_empty(); void should_throw_when_type_is_qobject(); void should_throw_when_object_is_null(); void should_accept_object_of_type(); void should_accept_object_of_sub_type(); void should_accept_object_of_sub_sub_type(); void should_not_accept_object_of_super_type(); void should_not_accept_object_of_other_type(); void should_properly_compare(); }; void implementation_test::should_throw_when_type_is_empty() { auto object = make_object(); expect([&]{ make_implementation(type{}, object.get()); }); } void implementation_test::should_throw_when_type_is_qobject() { auto object = make_object(); expect([&]{ make_implementation(make_type(), object.get()); }); } void implementation_test::should_throw_when_object_is_null() { expect({}, [&]{ make_implementation(make_type(), nullptr); }); } void implementation_test::should_accept_object_of_type() { auto object = make_object(); auto i = make_implementation(make_type(), object.get()); QCOMPARE(make_type(), i.interface_type()); QCOMPARE(object.get(), i.object()); } void implementation_test::should_accept_object_of_sub_type() { auto object = make_object(); auto i = make_implementation(make_type(), object.get()); QCOMPARE(make_type(), i.interface_type()); QCOMPARE(object.get(), i.object()); } void implementation_test::should_accept_object_of_sub_sub_type() { auto object = make_object(); auto i = make_implementation(make_type(), object.get()); QCOMPARE(make_type(), i.interface_type()); QCOMPARE(object.get(), i.object()); } void implementation_test::should_not_accept_object_of_super_type() { auto object = make_object(); expect({"type_1", "type_1_subtype_1_subtype_1"}, [&]{ make_implementation(make_type(), object.get()); }); } void implementation_test::should_not_accept_object_of_other_type() { auto object = make_object(); expect({"type_1", "type_2"}, [&]{ make_implementation(make_type(), object.get()); }); } void implementation_test::should_properly_compare() { auto o1a = make_object(); auto o1b = make_object(); auto o2 = make_object(); auto i1a = make_implementation(make_type(), o1a.get()); auto i1b = make_implementation(make_type(), o1a.get()); auto i2a = make_implementation(make_type(), o1b.get()); auto i2b = make_implementation(make_type(), o1b.get()); auto i3a = make_implementation(make_type(), o2.get()); auto i3b = make_implementation(make_type(), o2.get()); test_compare({{i1a, i1b}, {i2a, i2b}, {i3a, i3b}}); } QTEST_APPLESS_MAIN(implementation_test) #include "implementation-test.moc" injeqt-1.2.0/test/unit/implemented-by-test.cpp000066400000000000000000000053041307635157000213470ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include "internal/implemented-by.h" #include using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT }; class type_2 : public QObject { Q_OBJECT }; class type_1_subtype_1 : public type_1 { Q_OBJECT }; class type_1_subtype_1_subtype_1 : public type_1_subtype_1 { Q_OBJECT }; class implemented_by_test : public QObject { Q_OBJECT private slots: void should_accept_implemented_by_self(); void should_accept_implemented_by_subtype(); void should_properly_compare(); }; void implemented_by_test::should_accept_implemented_by_self() { auto i = implemented_by{make_type(), make_type()}; QCOMPARE(make_type(), i.interface_type()); QCOMPARE(make_type(), i.implementation_type()); } void implemented_by_test::should_accept_implemented_by_subtype() { auto i = implemented_by{make_type(), make_type()}; QCOMPARE(make_type(), i.interface_type()); QCOMPARE(make_type(), i.implementation_type()); } void implemented_by_test::should_properly_compare() { auto ib1a = implemented_by{make_type(), make_type()}; auto ib1b = implemented_by{make_type(), make_type()}; auto ib2a = implemented_by{make_type(), make_type()}; auto ib2b = implemented_by{make_type(), make_type()}; auto ib3a = implemented_by{make_type(), make_type()}; auto ib3b = implemented_by{make_type(), make_type()}; test_compare({{ib1a, ib1b}, {ib2a, ib2b}, {ib3a, ib3b}}); } QTEST_APPLESS_MAIN(implemented_by_test) #include "implemented-by-test.moc" injeqt-1.2.0/test/unit/injector-core-test.cpp000066400000000000000000000372221307635157000212030ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "../mocks/mocked-provider.h" #include "expect.h" #include "utils.h" #include #include #include #include #include "internal/injector-core.h" #include #include using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT }; class type_1_subtype_1 : public type_1 { Q_OBJECT }; class type_1_subtype_2 : public type_1 { Q_OBJECT }; class type_2 : public QObject { Q_OBJECT public: type_1 *o = nullptr; private slots: INJEQT_SET void set_type_1(type_1 *x) { o = x; } }; class type_3 : public QObject { Q_OBJECT }; class type_4; class type_5; class type_6; class type_4 : public QObject { Q_OBJECT public: type_5 *o = nullptr; private slots: INJEQT_SET void set_type_5(type_5 *x) { o = x; } }; class type_5 : public QObject { Q_OBJECT public: type_6 *o = nullptr; private slots: INJEQT_SET void set_type_6(type_6 *x) { o = x; } }; class type_6 : public QObject { Q_OBJECT public: type_4 *o = nullptr; private slots: INJEQT_SET void set_type_4(type_4 *x) { o = x; } }; class type_7 : public QObject { Q_OBJECT }; class type_8 : public QObject { Q_OBJECT }; class type_9 : public QObject { Q_OBJECT public: type_7 *o7 = nullptr; type_8 *o8 = nullptr; private slots: INJEQT_SET void set_type_7(type_7 *x) { o7 = x; } INJEQT_SET void set_type_8(type_8 *x) { o8 = x; } }; class unregistered_type : public QObject { Q_OBJECT public: type_1 *o1; type_2 *o2; unregistered_type() : QObject{}, o1{nullptr}, o2{nullptr} {} private slots: INJEQT_SET void set_type_1(type_1 *x) { o1 = x; } INJEQT_SET void set_type_1(type_2 *x) { o2 = x; } }; class injector_core_test : public QObject { Q_OBJECT private: template T * get(injector_core &i) { return qobject_cast(i.get(make_type())); } private slots: void should_create_empty_injector_core(); void should_create_simple_injector_core_and_return_object(); void should_not_accept_doubled_type(); void should_not_accept_type_and_subtype(); void should_not_accept_subtype_and_type(); void should_accept_two_subtypes(); void should_not_accept_unresolvable_dependency(); void should_accept_resolvable_dependency(); void should_accept_resolvable_supertype_dependency(); void should_not_accept_ambiguous_supertype_dependency(); void should_not_accept_unknown_required_type(); void should_accept_known_required_type(); void should_accept_known_required_supertype(); void should_not_accept_ambiguous_required_supertype(); void should_accept_cyclic_dependencies(); void should_accept_dependencies_that_are_required(); void should_inject_into_unregistered_type(); void should_not_inject_into_when_unknown_dependencies(); // TODO: https://github.com/vogel/injeqt/issues/3 /* void should_not_accept_cyclic_required_types(); void should_not_accept_dependent_as_required_type(); */ }; void injector_core_test::should_create_empty_injector_core() { auto i = injector_core{}; expect({"type_1"}, [&](){ i.get(make_type()); }); } void injector_core_test::should_create_simple_injector_core_and_return_object() { auto type_1_provider_p = make_mocked_provider(); auto type_1_provider = type_1_provider_p.get(); auto configuration = std::vector>{}; configuration.push_back(std::move(type_1_provider_p)); auto i = injector_core{types_by_name{}, std::move(configuration)}; QVERIFY(type_1_provider->object() == nullptr); auto o1 = get(i); auto o2 = get(i); QVERIFY(o1 != nullptr); QVERIFY(o1 == o2); QVERIFY(type_1_provider->object() == o1); } void injector_core_test::should_not_accept_doubled_type() { auto configuration = std::vector>{}; configuration.push_back(make_mocked_provider()); configuration.push_back(make_mocked_provider()); expect({}, [&](){ auto i = injector_core{types_by_name{}, std::move(configuration)}; }); } void injector_core_test::should_not_accept_type_and_subtype() { auto configuration = std::vector>{}; configuration.push_back(make_mocked_provider()); configuration.push_back(make_mocked_provider()); expect({"type_1"}, [&](){ auto i = injector_core{types_by_name{}, std::move(configuration)}; }); } void injector_core_test::should_not_accept_subtype_and_type() { auto configuration = std::vector>{}; configuration.push_back(make_mocked_provider()); configuration.push_back(make_mocked_provider()); expect({"type_1"}, [&](){ auto i = injector_core{types_by_name{}, std::move(configuration)}; }); } void injector_core_test::should_accept_two_subtypes() { auto configuration = std::vector>{}; configuration.push_back(make_mocked_provider()); configuration.push_back(make_mocked_provider()); auto i = injector_core{types_by_name{}, std::move(configuration)}; auto o1 = get(i); auto o2 = get(i); QVERIFY(o1 != nullptr); QVERIFY(o2 != nullptr); expect({"type_1"}, [&](){ get(i); }); } void injector_core_test::should_not_accept_unresolvable_dependency() { auto configuration = std::vector>{}; configuration.push_back(make_mocked_provider()); expect({"set_type_1"}, [&](){ // TODO: figure out better exception name auto i = injector_core{types_by_name{}, std::move(configuration)}; }); } void injector_core_test::should_accept_resolvable_dependency() { auto type_1_provider_p = make_mocked_provider(); auto type_1_provider = type_1_provider_p.get(); auto type_2_provider_p = make_mocked_provider(); auto type_2_provider = type_2_provider_p.get(); auto configuration = std::vector>{}; configuration.push_back(std::move(type_1_provider_p)); configuration.push_back(std::move(type_2_provider_p)); auto i = injector_core{types_by_name{make_type(), make_type()}, std::move(configuration)}; QVERIFY(type_1_provider->object() == nullptr); QVERIFY(type_2_provider->object() == nullptr); auto o2 = get(i); auto o1 = type_1_provider->object(); QVERIFY(o1 != nullptr); QVERIFY(o2 != nullptr); QVERIFY(o1 == get(i)); QVERIFY(o1 == o2->o); } void injector_core_test::should_accept_resolvable_supertype_dependency() { auto type_1_provider_p = make_mocked_provider(); auto type_1_provider = type_1_provider_p.get(); auto type_2_provider_p = make_mocked_provider(); auto type_2_provider = type_2_provider_p.get(); auto configuration = std::vector>{}; configuration.push_back(std::move(type_1_provider_p)); configuration.push_back(std::move(type_2_provider_p)); auto i = injector_core{types_by_name{make_type(), make_type(), make_type()}, std::move(configuration)}; QVERIFY(type_1_provider->object() == nullptr); QVERIFY(type_2_provider->object() == nullptr); auto o2 = get(i); auto o1 = type_1_provider->object(); QVERIFY(o1 != nullptr); QVERIFY(o2 != nullptr); QVERIFY(o1 == get(i)); QVERIFY(o1 == get(i)); QVERIFY(o1 = o2->o); } void injector_core_test::should_not_accept_ambiguous_supertype_dependency() { auto configuration = std::vector>{}; configuration.push_back(make_mocked_provider()); configuration.push_back(make_mocked_provider()); configuration.push_back(make_mocked_provider()); expect({"set_type_1"}, [&](){ // better exception name auto i = injector_core{types_by_name{}, std::move(configuration)}; }); } void injector_core_test::should_not_accept_unknown_required_type() { auto configuration = std::vector>{}; configuration.push_back(make_mocked_provider()); expect({"type_1"}, [&](){ auto i = injector_core{types_by_name{}, std::move(configuration)}; }); } void injector_core_test::should_accept_known_required_type() { auto type_1_provider_p = make_mocked_provider(); auto type_1_provider = type_1_provider_p.get(); auto type_3_provider_p = make_mocked_provider(); auto type_3_provider = type_3_provider_p.get(); auto configuration = std::vector>{}; configuration.push_back(std::move(type_1_provider_p)); configuration.push_back(std::move(type_3_provider_p)); auto i = injector_core{types_by_name{}, std::move(configuration)}; QVERIFY(type_1_provider->object() == nullptr); QVERIFY(type_3_provider->object() == nullptr); auto o3 = get(i); auto o1 = type_1_provider->object(); QVERIFY(o3 != nullptr); QVERIFY(o1 != nullptr); QVERIFY(o1 == get(i)); } void injector_core_test::should_accept_known_required_supertype() { auto type_1_provider_p = make_mocked_provider(); auto type_1_provider = type_1_provider_p.get(); auto type_3_provider_p = make_mocked_provider(); auto type_3_provider = type_3_provider_p.get(); auto configuration = std::vector>{}; configuration.push_back(std::move(type_1_provider_p)); configuration.push_back(std::move(type_3_provider_p)); auto i = injector_core{types_by_name{}, std::move(configuration)}; QVERIFY(type_1_provider->object() == nullptr); QVERIFY(type_3_provider->object() == nullptr); auto o3 = get(i); auto o1 = type_1_provider->object(); QVERIFY(o3 != nullptr); QVERIFY(o1 != nullptr); QVERIFY(o1 == get(i)); QVERIFY(o1 == get(i)); } void injector_core_test::should_not_accept_ambiguous_required_supertype() { auto configuration = std::vector>{}; configuration.push_back(make_mocked_provider()); configuration.push_back(make_mocked_provider()); configuration.push_back(make_mocked_provider()); expect({"type_1"}, [&](){ auto i = injector_core{types_by_name{}, std::move(configuration)}; }); } void injector_core_test::should_accept_cyclic_dependencies() { auto type_4_provider_p = make_mocked_provider(); auto type_4_provider = type_4_provider_p.get(); auto type_5_provider_p = make_mocked_provider(); auto type_5_provider = type_5_provider_p.get(); auto type_6_provider_p = make_mocked_provider(); auto type_6_provider = type_6_provider_p.get(); auto configuration = std::vector>{}; configuration.push_back(std::move(type_4_provider_p)); configuration.push_back(std::move(type_5_provider_p)); configuration.push_back(std::move(type_6_provider_p)); auto i = injector_core{types_by_name{make_type(), make_type(), make_type()}, std::move(configuration)}; QVERIFY(type_4_provider->object() == nullptr); QVERIFY(type_5_provider->object() == nullptr); QVERIFY(type_6_provider->object() == nullptr); auto o5 = get(i); auto o4 = type_4_provider->object(); auto o6 = type_6_provider->object(); QVERIFY(o4 != nullptr); QVERIFY(o5 != nullptr); QVERIFY(o6 != nullptr); QVERIFY(o4 == get(i)); QVERIFY(o6 == get(i)); QVERIFY(o4 == get(i)->o); QVERIFY(o5 == get(i)->o); QVERIFY(o6 == get(i)->o); } void injector_core_test::should_accept_dependencies_that_are_required() { auto type_7_provider_p = make_mocked_provider(); auto type_7_provider = type_7_provider_p.get(); auto type_8_provider_p = make_mocked_provider(); auto type_8_provider = type_8_provider_p.get(); auto type_9_provider_p = make_mocked_provider(); auto type_9_provider = type_8_provider_p.get(); auto configuration = std::vector>{}; configuration.push_back(std::move(type_7_provider_p)); configuration.push_back(std::move(type_8_provider_p)); configuration.push_back(std::move(type_9_provider_p)); auto i = injector_core{types_by_name{make_type(), make_type(), make_type()}, std::move(configuration)}; QVERIFY(type_7_provider->object() == nullptr); QVERIFY(type_8_provider->object() == nullptr); QVERIFY(type_9_provider->object() == nullptr); auto o9 = get(i); auto o7 = type_7_provider->object(); auto o8 = type_8_provider->object(); QVERIFY(o9 != nullptr); QVERIFY(o7 != nullptr); QVERIFY(o8 != nullptr); QVERIFY(o7 == get(i)); QVERIFY(o8 == get(i)); } void injector_core_test::should_inject_into_unregistered_type() { auto type_1_provider_p = make_mocked_provider(); auto type_2_provider_p = make_mocked_provider(); auto configuration = std::vector>{}; configuration.push_back(std::move(type_1_provider_p)); configuration.push_back(std::move(type_2_provider_p)); auto i = injector_core{types_by_name{make_type(), make_type()}, std::move(configuration)}; auto unregistered = std::unique_ptr(new unregistered_type{}); i.inject_into(unregistered.get()); QVERIFY(unregistered->o1 != nullptr); QVERIFY(unregistered->o2 != nullptr); QCOMPARE(unregistered->o1, get(i)); QCOMPARE(unregistered->o2, get(i)); } void injector_core_test::should_not_inject_into_when_unknown_dependencies() { auto type_1_provider_p = make_mocked_provider(); auto configuration = std::vector>{}; configuration.push_back(std::move(type_1_provider_p)); auto i = injector_core{types_by_name{make_type()}, std::move(configuration)}; auto unregistered = std::unique_ptr(new unregistered_type{}); expect({"type_2"}, [&](){ i.inject_into(unregistered.get()); }); } // TODO: https://github.com/vogel/injeqt/issues/3 /* void injector_core_test::should_not_accept_cyclic_required_types() { auto configuration = std::vector>{}; configuration.push_back(make_mocked_provider()); configuration.push_back(make_mocked_provider()); configuration.push_back(make_mocked_provider()); expect([&](){ auto i = injector_core{std::move(configuration)}; }); } void injector_core_test::should_not_accept_dependent_as_required_type() { auto configuration = std::vector>{}; configuration.push_back(make_mocked_provider()); configuration.push_back(make_mocked_provider()); expect([&](){ auto i = injector_core{std::move(configuration)}; }); } */ QTEST_APPLESS_MAIN(injector_core_test) #include "injector-core-test.moc" injeqt-1.2.0/test/unit/injector-test.cpp000066400000000000000000000152511307635157000202530ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include #include #include #include #include #include #include #include #include using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT public: Q_INVOKABLE type_1() {} }; class type_1_subtype_1 : public type_1 { Q_OBJECT public: Q_INVOKABLE type_1_subtype_1() {} }; class type_1_subtype_2 : public type_1 { Q_OBJECT public: Q_INVOKABLE type_1_subtype_2() {} }; class require_common_type : public QObject { Q_OBJECT public: Q_INVOKABLE require_common_type() {} private slots: INJEQT_SET void set_type_1(type_1 *) { } }; class created_by_factory : public QObject { Q_OBJECT public: created_by_factory() {} }; class default_constructible_factory : public QObject { Q_OBJECT public: Q_INVOKABLE default_constructible_factory() {} Q_INVOKABLE created_by_factory * create() { return new created_by_factory{}; } }; class ready_type : public QObject { Q_OBJECT }; class subinjector_object : public QObject { Q_OBJECT public: Q_INVOKABLE subinjector_object() {} created_by_factory *_x; private slots: INJEQT_SET void set_created_by_factory(created_by_factory *x) { _x = x; } }; class test_module : public module { public: test_module() { _ready_object = std::unique_ptr{new ready_type{}}; add_type(); add_type(); add_factory(); add_ready_object(_ready_object.get()); } private: std::unique_ptr _ready_object; }; class test_submodule : public module { public: test_submodule() { add_type(); } }; class disable_common_supertype_submodule : public module { public: disable_common_supertype_submodule() { add_type(); add_type(); } }; class injector_test : public QObject { Q_OBJECT private slots: void should_create_empty_injector(); void should_not_accept_qobject_type(); void should_not_accept_unknown_type(); void should_create_valid_injector(); void should_handle_subinjector(); void should_not_accept_double_superinjector(); void should_disable_common_type_in_superinjector(); void should_allow_move(); }; class not_configured_type : public QObject { Q_OBJECT }; void injector_test::should_create_empty_injector() { injector{}; } void injector_test::should_not_accept_qobject_type() { auto i = injector{}; expect([&](){ i.get(); }); } void injector_test::should_not_accept_unknown_type() { auto i = injector{}; expect({"default_constructible_factory"}, [&](){ i.get(); }); } void injector_test::should_create_valid_injector() { auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr(new test_module{})); auto i = injector{std::move(modules)}; QVERIFY(i.get() != nullptr); QVERIFY(i.get() != nullptr); QVERIFY(i.get() != nullptr); expect({"not_configured_type"}, [&](){ i.get(); }); } void injector_test::should_handle_subinjector() { auto super_modules = std::vector>{}; super_modules.emplace_back(std::unique_ptr(new test_module{})); auto super_injector = injector{std::move(super_modules)}; auto super_injectors = std::vector{&super_injector}; auto sub_modules = std::vector>{}; sub_modules.emplace_back(std::unique_ptr(new test_submodule{})); auto sub_injector = injector{super_injectors, std::move(sub_modules)}; QVERIFY(sub_injector.get() != nullptr); } void injector_test::should_not_accept_double_superinjector() { auto super_modules = std::vector>{}; super_modules.emplace_back(std::unique_ptr(new test_module{})); auto super_injector = injector{std::move(super_modules)}; auto super_injectors = std::vector{&super_injector, &super_injector}; auto sub_modules = std::vector>{}; sub_modules.emplace_back(std::unique_ptr(new test_submodule{})); expect({}, [&]{ injector{super_injectors, std::move(sub_modules)}; }); } void injector_test::should_disable_common_type_in_superinjector() { auto super_modules = std::vector>{}; super_modules.emplace_back(std::unique_ptr(new test_module{})); auto super_injector = injector{std::move(super_modules)}; auto super_injectors = std::vector{&super_injector}; auto sub_modules = std::vector>{}; sub_modules.emplace_back(std::unique_ptr(new disable_common_supertype_submodule{})); expect({"type_1"}, [&]{ injector{super_injectors, std::move(sub_modules)}; }); } void injector_test::should_allow_move() { auto modules = std::vector>{}; modules.emplace_back(std::unique_ptr(new test_module{})); auto i = injector{std::move(modules)}; auto i2 = std::move(i); auto i3 = injector{}; i3 = std::move(i2); QVERIFY(i3.get() != nullptr); QVERIFY(i3.get() != nullptr); QVERIFY(i3.get() != nullptr); expect({"not_configured_type"}, [&](){ i3.get(); }); } QTEST_APPLESS_MAIN(injector_test) #include "injector-test.moc" injeqt-1.2.0/test/unit/interfaces-utils-test.cpp000066400000000000000000000070311307635157000217140ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "internal/interfaces-utils.h" #include using namespace injeqt::internal; using namespace injeqt::v1; class direct_successor : public QObject { Q_OBJECT }; class indirect_successor_1 : public direct_successor { Q_OBJECT }; class indirect_successor_2 : public indirect_successor_1 { Q_OBJECT }; class interfaces_utils_test : public QObject { Q_OBJECT public: interfaces_utils_test(); private slots: void should_find_nothing_in_qobject(); void should_find_one_in_direct_successor(); void should_find_two_in_indirect_successor_1(); void should_find_three_in_indirect_successor_2(); private: type qobject_type; type direct_successor_type; type indirect_successor_1_type; type indirect_successor_2_type; }; interfaces_utils_test::interfaces_utils_test() : qobject_type{type(&QObject::staticMetaObject)}, direct_successor_type{make_type()}, indirect_successor_1_type{make_type()}, indirect_successor_2_type{make_type()} { } void interfaces_utils_test::should_find_nothing_in_qobject() { auto interfaces = extract_interfaces(qobject_type); QCOMPARE(interfaces.size(), size_t{0}); QVERIFY(!implements(qobject_type, qobject_type)); } void interfaces_utils_test::should_find_one_in_direct_successor() { auto interfaces = extract_interfaces(direct_successor_type); QCOMPARE(interfaces, (types{direct_successor_type})); QVERIFY(implements(direct_successor_type, direct_successor_type)); } void interfaces_utils_test::should_find_two_in_indirect_successor_1() { auto interfaces = extract_interfaces(indirect_successor_1_type); QCOMPARE(interfaces, (types{direct_successor_type, indirect_successor_1_type})); QVERIFY(!implements(indirect_successor_1_type, qobject_type)); QVERIFY(implements(indirect_successor_1_type, direct_successor_type)); QVERIFY(implements(indirect_successor_1_type, indirect_successor_1_type)); QVERIFY(!implements(indirect_successor_1_type, indirect_successor_2_type)); } void interfaces_utils_test::should_find_three_in_indirect_successor_2() { auto interfaces = extract_interfaces(indirect_successor_2_type); QCOMPARE(interfaces, (types{direct_successor_type, indirect_successor_1_type, indirect_successor_2_type})); QVERIFY(implements(direct_successor_type, direct_successor_type)); QVERIFY(!implements(indirect_successor_2_type, qobject_type)); QVERIFY(implements(indirect_successor_2_type, direct_successor_type)); QVERIFY(implements(indirect_successor_2_type, indirect_successor_1_type)); QVERIFY(implements(indirect_successor_2_type, indirect_successor_2_type)); } QTEST_APPLESS_MAIN(interfaces_utils_test); #include "interfaces-utils-test.moc" injeqt-1.2.0/test/unit/module-impl-test.cpp000066400000000000000000000046751307635157000206720ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "../mocks/mocked-provider-configuration.h" #include "expect.h" #include "utils.h" #include "internal/module-impl.h" #include #include using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT public: Q_INVOKABLE type_1() {} }; class factory_type_1 : public QObject { Q_OBJECT public: Q_INVOKABLE type_1 * create_type_1() { return nullptr; } }; class module_impl_test : public QObject { Q_OBJECT private slots: void should_properly_add_provider_configurations(); }; void module_impl_test::should_properly_add_provider_configurations() { auto m = module_impl{}; QCOMPARE(m.provider_configurations().size(), size_t{0}); auto p1 = std::make_shared(); m.add_provider_configuration(p1); QCOMPARE(m.provider_configurations().size(), size_t{1}); QCOMPARE(m.provider_configurations()[0].get(), p1.get()); auto p2 = std::make_shared(); m.add_provider_configuration(p2); QCOMPARE(m.provider_configurations().size(), size_t{2}); QCOMPARE(m.provider_configurations()[0].get(), p1.get()); QCOMPARE(m.provider_configurations()[1].get(), p2.get()); auto p3 = std::make_shared(); m.add_provider_configuration(p3); QCOMPARE(m.provider_configurations().size(), size_t{3}); QCOMPARE(m.provider_configurations()[0].get(), p1.get()); QCOMPARE(m.provider_configurations()[1].get(), p2.get()); QCOMPARE(m.provider_configurations()[2].get(), p3.get()); } QTEST_APPLESS_MAIN(module_impl_test) #include "module-impl-test.moc" injeqt-1.2.0/test/unit/module-test.cpp000066400000000000000000000135321307635157000177230ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "../mocks/mocked-provider.h" #include "expect.h" #include "utils.h" #include #include #include using namespace injeqt::internal; using namespace injeqt::v1; class not_default_constructible_type : public QObject { Q_OBJECT }; class not_default_constructible_type_subtype : public not_default_constructible_type { Q_OBJECT }; class default_constructible_type : public QObject { Q_OBJECT public: Q_INVOKABLE default_constructible_type() {} }; class factory_type : public QObject { Q_OBJECT public: Q_INVOKABLE default_constructible_type * create() const { return nullptr; } }; class factory_subtype_type : public QObject { Q_OBJECT public: Q_INVOKABLE not_default_constructible_type_subtype * create() const { return nullptr; } }; class factory_double_type : public QObject { Q_OBJECT public: Q_INVOKABLE not_default_constructible_type * create1() const { return nullptr; } Q_INVOKABLE not_default_constructible_type * create2() const { return nullptr; } }; class module_test : public QObject { Q_OBJECT private slots: void should_accept_empty_module(); void should_accept_null_ready_object(); void should_accept_qobject_ready_object(); void should_accept_valid_ready_object(); void should_accept_subtype_ready_object(); void should_accept_supertype_ready_object(); void should_accept_qobject_type(); void should_accept_not_default_constructible_type(); void should_accept_default_constructible_type(); void should_accept_qobject_factory_type(); void should_accept_qobject_created_type(); void should_accept_valid_factory_type(); void should_accept_supertype_factory_type(); void should_accept_subtype_factory_type(); void should_accept_double_factory_type(); }; void module_test::should_accept_empty_module() { class test_module : public module { }; test_module{}; } void module_test::should_accept_null_ready_object() { class test_module : public module { public: test_module() { add_ready_object(nullptr); } }; test_module{}; } void module_test::should_accept_qobject_ready_object() { class test_module : public module { public: test_module() { not_default_constructible_type object; add_ready_object(&object); } }; test_module{}; } void module_test::should_accept_valid_ready_object() { class test_module : public module { public: test_module() { not_default_constructible_type object; add_ready_object(&object); } }; test_module{}; } void module_test::should_accept_subtype_ready_object() { class test_module : public module { public: test_module() { not_default_constructible_type_subtype object; add_ready_object(&object); } }; test_module{}; } void module_test::should_accept_supertype_ready_object() { class test_module : public module { public: test_module() { not_default_constructible_type object; add_ready_object(&object); } }; test_module{}; } void module_test::should_accept_qobject_type() { class test_module : public module { public: test_module() { add_type(); } }; test_module{}; } void module_test::should_accept_not_default_constructible_type() { class test_module : public module { public: test_module() { add_type(); } }; test_module{}; } void module_test::should_accept_default_constructible_type() { class test_module : public module { public: test_module() { add_type(); } }; test_module{}; } void module_test::should_accept_qobject_factory_type() { class test_module : public module { public: test_module() { add_factory(); } }; test_module{}; } void module_test::should_accept_qobject_created_type() { class test_module : public module { public: test_module() { add_factory(); } }; test_module{}; } void module_test::should_accept_valid_factory_type() { class test_module : public module { public: test_module() { add_factory(); add_factory(); } }; test_module{}; } void module_test::should_accept_subtype_factory_type() { class test_module : public module { public: test_module() { add_factory(); } }; test_module{}; } void module_test::should_accept_supertype_factory_type() { class test_module : public module { public: test_module() { add_factory(); } }; test_module{}; } void module_test::should_accept_double_factory_type() { class test_module : public module { public: test_module() { add_factory(); } }; test_module{}; } QTEST_APPLESS_MAIN(module_test) #include "module-test.moc" injeqt-1.2.0/test/unit/provider-by-default-constructor-configuration-test.cpp000066400000000000000000000052141307635157000275500ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include #include #include "internal/injector-core.h" #include "internal/provider-by-default-constructor-configuration.h" #include #include using namespace injeqt::v1; using namespace injeqt::internal; class default_constructor_type : public QObject { Q_OBJECT public: Q_INVOKABLE default_constructor_type() {} }; class not_default_constructor_type : public QObject { Q_OBJECT }; class provider_by_default_constructor_configuration_test : public QObject { Q_OBJECT private slots: void should_accept_qobject_type_and_throw_on_create(); void should_accept_type_without_default_constructor_and_throw_on_create(); void should_accept_valid_configuration(); }; void provider_by_default_constructor_configuration_test::should_accept_qobject_type_and_throw_on_create() { auto pc = provider_by_default_constructor_configuration{make_type()}; expect([&](){ pc.create_provider({}); }); } void provider_by_default_constructor_configuration_test::should_accept_type_without_default_constructor_and_throw_on_create() { auto pc = provider_by_default_constructor_configuration{make_type()}; expect([&](){ pc.create_provider({}); }); } void provider_by_default_constructor_configuration_test::should_accept_valid_configuration() { auto i = injector_core{}; auto pc = provider_by_default_constructor_configuration{make_type()}; auto p = pc.create_provider({}); QVERIFY(nullptr != p->provide(i)); } QTEST_APPLESS_MAIN(provider_by_default_constructor_configuration_test) #include "provider-by-default-constructor-configuration-test.moc" injeqt-1.2.0/test/unit/provider-by-default-constructor-test.cpp000066400000000000000000000041601307635157000247020ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "internal/injector-core.h" #include "internal/provider-by-default-constructor.h" #include #include using namespace injeqt::v1; using namespace injeqt::internal; class default_constructor_type : public QObject { Q_OBJECT public: Q_INVOKABLE default_constructor_type() {} }; class provider_by_default_constructor_test : public QObject { Q_OBJECT private slots: void should_return_always_the_same_object(); }; void provider_by_default_constructor_test::should_return_always_the_same_object() { auto empty_injector1 = injector_core{}; auto empty_injector2 = injector_core{}; auto c = make_default_constructor_method(make_type()); auto p = std::unique_ptr{new provider_by_default_constructor{c}}; QCOMPARE(p->provided_type(), make_type()); QCOMPARE(p->required_types(), types{}); QCOMPARE(p->constructor(), c); auto o = p->provide(empty_injector1); QCOMPARE(p->provide(empty_injector1), o); QCOMPARE(p->provide(empty_injector2), o); QCOMPARE(o->metaObject(), &default_constructor_type::staticMetaObject); } QTEST_APPLESS_MAIN(provider_by_default_constructor_test) #include "provider-by-default-constructor-test.moc" injeqt-1.2.0/test/unit/provider-by-factory-configuration-test.cpp000066400000000000000000000117341307635157000252140ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include #include #include "internal/provider-by-factory-configuration.h" #include "internal/provider.h" #include "internal/types.h" #include #include using namespace injeqt::v1; using namespace injeqt::internal; class type_1 : public QObject { Q_OBJECT }; class type_2 : public QObject { Q_OBJECT }; class type_1_subtype_1 : public type_1 { Q_OBJECT }; class factory_type : public QObject { Q_OBJECT public: Q_INVOKABLE type_1 * create() { return new type_1{}; } }; class subtype_factory_type : public QObject { Q_OBJECT public: Q_INVOKABLE type_1_subtype_1 * create() { return new type_1_subtype_1{}; } }; class non_unique_factory_type : public QObject { Q_OBJECT public: Q_INVOKABLE type_1 * create() { return nullptr; } Q_INVOKABLE type_1 * create2() { return nullptr; } }; class provider_by_factory_configuration_test : public QObject { Q_OBJECT public: provider_by_factory_configuration_test(); private slots: void should_accept_qobject_object_type_and_throw_on_create(); void should_accept_qobject_factory_type_and_throw_on_create(); void should_accept_factory_without_factory_method_and_throw_on_create(); void should_accept_factory_without_unique_factory_method_and_throw_on_create(); void should_accept_supertype_factory_and_throw_on_create(); void should_accept_valid_configuration(); void should_accept_subtype_configuration(); private: types_by_name known_types; }; provider_by_factory_configuration_test::provider_by_factory_configuration_test() { known_types = types_by_name{std::vector{ make_type(), make_type(), make_type(), make_type(), make_type(), make_type() }}; } void provider_by_factory_configuration_test::should_accept_qobject_object_type_and_throw_on_create() { auto pc = provider_by_factory_configuration{make_type(), make_type()}; expect([&](){ pc.create_provider(known_types); }); } void provider_by_factory_configuration_test::should_accept_qobject_factory_type_and_throw_on_create() { auto pc = provider_by_factory_configuration{make_type(), make_type()}; expect([&](){ pc.create_provider(known_types); }); } void provider_by_factory_configuration_test::should_accept_factory_without_factory_method_and_throw_on_create() { auto pc = provider_by_factory_configuration{make_type(), make_type()}; expect([&](){ pc.create_provider(known_types); }); } void provider_by_factory_configuration_test::should_accept_factory_without_unique_factory_method_and_throw_on_create() { auto pc = provider_by_factory_configuration{make_type(), make_type()}; expect([&](){ pc.create_provider(known_types); }); } void provider_by_factory_configuration_test::should_accept_supertype_factory_and_throw_on_create() { auto pc = provider_by_factory_configuration{make_type(), make_type()}; expect([&](){ pc.create_provider(known_types); }); } void provider_by_factory_configuration_test::should_accept_valid_configuration() { auto pc = provider_by_factory_configuration{make_type(), make_type()}; auto p = pc.create_provider(known_types); QCOMPARE(types{make_type()}, p->required_types()); QCOMPARE(make_type(), p->provided_type()); } void provider_by_factory_configuration_test::should_accept_subtype_configuration() { auto pc = provider_by_factory_configuration{make_type(), make_type()}; auto p = pc.create_provider(known_types); QCOMPARE(types{make_type()}, p->required_types()); QCOMPARE(make_type(), p->provided_type()); } QTEST_APPLESS_MAIN(provider_by_factory_configuration_test) #include "provider-by-factory-configuration-test.moc" injeqt-1.2.0/test/unit/provider-by-factory-test.cpp000066400000000000000000000103331307635157000223410ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include #include #include "internal/factory-method.h" #include "internal/injector-core.h" #include "internal/provider-by-default-constructor.h" #include "internal/provider-by-factory.h" #include "internal/types-by-name.h" #include #include using namespace injeqt::v1; using namespace injeqt::internal; class by_factory_type : public QObject { Q_OBJECT public: Q_INVOKABLE by_factory_type() {} }; class factory_type : public QObject { Q_OBJECT public: Q_INVOKABLE factory_type() {} Q_INVOKABLE by_factory_type * create() { return new by_factory_type{}; } }; class invalid_factory_type : public QObject { Q_OBJECT public: Q_INVOKABLE invalid_factory_type() {} Q_INVOKABLE by_factory_type * create() { return nullptr; } }; class factory_module : public module { public: factory_module() { add_type(); } virtual ~factory_module() {} }; class provider_by_factory_test : public QObject { Q_OBJECT public: provider_by_factory_test(); private slots: void should_return_always_the_same_object(); void should_throw_instantiation_failed_when_invalid_factory(); private: types_by_name known_types; }; provider_by_factory_test::provider_by_factory_test() { known_types = types_by_name{std::vector{ make_type(), make_type(), make_type() }}; } void provider_by_factory_test::should_return_always_the_same_object() { auto fm = make_factory_method(known_types, make_type(), make_type()); auto fp = std::unique_ptr{new provider_by_factory{fm}}; auto p = fp.get(); auto configuration = std::vector>{}; configuration.emplace_back(std::move(fp)); configuration.emplace_back(std::unique_ptr{new provider_by_default_constructor{make_default_constructor_method(make_type())}}); auto injector = injector_core{types_by_name{}, std::move(configuration)}; QCOMPARE(p->provided_type(), make_type()); QCOMPARE(p->required_types(), types{make_type()}); QCOMPARE(p->factory(), fm); auto o = p->provide(injector); QCOMPARE(p->provide(injector), o); QCOMPARE(p->provide(injector), o); QCOMPARE(o->metaObject(), &by_factory_type::staticMetaObject); } void provider_by_factory_test::should_throw_instantiation_failed_when_invalid_factory() { auto fm = make_factory_method(known_types, make_type(), make_type()); auto fp = std::unique_ptr{new provider_by_factory{fm}}; auto p = fp.get(); auto configuration = std::vector>{}; configuration.emplace_back(std::move(fp)); configuration.emplace_back(std::unique_ptr{new provider_by_default_constructor{make_default_constructor_method(make_type())}}); auto injector = injector_core{types_by_name{}, std::move(configuration)}; QCOMPARE(p->provided_type(), make_type()); QCOMPARE(p->required_types(), types{make_type()}); QCOMPARE(p->factory(), fm); expect({"by_factory_type"}, [&](){ p->provide(injector); }); } QTEST_APPLESS_MAIN(provider_by_factory_test) #include "provider-by-factory-test.moc" injeqt-1.2.0/test/unit/provider-ready-configuration-test.cpp000066400000000000000000000054201307635157000242340ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include #include #include #include "internal/injector-core.h" #include "internal/provider-ready-configuration.h" #include #include using namespace injeqt::v1; using namespace injeqt::internal; class type_1 : public QObject { Q_OBJECT }; class type_2 : public QObject { Q_OBJECT }; class provider_ready_configuration_test : public QObject { Q_OBJECT private slots: void should_accept_qobject_type_and_throw_on_create(); void should_accept_nullptr_object_and_throw_on_create(); void should_accept_not_implemented_interface_and_throw_on_create(); void should_accept_valid_configuration(); }; void provider_ready_configuration_test::should_accept_qobject_type_and_throw_on_create() { auto pc = provider_ready_configuration{make_type(), nullptr}; expect([&](){ pc.create_provider({}); }); } void provider_ready_configuration_test::should_accept_nullptr_object_and_throw_on_create() { auto pc = provider_ready_configuration{make_type(), nullptr}; expect([&](){ pc.create_provider({}); }); } void provider_ready_configuration_test::should_accept_not_implemented_interface_and_throw_on_create() { auto o = make_object(); auto pc = provider_ready_configuration{make_type(), o.get()}; expect([&](){ pc.create_provider({}); }); } void provider_ready_configuration_test::should_accept_valid_configuration() { auto i = injector_core{}; auto o = make_object(); auto pc = provider_ready_configuration{make_type(), o.get()}; auto p = pc.create_provider({}); QCOMPARE(o.get(), p->provide(i)); } QTEST_APPLESS_MAIN(provider_ready_configuration_test) #include "provider-ready-configuration-test.moc" injeqt-1.2.0/test/unit/provider-ready-test.cpp000066400000000000000000000035271307635157000213750ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "internal/injector-core.h" #include "internal/provider-ready.h" #include #include using namespace injeqt::v1; using namespace injeqt::internal; class ready_type : public QObject { Q_OBJECT }; class provider_ready_test : public QObject { Q_OBJECT private slots: void should_return_always_the_same_object(); }; void provider_ready_test::should_return_always_the_same_object() { auto empty_injector1 = injector_core{}; auto empty_injector2 = injector_core{}; auto object = std::unique_ptr(new ready_type()); auto i = implementation{make_type(), object.get()}; auto p = provider_ready{i}; QCOMPARE(p.provided_type(), make_type()); QCOMPARE(p.required_types(), types{}); QCOMPARE(p.ready_implementation(), i); QCOMPARE(p.provide(empty_injector1), object.get()); QCOMPARE(p.provide(empty_injector2), object.get()); } QTEST_APPLESS_MAIN(provider_ready_test) #include "provider-ready-test.moc" injeqt-1.2.0/test/unit/required-to-satisfy-test.cpp000066400000000000000000000251771307635157000223660ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include #include "internal/required-to-satisfy.h" #include "internal/types-model.h" #include "internal/types.h" #include using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT }; class type_1_subtype_1 : public type_1 { Q_OBJECT }; class type_2 : public QObject { Q_OBJECT public slots: INJEQT_SET void set_type_1(type_1 *) {} }; class type_2_subtype_1 : public type_2 { Q_OBJECT }; class type_3 : public QObject { Q_OBJECT public slots: INJEQT_SET void set_type_2(type_2 *) {} }; class type_3_subtype_1 : public type_3 { Q_OBJECT }; class cyclic_type_3; class cyclic_type_1 : public QObject { Q_OBJECT public slots: INJEQT_SET void set_type_3(cyclic_type_3 *) {} }; class cyclic_type_1_subtype_1 : public cyclic_type_1 { Q_OBJECT }; class cyclic_type_2 : public QObject { Q_OBJECT public slots: INJEQT_SET void set_type_1(cyclic_type_1 *) {} }; class cyclic_type_2_subtype_1 : public cyclic_type_2 { Q_OBJECT }; class cyclic_type_3 : public QObject { Q_OBJECT public slots: INJEQT_SET void set_type_2(cyclic_type_2 *) {} }; class cyclic_type_3_subtype_1 : public cyclic_type_3 { Q_OBJECT }; class required_to_satisfy_test : public QObject { Q_OBJECT public: required_to_satisfy_test(); private slots: void should_return_nothing_when_empty_dependencies(); void should_return_dependencies_for_simple_model_with_empty_implementations(); void should_return_nothing_for_simple_model_with_full_implementations(); void should_return_subtype_dependencies_for_inheriting_model_with_empty_implementations(); void should_return_nothing_for_inheriting_model_with_full_implementations(); void should_return_dependencies_for_inheriting_model_with_supertype_implementations(); void should_return_all_dependencies_for_simple_model_with_empty_implementations(); void should_return_partial_dependencies_for_simple_model_with_partial_implementations(); void should_return_all_types_with_cyclic_dependnecies_for_simple_model_with_partial_implementations(); void should_return_all_subtypes_with_cyclic_dependnecies_for_inheriting_model_with_partial_implementations(); void should_return_type_when_supertype_is_already_available(); private: types_by_name known_types; type type_1_type; type type_1_subtype_1_type; type type_2_type; type type_2_subtype_1_type; type type_3_type; type type_3_subtype_1_type; type cyclic_type_1_type; type cyclic_type_1_subtype_1_type; type cyclic_type_2_type; type cyclic_type_2_subtype_1_type; type cyclic_type_3_type; type cyclic_type_3_subtype_1_type; types_model empty_types_model; types_model simple_types_model; types_model inheriting_types_model; dependencies type_1_dependencies; dependencies type_1_subtype_1_dependencies; dependencies type_2_dependencies; dependencies type_3_dependencies; dependencies cyclic_type_1_dependencies; dependencies cyclic_type_2_dependencies; dependencies cyclic_type_3_dependencies; }; required_to_satisfy_test::required_to_satisfy_test() : known_types{types_by_name{std::vector{ make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type(), make_type() }}}, type_1_type{make_type()}, type_1_subtype_1_type{make_type()}, type_2_type{make_type()}, type_2_subtype_1_type{make_type()}, type_3_type{make_type()}, type_3_subtype_1_type{make_type()}, cyclic_type_1_type{make_type()}, cyclic_type_1_subtype_1_type{make_type()}, cyclic_type_2_type{make_type()}, cyclic_type_2_subtype_1_type{make_type()}, cyclic_type_3_type{make_type()}, cyclic_type_3_subtype_1_type{make_type()} { auto simple_types = std::vector{ type_1_type, type_2_type, type_3_type, cyclic_type_1_type, cyclic_type_2_type, cyclic_type_3_type }; auto inheriting_types = std::vector{ type_1_subtype_1_type, type_2_subtype_1_type, type_3_subtype_1_type, cyclic_type_1_subtype_1_type, cyclic_type_2_subtype_1_type, cyclic_type_3_subtype_1_type }; simple_types_model = make_types_model(known_types, simple_types, simple_types); inheriting_types_model = make_types_model(known_types, inheriting_types, inheriting_types); type_1_dependencies = simple_types_model.mapped_dependencies().get(type_1_type)->dependency_list(); type_1_subtype_1_dependencies = inheriting_types_model.mapped_dependencies().get(type_1_subtype_1_type)->dependency_list(); type_2_dependencies = simple_types_model.mapped_dependencies().get(type_2_type)->dependency_list(); type_3_dependencies = simple_types_model.mapped_dependencies().get(type_3_type)->dependency_list(); cyclic_type_1_dependencies = simple_types_model.mapped_dependencies().get(cyclic_type_1_type)->dependency_list(); cyclic_type_2_dependencies = simple_types_model.mapped_dependencies().get(cyclic_type_2_type)->dependency_list(); cyclic_type_3_dependencies = simple_types_model.mapped_dependencies().get(cyclic_type_3_type)->dependency_list(); } void required_to_satisfy_test::should_return_nothing_when_empty_dependencies() { auto result = required_to_satisfy(dependencies{}, simple_types_model, {}); QCOMPARE(result, types{}); } void required_to_satisfy_test::should_return_dependencies_for_simple_model_with_empty_implementations() { auto result = required_to_satisfy(type_2_dependencies, simple_types_model, {}); QCOMPARE(result, (types{type_1_type})); } void required_to_satisfy_test::should_return_nothing_for_simple_model_with_full_implementations() { auto type_1_object = make_object(); auto available_implementations = implementations { implementation{type_1_type, type_1_object.get()} }; auto result = required_to_satisfy(type_2_dependencies, simple_types_model, available_implementations); QCOMPARE(result, (types{})); } void required_to_satisfy_test::should_return_subtype_dependencies_for_inheriting_model_with_empty_implementations() { auto result = required_to_satisfy(type_2_dependencies, inheriting_types_model, {}); QCOMPARE(result, (types{type_1_subtype_1_type})); } void required_to_satisfy_test::should_return_nothing_for_inheriting_model_with_full_implementations() { auto type_1_subtype_1_object = make_object(); auto available_implementations = implementations { implementation{type_1_subtype_1_type, type_1_subtype_1_object.get()} }; auto result = required_to_satisfy(type_2_dependencies, inheriting_types_model, available_implementations); QCOMPARE(result, (types{})); } void required_to_satisfy_test::should_return_dependencies_for_inheriting_model_with_supertype_implementations() { auto type_1_object = make_object(); auto available_implementations = implementations { implementation{type_1_type, type_1_object.get()} }; auto result = required_to_satisfy(type_2_dependencies, inheriting_types_model, available_implementations); QCOMPARE(result, (types{type_1_subtype_1_type})); } void required_to_satisfy_test::should_return_all_dependencies_for_simple_model_with_empty_implementations() { auto result = required_to_satisfy(type_3_dependencies, simple_types_model, {}); QCOMPARE(result, (types{type_1_type, type_2_type})); } void required_to_satisfy_test::should_return_partial_dependencies_for_simple_model_with_partial_implementations() { auto type_1_object = make_object(); auto available_implementations = implementations { implementation{type_1_type, type_1_object.get()} }; auto result = required_to_satisfy(type_3_dependencies, simple_types_model, available_implementations); QCOMPARE(result, (types{type_2_type})); } void required_to_satisfy_test::should_return_all_types_with_cyclic_dependnecies_for_simple_model_with_partial_implementations() { auto result1 = required_to_satisfy(cyclic_type_1_dependencies, simple_types_model, {}); QCOMPARE(result1, (types{cyclic_type_1_type, cyclic_type_2_type, cyclic_type_3_type})); auto result2 = required_to_satisfy(cyclic_type_2_dependencies, simple_types_model, {}); QCOMPARE(result2, (types{cyclic_type_1_type, cyclic_type_2_type, cyclic_type_3_type})); auto result3 = required_to_satisfy(cyclic_type_3_dependencies, simple_types_model, {}); QCOMPARE(result3, (types{cyclic_type_1_type, cyclic_type_2_type, cyclic_type_3_type})); } void required_to_satisfy_test::should_return_all_subtypes_with_cyclic_dependnecies_for_inheriting_model_with_partial_implementations() { auto result1 = required_to_satisfy(cyclic_type_1_dependencies, inheriting_types_model, {}); QCOMPARE(result1, (types{cyclic_type_1_subtype_1_type, cyclic_type_2_subtype_1_type, cyclic_type_3_subtype_1_type})); auto result2 = required_to_satisfy(cyclic_type_2_dependencies, inheriting_types_model, {}); QCOMPARE(result2, (types{cyclic_type_1_subtype_1_type, cyclic_type_2_subtype_1_type, cyclic_type_3_subtype_1_type})); auto result3 = required_to_satisfy(cyclic_type_3_dependencies, inheriting_types_model, {}); QCOMPARE(result3, (types{cyclic_type_1_subtype_1_type, cyclic_type_2_subtype_1_type, cyclic_type_3_subtype_1_type})); } void required_to_satisfy_test::should_return_type_when_supertype_is_already_available() { auto type_1_object = make_object(); auto available_implementations = implementations { implementation{type_1_type, type_1_object.get()}, }; auto result = required_to_satisfy(type_1_subtype_1_dependencies, inheriting_types_model, available_implementations); QCOMPARE(result, (types{})); } QTEST_APPLESS_MAIN(required_to_satisfy_test); #include "required-to-satisfy-test.moc" injeqt-1.2.0/test/unit/resolve-dependencies-test.cpp000066400000000000000000000224721307635157000225440ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "utils.h" #include "internal/dependencies.h" #include "internal/dependency.h" #include "internal/implementations.h" #include "internal/implementation.h" #include "internal/resolved-dependency.h" #include "internal/resolve-dependencies.h" #include using namespace injeqt::internal; using namespace injeqt::v1; class injectable_type1 : public QObject { Q_OBJECT }; class injectable_type2 : public QObject { Q_OBJECT }; class injectable_type3 : public QObject { Q_OBJECT }; class sublcass_injectable_type1 : public injectable_type1 { Q_OBJECT }; class valid_type : public QObject { Q_OBJECT public slots: INJEQT_SET void set_type1(injectable_type1 *) {} INJEQT_SET void set_type2(injectable_type2 *) {} INJEQT_SET void set_type3(injectable_type3 *) {} INJEQT_SET void set_sub_type1(sublcass_injectable_type1 *) {} }; class resolve_dependencies_test : public QObject { Q_OBJECT public: resolve_dependencies_test(); private slots: void should_resolve_no_dependencies_when_no_objects_available(); void should_resolve_all_dependencies(); void should_resolve_available_dependencies(); void should_resolve_available_dependencies_using_exact_matching(); void should_resolve_available_dependencies_using_exact_matching_not_using_subclass(); void should_resolve_available_dependencies_not_using_superclass(); private: type injectable_type1_type; type injectable_type2_type; type injectable_type3_type; type sublcass_injectable_type1_type; setter_method injectable_type1_setter; setter_method injectable_type2_setter; setter_method injectable_type3_setter; setter_method subclass_injectable_type1_setter; }; resolve_dependencies_test::resolve_dependencies_test() : injectable_type1_type{make_type()}, injectable_type2_type{make_type()}, injectable_type3_type{make_type()}, sublcass_injectable_type1_type{make_type()}, injectable_type1_setter{make_test_setter_method("set_type1(injectable_type1*)")}, injectable_type2_setter{make_test_setter_method("set_type2(injectable_type2*)")}, injectable_type3_setter{make_test_setter_method("set_type3(injectable_type3*)")}, subclass_injectable_type1_setter{make_test_setter_method("set_sub_type1(sublcass_injectable_type1*)")} { } void resolve_dependencies_test::should_resolve_no_dependencies_when_no_objects_available() { auto objects = std::vector{}; auto to_resolve = std::vector { dependency{injectable_type1_setter}, dependency{injectable_type2_setter}, dependency{injectable_type3_setter} }; auto result = resolve_dependencies(dependencies{to_resolve}, implementations{objects}); QVERIFY(result.resolved.empty()); QCOMPARE(result.unresolved, dependencies{to_resolve}); } void resolve_dependencies_test::should_resolve_all_dependencies() { auto object1 = make_object(); auto object2 = make_object(); auto object3 = make_object(); auto objects = std::vector { implementation{injectable_type1_type, object1.get()}, implementation{injectable_type2_type, object2.get()}, implementation{injectable_type3_type, object3.get()}, }; auto to_resolve = std::vector { dependency{injectable_type1_setter}, dependency{injectable_type2_setter}, dependency{injectable_type3_setter} }; auto expected = std::vector{ resolved_dependency{objects.at(0), injectable_type1_setter}, resolved_dependency{objects.at(1), injectable_type2_setter}, resolved_dependency{objects.at(2), injectable_type3_setter} }; auto result = resolve_dependencies(dependencies{to_resolve}, implementations{objects}); std::sort(std::begin(expected), std::end(expected)); std::sort(std::begin(result.resolved), std::end(result.resolved)); QCOMPARE(result.resolved, expected); QVERIFY(result.unresolved.empty()); } void resolve_dependencies_test::should_resolve_available_dependencies() { auto object1 = make_object(); auto object3 = make_object(); auto objects = std::vector { implementation{injectable_type1_type, object1.get()}, implementation{injectable_type3_type, object3.get()} }; auto to_resolve = std::vector { dependency{injectable_type1_setter}, dependency{injectable_type2_setter}, dependency{injectable_type3_setter} }; auto expected = std::vector{ resolved_dependency{objects.at(0), injectable_type1_setter}, resolved_dependency{objects.at(1), injectable_type3_setter} }; auto result = resolve_dependencies(dependencies{to_resolve}, implementations{objects}); std::sort(std::begin(expected), std::end(expected)); std::sort(std::begin(result.resolved), std::end(result.resolved)); QCOMPARE(result.resolved, expected); QVERIFY(result.unresolved.contains(to_resolve.at(1))); } void resolve_dependencies_test::should_resolve_available_dependencies_using_exact_matching() { auto object1 = make_object(); auto object1b = make_object(); auto object3 = make_object(); auto object3b = make_object(); auto objects = std::vector { implementation{injectable_type1_type, object1.get()}, implementation{injectable_type1_type, object1b.get()}, implementation{injectable_type3_type, object3.get()}, implementation{injectable_type3_type, object3b.get()}, }; auto to_resolve = std::vector { dependency{injectable_type1_setter}, dependency{injectable_type2_setter}, dependency{injectable_type3_setter} }; auto expected = std::vector{ resolved_dependency{objects.at(0), injectable_type1_setter}, resolved_dependency{objects.at(2), injectable_type3_setter} }; auto result = resolve_dependencies(dependencies{to_resolve}, implementations{objects}); std::sort(std::begin(expected), std::end(expected)); std::sort(std::begin(result.resolved), std::end(result.resolved)); QCOMPARE(result.resolved, expected); QCOMPARE(*result.unresolved.begin(), to_resolve.at(1)); QVERIFY(&object1 != &object1b); QVERIFY(&object3 != &object3b); } void resolve_dependencies_test::should_resolve_available_dependencies_using_exact_matching_not_using_subclass() { auto object1 = make_object(); auto subobject1 = make_object(); auto object3 = make_object(); auto object3b = make_object(); auto objects = std::vector { implementation{injectable_type1_type, object1.get()}, implementation{sublcass_injectable_type1_type, subobject1.get()}, implementation{injectable_type3_type, object3.get()}, implementation{injectable_type3_type, object3b.get()} }; auto to_resolve = std::vector { dependency{injectable_type1_setter}, dependency{injectable_type2_setter}, dependency{injectable_type3_setter} }; auto expected = std::vector{ resolved_dependency{objects.at(0), injectable_type1_setter}, resolved_dependency{objects.at(2), injectable_type3_setter} }; auto result = resolve_dependencies(dependencies{to_resolve}, implementations{objects}); std::sort(std::begin(expected), std::end(expected)); std::sort(std::begin(result.resolved), std::end(result.resolved)); QCOMPARE(result.resolved, expected); QCOMPARE(result.unresolved.size(), size_t{1}); QVERIFY(result.unresolved.contains(to_resolve.at(1))); QVERIFY(&object1 != &subobject1); QVERIFY(&object3 != &object3b); } void resolve_dependencies_test::should_resolve_available_dependencies_not_using_superclass() { auto object1 = make_object(); auto object2 = make_object(); auto objects = std::vector { implementation{injectable_type1_type, object1.get()}, implementation{injectable_type2_type, object2.get()} }; auto to_resolve = std::vector { dependency{subclass_injectable_type1_setter}, dependency{injectable_type2_setter} }; auto result = resolve_dependencies(dependencies{to_resolve}, implementations{objects}); QCOMPARE(result.resolved.size(), size_t{1}); QCOMPARE(result.resolved.at(0), (resolved_dependency{objects.at(1), injectable_type2_setter})); QCOMPARE(result.unresolved.size(), size_t{1}); QVERIFY(result.unresolved.contains(to_resolve.at(0))); } QTEST_APPLESS_MAIN(resolve_dependencies_test); #include "resolve-dependencies-test.moc" injeqt-1.2.0/test/unit/resolved-dependency-test.cpp000066400000000000000000000076041307635157000224000ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This lrdrary is free software; you can redistrrdute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This lrdrary is distrrduted in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this lrdrary; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include "internal/resolved-dependency.h" #include using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT }; class type_1_subtype_1 : public QObject { Q_OBJECT }; class type_2 : public QObject { Q_OBJECT }; class injected_type : public QObject { Q_OBJECT public: type_1 *_1 = nullptr; type_2 *_2 = nullptr; public slots: INJEQT_SET void setter_1(type_1 *a) { _1 = a; } INJEQT_SET void setter_1b(type_1 *a) { _1 = a; } INJEQT_SET void setter_1_subtype_1(type_1_subtype_1 *) {} INJEQT_SET void setter_2(type_2 *a) { _2 = a; } }; class resolved_dependency_test : public QObject { Q_OBJECT private slots: void should_properly_apply_on_valid_object(); void should_properly_compare(); }; void resolved_dependency_test::should_properly_apply_on_valid_object() { auto object_1 = make_object(); auto object_2 = make_object(); auto apply_on_object = make_object(); auto resolved_1 = resolved_dependency{implementation{make_type(), object_1.get()}, make_test_setter_method("setter_1(type_1*)")}; auto resolved_2 = resolved_dependency{implementation{make_type(), object_2.get()}, make_test_setter_method("setter_2(type_2*)")}; QCOMPARE(static_cast(nullptr), static_cast(apply_on_object.get())->_1); QCOMPARE(static_cast(nullptr), static_cast(apply_on_object.get())->_2); resolved_1.apply_on(apply_on_object.get()); QCOMPARE(object_1.get(), static_cast(apply_on_object.get())->_1); QCOMPARE(static_cast(nullptr), static_cast(apply_on_object.get())->_2); resolved_2.apply_on(apply_on_object.get()); QCOMPARE(object_1.get(), static_cast(apply_on_object.get())->_1); QCOMPARE(object_2.get(), static_cast(apply_on_object.get())->_2); } void resolved_dependency_test::should_properly_compare() { auto object_1a = make_object(); auto object_1b = make_object(); auto i1a = implementation{make_type(), object_1a.get()}; auto i1b = implementation{make_type(), object_1b.get()}; auto rd1a = resolved_dependency{i1a, make_test_setter_method("setter_1(type_1*)")}; auto rd1b = resolved_dependency{i1a, make_test_setter_method("setter_1(type_1*)")}; auto rd2a = resolved_dependency{i1b, make_test_setter_method("setter_1(type_1*)")}; auto rd2b = resolved_dependency{i1b, make_test_setter_method("setter_1(type_1*)")}; auto rd3a = resolved_dependency{i1b, make_test_setter_method("setter_1b(type_1*)")}; auto rd3b = resolved_dependency{i1b, make_test_setter_method("setter_1b(type_1*)")}; test_compare({{rd1a, rd1b}, {rd2a, rd2b}, {rd3a, rd3b}}); } QTEST_APPLESS_MAIN(resolved_dependency_test) #include "resolved-dependency-test.moc" injeqt-1.2.0/test/unit/setter-method-test.cpp000066400000000000000000000136271307635157000212270ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include #include "internal/types-by-name.h" #include #ifndef Q_MOC_RUN # define INVALID_SETTER_TAG #endif using namespace injeqt::internal; using namespace injeqt::v1; class injectable_type1 : public QObject { Q_OBJECT }; class injectable_type2 : public QObject { Q_OBJECT }; class test_type : public QObject { Q_OBJECT public: injectable_type1 *_1 = nullptr; test_type() {} Q_INVOKABLE test_type(injectable_type1 *) {} Q_INVOKABLE INJEQT_SET void tagged_setter_method_1(injectable_type1 *a) { _1 = a; } Q_INVOKABLE INJEQT_SETTER void tagged_setter_method_2(injectable_type1 *a) { _1 = a; } public slots: INJEQT_SET void tagged_setter_slot_1(injectable_type1 *a) { _1 = a; } INJEQT_SETTER void tagged_setter_slot_2(injectable_type1 *a) { _1 = a; } INJEQT_SETTER void invalid_setter_multi_arguments(injectable_type1 *, injectable_type2 *) { } INVALID_SETTER_TAG void invalid_setter_invalid_tag(injectable_type1 *) { } void invalid_setter_no_tag(injectable_type1 *) { } signals: INJEQT_SETTER void invalid_setter_signal(injectable_type1 *); }; class setter_method_test : public QObject { Q_OBJECT public: setter_method_test(); private: types_by_name _known_types; private slots: void should_create_empty(); void should_create_valid_from_tagged_setter_method(); void should_create_valid_from_tagged_setter_slot(); void should_invoke_have_results(); void should_throw_when_empty_method(); void should_throw_when_multiple_arguments(); void should_throw_when_invalid_tag(); void should_throw_when_no_tag(); void should_throw_when_signal(); void should_throw_when_constructor(); }; setter_method_test::setter_method_test() : _known_types{ make_type(), make_type(), make_type() } { } void setter_method_test::should_create_empty() { auto setter = setter_method{}; QVERIFY(setter.is_empty()); } void setter_method_test::should_create_valid_from_tagged_setter_method() { auto setter = make_setter_method(_known_types, get_method("tagged_setter_method_1(injectable_type1*)")); QVERIFY(!setter.is_empty()); QCOMPARE(setter.object_type(), make_type()); QCOMPARE(setter.parameter_type(), make_type()); setter = make_setter_method(_known_types, get_method("tagged_setter_method_2(injectable_type1*)")); QVERIFY(!setter.is_empty()); QCOMPARE(setter.object_type(), make_type()); QCOMPARE(setter.parameter_type(), make_type()); } void setter_method_test::should_create_valid_from_tagged_setter_slot() { auto setter = make_setter_method(_known_types, get_method("tagged_setter_slot_1(injectable_type1*)")); QVERIFY(!setter.is_empty()); QCOMPARE(setter.object_type(), make_type()); QCOMPARE(setter.parameter_type(), make_type()); setter = make_setter_method(_known_types, get_method("tagged_setter_slot_2(injectable_type1*)")); QVERIFY(!setter.is_empty()); QCOMPARE(setter.object_type(), make_type()); QCOMPARE(setter.parameter_type(), make_type()); } void setter_method_test::should_invoke_have_results() { auto setter = make_setter_method(_known_types, get_method("tagged_setter_slot_1(injectable_type1*)")); auto on = make_object(); auto with = make_object(); QCOMPARE(static_cast(nullptr), static_cast(on.get())->_1); setter.invoke(on.get(), with.get()); QCOMPARE(with.get(), static_cast(on.get())->_1); } void setter_method_test::should_throw_when_empty_method() { expect({"setter does not have enclosing meta object"}, [&]{ make_setter_method(_known_types, QMetaMethod{}); }); } void setter_method_test::should_throw_when_multiple_arguments() { expect({"invalid parameter count"}, [&]{ make_setter_method(_known_types, get_method("invalid_setter_multi_arguments(injectable_type1*,injectable_type2*)")); }); } void setter_method_test::should_throw_when_invalid_tag() { expect({"setter does not have valid tag"}, [&]{ make_setter_method(_known_types, get_method("invalid_setter_invalid_tag(injectable_type1*)")); }); } void setter_method_test::should_throw_when_no_tag() { expect({"setter does not have valid tag"}, [&]{ make_setter_method(_known_types, get_method("invalid_setter_no_tag(injectable_type1*)")); }); } void setter_method_test::should_throw_when_signal() { expect({"setter is signal"}, [&]{ make_setter_method(_known_types, get_method("invalid_setter_signal(injectable_type1*)")); }); } void setter_method_test::should_throw_when_constructor() { expect({"setter is constructor"}, [&]{ make_setter_method(_known_types, get_constructor("test_type(injectable_type1*)")); }); } QTEST_APPLESS_MAIN(setter_method_test) #include "setter-method-test.moc" injeqt-1.2.0/test/unit/sorted-unique-vector-test.cpp000066400000000000000000000273601307635157000225460ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "sorted-unique-vector.h" #include using namespace injeqt::internal; class sorted_unique_vector_test : public QObject { Q_OBJECT static int extract_key(const int &x) { return x; } static int extract_key_pair(const std::pair &x) { return x.first; } using suv_int = sorted_unique_vector; using suv_pair = sorted_unique_vector, extract_key_pair>; private slots: void should_be_empty_after_default_construction(); void should_be_empty_after_clear(); void should_be_valid_after_adding_two_same_items_to_empty(); void should_be_valid_after_adding_two_different_items_to_empty(); void should_be_valid_after_conversion_from_unique_vector(); void should_be_valid_after_conversion_from_non_unique_vector(); void should_be_valid_after_conversion_from_unique_sorted_vector(); void should_be_valid_after_conversion_from_non_unique_sorted_vector(); void should_be_valid_after_adding_less_than_smallest_element(); void should_be_valid_after_adding_smallest_element(); void should_be_valid_after_adding_medium_element(); void should_be_valid_after_adding_largest_element(); void should_be_valid_after_adding_greater_than_largest_element(); void should_be_valid_after_merging_itself(); void should_be_valid_after_merging_lesser_elements(); void should_be_valid_after_merging_lesser_or_equal_elements(); void should_be_valid_after_merging_misc_elements(); void should_be_valid_after_merging_misc_unique_elements(); void should_be_valid_after_merging_greater_or_equal_elements(); void should_be_valid_after_merging_greater_elements(); void should_match_return_nothing_for_two_empty_vectors(); void should_match_return_only_unresolved_for_first_empty_vector(); void should_match_return_only_unresolved_for_second_empty_vector(); void should_match_return_only_unresolved_for_non_matching_vectors(); void should_match_return_only_resolved_for_matching_vectors(); void should_match_return_valid_data_for_partially_matching_vectors(); void should_return_false_for_contains_when_empty(); void should_return_false_for_contains_when_does_not_contain(); void should_return_true_for_contains_when_contains(); void should_return_false_for_contains_when_contains_key_with_different_value(); void should_return_false_for_contains_key_when_empty(); void should_return_false_for_contains_when_does_not_contain_key(); void should_return_true_for_contains_when_contains_key(); }; void sorted_unique_vector_test::should_be_empty_after_default_construction() { auto data = suv_int{}; QVERIFY(data.empty()); QCOMPARE(data.size(), size_t{0}); QCOMPARE(data.content(), (std::vector{})); } void sorted_unique_vector_test::should_be_empty_after_clear() { auto data = suv_int{1, 4, 5, 2}; QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{4}); data.clear(); QVERIFY(data.empty()); QCOMPARE(data.size(), size_t{0}); } void sorted_unique_vector_test::should_be_valid_after_adding_two_same_items_to_empty() { auto data = suv_int{}; data.add(1); data.add(1); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{1}); } void sorted_unique_vector_test::should_be_valid_after_adding_two_different_items_to_empty() { auto data = suv_int{}; data.add(1); data.add(2); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{2}); } void sorted_unique_vector_test::should_be_valid_after_conversion_from_unique_vector() { auto data = suv_int{1, 4, 5, 2}; QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{4}); QCOMPARE(data.content(), (std::vector{1, 2, 4, 5})); } void sorted_unique_vector_test::should_be_valid_after_conversion_from_non_unique_vector() { auto data = suv_int{1, 4, 5, 2, 1, 4, 5, 2}; QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{4}); QCOMPARE(data.content(), (std::vector{1, 2, 4, 5})); } void sorted_unique_vector_test::should_be_valid_after_conversion_from_unique_sorted_vector() { auto data = suv_int{1, 2, 4, 5}; QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{4}); QCOMPARE(data.content(), (std::vector{1, 2, 4, 5})); } void sorted_unique_vector_test::should_be_valid_after_conversion_from_non_unique_sorted_vector() { auto data = suv_int{1, 1, 2, 2, 4, 4, 5, 5}; QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{4}); QCOMPARE(data.content(), (std::vector{1, 2, 4, 5})); } void sorted_unique_vector_test::should_be_valid_after_adding_less_than_smallest_element() { auto data = suv_int{1, 2, 4, 5}; data.add(0); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{5}); QCOMPARE(data.content(), (std::vector{0, 1, 2, 4, 5})); } void sorted_unique_vector_test::should_be_valid_after_adding_smallest_element() { auto data = suv_int{1, 2, 4, 5}; data.add(1); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{4}); QCOMPARE(data.content(), (std::vector{1, 2, 4, 5})); } void sorted_unique_vector_test::should_be_valid_after_adding_medium_element() { auto data = suv_int{1, 2, 4, 5}; data.add(3); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{5}); QCOMPARE(data.content(), (std::vector{1, 2, 3, 4, 5})); } void sorted_unique_vector_test::should_be_valid_after_adding_largest_element() { auto data = suv_int{1, 2, 4, 5}; data.add(5); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{4}); QCOMPARE(data.content(), (std::vector{1, 2, 4, 5})); } void sorted_unique_vector_test::should_be_valid_after_adding_greater_than_largest_element() { auto data = suv_int{1, 2, 4, 5}; data.add(6); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{5}); QCOMPARE(data.content(), (std::vector{1, 2, 4, 5, 6})); } void sorted_unique_vector_test::should_be_valid_after_merging_itself() { auto data = suv_int{1, 2, 4, 5}; data.merge(data); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{4}); QCOMPARE(data.content(), (std::vector{1, 2, 4, 5})); } void sorted_unique_vector_test::should_be_valid_after_merging_lesser_elements() { auto data = suv_int{1, 2, 4, 5}; auto data_to_add = suv_int{0, -1, -2}; data.merge(data_to_add); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{7}); QCOMPARE(data.content(), (std::vector{-2, -1, 0, 1, 2, 4, 5})); } void sorted_unique_vector_test::should_be_valid_after_merging_lesser_or_equal_elements() { auto data = suv_int{1, 2, 4, 5}; auto data_to_add = suv_int{1, 0, -1, -2}; data.merge(data_to_add); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{7}); QCOMPARE(data.content(), (std::vector{-2, -1, 0, 1, 2, 4, 5})); } void sorted_unique_vector_test::should_be_valid_after_merging_misc_elements() { auto data = suv_int{0, 5, 10, 1, 3, 2}; auto data_to_add = suv_int{-1, 17, 2, 3, 4, 5}; data.merge(data_to_add); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{9}); QCOMPARE(data.content(), (std::vector{-1, 0, 1, 2, 3, 4, 5, 10, 17})); } void sorted_unique_vector_test::should_be_valid_after_merging_misc_unique_elements() { auto data = suv_int{0, 5, 10, 1, 3, 2}; auto data_to_add = suv_int{-1, 17, 4}; data.merge(data_to_add); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{9}); QCOMPARE(data.content(), (std::vector{-1, 0, 1, 2, 3, 4, 5, 10, 17})); } void sorted_unique_vector_test::should_be_valid_after_merging_greater_or_equal_elements() { auto data = suv_int{1, 2, 4, 5}; auto data_to_add = suv_int{7, 8, 6}; data.merge(data_to_add); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{7}); QCOMPARE(data.content(), (std::vector{1, 2, 4, 5, 6, 7, 8})); } void sorted_unique_vector_test::should_be_valid_after_merging_greater_elements() { auto data = suv_int{1, 2, 4, 5}; auto data_to_add = suv_int{7, 5, 6}; data.merge(data_to_add); QVERIFY(!data.empty()); QCOMPARE(data.size(), size_t{6}); QCOMPARE(data.content(), (std::vector{1, 2, 4, 5, 6, 7})); } void sorted_unique_vector_test::should_match_return_nothing_for_two_empty_vectors() { auto result = match(suv_int{}, suv_int{}); QVERIFY(result.matched.empty()); QVERIFY(result.unmatched_1.empty()); QVERIFY(result.unmatched_2.empty()); } void sorted_unique_vector_test::should_match_return_only_unresolved_for_first_empty_vector() { auto result = match(suv_int{}, suv_int{}); QVERIFY(result.matched.empty()); QVERIFY(result.unmatched_1.empty()); QVERIFY(result.unmatched_2.empty()); } void sorted_unique_vector_test::should_match_return_only_unresolved_for_second_empty_vector() { auto result = match(suv_int{}, suv_int{1, 2, 3, 4, 5}); QVERIFY(result.matched.empty()); QVERIFY(result.unmatched_1.empty()); QCOMPARE(result.unmatched_2.content(), (std::vector{1, 2, 3, 4, 5})); } void sorted_unique_vector_test::should_match_return_only_unresolved_for_non_matching_vectors() { auto result = match(suv_int{1, 2, 3, 4, 5}, suv_int{}); QVERIFY(result.matched.empty()); QCOMPARE(result.unmatched_1.content(), (std::vector{1, 2, 3, 4, 5})); QVERIFY(result.unmatched_2.empty()); } void sorted_unique_vector_test::should_match_return_only_resolved_for_matching_vectors() { auto result = match(suv_int{1, 2, 3, 4, 5}, suv_int{1, 2, 3, 4, 5}); QCOMPARE(result.matched, (std::vector>{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}})); QVERIFY(result.unmatched_1.empty()); QVERIFY(result.unmatched_2.empty()); } void sorted_unique_vector_test::should_match_return_valid_data_for_partially_matching_vectors() { auto result = match(suv_int{1, 2, 3}, suv_int{2, 3, 4, 5}); QCOMPARE(result.matched, (std::vector>{{2, 2}, {3, 3}})); QCOMPARE(result.unmatched_1.content(), (std::vector{1})); QCOMPARE(result.unmatched_2.content(), (std::vector{4, 5})); } void sorted_unique_vector_test::should_return_false_for_contains_when_empty() { auto data = suv_pair{}; QVERIFY(!data.contains(std::make_pair(0, std::string{"0"}))); } void sorted_unique_vector_test::should_return_false_for_contains_when_does_not_contain() { auto data = suv_pair{std::make_pair(0, std::string{"0"})}; QVERIFY(!data.contains(std::make_pair(1, std::string{"1"}))); } void sorted_unique_vector_test::should_return_true_for_contains_when_contains() { auto data = suv_pair{std::make_pair(0, std::string{"0"})}; QVERIFY(data.contains(std::make_pair(0, std::string{"0"}))); } void sorted_unique_vector_test::should_return_false_for_contains_when_contains_key_with_different_value() { auto data = suv_pair{std::make_pair(0, std::string{"0"})}; QVERIFY(!data.contains(std::make_pair(0, std::string{"1"}))); } void sorted_unique_vector_test::should_return_false_for_contains_key_when_empty() { auto data = suv_pair{}; QVERIFY(!data.contains_key(0)); } void sorted_unique_vector_test::should_return_false_for_contains_when_does_not_contain_key() { auto data = suv_pair{std::make_pair(0, std::string{"0"})}; QVERIFY(!data.contains_key(1)); } void sorted_unique_vector_test::should_return_true_for_contains_when_contains_key() { auto data = suv_pair{std::make_pair(0, std::string{"0"})}; QVERIFY(data.contains_key(0)); } QTEST_APPLESS_MAIN(sorted_unique_vector_test) #include "sorted-unique-vector-test.moc" injeqt-1.2.0/test/unit/type-dependencies-test.cpp000066400000000000000000000053231307635157000220420ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include "internal/dependency.h" #include "internal/type-dependencies.h" #include #include using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT }; class type_2 : public QObject { Q_OBJECT }; class type_with_dependency_1 : public QObject { Q_OBJECT public slots: INJEQT_SET void setter_1(type_1 *) { } INJEQT_SET void setter_2(type_2 *) { } }; class type_with_dependency_2 : public QObject { Q_OBJECT public slots: INJEQT_SET void setter_1(type_1 *) { } INJEQT_SET void setter_2(type_2 *) { } }; class type_dependencies_test : public QObject { Q_OBJECT private slots: void should_properly_compare(); }; void type_dependencies_test::should_properly_compare() { auto d11 = dependency{make_test_setter_method("setter_1(type_1*)")}; auto d12 = dependency{make_test_setter_method("setter_2(type_2*)")}; auto d21 = dependency{make_test_setter_method("setter_1(type_1*)")}; auto d22 = dependency{make_test_setter_method("setter_2(type_2*)")}; auto td_empty = type_dependencies{type{}, dependencies{}}; auto td1a = type_dependencies{make_type(), dependencies{d11, d12}}; auto td1b = type_dependencies{make_type(), dependencies{d11, d12}}; auto td2a = type_dependencies{make_type(), dependencies{}}; auto td2b = type_dependencies{make_type(), dependencies{}}; auto td3a = type_dependencies{make_type(), dependencies{d21, d22}}; auto td3b = type_dependencies{make_type(), dependencies{d21, d22}}; test_compare({{td_empty}, {td1a, td1b}, {td2a, td2b}, {td3a, td3b}}); } QTEST_APPLESS_MAIN(type_dependencies_test) #include "type-dependencies-test.moc" injeqt-1.2.0/test/unit/type-relations-test.cpp000066400000000000000000000134051307635157000214140ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "internal/type-relations.h" using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT }; class type_1_sub_1 : public type_1 { Q_OBJECT }; class type_1_sub_1_sub_1 : public type_1_sub_1 { Q_OBJECT }; class type_1_sub_1_sub_2 : public type_1_sub_1 { Q_OBJECT }; class type_1_sub_2 : public type_1 { Q_OBJECT }; class type_2 : public QObject { Q_OBJECT }; class type_2_sub_1 : public type_2 { Q_OBJECT }; class type_relations_test : public QObject { Q_OBJECT public: type_relations_test(); private slots: void should_create_empty_relations(); void should_create_empty_relations_for_no_types(); void should_create_unique_relations_for_unrelated_types(); void should_create_unique_relations_for_unrelated_subtypes(); void should_create_unique_relations_for_type_with_supertypes(); void should_create_ambiguous_relations_for_the_same_type(); void should_create_mixed_relations_for_subtypes(); void should_create_mixed_relations_for_type_and_subtype(); void should_create_mixed_relations_for_subtype_and_type(); private: type type_1_type; type type_1_sub_1_type; type type_1_sub_1_sub_1_type; type type_1_sub_1_sub_2_type; type type_1_sub_2_type; type type_2_type; type type_2_sub_1_type; }; type_relations_test::type_relations_test() : type_1_type{make_type()}, type_1_sub_1_type{make_type()}, type_1_sub_1_sub_1_type{make_type()}, type_1_sub_1_sub_2_type{make_type()}, type_1_sub_2_type{make_type()}, type_2_type{make_type()}, type_2_sub_1_type{make_type()} { } void type_relations_test::should_create_empty_relations() { auto result = type_relations{}; QCOMPARE(result.unique(), implemented_by_mapping{}); QCOMPARE(result.ambiguous(), types{}); } void type_relations_test::should_create_empty_relations_for_no_types() { auto result = make_type_relations({}); QCOMPARE(result.unique(), implemented_by_mapping{}); QCOMPARE(result.ambiguous(), types{}); } void type_relations_test::should_create_unique_relations_for_unrelated_types() { auto result = make_type_relations({type_1_type, type_2_type}); QCOMPARE(result.unique(), (implemented_by_mapping { implemented_by{type_1_type, type_1_type}, implemented_by{type_2_type, type_2_type} })); QCOMPARE(result.ambiguous(), types{}); } void type_relations_test::should_create_unique_relations_for_unrelated_subtypes() { auto result = make_type_relations({type_1_sub_1_sub_1_type, type_2_sub_1_type}); QCOMPARE(result.unique(), (implemented_by_mapping { implemented_by{type_1_type, type_1_sub_1_sub_1_type}, implemented_by{type_1_sub_1_type, type_1_sub_1_sub_1_type}, implemented_by{type_1_sub_1_sub_1_type, type_1_sub_1_sub_1_type}, implemented_by{type_2_type, type_2_sub_1_type}, implemented_by{type_2_sub_1_type, type_2_sub_1_type} })); QCOMPARE(result.ambiguous(), types{}); } void type_relations_test::should_create_unique_relations_for_type_with_supertypes() { auto result = make_type_relations({type_1_sub_1_sub_1_type}); QCOMPARE(result.unique(), (implemented_by_mapping { implemented_by{type_1_type, type_1_sub_1_sub_1_type}, implemented_by{type_1_sub_1_type, type_1_sub_1_sub_1_type}, implemented_by{type_1_sub_1_sub_1_type, type_1_sub_1_sub_1_type} })); QCOMPARE(result.ambiguous(), types{}); } void type_relations_test::should_create_ambiguous_relations_for_the_same_type() { auto result = make_type_relations({type_1_type, type_1_type}); QCOMPARE(result.unique(), implemented_by_mapping{}); QCOMPARE(result.ambiguous(), types{type_1_type}); } void type_relations_test::should_create_mixed_relations_for_subtypes() { auto result = make_type_relations({type_1_sub_1_sub_1_type, type_1_sub_1_sub_2_type}); QCOMPARE(result.unique(), (implemented_by_mapping { implemented_by{type_1_sub_1_sub_1_type, type_1_sub_1_sub_1_type}, implemented_by{type_1_sub_1_sub_2_type, type_1_sub_1_sub_2_type} })); QCOMPARE(result.ambiguous(), (types{type_1_type, type_1_sub_1_type})); } void type_relations_test::should_create_mixed_relations_for_type_and_subtype() { auto result = make_type_relations({type_1_type, type_1_sub_1_sub_1_type}); QCOMPARE(result.unique(), (implemented_by_mapping { implemented_by{type_1_sub_1_type, type_1_sub_1_sub_1_type}, implemented_by{type_1_sub_1_sub_1_type, type_1_sub_1_sub_1_type} })); QCOMPARE(result.ambiguous(), types{type_1_type}); } void type_relations_test::should_create_mixed_relations_for_subtype_and_type() { auto result = make_type_relations({type_1_sub_1_sub_1_type, type_1_type}); QCOMPARE(result.unique(), (implemented_by_mapping { implemented_by{type_1_sub_1_type, type_1_sub_1_sub_1_type}, implemented_by{type_1_sub_1_sub_1_type, type_1_sub_1_sub_1_type} })); QCOMPARE(result.ambiguous(), types{type_1_type}); } QTEST_APPLESS_MAIN(type_relations_test); #include "type-relations-test.moc" injeqt-1.2.0/test/unit/type-role-test.cpp000066400000000000000000000061211307635157000203520ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include "internal/type-role.h" #include #include using namespace injeqt::internal; using namespace injeqt::v1; #define ROLE_1 "role1" #define ROLE_2 "role2" class no_role_type : public QObject { Q_OBJECT }; class role_1_type : public no_role_type { Q_OBJECT INJEQT_TYPE_ROLE(ROLE_1) }; class role_1_inherited_type : public role_1_type { Q_OBJECT }; class role_1_double_type : public no_role_type { Q_OBJECT INJEQT_TYPE_ROLE(ROLE_1) INJEQT_TYPE_ROLE(ROLE_1) }; class role_2_inherited_from_role_1_type : public role_1_type { Q_OBJECT INJEQT_TYPE_ROLE(ROLE_2) }; class role_1_and_2_type : public no_role_type { Q_OBJECT INJEQT_TYPE_ROLE(ROLE_1) INJEQT_TYPE_ROLE(ROLE_2) }; class type_role_test : public QObject { Q_OBJECT private slots: void should_have_no_role_by_default(); void should_have_one_role_when_directly_declared(); void should_have_one_role_when_declared_in_supertype(); void should_have_one_role_when_declared_twice(); void should_have_two_roles_when_added_in_subtype(); void should_have_two_roles_when_directly_declared(); }; void type_role_test::should_have_no_role_by_default() { QVERIFY(!has_type_role(ROLE_1)); QVERIFY(!has_type_role(ROLE_2)); } void type_role_test::should_have_one_role_when_directly_declared() { QVERIFY(has_type_role(ROLE_1)); QVERIFY(!has_type_role(ROLE_2)); } void type_role_test::should_have_one_role_when_declared_in_supertype() { QVERIFY(has_type_role(ROLE_1)); QVERIFY(!has_type_role(ROLE_2)); } void type_role_test::should_have_one_role_when_declared_twice() { QVERIFY(has_type_role(ROLE_1)); QVERIFY(!has_type_role(ROLE_2)); } void type_role_test::should_have_two_roles_when_added_in_subtype() { QVERIFY(has_type_role(ROLE_1)); QVERIFY(has_type_role(ROLE_2)); } void type_role_test::should_have_two_roles_when_directly_declared() { QVERIFY(has_type_role(ROLE_1)); QVERIFY(has_type_role(ROLE_2)); } QTEST_APPLESS_MAIN(type_role_test) #include "type-role-test.moc" injeqt-1.2.0/test/unit/type-test.cpp000066400000000000000000000043171307635157000174200ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include #include using namespace injeqt::v1; class type_test : public QObject { Q_OBJECT private slots: void should_return_empty_when_created_with_null_meta_object(); void should_return_qobject_when_created_with_qobject_meta_object(); void should_return_valid_meta_object(); void should_properly_compare(); }; class valid_type : public QObject { Q_OBJECT }; class valid_type2 : public QObject { Q_OBJECT }; void type_test::should_return_empty_when_created_with_null_meta_object() { auto t = type{nullptr}; QVERIFY(t.is_empty()); } void type_test::should_return_qobject_when_created_with_qobject_meta_object() { auto t = make_type(); QVERIFY(!t.is_empty()); QVERIFY(t.is_qobject()); } void type_test::should_return_valid_meta_object() { auto t = make_type(); QCOMPARE(t.meta_object(), &valid_type::staticMetaObject); } void type_test::should_properly_compare() { auto t1a = type{}; auto t1b = type{}; auto t2a = make_type(); auto t2b = make_type(); auto t3a = make_type(); auto t3b = make_type(); auto t4a = make_type(); auto t4b = make_type(); test_compare_ex({{t1a, t1b}, {t2a, t2b}, {t3a, t3b}, {t4a, t4b}}); } QTEST_APPLESS_MAIN(type_test) #include "type-test.moc" injeqt-1.2.0/test/unit/types-by-name-test.cpp000066400000000000000000000047741307635157000211400ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "internal/types-by-name.h" using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT }; class type_2 : public QObject { Q_OBJECT }; class type_3 : public QObject { Q_OBJECT }; class types_by_name_test : public QObject { Q_OBJECT public: types_by_name_test(); private slots: void should_return_empty_for_empty_name(); void should_return_empty_for_asterix(); void should_return_empty_for_type_name(); void should_return_valid_for_type_name_with_asterix(); void should_return_empty_for_unknown_type_name_with_asterix(); private: types_by_name _known_types; }; types_by_name_test::types_by_name_test() : _known_types{ make_type(), make_type() } { } void types_by_name_test::should_return_empty_for_empty_name() { auto t = type_by_pointer(_known_types, {}); QVERIFY(t.is_empty()); } void types_by_name_test::should_return_empty_for_asterix() { auto t = type_by_pointer(_known_types, "*"); QVERIFY(t.is_empty()); } void types_by_name_test::should_return_empty_for_type_name() { auto t = type_by_pointer(_known_types, "type_1"); QVERIFY(t.is_empty()); } void types_by_name_test::should_return_valid_for_type_name_with_asterix() { auto t1 = type_by_pointer(_known_types, "type_1*"); QCOMPARE(make_type(), t1); auto t2 = type_by_pointer(_known_types, "type_2*"); QCOMPARE(make_type(), t2); } void types_by_name_test::should_return_empty_for_unknown_type_name_with_asterix() { auto t = type_by_pointer(_known_types, "type_3*"); QVERIFY(t.is_empty()); } QTEST_APPLESS_MAIN(types_by_name_test) #include "types-by-name-test.moc" injeqt-1.2.0/test/unit/types-model-test.cpp000066400000000000000000000153661307635157000207070ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "expect.h" #include "utils.h" #include #include #include #include "internal/types-model.h" #include using namespace injeqt::internal; using namespace injeqt::v1; class type_1 : public QObject { Q_OBJECT }; class type_1_subtype_1 : public type_1 { Q_OBJECT }; class type_1_subtype_2 : public type_1 { Q_OBJECT }; class type_1_subtype_2_subtype_1 : public type_1_subtype_2 { Q_OBJECT }; class type_1_subtype_3 : public type_1 { Q_OBJECT public slots: INJEQT_SET void set_type_1_subtype_1(type_1_subtype_1 *) {} INJEQT_SET void set_type_1_subtype_2(type_1_subtype_2 *) {} }; class types_model_test : public QObject { Q_OBJECT public: types_model_test(); private slots: void should_create_empty_types_model(); void should_create_one_type_types_model(); void should_throw_when_one_type_duplicated(); void should_throw_when_type_and_subtype_passed(); void should_create_with_common_supertype(); void should_create_with_dependencies(); void should_throw_when_unresolvable_dependency(); private: types_by_name known_types; type type_1_type; type type_1_subtype_1_type; type type_1_subtype_2_type; type type_1_subtype_2_subtype_1_type; type type_1_subtype_3_type; }; types_model_test::types_model_test() : type_1_type{make_type()}, type_1_subtype_1_type{make_type()}, type_1_subtype_2_type{make_type()}, type_1_subtype_2_subtype_1_type{make_type()}, type_1_subtype_3_type{make_type()} { known_types = types_by_name{std::vector{ make_type(), make_type(), make_type(), make_type(), make_type() }}; } void types_model_test::should_create_empty_types_model() { auto empty_1 = types_model{}; auto empty_2 = make_types_model(known_types, std::vector{}, std::vector{}); QCOMPARE(empty_1.available_types(), implemented_by_mapping{}); QCOMPARE(empty_1.mapped_dependencies(), types_dependencies{}); } void types_model_test::should_create_one_type_types_model() { auto m1 = make_types_model(known_types, {type_1_type}, {type_1_type}); QCOMPARE(m1.available_types(), (implemented_by_mapping { implemented_by{type_1_type, type_1_type} })); QCOMPARE(m1.mapped_dependencies(), (types_dependencies { make_type_dependencies(known_types, type_1_type) })); auto m2 = make_types_model(known_types, {type_1_subtype_1_type}, {type_1_subtype_1_type}); QCOMPARE(m2.available_types(), (implemented_by_mapping { implemented_by{type_1_type, type_1_subtype_1_type}, implemented_by{type_1_subtype_1_type, type_1_subtype_1_type} })); QCOMPARE(m2.mapped_dependencies(), (types_dependencies { make_type_dependencies(known_types, type_1_subtype_1_type) })); } void types_model_test::should_throw_when_one_type_duplicated() { expect({}, [&]{ make_types_model(known_types, {type_1_type, type_1_type}, {type_1_type, type_1_type}); }); } void types_model_test::should_throw_when_type_and_subtype_passed() { expect({}, [&]{ make_types_model(known_types, {type_1_type, type_1_subtype_1_type}, {type_1_type, type_1_subtype_1_type}); }); expect({}, [&]{ make_types_model(known_types, {type_1_subtype_1_type, type_1_type}, {type_1_subtype_1_type, type_1_type}); }); } void types_model_test::should_create_with_common_supertype() { auto m = make_types_model(known_types, {type_1_subtype_1_type, type_1_subtype_2_type}, {type_1_subtype_1_type, type_1_subtype_2_type}); QCOMPARE(m.available_types(), (implemented_by_mapping { implemented_by{type_1_subtype_1_type, type_1_subtype_1_type}, implemented_by{type_1_subtype_2_type, type_1_subtype_2_type} })); QCOMPARE(m.mapped_dependencies(), (types_dependencies { make_type_dependencies(known_types, type_1_subtype_1_type), make_type_dependencies(known_types, type_1_subtype_2_type) })); } void types_model_test::should_create_with_dependencies() { auto m1 = make_types_model(known_types, {type_1_subtype_1_type, type_1_subtype_2_type, type_1_subtype_3_type}, {type_1_subtype_1_type, type_1_subtype_2_type, type_1_subtype_3_type}); QCOMPARE(m1.available_types(), (implemented_by_mapping { implemented_by{type_1_subtype_1_type, type_1_subtype_1_type}, implemented_by{type_1_subtype_2_type, type_1_subtype_2_type}, implemented_by{type_1_subtype_3_type, type_1_subtype_3_type} })); QCOMPARE(m1.mapped_dependencies(), (types_dependencies { make_type_dependencies(known_types, type_1_subtype_1_type), make_type_dependencies(known_types, type_1_subtype_2_type), make_type_dependencies(known_types, type_1_subtype_3_type) })); auto m2 = make_types_model(known_types, {type_1_subtype_1_type, type_1_subtype_2_subtype_1_type, type_1_subtype_3_type}, {type_1_subtype_1_type, type_1_subtype_2_subtype_1_type, type_1_subtype_3_type}); QCOMPARE(m2.available_types(), (implemented_by_mapping { implemented_by{type_1_subtype_1_type, type_1_subtype_1_type}, implemented_by{type_1_subtype_2_type, type_1_subtype_2_subtype_1_type}, implemented_by{type_1_subtype_2_subtype_1_type, type_1_subtype_2_subtype_1_type}, implemented_by{type_1_subtype_3_type, type_1_subtype_3_type} })); QCOMPARE(m2.mapped_dependencies(), (types_dependencies { make_type_dependencies(known_types, type_1_subtype_1_type), make_type_dependencies(known_types, type_1_subtype_2_subtype_1_type), make_type_dependencies(known_types, type_1_subtype_3_type) })); } void types_model_test::should_throw_when_unresolvable_dependency() { expect({"set_type_1_subtype_1", "set_type_1_subtype_2"}, [&]{ make_types_model(known_types, {type_1_subtype_3_type}, {type_1_subtype_3_type}); }); } QTEST_APPLESS_MAIN(types_model_test) #include "types-model-test.moc" injeqt-1.2.0/test/unit/utils.h000066400000000000000000000073141307635157000162670ustar00rootroot00000000000000/* * %injeqt copyright begin% * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) * %injeqt copyright end% * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include "internal/setter-method.h" #include #include #include #include namespace injeqt { namespace v1 { template inline QMetaMethod get_method(const std::string &signature) { return T::staticMetaObject.method(T::staticMetaObject.indexOfMethod(signature.data())); } template inline QMetaMethod get_constructor(const std::string &signature) { return T::staticMetaObject.constructor(T::staticMetaObject.indexOfConstructor(signature.data())); } template inline injeqt::internal::setter_method make_test_setter_method(const std::string &signature) { return injeqt::internal::setter_method{make_type

(), get_method(signature)}; } template std::unique_ptr make_object() { return std::unique_ptr(new T{}); } template inline QMetaMethod make_method(const std::string &signature) { return T::staticMetaObject.method(T::staticMetaObject.indexOfMethod(signature.data())); } template void test_compare(const std::vector> objects) { for (decltype(objects.size()) i = 0; i < objects.size(); i++) for (decltype(objects.size()) j = 0; j < objects.size(); j++) if (i != j) { for (auto &&x : objects[i]) for (auto &&y : objects[j]) { QVERIFY(x != y); QVERIFY(y != x); } } else { for (auto &&x : objects[i]) for (auto &&y : objects[j]) { QVERIFY(x == y); QVERIFY(y == x); } } } template void test_compare_ex(const std::vector> objects) { for (decltype(objects.size()) i = 0; i < objects.size(); i++) for (decltype(objects.size()) j = 0; j < objects.size(); j++) if (i != j) { for (auto &&x : objects[i]) { auto first = true; auto c1 = false; auto c2 = false; auto c3 = false; auto c4 = false; auto c5 = false; auto c6 = false; auto c7 = false; auto c8 = false; for (auto &&y : objects[j]) { QVERIFY(x != y); QVERIFY(y != x); QVERIFY((x < y) ^ (y < x)); QVERIFY((x > y) ^ (y > x)); QVERIFY((x <= y) ^ (y <= x)); QVERIFY((x >= y) ^ (y >= x)); if (first) { c1 = x < y; c2 = y < x; c3 = x <= y; c4 = y <= x; c5 = x > y; c6 = y > x; c7 = x >= y; c8 = y >= x; } else { QCOMPARE(c1, x < y); QCOMPARE(c2, y < x); QCOMPARE(c3, x <= y); QCOMPARE(c4, y <= y); QCOMPARE(c5, x > y); QCOMPARE(c6, y > x); QCOMPARE(c7, x >= y); QCOMPARE(c8, y >= x); } } } } else { for (auto &&x : objects[i]) for (auto &&y : objects[j]) { QVERIFY(x == y); QVERIFY(y == x); } } } }}