suppress.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #
  2. # Metrix++, Copyright 2009-2019, Metrix++ Project
  3. # Link: https://github.com/metrixplusplus/metrixplusplus
  4. #
  5. # This file is a part of Metrix++ Tool.
  6. #
  7. import mpp.api
  8. import mpp.cout
  9. import re
  10. class Plugin(mpp.api.Plugin, mpp.api.Child, mpp.api.IConfigurable):
  11. def declare_configuration(self, parser):
  12. parser.add_option("--std.suppress", "--ss", action="store_true", default=False,
  13. help="If set (True), suppression markers are collected from comments in code. "
  14. "Suppressions are used by post-processing tools, like limit, to remove false-positive warnings. "
  15. "Suppressions should be in the first comment block of a region (function/class/interface). "
  16. "Format of suppressions: 'metrix++: suppress metric-name'. "
  17. "For example: 'metrix++: suppress std.code.complexity:cyclomatic'. "
  18. " [default: %default]")
  19. def configure(self, options):
  20. self.is_active = options.__dict__['std.suppress']
  21. def initialize(self):
  22. fields = []
  23. if self.is_active == True:
  24. fields.append(self.Field('count', int, non_zero=True))
  25. fields.append(self.Field('list', str))
  26. # - init per regions table
  27. mpp.api.Plugin.initialize(self, fields=fields)
  28. # - init per file table
  29. mpp.api.Plugin.initialize(self,
  30. namespace = self.get_name() + '.file',
  31. support_regions = False,
  32. fields=fields)
  33. if len(fields) != 0:
  34. self.subscribe_by_parents_interface(mpp.api.ICode)
  35. # suppress pattern
  36. pattern = re.compile(r'''metrix[+][+][:][ \t]+suppress[ \t]+([^ \t\r\n\*]+)''')
  37. def callback(self, parent, data, is_updated):
  38. is_updated = is_updated or self.is_updated
  39. if is_updated == True:
  40. text = data.get_content()
  41. file_count = 0
  42. file_list_text = []
  43. for region in data.iterate_regions():
  44. count = 0
  45. list_text = []
  46. last_comment_end = None
  47. for marker in data.iterate_markers(
  48. filter_group = mpp.api.Marker.T.COMMENT,
  49. region_id = region.get_id(),
  50. exclude_children = True):
  51. if last_comment_end != None and len(text[last_comment_end:marker.get_offset_begin()].strip()) > 0:
  52. # check continues comment blocks
  53. # stop searching, if this comment block is separated from the last by non-blank string
  54. break
  55. last_comment_end = marker.get_offset_end()
  56. matches = self.pattern.findall(text, marker.get_offset_begin(), marker.get_offset_end())
  57. for m in matches:
  58. namespace_name, field = m.split(':')
  59. db_loader = self.get_plugin('mpp.dbf').get_loader()
  60. namespace = db_loader.get_namespace(namespace_name)
  61. if namespace == None or namespace.check_field(field) == False:
  62. mpp.cout.notify(data.get_path(), region.get_cursor(),
  63. mpp.cout.SEVERITY_WARNING,
  64. "Suppressed metric '" + namespace_name + ":" + field +
  65. "' is not being collected",
  66. [("Metric name", namespace_name + ":" + field),
  67. ("Region name", region.get_name())])
  68. continue
  69. if namespace.are_regions_supported() == False:
  70. if region.get_id() != 1:
  71. mpp.cout.notify(data.get_path(), region.get_cursor(),
  72. mpp.cout.SEVERITY_WARNING,
  73. "Suppressed metric '" + namespace_name + ":" + field +
  74. "' is attributed to a file, not a region. "
  75. "Remove it or move to the beginning of the file.",
  76. [("Metric name", namespace_name + ":" + field),
  77. ("Region name", region.get_name())])
  78. continue
  79. if m in file_list_text:
  80. mpp.cout.notify(data.get_path(), region.get_cursor(),
  81. mpp.cout.SEVERITY_WARNING,
  82. "Duplicate suppression of the metric '" +
  83. namespace_name + ":" + field + "'",
  84. [("Metric name", namespace_name + ":" + field),
  85. ("Region name", None)])
  86. continue
  87. file_count += 1
  88. file_list_text.append(m)
  89. continue
  90. if m in list_text:
  91. mpp.cout.notify(data.get_path(), region.get_cursor(),
  92. mpp.cout.SEVERITY_WARNING,
  93. "Duplicate suppression of the metric '" +
  94. namespace_name + ":" + field + "'",
  95. [("Metric name", namespace_name + ":" + field),
  96. ("Region name", region.get_name())])
  97. continue
  98. count += 1
  99. list_text.append(m)
  100. continue
  101. if count > 0:
  102. region.set_data(self.get_name(), 'count', count)
  103. region.set_data(self.get_name(), 'list', '[' + ']['.join(list_text) + ']')
  104. if file_count > 0:
  105. data.set_data(self.get_name() + '.file', 'count', file_count)
  106. data.set_data(self.get_name() + '.file', 'list', '[' + ']['.join(file_list_text) + ']')