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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//! Typed failures returned while snapshotting a Go module project.
use std::fmt;
use pedant_syntax::go::GoFactError;
/// Why one admitted source states no complete inventory.
///
/// Capability detection keeps findings from a recovered tree beside an
/// unavailable attribution status. A resolution snapshot cannot: a declaration
/// the parser dropped becomes a missing definition in a report and a missing
/// node in a graph, with nothing to say it was ever there.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum GoSourceDefect {
/// The grammar produced no tree for the source at all.
Unparsed,
/// The grammar produced a tree by recovering from a syntax error.
Recovered,
}
impl fmt::Display for GoSourceDefect {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Unparsed => formatter.write_str("the grammar produced no tree"),
Self::Recovered => formatter.write_str("the parser recovered from a syntax error"),
}
}
}
/// Failure encountered while walking a Go project's packages and sources.
#[derive(Debug, thiserror::Error)]
pub enum GoSnapshotError {
/// A path the walk reached is not inside the repository root.
#[error("path {path} lies outside the project root {root}")]
OutOfRoot {
/// The canonical path that escaped.
path: Box<str>,
/// The root that does not contain it.
root: Box<str>,
},
/// A path beneath the repository root is not valid UTF-8.
#[error("path {path} beneath the project root is not valid UTF-8")]
NonUtf8Path {
/// The offending path, rendered lossily for the message only.
path: Box<str>,
},
/// A path beneath the repository root could not be resolved.
///
/// Absence is not this: a directory holding no source and a replacement
/// target holding no manifest are both reported by the stage that asked.
/// This is a path the filesystem refused to answer for — a denied
/// permission, a symlink loop, an over-long name — which must not read as
/// a file the repository never held.
#[error("failed to resolve {path}: {source}")]
PathRead {
/// The path that could not be resolved.
path: Box<str>,
/// The underlying I/O failure.
#[source]
source: std::io::Error,
},
/// A package directory could not be listed.
#[error("failed to list {path}: {source}")]
DirectoryRead {
/// The unreadable directory, repository-relative.
path: Box<str>,
/// The underlying I/O failure.
#[source]
source: std::io::Error,
},
/// A source could not be read.
#[error("failed to read {path}: {source}")]
SourceRead {
/// The unreadable source, repository-relative.
path: Box<str>,
/// The underlying I/O failure.
#[source]
source: std::io::Error,
},
/// A source's bytes are not valid UTF-8, so they state no Go text.
#[error("source {path} is not valid UTF-8")]
NonUtf8Source {
/// The rejected source, repository-relative.
path: Box<str>,
},
/// A source states no complete tree.
#[error("source {path} cannot be snapshotted: {defect}")]
IncompleteSource {
/// The rejected source, repository-relative.
path: Box<str>,
/// Why the tree is not complete.
defect: GoSourceDefect,
},
/// A source states no package clause, so it belongs to no package.
#[error("source {path} states no package clause")]
MissingPackageClause {
/// The rejected source, repository-relative.
path: Box<str>,
},
/// A path the store interned names no source the store holds.
///
/// Defensive, and deliberately not a missing package clause: the store
/// refuses any source without one before it retains it, so a path it just
/// returned that answers with no clause is the store disagreeing with
/// itself rather than a repository stating a source that declares nothing.
#[error("source {path} was interned but is not held by the store")]
MissingStoredSource {
/// The interned path that names no stored source.
path: Box<str>,
},
/// One directory's sources state package clauses Go cannot compile
/// together.
#[error("directory {directory} declares both {first} and {second}")]
ConflictingPackageClause {
/// The directory holding both clauses, repository-relative.
directory: Box<str>,
/// The clause the directory's package was taken from.
first: Box<str>,
/// The clause that cannot join it.
second: Box<str>,
},
/// A source's fact inventory was refused.
#[error("failed to extract Go facts from {path}: {source}")]
FactExtraction {
/// The refused source, repository-relative.
path: Box<str>,
/// The ceiling or grammar mismatch that refused it.
#[source]
source: GoFactError,
},
/// The package walk reached more directory entries than the limit allows.
#[error("snapshot visits more than {limit} directory entries")]
DirectoryEntryLimitExceeded {
/// The configured directory-entry ceiling.
limit: u32,
},
/// The snapshot holds more package units than the limit allows.
#[error("snapshot holds more than {limit} resolution units")]
UnitLimitExceeded {
/// The configured unit ceiling.
limit: u32,
},
/// The snapshot holds more distinct sources than the limit allows.
#[error("snapshot holds more than {limit} source files")]
SourceFileLimitExceeded {
/// The configured source-file ceiling.
limit: u32,
},
/// One source is larger than the per-file limit allows.
#[error("source {path} holds more than {limit} bytes")]
SourceBytesLimitExceeded {
/// The oversized source, repository-relative.
path: Box<str>,
/// The configured per-file byte ceiling.
limit: u64,
},
/// The snapshot's sources hold more bytes together than the limit allows.
#[error("snapshot holds more than {limit} source bytes")]
TotalSourceBytesLimitExceeded {
/// The configured total byte ceiling.
limit: u64,
},
}