@@ -114,16 +114,15 @@ def coverage_init(reg, options):
114
114
115
115
from __future__ import annotations
116
116
117
+ import dataclasses
117
118
import functools
118
119
119
120
from types import FrameType
120
121
from typing import Any , Iterable
121
122
122
123
from coverage import files
123
124
from coverage .misc import _needs_to_implement
124
- from coverage .types import (
125
- CodeRegion , TArc , TConfigurable , TLineNo , TSourceTokenLines ,
126
- )
125
+ from coverage .types import TArc , TConfigurable , TLineNo , TSourceTokenLines
127
126
128
127
129
128
class CoveragePlugin :
@@ -346,6 +345,35 @@ def line_number_range(self, frame: FrameType) -> tuple[TLineNo, TLineNo]:
346
345
return lineno , lineno
347
346
348
347
348
+ @dataclasses .dataclass
349
+ class CodeRegion :
350
+ """Data for a region of code found by :meth:`FileReporter.code_regions`."""
351
+
352
+ #: The kind of region, like `"function"` or `"class"`. Must be one of the
353
+ #: singular values returned by :meth:`FileReporter.code_region_kinds`.
354
+ kind : str
355
+
356
+ #: The name of the region. For example, a function or class name.
357
+ name : str
358
+
359
+ #: The line in the source file to link to when navigating to the region.
360
+ #: Can be a line not mentioned in `lines`.
361
+ start : int
362
+
363
+ #: The lines in the region. Should be lines that could be executed in the
364
+ #: region. For example, a class region includes all of the lines in the
365
+ #: methods of the class, but not the lines defining class attributes, since
366
+ #: they are executed on import, not as part of exercising the class. The
367
+ #: set can include non-executable lines like blanks and comments.
368
+ lines : set [int ]
369
+
370
+ def __lt__ (self , other : CodeRegion ) -> bool :
371
+ """To support sorting to make test-writing easier."""
372
+ if self .name == other .name :
373
+ return min (self .lines ) < min (other .lines )
374
+ return self .name < other .name
375
+
376
+
349
377
@functools .total_ordering
350
378
class FileReporter (CoveragePluginBase ):
351
379
"""Support needed for files during the analysis and reporting phases.
@@ -546,11 +574,28 @@ def source_token_lines(self) -> TSourceTokenLines:
546
574
yield [("txt" , line )]
547
575
548
576
def code_regions (self ) -> Iterable [CodeRegion ]:
549
- """TODO XXX"""
577
+ """Identify regions in the source file for finer reporting than by file.
578
+
579
+ Returns an iterable of :class:`CodeRegion` objects. The kinds reported
580
+ should be in the possibilities returned by :meth:`code_region_kinds`.
581
+
582
+ """
550
583
return []
551
584
552
585
def code_region_kinds (self ) -> Iterable [tuple [str , str ]]:
553
- """TODO XXX"""
586
+ """Return the kinds of code regions this plugin can find.
587
+
588
+ The returned pairs are the singular and plural forms of the kinds::
589
+
590
+ [
591
+ ("function", "functions"),
592
+ ("class", "classes"),
593
+ ]
594
+
595
+ This will usually be hard-coded, but could also differ by the specific
596
+ source file involved.
597
+
598
+ """
554
599
return []
555
600
556
601
def __eq__ (self , other : Any ) -> bool :
0 commit comments