cairo_annotations/annotations/
coverage.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use crate::annotations::impl_helpers::impl_namespace;
use cairo_lang_sierra::program::StatementIdx;
use derive_more::{Add, AddAssign, Display, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::HashMap;

/// Versioned representation of Coverage Annotations.
///
/// Always prefer using this enum when Serializing/Deserializing instead of inner ones.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum VersionedCoverageAnnotations {
    V1(CoverageAnnotationsV1),
}

/// The mapping from sierra statement index
/// to stack of a locations in Cairo code
/// which caused the statement to be generated.
/// And all functions that were inlined
/// or generated along the way up to the first non-inlined function from the original code.
///
/// The vector represents the stack from the least meaningful elements.
///
/// Introduced in Scarb 2.8.0.
///
/// Needs `unstable-add-statements-code-locations-debug-info = true`
/// under `[profile.dev.cairo]` in the Scarb config to be generated.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct CoverageAnnotationsV1 {
    pub statements_code_locations: HashMap<StatementIdx, Vec<CodeLocation>>,
}

/// A location of Sierra statement.
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct CodeLocation(pub SourceFileFullPath, pub SourceCodeSpan);

/// A full path to a Cairo source file.
///
/// May contain multiple Cairo virtual file markings if the code is generated by macros.
/// Like `/path/to/project/lib.cairo[array_inline_macro][assert_macro]`
/// where `array_inline_macro` and `assert_macro` is a virtual file marking.
#[derive(
    Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize, Display, Default,
)]
pub struct SourceFileFullPath(pub String);

/// A span in a Cairo source file.
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct SourceCodeSpan {
    /// Beginning of the text span in the Cairo source file.
    pub start: SourceCodeLocation,
    /// End of the text span in the Cairo source file. Currently, always the same as `start`.
    pub end: SourceCodeLocation,
}

/// A location in a Cairo source file.
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct SourceCodeLocation {
    /// Line index, 0 based.
    /// Most editors show line numbers starting from 1, so when displaying to users, add 1 to this value.
    pub line: LineNumber,
    /// Character index inside the line, 0 based.
    /// Most editors show column numbers starting from 1, so when displaying to users, add 1 to this value.
    pub col: ColumnNumber,
}

#[derive(
    Clone,
    Copy,
    Debug,
    Eq,
    PartialEq,
    Hash,
    Ord,
    PartialOrd,
    Serialize,
    Deserialize,
    Add,
    AddAssign,
    Sub,
    SubAssign,
    Mul,
    MulAssign,
    Div,
    DivAssign,
    Display,
    Default,
)]
pub struct ColumnNumber(pub usize);

#[derive(
    Clone,
    Copy,
    Debug,
    Eq,
    PartialEq,
    Hash,
    Ord,
    PartialOrd,
    Serialize,
    Deserialize,
    Add,
    AddAssign,
    Sub,
    SubAssign,
    Mul,
    MulAssign,
    Div,
    DivAssign,
    Display,
    Default,
)]
pub struct LineNumber(pub usize);

// We can't use untagged enum here. See https://github.com/serde-rs/json/issues/1103
impl Serialize for VersionedCoverageAnnotations {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            VersionedCoverageAnnotations::V1(v1) => v1.serialize(serializer),
        }
    }
}

impl<'de> Deserialize<'de> for VersionedCoverageAnnotations {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        CoverageAnnotationsV1::deserialize(deserializer).map(VersionedCoverageAnnotations::V1)
    }
}

impl_namespace!(
    "github.com/software-mansion/cairo-coverage",
    CoverageAnnotationsV1,
    VersionedCoverageAnnotations
);