diff-cover 10.4.2__tar.gz → 10.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. {diff_cover-10.4.2 → diff_cover-10.5.0}/PKG-INFO +1 -1
  2. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/violationsreporters/violations_reporter.py +47 -10
  3. {diff_cover-10.4.2 → diff_cover-10.5.0}/pyproject.toml +1 -1
  4. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_violations_reporter.py +64 -1
  5. {diff_cover-10.4.2 → diff_cover-10.5.0}/LICENSE +0 -0
  6. {diff_cover-10.4.2 → diff_cover-10.5.0}/NOTICE +0 -0
  7. {diff_cover-10.4.2 → diff_cover-10.5.0}/README.rst +0 -0
  8. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/__init__.py +0 -0
  9. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/command_runner.py +0 -0
  10. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/config_parser.py +0 -0
  11. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/diff_cover_tool.py +0 -0
  12. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/diff_quality_tool.py +0 -0
  13. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/diff_reporter.py +0 -0
  14. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/git_diff.py +0 -0
  15. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/git_path.py +0 -0
  16. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/hook.py +0 -0
  17. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/hookspecs.py +0 -0
  18. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/report_generator.py +0 -0
  19. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/snippets.py +0 -0
  20. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/console_coverage_report.txt +0 -0
  21. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/console_quality_report.txt +0 -0
  22. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/external_style.css +0 -0
  23. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/github_coverage_annotations.txt +0 -0
  24. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/html_coverage_report.html +0 -0
  25. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/html_quality_report.html +0 -0
  26. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/markdown_coverage_report.md +0 -0
  27. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/markdown_quality_report.md +0 -0
  28. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/snippet_content.html +0 -0
  29. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/snippet_content.md +0 -0
  30. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/snippet_content.txt +0 -0
  31. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/templates/snippet_style.html +0 -0
  32. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/util.py +0 -0
  33. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/violationsreporters/__init__.py +0 -0
  34. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/violationsreporters/base.py +0 -0
  35. {diff_cover-10.4.2 → diff_cover-10.5.0}/diff_cover/violationsreporters/java_violations_reporter.py +0 -0
  36. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/__init__.py +0 -0
  37. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/conftest.py +0 -0
  38. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/add_console_report.txt +0 -0
  39. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/add_html_report.html +0 -0
  40. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/add_json_report.json +0 -0
  41. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/add_json_report_float.json +0 -0
  42. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/add_markdown_report.md +0 -0
  43. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/changed_console_report.txt +0 -0
  44. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/changed_html_report.html +0 -0
  45. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/coverage.xml +0 -0
  46. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/coverage1.xml +0 -0
  47. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/coverage2.xml +0 -0
  48. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/coverage_missing_lines.xml +0 -0
  49. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/cpp_functions_console_report.txt +0 -0
  50. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/cpp_functions_coverage.lcov +0 -0
  51. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/delete_console_report.txt +0 -0
  52. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/delete_html_report.html +0 -0
  53. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/dotnet_coverage.xml +0 -0
  54. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/empty.txt +0 -0
  55. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/empty_pycodestyle_violations.txt +0 -0
  56. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/expand_console_report.txt +0 -0
  57. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/external_css_html_report.html +0 -0
  58. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/external_style.css +0 -0
  59. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_add.txt +0 -0
  60. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_changed.txt +0 -0
  61. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_code_dupe.txt +0 -0
  62. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_cpp.txt +0 -0
  63. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_cpp_functions.txt +0 -0
  64. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_delete.txt +0 -0
  65. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_dotnet.txt +0 -0
  66. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_external_css.txt +0 -0
  67. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_lua.txt +0 -0
  68. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_moved.txt +0 -0
  69. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_mult.txt +0 -0
  70. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_python.txt +0 -0
  71. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_subdir.txt +0 -0
  72. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_typescript.txt +0 -0
  73. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_typescript_branches.txt +0 -0
  74. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_unicode.txt +0 -0
  75. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_violations.txt +0 -0
  76. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/git_diff_violations_two_files.txt +0 -0
  77. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/hello.py +0 -0
  78. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/hi.py +0 -0
  79. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/html_report.html +0 -0
  80. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/html_report_empty.html +0 -0
  81. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/html_report_one_snippet.html +0 -0
  82. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/html_report_two_snippets.html +0 -0
  83. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/lcov.info +0 -0
  84. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/lua_console_report.txt +0 -0
  85. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/luacoverage.xml +0 -0
  86. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/markdown_report_one_snippet.md +0 -0
  87. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/markdown_report_two_snippets.md +0 -0
  88. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/moved_console_report.txt +0 -0
  89. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/moved_coverage.xml +0 -0
  90. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/moved_html_report.html +0 -0
  91. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/mult_inputs_console_report.txt +0 -0
  92. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/mult_inputs_html_report.html +0 -0
  93. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pycodestyle_report.txt +0 -0
  94. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pycodestyle_violations_report.html +0 -0
  95. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pycodestyle_violations_report.json +0 -0
  96. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pycodestyle_violations_report.md +0 -0
  97. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pycodestyle_violations_report.txt +0 -0
  98. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pycodestyle_violations_report_external_css.html +0 -0
  99. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pycodestyle_violations_report_float.json +0 -0
  100. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pyflakes_two_files.txt +0 -0
  101. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pyflakes_violations_report.html +0 -0
  102. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pyflakes_violations_report.txt +0 -0
  103. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pylint_dupe.txt +0 -0
  104. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pylint_dupe_violations_report.txt +0 -0
  105. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pylint_report.txt +0 -0
  106. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pylint_violations_console_report.txt +0 -0
  107. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pylint_violations_report.html +0 -0
  108. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pylint_violations_report.txt +0 -0
  109. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/pylintrc +0 -0
  110. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/real_cpp_console_report.txt +0 -0
  111. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/real_cpp_coverage.lcov +0 -0
  112. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/real_python_console_report.txt +0 -0
  113. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/real_python_coverage.lcov +0 -0
  114. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/real_typescript_console_report.txt +0 -0
  115. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/real_typescript_coverage.lcov +0 -0
  116. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/show_uncovered_lines_console.txt +0 -0
  117. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet.css +0 -0
  118. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_8859.py +0 -0
  119. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_arabic_output.html +0 -0
  120. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_default.html +0 -0
  121. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_invalid_violations.html +0 -0
  122. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_list.html +0 -0
  123. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_list.md +0 -0
  124. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_list2.md +0 -0
  125. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_list3.md +0 -0
  126. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_no_filename_ext.html +0 -0
  127. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_src.py +0 -0
  128. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_src2.cpp +0 -0
  129. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_src3.cpp +0 -0
  130. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_unicode.html +0 -0
  131. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_unicode.py +0 -0
  132. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/snippet_unicode_html_output.html +0 -0
  133. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/subdir_coverage_console_report.txt +0 -0
  134. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/subdir_coverage_html_report.html +0 -0
  135. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/test_src.txt +0 -0
  136. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/typescript_branches_console_report.txt +0 -0
  137. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/typescript_branches_coverage.lcov +0 -0
  138. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/unicode_console_report.txt +0 -0
  139. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/unicode_coverage.xml +0 -0
  140. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/unicode_html_report.html +0 -0
  141. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/unicode_test_src.txt +0 -0
  142. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/fixtures/violations_test_file.py +0 -0
  143. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/helpers.py +0 -0
  144. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/snippet_list_unicode.html +0 -0
  145. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_clover_violations_reporter/test.xml +0 -0
  146. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_clover_violations_reporter.py +0 -0
  147. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_config_parser.py +0 -0
  148. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_diff_cover_main.py +0 -0
  149. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_diff_cover_tool.py +0 -0
  150. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_diff_quality_main.py +0 -0
  151. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_diff_reporter.py +0 -0
  152. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_git_diff.py +0 -0
  153. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_git_diff_file.py +0 -0
  154. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_git_path.py +0 -0
  155. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_integration.py +0 -0
  156. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_java_violations_reporter.py +0 -0
  157. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_report_generator.py +0 -0
  158. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_snippets.py +0 -0
  159. {diff_cover-10.4.2 → diff_cover-10.5.0}/tests/test_util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: diff_cover
3
- Version: 10.4.2
3
+ Version: 10.5.0
4
4
  Summary: Run coverage and linting reports on diffs
5
5
  License: Apache-2.0
6
6
  Author: See Contributors
@@ -46,6 +46,11 @@ class XmlCoverageReporter(BaseViolationReporter):
46
46
  # Values are output of `self._get_xml_classes()`
47
47
  self._xml_cache = [{} for i in range(len(xml_roots))]
48
48
 
49
+ # Which format each report is in. Classifying costs a search through the
50
+ # document, and the answer cannot change, so do it once here rather than
51
+ # once per source file in `_cache_file`.
52
+ self._report_formats = [self._detect_report_format(root) for root in xml_roots]
53
+
49
54
  self._src_roots = src_roots or [""]
50
55
  self._expand_coverage_report = expand_coverage_report
51
56
  self._branch_coverage = branch_coverage
@@ -129,19 +134,53 @@ class XmlCoverageReporter(BaseViolationReporter):
129
134
  If file is not present in `xml_document`, return None
130
135
  """
131
136
 
132
- files = [
133
- file_tree
134
- for file_tree in xml_document.findall(".//file")
135
- if GitPathTool.relative_path(file_tree.get("path")) == src_path
136
- ]
137
+ files = []
138
+ normalized_src_path = util.to_unix_path(src_path)
139
+ for file_tree in xml_document.findall(".//file"):
140
+ file_path = file_tree.get("path") or file_tree.get("name")
141
+ if not file_path:
142
+ continue
143
+
144
+ normalized_file_path = util.to_unix_path(file_path)
145
+ relative_file_path = util.to_unix_path(GitPathTool.relative_path(file_path))
146
+ if (
147
+ relative_file_path == normalized_src_path
148
+ or normalized_file_path.endswith(f"/{normalized_src_path}")
149
+ ):
150
+ files.append(file_tree)
137
151
  if not files:
138
152
  return None
139
153
  lines = []
140
154
  for file_tree in files:
155
+ # Clover marks an executable line as one of these three types. PHPUnit's
156
+ # writer emits `method` for the declaration line of every function it
157
+ # measured; leaving it out reported those lines as unmeasured.
158
+ # https://github.com/sebastianbergmann/php-code-coverage/blob/main/src/Report/Clover.php
159
+ lines.append(file_tree.findall('./line[@type="method"]'))
141
160
  lines.append(file_tree.findall('./line[@type="stmt"]'))
142
161
  lines.append(file_tree.findall('./line[@type="cond"]'))
143
162
  return list(itertools.chain(*lines))
144
163
 
164
+ @staticmethod
165
+ def _detect_report_format(xml_document):
166
+ """
167
+ Return which of the supported formats `xml_document` is in.
168
+
169
+ Clover writes a `clover` attribute on the root, but PHPUnit's Clover
170
+ writer does not, so fall back to the shape of its line elements.
171
+ """
172
+ if (
173
+ xml_document.findall(".[@clover]")
174
+ or xml_document.find(".//file/line[@num][@count]") is not None
175
+ ):
176
+ # see etc/schema/clover.xsd at https://bitbucket.org/atlassian/clover/src
177
+ return "clover"
178
+ if xml_document.findall(".[@name]"):
179
+ # https://github.com/jacoco/jacoco/blob/master/org.jacoco.report/src/org/jacoco/report/xml/report.dtd
180
+ return "jacoco"
181
+ # https://github.com/cobertura/web/blob/master/htdocs/xml/coverage-04.dtd
182
+ return "cobertura"
183
+
145
184
  def _measured_source_path_matches(self, package_name, file_name, src_path):
146
185
  # find src_path in any of the source roots
147
186
  if not src_path.endswith(util.to_unix_path(file_name)):
@@ -204,22 +243,20 @@ class XmlCoverageReporter(BaseViolationReporter):
204
243
 
205
244
  # Loop through the files that contain the xml roots
206
245
  for i, xml_document in enumerate(self._xml_roots):
207
- if xml_document.findall(".[@clover]"):
208
- # see etc/schema/clover.xsd at https://bitbucket.org/atlassian/clover/src
246
+ report_format = self._report_formats[i]
247
+ if report_format == "clover":
209
248
  line_nodes = self.get_src_path_line_nodes_clover(
210
249
  xml_document, src_path
211
250
  )
212
251
  _number = "num"
213
252
  _hits = "count"
214
- elif xml_document.findall(".[@name]"):
215
- # https://github.com/jacoco/jacoco/blob/master/org.jacoco.report/src/org/jacoco/report/xml/report.dtd
253
+ elif report_format == "jacoco":
216
254
  line_nodes = self.get_src_path_line_nodes_jacoco(
217
255
  xml_document, src_path
218
256
  )
219
257
  _number = "nr"
220
258
  _hits = "ci"
221
259
  else:
222
- # https://github.com/cobertura/web/blob/master/htdocs/xml/coverage-04.dtd
223
260
  line_nodes = self.get_src_path_line_nodes_cobertura(
224
261
  i, xml_document, src_path
225
262
  )
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "diff_cover"
3
- version = "10.4.2"
3
+ version = "10.5.0"
4
4
  description = "Run coverage and linting reports on diffs"
5
5
  authors = ["See Contributors"]
6
6
  homepage = "https://github.com/Bachmann1234/diff-cover"
@@ -497,6 +497,60 @@ class TestCloverXmlCoverageReporterTest:
497
497
  result = coverage.violations("file1.java")
498
498
  assert result == violations
499
499
 
500
+ def test_phpunit_clover_without_clover_attribute(self):
501
+ xml = self._coverage_xml(
502
+ ["/workspace/project/subdir/file.java"],
503
+ self.FEW_VIOLATIONS,
504
+ self.FEW_MEASURED,
505
+ )
506
+ del xml.attrib["clover"]
507
+ file_node = xml.find(".//file")
508
+ file_node.set("name", file_node.attrib.pop("path"))
509
+
510
+ coverage = XmlCoverageReporter([xml])
511
+
512
+ assert coverage.violations("subdir/file.java") == self.FEW_VIOLATIONS
513
+ assert coverage.measured_lines("subdir/file.java") == self.FEW_MEASURED
514
+
515
+ def test_method_lines_are_measured(self):
516
+ # PHPUnit's Clover writer emits type="method" for the declaration line of
517
+ # every measured function. Those lines carry a count like any other and
518
+ # must not be reported as unmeasured.
519
+ xml = self._coverage_xml(
520
+ ["file1.java"], self.FEW_VIOLATIONS, self.FEW_MEASURED, method_lines={42}
521
+ )
522
+
523
+ coverage = XmlCoverageReporter([xml])
524
+
525
+ assert 42 in coverage.measured_lines("file1.java")
526
+ assert coverage.violations("file1.java") == self.FEW_VIOLATIONS
527
+
528
+ def test_method_line_can_be_a_violation(self):
529
+ xml = self._coverage_xml(
530
+ ["file1.java"], self.FEW_VIOLATIONS, self.FEW_MEASURED, method_lines={42}
531
+ )
532
+ method_line = xml.find('.//line[@type="method"]')
533
+ method_line.set("count", "0")
534
+
535
+ coverage = XmlCoverageReporter([xml])
536
+
537
+ assert 42 in coverage.measured_lines("file1.java")
538
+ assert Violation(42, None) in coverage.violations("file1.java")
539
+
540
+ def test_report_format_is_detected_once(self):
541
+ # Classifying the report is a search through the whole document; doing it
542
+ # per source file was the review comment on #617.
543
+ xml = self._coverage_xml(
544
+ ["file1.java", "file2.java"], self.FEW_VIOLATIONS, self.FEW_MEASURED
545
+ )
546
+
547
+ coverage = XmlCoverageReporter([xml])
548
+
549
+ assert coverage._report_formats == ["clover"]
550
+ coverage.violations("file1.java")
551
+ coverage.violations("file2.java")
552
+ assert coverage._report_formats == ["clover"]
553
+
500
554
  def test_two_inputs_first_violate(self):
501
555
  # Construct the XML report
502
556
  file_paths = ["file1.java"]
@@ -620,7 +674,7 @@ class TestCloverXmlCoverageReporterTest:
620
674
  result = coverage.violations("file.java")
621
675
  assert result == set()
622
676
 
623
- def _coverage_xml(self, file_paths, violations, measured):
677
+ def _coverage_xml(self, file_paths, violations, measured, method_lines=None):
624
678
  """
625
679
  Build an XML tree with source files specified by `file_paths`.
626
680
  Each source fill will have the same set of covered and
@@ -630,6 +684,9 @@ class TestCloverXmlCoverageReporterTest:
630
684
  `line_dict` is a dictionary with keys that are line numbers
631
685
  and values that are True/False indicating whether the line
632
686
  is covered
687
+ `method_lines` is an optional set of line numbers to emit as
688
+ `type="method"` instead of `type="stmt"`, the way PHPUnit's Clover
689
+ writer marks the declaration line of a measured function
633
690
 
634
691
  This leaves out some attributes of the Cobertura format,
635
692
  but includes all the elements.
@@ -654,6 +711,12 @@ class TestCloverXmlCoverageReporterTest:
654
711
  line.set("count", str(hits))
655
712
  line.set("num", str(line_num))
656
713
  line.set("type", "stmt")
714
+
715
+ for line_num in method_lines or ():
716
+ line = etree.SubElement(src_node, "line")
717
+ line.set("count", "1")
718
+ line.set("num", str(line_num))
719
+ line.set("type", "method")
657
720
  return root
658
721
 
659
722
 
File without changes
File without changes
File without changes