Browse Source

more api docs code samples

avkonst 11 years ago
parent
commit
3493c0f02b
41 changed files with 382 additions and 105 deletions
  1. 5 3
      mainline/ext/std/code/complexity.py
  2. 1 1
      mainline/ext/std/code/length.py
  3. 8 2
      mainline/mpp/api.py
  4. 3 1
      mainline/mpp/internal/loader.py
  5. 20 53
      mainline/tests/system/test_api_tutorial.py
  6. 9 4
      mainline/tests/system/test_api_tutorial/ext/step2/myext/magic.py
  7. 9 3
      mainline/tests/system/test_api_tutorial/ext/step3/myext/magic.py
  8. 15 10
      mainline/tests/system/test_api_tutorial/ext/step4/myext/magic.py
  9. 19 13
      mainline/tests/system/test_api_tutorial/ext/step5/myext/magic.py
  10. 18 0
      mainline/tests/system/test_api_tutorial/ext/step6/myext/__init__.py
  11. 27 0
      mainline/tests/system/test_api_tutorial/ext/step6/myext/magic.ini
  12. 66 0
      mainline/tests/system/test_api_tutorial/ext/step6/myext/magic.py
  13. 18 0
      mainline/tests/system/test_api_tutorial/ext/step7/myext/__init__.py
  14. 27 0
      mainline/tests/system/test_api_tutorial/ext/step7/myext/magic.ini
  15. 65 0
      mainline/tests/system/test_api_tutorial/ext/step7/myext/magic.py
  16. 10 0
      mainline/tests/system/test_api_tutorial/sources/test.cpp
  17. 0 14
      mainline/tests/system/test_api_tutorial/test_basic_view_step4_stdout.gold.txt
  18. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step0_stderr.gold.txt
  19. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step0_stdout.gold.txt
  20. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step1_stderr.gold.txt
  21. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step1_stdout.gold.txt
  22. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step2_stderr.gold.txt
  23. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step2_stdout.gold.txt
  24. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step3_stderr.gold.txt
  25. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step3_stdout.gold.txt
  26. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step4_stderr.gold.txt
  27. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step4_stdout.gold.txt
  28. 3 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step5_stderr.gold.txt
  29. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step5_stdout.gold.txt
  30. 3 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step6_stderr.gold.txt
  31. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step6_stdout.gold.txt
  32. 3 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step7_stderr.gold.txt
  33. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step7_stdout.gold.txt
  34. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step4_stderr.gold.txt
  35. 16 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step4_stdout.gold.txt
  36. 0 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step5_stderr.gold.txt
  37. 15 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step5_stdout.gold.txt
  38. 3 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step6_stderr.gold.txt
  39. 15 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step6_stdout.gold.txt
  40. 3 0
      mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step7_stderr.gold.txt
  41. 1 1
      mainline/tests/system/test_api_tutorial/test_basic_view_step5_stdout.gold.txt

+ 5 - 3
mainline/ext/std/code/complexity.py

@@ -68,9 +68,11 @@ class Plugin(mpp.api.Plugin, mpp.api.MetricPluginMixin, mpp.api.Child, mpp.api.I
         super(Plugin, self).initialize(fields=self.get_fields())
         super(Plugin, self).initialize(fields=self.get_fields())
         
         
         if self.is_active() == True:
         if self.is_active() == True:
-            self.subscribe_by_parents_name('std.code.cpp')
-            self.subscribe_by_parents_name('std.code.cs')
-            self.subscribe_by_parents_name('std.code.java')
+            self.subscribe_by_parents_names([
+                'std.code.cpp',
+                'std.code.cs',
+                'std.code.java'
+            ])
 
 
     def _maxindent_count_initialize(self, alias, data, region):
     def _maxindent_count_initialize(self, alias, data, region):
         return (0, {'cur_level': 0})
         return (0, {'cur_level': 0})

+ 1 - 1
mainline/ext/std/code/length.py

@@ -35,7 +35,7 @@ class Plugin(mpp.api.Plugin, mpp.api.Child, mpp.api.IConfigurable):
         mpp.api.Plugin.initialize(self, fields=fields)
         mpp.api.Plugin.initialize(self, fields=fields)
         
         
         if len(fields) != 0:
         if len(fields) != 0:
-            self.subscribe_by_parents_interface(mpp.api.ICode, 'callback')
+            self.subscribe_by_parents_interface(mpp.api.ICode)
 
 
     def callback(self, parent, data, is_updated):
     def callback(self, parent, data, is_updated):
         is_updated = is_updated or self.is_updated
         is_updated = is_updated or self.is_updated

+ 8 - 2
mainline/mpp/api.py

@@ -1061,7 +1061,8 @@ class MetricPluginMixin(object):
                     end = marker.get_offset_end()
                     end = marker.get_offset_end()
                     for match in pattern_to_search.finditer(text, begin, end):
                     for match in pattern_to_search.finditer(text, begin, end):
                         count = counter_callback(alias, data, region, marker, match, count, counter_data)
                         count = counter_callback(alias, data, region, marker, match, count, counter_data)
-                region.set_data(namespace, metric_name, count)
+                if count != 0 or field_data[0].non_zero == False:
+                    region.set_data(namespace, metric_name, count)
         else:
         else:
             for region in data.iterate_regions(filter_group=field_data[5]):
             for region in data.iterate_regions(filter_group=field_data[5]):
                 count = 0
                 count = 0
@@ -1071,7 +1072,8 @@ class MetricPluginMixin(object):
                                 exclude_children = field_data[2],
                                 exclude_children = field_data[2],
                                 merge=field_data[3]):
                                 merge=field_data[3]):
                     count += len(pattern_to_search.findall(text, marker.get_offset_begin(), marker.get_offset_end()))
                     count += len(pattern_to_search.findall(text, marker.get_offset_begin(), marker.get_offset_end()))
-                region.set_data(namespace, metric_name, count)
+                if count != 0 or field_data[0].non_zero == False:
+                    region.set_data(namespace, metric_name, count)
 
 
 class InterfaceNotImplemented(Exception):
 class InterfaceNotImplemented(Exception):
     def __init__(self, obj):
     def __init__(self, obj):
@@ -1116,6 +1118,10 @@ class Child(object):
     def subscribe_by_parents_name(self, parent_name, callback_name='callback'):
     def subscribe_by_parents_name(self, parent_name, callback_name='callback'):
         self.get_plugin(parent_name).subscribe(self, callback_name)
         self.get_plugin(parent_name).subscribe(self, callback_name)
     
     
+    def subscribe_by_parents_names(self, parent_names, callback_name='callback'):
+        for parent_name in parent_names:
+            self.get_plugin(parent_name).subscribe(self, callback_name)
+
     def subscribe_by_parents_interface(self, interface, callback_name='callback'):
     def subscribe_by_parents_interface(self, interface, callback_name='callback'):
         for plugin in self._get_plugin_loader().iterate_plugins():
         for plugin in self._get_plugin_loader().iterate_plugins():
             if isinstance(plugin, interface):
             if isinstance(plugin, interface):

+ 3 - 1
mainline/mpp/internal/loader.py

@@ -74,8 +74,10 @@ class Loader(object):
                 
                 
         def load_recursively(inicontainer, directory):
         def load_recursively(inicontainer, directory):
             active_plugins = []
             active_plugins = []
+            if os.path.exists(directory) == False or os.path.isdir(directory) == False:
+                return active_plugins
+
             pattern = re.compile(r'.*[.]ini$', flags=re.IGNORECASE)
             pattern = re.compile(r'.*[.]ini$', flags=re.IGNORECASE)
-        
             dirList = os.listdir(directory)
             dirList = os.listdir(directory)
             for fname in dirList:
             for fname in dirList:
                 fname = os.path.join(directory, fname)
                 fname = os.path.join(directory, fname)

+ 20 - 53
mainline/tests/system/test_api_tutorial.py

@@ -25,7 +25,7 @@ import tests.common
 
 
 class Test(tests.common.TestCase):
 class Test(tests.common.TestCase):
 
 
-    def test_basic(self):
+    def test_metric_plugin_api(self):
         
         
         #
         #
         # WARNING:
         # WARNING:
@@ -36,60 +36,27 @@ class Test(tests.common.TestCase):
         if 'METRIXPLUSPLUS_PATH' in os.environ.keys():
         if 'METRIXPLUSPLUS_PATH' in os.environ.keys():
             METRIXPLUSPLUS_PATH = os.environ['METRIXPLUSPLUS_PATH']
             METRIXPLUSPLUS_PATH = os.environ['METRIXPLUSPLUS_PATH']
         
         
-        os.environ['METRIXPLUSPLUS_PATH'] = os.path.join(os.path.dirname(os.path.abspath(__file__)),
-                                                         'test_api_tutorial', 'ext', 'step1')
-        runner = tests.common.ToolRunner('collect',
+        for step in range(8):
+            opts = ['--log-level=INFO']
+            if step > 1:
+                opts.append('--myext.magic.numbers')
+            
+            os.environ['METRIXPLUSPLUS_PATH'] = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+                                                             'test_api_tutorial', 'ext', 'step' + str(step))
+            runner = tests.common.ToolRunner('collect',
+                                             opts,
+                                             prefix='step' + str(step),
+                                             check_stderr=[(0, -1)])
+            self.assertExec(runner.run())
+            
+            if step < 4:
+                continue
+            
+            runner = tests.common.ToolRunner('view',
                                          ['--log-level=INFO'],
                                          ['--log-level=INFO'],
-                                         prefix='step1',
+                                         prefix='step' + str(step),
                                          check_stderr=[(0, -1)])
                                          check_stderr=[(0, -1)])
-        self.assertExec(runner.run())
-
-        os.environ['METRIXPLUSPLUS_PATH'] = os.path.join(os.path.dirname(os.path.abspath(__file__)),
-                                                         'test_api_tutorial', 'ext', 'step2')
-        runner = tests.common.ToolRunner('collect',
-                                         ['--log-level=INFO',
-                                          '--myext.magic.numbers'],
-                                         prefix='step2',
-                                         check_stderr=[(0, -1)])
-        self.assertExec(runner.run())
-
-        os.environ['METRIXPLUSPLUS_PATH'] = os.path.join(os.path.dirname(os.path.abspath(__file__)),
-                                                         'test_api_tutorial', 'ext', 'step3')
-        runner = tests.common.ToolRunner('collect',
-                                         ['--log-level=INFO',
-                                          '--myext.magic.numbers'],
-                                         prefix='step3',
-                                         check_stderr=[(0, -1)])
-        self.assertExec(runner.run())
-
-        os.environ['METRIXPLUSPLUS_PATH'] = os.path.join(os.path.dirname(os.path.abspath(__file__)),
-                                                         'test_api_tutorial', 'ext', 'step4')
-        runner = tests.common.ToolRunner('collect',
-                                         ['--log-level=INFO',
-                                          '--myext.magic.numbers'],
-                                         prefix='step4',
-                                         check_stderr=[(0, -1)])
-        self.assertExec(runner.run())
-        runner = tests.common.ToolRunner('view',
-                                         ['--log-level=INFO'],
-                                         prefix='step4',
-                                         check_stderr=[(0, -1)])
-        self.assertExec(runner.run())
-
-        os.environ['METRIXPLUSPLUS_PATH'] = os.path.join(os.path.dirname(os.path.abspath(__file__)),
-                                                         'test_api_tutorial', 'ext', 'step5')
-        runner = tests.common.ToolRunner('collect',
-                                         ['--log-level=INFO',
-                                          '--myext.magic.numbers'],
-                                         prefix='step5',
-                                         check_stderr=[(0, -1)])
-        self.assertExec(runner.run())
-        runner = tests.common.ToolRunner('view',
-                                         ['--log-level=INFO'],
-                                         prefix='step5',
-                                         check_stderr=[(0, -1)])
-        self.assertExec(runner.run())
-
+            self.assertExec(runner.run())
 
 
         if METRIXPLUSPLUS_PATH != None:
         if METRIXPLUSPLUS_PATH != None:
             os.environ['METRIXPLUSPLUS_PATH'] = METRIXPLUSPLUS_PATH
             os.environ['METRIXPLUSPLUS_PATH'] = METRIXPLUSPLUS_PATH

+ 9 - 4
mainline/tests/system/test_api_tutorial/ext/step2/myext/magic.py

@@ -19,16 +19,21 @@
 
 
 import mpp.api
 import mpp.api
 
 
-class Plugin(mpp.api.Plugin, mpp.api.IConfigurable):
+class Plugin(mpp.api.Plugin,
+             # make this instance configurable...
+             mpp.api.IConfigurable):
+    # ... and implement 2 interfaces
     
     
     def declare_configuration(self, parser):
     def declare_configuration(self, parser):
-        parser.add_option("--myext.magic.numbers", "--mmn", action="store_true", default=False,
-                         help="Enables collection of magic numbers metric [default: %default]")
-    
+        parser.add_option("--myext.magic.numbers", "--mmn",
+            action="store_true", default=False,
+            help="Enables collection of magic numbers metric [default: %default]")
+        
     def configure(self, options):
     def configure(self, options):
         self.is_active_numbers = options.__dict__['myext.magic.numbers']
         self.is_active_numbers = options.__dict__['myext.magic.numbers']
     
     
     def initialize(self):
     def initialize(self):
+        # use configuration option here
         if self.is_active_numbers == True:
         if self.is_active_numbers == True:
             print "Hello world"
             print "Hello world"
 
 

+ 9 - 3
mainline/tests/system/test_api_tutorial/ext/step3/myext/magic.py

@@ -19,19 +19,25 @@
 
 
 import mpp.api
 import mpp.api
 
 
-class Plugin(mpp.api.Plugin, mpp.api.IConfigurable, mpp.api.Child):
+class Plugin(mpp.api.Plugin,
+             mpp.api.IConfigurable,
+             # declare that it can subscribe on notifications
+             mpp.api.Child):
     
     
     def declare_configuration(self, parser):
     def declare_configuration(self, parser):
-        parser.add_option("--myext.magic.numbers", "--mmn", action="store_true", default=False,
-                         help="Enables collection of magic numbers metric [default: %default]")
+        parser.add_option("--myext.magic.numbers", "--mmn",
+            action="store_true", default=False,
+            help="Enables collection of magic numbers metric [default: %default]")
     
     
     def configure(self, options):
     def configure(self, options):
         self.is_active_numbers = options.__dict__['myext.magic.numbers']
         self.is_active_numbers = options.__dict__['myext.magic.numbers']
     
     
     def initialize(self):
     def initialize(self):
         if self.is_active_numbers == True:
         if self.is_active_numbers == True:
+            # subscribe to notifications from all code parsers
             self.subscribe_by_parents_interface(mpp.api.ICode, 'callback')
             self.subscribe_by_parents_interface(mpp.api.ICode, 'callback')
 
 
+    # parents (code parsers) will call the callback declared
     def callback(self, parent, data, is_updated):
     def callback(self, parent, data, is_updated):
         print parent.get_name(), data.get_path(), is_updated
         print parent.get_name(), data.get_path(), is_updated
         
         

+ 15 - 10
mainline/tests/system/test_api_tutorial/ext/step4/myext/magic.py

@@ -20,27 +20,32 @@
 import mpp.api
 import mpp.api
 import re
 import re
 
 
-class Plugin(mpp.api.Plugin, mpp.api.IConfigurable, mpp.api.Child, mpp.api.MetricPluginMixin):
+class Plugin(mpp.api.Plugin,
+             mpp.api.IConfigurable,
+             mpp.api.Child,
+             # reuse by inheriting standard metric facilities
+             mpp.api.MetricPluginMixin):
     
     
     def declare_configuration(self, parser):
     def declare_configuration(self, parser):
-        parser.add_option("--myext.magic.numbers", "--mmn", action="store_true", default=False,
-                         help="Enables collection of magic numbers metric [default: %default]")
+        parser.add_option("--myext.magic.numbers", "--mmn",
+            action="store_true", default=False,
+            help="Enables collection of magic numbers metric [default: %default]")
     
     
     def configure(self, options):
     def configure(self, options):
         self.is_active_numbers = options.__dict__['myext.magic.numbers']
         self.is_active_numbers = options.__dict__['myext.magic.numbers']
     
     
     def initialize(self):
     def initialize(self):
         # declare metric rules
         # declare metric rules
-        self.declare_metric(self.is_active_numbers, # to count if active in callback
-                            self.Field('numbers', int), # field name and type in the database
-                            re.compile(r'''[0-9]+'''), # pattern to search
-                            marker_type_mask=mpp.api.Marker.T.CODE, # search in code
-                            region_type_mask=mpp.api.Region.T.ANY) # search in all types of regions
+        self.declare_metric(
+            self.is_active_numbers, # to count if active in callback
+            self.Field('numbers', int), # field name and type in the database
+            re.compile(r'''[0-9]+'''), # pattern to search
+            marker_type_mask=mpp.api.Marker.T.CODE, # search in code
+            region_type_mask=mpp.api.Region.T.ANY) # search in all types of regions
         
         
-        # use superclass facilities to initialize everything using declared fields
+        # use superclass facilities to initialize everything from declared fields
         super(Plugin, self).initialize(fields=self.get_fields())
         super(Plugin, self).initialize(fields=self.get_fields())
         
         
         # subscribe to all code parsers if at least one metric is active
         # subscribe to all code parsers if at least one metric is active
         if self.is_active() == True:
         if self.is_active() == True:
             self.subscribe_by_parents_interface(mpp.api.ICode)
             self.subscribe_by_parents_interface(mpp.api.ICode)
-           

+ 19 - 13
mainline/tests/system/test_api_tutorial/ext/step5/myext/magic.py

@@ -20,31 +20,37 @@
 import mpp.api
 import mpp.api
 import re
 import re
 
 
-class Plugin(mpp.api.Plugin, mpp.api.IConfigurable, mpp.api.Child, mpp.api.MetricPluginMixin):
+class Plugin(mpp.api.Plugin,
+             mpp.api.IConfigurable,
+             mpp.api.Child,
+             mpp.api.MetricPluginMixin):
     
     
     def declare_configuration(self, parser):
     def declare_configuration(self, parser):
-        parser.add_option("--myext.magic.numbers", "--mmn", action="store_true", default=False,
-                         help="Enables collection of magic numbers metric [default: %default]")
+        parser.add_option("--myext.magic.numbers", "--mmn",
+            action="store_true", default=False,
+            help="Enables collection of magic numbers metric [default: %default]")
     
     
     def configure(self, options):
     def configure(self, options):
         self.is_active_numbers = options.__dict__['myext.magic.numbers']
         self.is_active_numbers = options.__dict__['myext.magic.numbers']
     
     
     def initialize(self):
     def initialize(self):
-        pattern_to_search = re.compile(r'''(const\s+([_a-zA-Z][_a-zA-Z0-9]*\s+)+[=]\s*)?[-+]?[0-9]+''')
-        # declare metric rules
-        self.declare_metric(self.is_active_numbers, # to count if active in callback
-                            self.Field('numbers', int), # field name and type in the database
-                            pattern_to_search, 
-                            marker_type_mask=mpp.api.Marker.T.CODE, # search in code
-                            region_type_mask=mpp.api.Region.T.ANY) # search in all types of regions
+        # improve pattern to find declarations of constants
+        pattern_to_search = re.compile(
+            r'''(const\s+([_a-zA-Z][_a-zA-Z0-9]*\s+)+[=]\s*)?[-+]?[0-9]+''')
+        self.declare_metric(self.is_active_numbers,
+                            self.Field('numbers', int),
+                            pattern_to_search, # and use it here
+                            marker_type_mask=mpp.api.Marker.T.CODE,
+                            region_type_mask=mpp.api.Region.T.ANY)
         
         
-        # use superclass facilities to initialize everything using declared fields
         super(Plugin, self).initialize(fields=self.get_fields())
         super(Plugin, self).initialize(fields=self.get_fields())
         
         
-        # subscribe to all code parsers if at least one metric is active
         if self.is_active() == True:
         if self.is_active() == True:
             self.subscribe_by_parents_interface(mpp.api.ICode)
             self.subscribe_by_parents_interface(mpp.api.ICode)
-            
+    
+    # implement custom counter behavior:
+    # increments counter by 1 only if single number spotted,
+    # but not declaration of a constant
     def _numbers_count(self, alias, data, region, marker, match, count, counter_data):
     def _numbers_count(self, alias, data, region, marker, match, count, counter_data):
         if match.group(0).startswith('const'):
         if match.group(0).startswith('const'):
             return count
             return count

+ 18 - 0
mainline/tests/system/test_api_tutorial/ext/step6/myext/__init__.py

@@ -0,0 +1,18 @@
+#
+#    Metrix++, Copyright 2009-2013, Metrix++ Project
+#    Link: http://metrixplusplus.sourceforge.net
+#    
+#    This file is a part of Metrix++ Tool.
+#    
+#    Metrix++ 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, version 3 of the License.
+#    
+#    Metrix++ 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 Metrix++.  If not, see <http://www.gnu.org/licenses/>.
+#

+ 27 - 0
mainline/tests/system/test_api_tutorial/ext/step6/myext/magic.ini

@@ -0,0 +1,27 @@
+;
+;    Metrix++, Copyright 2009-2013, Metrix++ Project
+;    Link: http://metrixplusplus.sourceforge.net
+;    
+;    This file is a part of Metrix++ Tool.
+;    
+;    Metrix++ 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, version 3 of the License.
+;    
+;    Metrix++ 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 Metrix++.  If not, see <http://www.gnu.org/licenses/>.
+;
+
+[Plugin]
+version: 1.0
+package: myext
+module:  magic
+class:   Plugin
+depends: None
+actions: collect
+enabled: True

+ 66 - 0
mainline/tests/system/test_api_tutorial/ext/step6/myext/magic.py

@@ -0,0 +1,66 @@
+#
+#    Metrix++, Copyright 2009-2013, Metrix++ Project
+#    Link: http://metrixplusplus.sourceforge.net
+#    
+#    This file is a part of Metrix++ Tool.
+#    
+#    Metrix++ 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, version 3 of the License.
+#    
+#    Metrix++ 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 Metrix++.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import mpp.api
+import re
+
+class Plugin(mpp.api.Plugin,
+             mpp.api.IConfigurable,
+             mpp.api.Child,
+             mpp.api.MetricPluginMixin):
+    
+    def declare_configuration(self, parser):
+        parser.add_option("--myext.magic.numbers", "--mmn",
+            action="store_true", default=False,
+            help="Enables collection of magic numbers metric [default: %default]")
+    
+    def configure(self, options):
+        self.is_active_numbers = options.__dict__['myext.magic.numbers']
+    
+    def initialize(self):
+        # specialized pattern for java
+        pattern_to_search_java = re.compile(
+            r'''(const\s+([_$a-zA-Z][_$a-zA-Z0-9]*\s+)+[=]\s*)?[-+]?[0-9]+''')
+        # pattern for C++ and C# languages
+        pattern_to_search_cpp_cs = re.compile(
+            r'''(const\s+([_a-zA-Z][_a-zA-Z0-9]*\s+)+[=]\s*)?[-+]?[0-9]+''')
+        # pattern for all other languages
+        pattern_to_search = re.compile(
+            r'''[0-9]+''')
+        self.declare_metric(self.is_active_numbers,
+                            self.Field('numbers', int),
+                            # dictionary of patterns instead of a single one
+                            {
+                             'std.code.java': pattern_to_search_java,
+                             'std.code.cpp': pattern_to_search_cpp_cs,
+                             'std.code.cs': pattern_to_search_cpp_cs,
+                             '*': pattern_to_search
+                            },
+                            marker_type_mask=mpp.api.Marker.T.CODE,
+                            region_type_mask=mpp.api.Region.T.ANY)
+        
+        super(Plugin, self).initialize(fields=self.get_fields())
+        
+        if self.is_active() == True:
+            self.subscribe_by_parents_interface(mpp.api.ICode)
+
+    def _numbers_count(self, alias, data, region, marker, match, count, counter_data):
+        if match.group(0).startswith('const'):
+            return count
+        return count + 1

+ 18 - 0
mainline/tests/system/test_api_tutorial/ext/step7/myext/__init__.py

@@ -0,0 +1,18 @@
+#
+#    Metrix++, Copyright 2009-2013, Metrix++ Project
+#    Link: http://metrixplusplus.sourceforge.net
+#    
+#    This file is a part of Metrix++ Tool.
+#    
+#    Metrix++ 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, version 3 of the License.
+#    
+#    Metrix++ 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 Metrix++.  If not, see <http://www.gnu.org/licenses/>.
+#

+ 27 - 0
mainline/tests/system/test_api_tutorial/ext/step7/myext/magic.ini

@@ -0,0 +1,27 @@
+;
+;    Metrix++, Copyright 2009-2013, Metrix++ Project
+;    Link: http://metrixplusplus.sourceforge.net
+;    
+;    This file is a part of Metrix++ Tool.
+;    
+;    Metrix++ 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, version 3 of the License.
+;    
+;    Metrix++ 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 Metrix++.  If not, see <http://www.gnu.org/licenses/>.
+;
+
+[Plugin]
+version: 1.0
+package: myext
+module:  magic
+class:   Plugin
+depends: None
+actions: collect
+enabled: True

+ 65 - 0
mainline/tests/system/test_api_tutorial/ext/step7/myext/magic.py

@@ -0,0 +1,65 @@
+#
+#    Metrix++, Copyright 2009-2013, Metrix++ Project
+#    Link: http://metrixplusplus.sourceforge.net
+#    
+#    This file is a part of Metrix++ Tool.
+#    
+#    Metrix++ 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, version 3 of the License.
+#    
+#    Metrix++ 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 Metrix++.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import mpp.api
+import re
+
+class Plugin(mpp.api.Plugin,
+             mpp.api.IConfigurable,
+             mpp.api.Child,
+             mpp.api.MetricPluginMixin):
+    
+    def declare_configuration(self, parser):
+        parser.add_option("--myext.magic.numbers", "--mmn",
+            action="store_true", default=False,
+            help="Enables collection of magic numbers metric [default: %default]")
+    
+    def configure(self, options):
+        self.is_active_numbers = options.__dict__['myext.magic.numbers']
+    
+    def initialize(self):
+        pattern_to_search_java = re.compile(
+            r'''(const\s+([_$a-zA-Z][_$a-zA-Z0-9]*\s+)+[=]\s*)?[-+]?[0-9]+''')
+        pattern_to_search_cpp_cs = re.compile(
+            r'''(const\s+([_a-zA-Z][_a-zA-Z0-9]*\s+)+[=]\s*)?[-+]?[0-9]+''')
+        pattern_to_search = re.compile(
+            r'''[0-9]+''')
+        self.declare_metric(self.is_active_numbers,
+                            self.Field('numbers', int,
+                                # optimize the size of datafile:
+                                # store only non-zero results
+                                non_zero=True),
+                            {
+                             'std.code.java': pattern_to_search_java,
+                             'std.code.cpp': pattern_to_search_cpp_cs,
+                             'std.code.cs': pattern_to_search_cpp_cs,
+                             '*': pattern_to_search
+                            },
+                            marker_type_mask=mpp.api.Marker.T.CODE,
+                            region_type_mask=mpp.api.Region.T.ANY)
+        
+        super(Plugin, self).initialize(fields=self.get_fields())
+        
+        if self.is_active() == True:
+            self.subscribe_by_parents_interface(mpp.api.ICode)
+
+    def _numbers_count(self, alias, data, region, marker, match, count, counter_data):
+        if match.group(0).startswith('const'):
+            return count
+        return count + 1

+ 10 - 0
mainline/tests/system/test_api_tutorial/sources/test.cpp

@@ -18,3 +18,13 @@ int main(int a = 1, int b = -2)
 		a = 4;
 		a = 4;
 	}
 	}
 }
 }
+
+int plain_func()
+{
+	const unsigned int c = 3;
+}
+
+int simple_func()
+{
+	const unsigned int c = c;
+}

+ 0 - 14
mainline/tests/system/test_api_tutorial/test_basic_view_step4_stdout.gold.txt

@@ -1,14 +0,0 @@
-:: info: Overall metrics for 'myext.magic:numbers' metric
-	Average        : 5.0
-	Minimum        : 3
-	Maximum        : 7
-	Total          : 10.0
-	Distribution   : 2 regions in total (including 0 suppressed)
-	  Metric value : Ratio : R-sum : Number of regions
-	             3 : 0.500 : 0.500 : 1	||||||||||||||||||||||||||||||||||||||||||||||||||
-	             7 : 0.500 : 1.000 : 1	||||||||||||||||||||||||||||||||||||||||||||||||||
-
-:: info: Directory content:
-	Directory      : .
-
-

mainline/tests/system/test_api_tutorial/test_basic_collect_step1_stderr.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step0_stderr.gold.txt


mainline/tests/system/test_api_tutorial/test_basic_collect_step4_stdout.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step0_stdout.gold.txt


mainline/tests/system/test_api_tutorial/test_basic_collect_step2_stderr.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step1_stderr.gold.txt


mainline/tests/system/test_api_tutorial/test_basic_collect_step1_stdout.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step1_stdout.gold.txt


mainline/tests/system/test_api_tutorial/test_basic_collect_step3_stderr.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step2_stderr.gold.txt


mainline/tests/system/test_api_tutorial/test_basic_collect_step2_stdout.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step2_stdout.gold.txt


mainline/tests/system/test_api_tutorial/test_basic_collect_step4_stderr.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step3_stderr.gold.txt


mainline/tests/system/test_api_tutorial/test_basic_collect_step3_stdout.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step3_stdout.gold.txt


mainline/tests/system/test_api_tutorial/test_basic_collect_step5_stderr.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step4_stderr.gold.txt


mainline/tests/system/test_api_tutorial/test_basic_collect_step5_stdout.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step4_stdout.gold.txt


+ 3 - 0
mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step5_stderr.gold.txt

@@ -0,0 +1,3 @@
+[LOG]: WARNING:	Logging enabled with INFO level
+[LOG]: INFO:	Processing: ./test.cpp
+[LOG]: WARNING:	Done (1 seconds). Exit code: 0

+ 0 - 0
mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step5_stdout.gold.txt


+ 3 - 0
mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step6_stderr.gold.txt

@@ -0,0 +1,3 @@
+[LOG]: WARNING:	Logging enabled with INFO level
+[LOG]: INFO:	Processing: ./test.cpp
+[LOG]: WARNING:	Done (1 seconds). Exit code: 0

+ 0 - 0
mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step6_stdout.gold.txt


+ 3 - 0
mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step7_stderr.gold.txt

@@ -0,0 +1,3 @@
+[LOG]: WARNING:	Logging enabled with INFO level
+[LOG]: INFO:	Processing: ./test.cpp
+[LOG]: WARNING:	Done (1 seconds). Exit code: 0

+ 0 - 0
mainline/tests/system/test_api_tutorial/test_metric_plugin_api_collect_step7_stdout.gold.txt


mainline/tests/system/test_api_tutorial/test_basic_view_step4_stderr.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step4_stderr.gold.txt


+ 16 - 0
mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step4_stdout.gold.txt

@@ -0,0 +1,16 @@
+:: info: Overall metrics for 'myext.magic:numbers' metric
+	Average        : 2.75
+	Minimum        : 0
+	Maximum        : 7
+	Total          : 11.0
+	Distribution   : 4 regions in total (including 0 suppressed)
+	  Metric value : Ratio : R-sum : Number of regions
+	             0 : 0.250 : 0.250 : 1	|||||||||||||||||||||||||
+	             1 : 0.250 : 0.500 : 1	|||||||||||||||||||||||||
+	             3 : 0.250 : 0.750 : 1	|||||||||||||||||||||||||
+	             7 : 0.250 : 1.000 : 1	|||||||||||||||||||||||||
+
+:: info: Directory content:
+	Directory      : .
+
+

mainline/tests/system/test_api_tutorial/test_basic_view_step5_stderr.gold.txt → mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step5_stderr.gold.txt


+ 15 - 0
mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step5_stdout.gold.txt

@@ -0,0 +1,15 @@
+:: info: Overall metrics for 'myext.magic:numbers' metric
+	Average        : 2.0
+	Minimum        : 0
+	Maximum        : 6
+	Total          : 8.0
+	Distribution   : 4 regions in total (including 0 suppressed)
+	  Metric value : Ratio : R-sum : Number of regions
+	             0 : 0.500 : 0.500 : 2	||||||||||||||||||||||||||||||||||||||||||||||||||
+	             2 : 0.250 : 0.750 : 1	|||||||||||||||||||||||||
+	             6 : 0.250 : 1.000 : 1	|||||||||||||||||||||||||
+
+:: info: Directory content:
+	Directory      : .
+
+

+ 3 - 0
mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step6_stderr.gold.txt

@@ -0,0 +1,3 @@
+[LOG]: WARNING:	Logging enabled with INFO level
+[LOG]: INFO:	Processing: 
+[LOG]: WARNING:	Done (1 seconds). Exit code: 0

+ 15 - 0
mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step6_stdout.gold.txt

@@ -0,0 +1,15 @@
+:: info: Overall metrics for 'myext.magic:numbers' metric
+	Average        : 2.0
+	Minimum        : 0
+	Maximum        : 6
+	Total          : 8.0
+	Distribution   : 4 regions in total (including 0 suppressed)
+	  Metric value : Ratio : R-sum : Number of regions
+	             0 : 0.500 : 0.500 : 2	||||||||||||||||||||||||||||||||||||||||||||||||||
+	             2 : 0.250 : 0.750 : 1	|||||||||||||||||||||||||
+	             6 : 0.250 : 1.000 : 1	|||||||||||||||||||||||||
+
+:: info: Directory content:
+	Directory      : .
+
+

+ 3 - 0
mainline/tests/system/test_api_tutorial/test_metric_plugin_api_view_step7_stderr.gold.txt

@@ -0,0 +1,3 @@
+[LOG]: WARNING:	Logging enabled with INFO level
+[LOG]: INFO:	Processing: 
+[LOG]: WARNING:	Done (1 seconds). Exit code: 0

+ 1 - 1
mainline/tests/system/test_api_tutorial/test_basic_view_step5_stdout.gold.txt

@@ -1,5 +1,5 @@
 :: info: Overall metrics for 'myext.magic:numbers' metric
 :: info: Overall metrics for 'myext.magic:numbers' metric
-	Average        : 4.0
+	Average        : 4.0 (excluding zero metric values)
 	Minimum        : 2
 	Minimum        : 2
 	Maximum        : 6
 	Maximum        : 6
 	Total          : 8.0
 	Total          : 8.0