From 0c5fe7e5fe5506bda2f936341cb8a33880a88ca3 Mon Sep 17 00:00:00 2001 From: Cyril Adrian Date: Sat, 31 Oct 2015 11:58:24 +0100 Subject: [PATCH] New mock tool. The start of a new adventure: a real mocker tool, based on the SmartEiffel code to access the complete definition of a class with all its deferred features, including the inherited ones. Note finished: the tool currently only displays the list of the deferred features it found. The actual mock class need to be generated. --- src/smarteiffel/commands/mock.e | 237 ++++++++++++++++++ .../generation/mock/mock_printer.e | 46 ++++ src/smarteiffel/kernel/type.e | 2 +- src/smarteiffel/loadpath.se | 1 + .../utils/mock_features_collector.e | 147 +++++++++++ 5 files changed, 432 insertions(+), 1 deletion(-) create mode 100644 src/smarteiffel/commands/mock.e create mode 100644 src/smarteiffel/generation/mock/mock_printer.e create mode 100644 src/smarteiffel/utils/mock_features_collector.e diff --git a/src/smarteiffel/commands/mock.e b/src/smarteiffel/commands/mock.e new file mode 100644 index 0000000000..7201cd7899 --- /dev/null +++ b/src/smarteiffel/commands/mock.e @@ -0,0 +1,237 @@ +-- This file is part of Liberty Eiffel The GNU Eiffel Compiler Tools and Libraries. +-- See the Copyright notice at the end of this file. +-- +class MOCK + -- + -- The `mock' command. + -- + + --| **** TODO: this class is a sibling of CLASS_CHECK and SHORT. It should be an heir of CLASS_CHECKER, + --| which needs some refactoring. The short framework should be a visitor instead of being hard-coded + --| throughout the whole AST. + +inherit + COMMAND_LINE_TOOLS + +create {} + make + +feature {ANY} + command_line_name: STRING "mock" + + command_line_help_summary: STRING "[ + Usage: mock [options] + + Option summary: + + Information: + -help Display this help information + -version Display Liberty Eiffel version information + -verbose Display detailed information about what the + program is doing + + Warning levels: + -style_warning Do print warnings about style violations + -no_warning Don't print any warnings + + Class lookup: + -loadpath Specify an extra loadpath file to read + + Mock generation: + -mock Specify the name of the "MOCK" class file + (the class name is derived from the file name) + + -expect Specify the name of the "EXPECT" class file + (the class name is derived from the file name) + + ]" + +feature {} + is_valid_argument_for_ace_mode (arg: STRING): BOOLEAN + do + Result := True + if is_version_flag(arg) then + elseif is_verbose_flag(arg) then + elseif is_help_flag(arg) then + elseif is_case_insensitive_flag(arg) then + elseif is_no_warning_flag(arg) then + elseif is_flymake_mode_flag(arg) then + elseif is_style_warning_flag(arg) then + elseif arg.item(1) = '-' then + Result := False + else + if arg.has_suffix(eiffel_suffix) then + arg.remove_suffix(eiffel_suffix) + end + ace.set_root_class_name_using(arg) + end + end + + valid_argument_for_ace_mode: STRING "Only the -version, -help, -no_warning, and -style_warning are%N% + %allowed in ACE file mode.%N" + + parse_arguments + local + i: INTEGER; arg: STRING + do + -- `mock' has the same needs as `short' and `class_check' + smart_eiffel.set_short_or_class_check_flag + if argument_count = 0 then + fatal_bad_usage + end + if ace_file_mode then + else + from + i := 1 + until + i > argument_count + loop + arg := argument(i) + if flag_match(fz_loadpath, arg) then + if i = argument_count then + fatal_bad_usage + else + system_tools.add_loadpath_file(argument(i + 1)) + i := i + 1 + end + elseif is_valid_argument_for_ace_mode(arg) then + else + fatal_bad_usage + end + i := i + 1 + end + ace.command_line_parsed(command_line_name) + end + if help_flag then + die_with_code(exit_success_code) + end + if version_flag then + die_with_code(exit_success_code) + end + + ace.reset_roots + if not ace.has_root then + fatal_bad_usage + else + root_class_name := ace.root_class_name + ace.next_root + if ace.has_root then + fatal_bad_usage + end + end + ensure + root_class_name /= Void + end + + fatal_bad_usage + do + system_tools.bad_use_exit(command_name, command_line_help_summary) + end + +feature {} + mock (class_text: CLASS_TEXT) + require + class_text /= Void + parent_list.is_empty + not class_text.name.is_tuple_related -- because TUPLE is not deferred + local + i: INTEGER + do + parent_list.add_last(class_text.declaration_type_of_like_current) + parent_list.last.up_to_any_in(parent_list) + ace.set_command_line_debug --| **** what for??? + + type := class_text.declaration_type_of_like_current + collect_features + + from + i := features_collector.features.lower + until + i > features_collector.features.upper + loop + std_output.put_line(features_collector.features.key(i).to_string) + i := i + 1 + end + end + + collect_features + local + i: INTEGER + do + create features_collector.make + from + i := parent_list.lower + until + i > parent_list.upper + loop + features_collector.collect(parent_list.item(i)) + i := i + 1 + end + end + + make + local + bc: CLASS_TEXT; cn: CLASS_NAME + do + smart_eiffel.set_short_or_class_check_flag + parse_arguments + smart_eiffel.initialize_any_tuple + + create cn.unknown_position(root_class_name, False) + bc := smart_eiffel.class_text(cn) + if not bc.is_deferred then + error_handler.append(once "The class ") + error_handler.append(root_class_name.to_string) + error_handler.append(once " is not deferred. It cannot be mocked.") + error_handler.print_as_fatal_error + end + if bc.obsolete_mark /= Void then + error_handler.append(once "The class ") + error_handler.append(root_class_name.to_string) + error_handler.append(once " is obsolete: ") + error_handler.append(bc.obsolete_mark.to_string) + error_handler.print_as_warning + end + + mock(bc) + + smart_eiffel.very_last_information + end + + root_class_name: HASHED_STRING + type: TYPE + + features_collector: MOCK_FEATURES_COLLECTOR + + parent_list: FAST_ARRAY[TYPE] + -- All paths from the type to `mock' to the ANY type excluded. Actually, this `parent_list' is used + -- to select the order of features output of command `mock'. + once + create Result.with_capacity(4) + end + +end -- class MOCK +-- +-- ------------------------------------------------------------------------------------------------------------------------------ +-- Copyright notice below. Please read. +-- +-- Liberty Eiffel is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, +-- as published by the Free Software Foundation; either version 2, or (at your option) any later version. +-- Liberty Eiffel 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 General Public License for more details. You should have +-- received a copy of the GNU General Public License along with Liberty Eiffel; see the file COPYING. If not, write to the Free +-- Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +-- +-- Copyright(C) 2011-2015: Cyril ADRIAN, Paolo REDAELLI, Raphael MACK +-- +-- http://www.gnu.org/software/liberty-eiffel/ +-- +-- +-- Liberty Eiffel is based on SmartEiffel (Copyrights below) +-- +-- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P. - University of Nancy 1 - FRANCE +-- Copyright(C) 2003-2006: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE +-- +-- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN +-- +-- ------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/smarteiffel/generation/mock/mock_printer.e b/src/smarteiffel/generation/mock/mock_printer.e new file mode 100644 index 0000000000..397b9734a5 --- /dev/null +++ b/src/smarteiffel/generation/mock/mock_printer.e @@ -0,0 +1,46 @@ +-- This file is part of Liberty Eiffel The GNU Eiffel Compiler Tools and Libraries. +-- See the Copyright notice at the end of this file. +-- +class MOCK_PRINTER + -- + -- Driver for the 'mock' command. + -- + +insert + GLOBALS + +inherit + IN_OUT_VISITOR + +create {ANY} + make + +feature {ANY} + type: TYPE + -- The `type' to mock. + +end -- class MOCK_PRINTER +-- +-- ------------------------------------------------------------------------------------------------------------------------------ +-- Copyright notice below. Please read. +-- +-- Liberty Eiffel is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, +-- as published by the Free Software Foundation; either version 2, or (at your option) any later version. +-- Liberty Eiffel 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 General Public License for more details. You should have +-- received a copy of the GNU General Public License along with Liberty Eiffel; see the file COPYING. If not, write to the Free +-- Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +-- +-- Copyright(C) 2011-2015: Cyril ADRIAN, Paolo REDAELLI, Raphael MACK +-- +-- http://www.gnu.org/software/liberty-eiffel/ +-- +-- +-- Liberty Eiffel is based on SmartEiffel (Copyrights below) +-- +-- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P. - University of Nancy 1 - FRANCE +-- Copyright(C) 2003-2006: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE +-- +-- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN +-- +-- ------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/smarteiffel/kernel/type.e b/src/smarteiffel/kernel/type.e index 9f2540fb52..c0c7355807 100644 --- a/src/smarteiffel/kernel/type.e +++ b/src/smarteiffel/kernel/type.e @@ -457,7 +457,7 @@ feature {FEATURE_ACCUMULATOR} class_text.check_level_2(Current) end -feature {CLASS_CHECKER, TYPE, IFTHENELSE_EXP} +feature {CLASS_CHECKER, MOCK, TYPE, IFTHENELSE_EXP} up_to_any_in (parent_list: FAST_ARRAY[TYPE]) -- Add in `parent_list', a path to the ANY class, without including the ANY class itself. --|*** Wrong comment diff --git a/src/smarteiffel/loadpath.se b/src/smarteiffel/loadpath.se index 3448128849..b6de5a5820 100644 --- a/src/smarteiffel/loadpath.se +++ b/src/smarteiffel/loadpath.se @@ -12,6 +12,7 @@ generation/c/loadpath.se generation/context/ generation/eiffeldoc/ generation/fake_generator/ +generation/mock/ generation/pretty/ generation/run/loadpath.se generation/sedb/ diff --git a/src/smarteiffel/utils/mock_features_collector.e b/src/smarteiffel/utils/mock_features_collector.e new file mode 100644 index 0000000000..f8f46e1ffb --- /dev/null +++ b/src/smarteiffel/utils/mock_features_collector.e @@ -0,0 +1,147 @@ +-- This file is part of Liberty Eiffel The GNU Eiffel Compiler Tools and Libraries. +-- See the Copyright notice at the end of this file. +-- +class MOCK_FEATURES_COLLECTOR + -- + -- Deferred features collector + -- + +inherit + CLASS_TEXT_VISITOR + FEATURE_CLAUSE_LIST_VISITOR + FEATURE_CLAUSE_VISITOR + FEATURE_TEXT_VISITOR + FEATURE_NAME_LIST_VISITOR + FEATURE_NAME_VISITOR + +create {MOCK} + make + +feature {MOCK} + collect (a_type: like type) + require + a_type /= Void + not collecting + do + type := a_type + type.class_text.accept(Current) + type := Void + end + + collecting: BOOLEAN then type /= Void end + features: LINKED_HASHED_DICTIONARY[ANONYMOUS_FEATURE, FEATURE_NAME] + +feature {CLASS_TEXT} + visit_class_text (visited: CLASS_TEXT) + local + fcl: FEATURE_CLAUSE_LIST + do + fcl := visited.feature_clause_list + if fcl /= Void then + fcl.accept(Current) + end + end + +feature {FEATURE_CLAUSE_LIST} + visit_feature_clause_list (visited: FEATURE_CLAUSE_LIST) + local + i: INTEGER + do + from + i := visited.list.lower + until + i > visited.list.upper + loop + visited.list.item(i).accept(Current) + i := i + 1 + end + end + +feature {FEATURE_CLAUSE} + visit_feature_clause (visited: FEATURE_CLAUSE) + local + i: INTEGER + do + if visited.list /= Void then + from + i := visited.list.lower + until + i > visited.list.upper + loop + visited.list.item(i).accept(Current) + i := i + 1 + end + end + end + +feature {FEATURE_TEXT} + visit_feature_text (visited: FEATURE_TEXT) + do + if visited.anonymous_feature.is_deferred then + anonymous_feature := visited.anonymous_feature + anonymous_feature.names.accept(Current) + anonymous_feature := Void + end + end + +feature {FEATURE_NAME_LIST} + visit_feature_name_list (visited: FEATURE_NAME_LIST) + local + i: INTEGER + do + from + i := 1 + until + i > visited.count + loop + visited.item(i).accept(Current) + i := i + 1 + end + end + +feature {FEATURE_NAME} + visit_feature_name (visited: FEATURE_NAME) + do + check anonymous_feature.is_deferred end + features.put(anonymous_feature, visited) + end + +feature {} + make + do + create features.make + end + + anonymous_feature: ANONYMOUS_FEATURE + + type: TYPE + +invariant + anonymous_feature /= Void implies anonymous_feature.is_deferred + features.for_all(agent (af: ANONYMOUS_FEATURE): BOOLEAN then af.is_deferred end(?)) + +end -- class MOCK_FEATURES_COLLECTOR +-- +-- ------------------------------------------------------------------------------------------------------------------------------ +-- Copyright notice below. Please read. +-- +-- Liberty Eiffel is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, +-- as published by the Free Software Foundation; either version 2, or (at your option) any later version. +-- Liberty Eiffel 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 General Public License for more details. You should have +-- received a copy of the GNU General Public License along with Liberty Eiffel; see the file COPYING. If not, write to the Free +-- Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +-- +-- Copyright(C) 2011-2015: Cyril ADRIAN, Paolo REDAELLI, Raphael MACK +-- +-- http://www.gnu.org/software/liberty-eiffel/ +-- +-- +-- Liberty Eiffel is based on SmartEiffel (Copyrights below) +-- +-- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P. - University of Nancy 1 - FRANCE +-- Copyright(C) 2003-2006: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE +-- +-- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN +-- +-- ------------------------------------------------------------------------------------------------------------------------------