Skip to content

Commit f15825b

Browse files
authored
Add original token to string literal (#3042)
1 parent 6fa7358 commit f15825b

File tree

14 files changed

+182
-247
lines changed

14 files changed

+182
-247
lines changed

src/analyzer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ impl<'run, 'src> Analyzer<'run, 'src> {
1616
asts: &'run HashMap<PathBuf, Ast<'src>>,
1717
config: &Config,
1818
doc: Option<String>,
19-
groups: &[StringLiteral],
19+
groups: &[StringLiteral<'src>],
2020
loaded: &[PathBuf],
2121
name: Option<Name<'src>>,
2222
paths: &HashMap<PathBuf, PathBuf>,
@@ -30,7 +30,7 @@ impl<'run, 'src> Analyzer<'run, 'src> {
3030
asts: &'run HashMap<PathBuf, Ast<'src>>,
3131
config: &Config,
3232
doc: Option<String>,
33-
groups: &[StringLiteral],
33+
groups: &[StringLiteral<'src>],
3434
loaded: &[PathBuf],
3535
name: Option<Name<'src>>,
3636
paths: &HashMap<PathBuf, PathBuf>,

src/arg_attribute.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub(crate) struct ArgAttribute<'src> {
44
pub(crate) help: Option<String>,
55
pub(crate) long: Option<String>,
66
pub(crate) name: Token<'src>,
7-
pub(crate) pattern: Option<Pattern>,
7+
pub(crate) pattern: Option<Pattern<'src>>,
88
pub(crate) short: Option<char>,
99
pub(crate) value: Option<String>,
1010
}

src/attribute.rs

Lines changed: 76 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,33 @@ use super::*;
1111
#[strum_discriminants(strum(serialize_all = "kebab-case"))]
1212
pub(crate) enum Attribute<'src> {
1313
Arg {
14-
help: Option<StringLiteral>,
15-
long: Option<StringLiteral>,
16-
#[serde(skip)]
17-
long_token: Option<Token<'src>>,
18-
name: StringLiteral,
19-
#[serde(skip)]
20-
name_token: Token<'src>,
21-
#[serde(skip)]
22-
pattern: Option<Pattern>,
23-
#[serde(rename = "pattern")]
24-
pattern_literal: Option<StringLiteral>,
25-
short: Option<StringLiteral>,
26-
#[serde(skip)]
27-
short_token: Option<Token<'src>>,
28-
value: Option<StringLiteral>,
14+
help: Option<StringLiteral<'src>>,
15+
long: Option<StringLiteral<'src>>,
16+
name: StringLiteral<'src>,
17+
pattern: Option<Pattern<'src>>,
18+
short: Option<StringLiteral<'src>>,
19+
value: Option<StringLiteral<'src>>,
2920
},
30-
Confirm(Option<StringLiteral>),
21+
Confirm(Option<StringLiteral<'src>>),
3122
Default,
32-
Doc(Option<StringLiteral>),
23+
Doc(Option<StringLiteral<'src>>),
3324
ExitMessage,
34-
Extension(StringLiteral),
35-
Group(StringLiteral),
25+
Extension(StringLiteral<'src>),
26+
Group(StringLiteral<'src>),
3627
Linux,
3728
Macos,
38-
Metadata(Vec<StringLiteral>),
29+
Metadata(Vec<StringLiteral<'src>>),
3930
NoCd,
4031
NoExitMessage,
4132
NoQuiet,
4233
Openbsd,
4334
Parallel,
4435
PositionalArguments,
4536
Private,
46-
Script(Option<Interpreter<StringLiteral>>),
37+
Script(Option<Interpreter<StringLiteral<'src>>>),
4738
Unix,
4839
Windows,
49-
WorkingDirectory(StringLiteral),
40+
WorkingDirectory(StringLiteral<'src>),
5041
}
5142

5243
impl AttributeDiscriminant {
@@ -74,16 +65,38 @@ impl AttributeDiscriminant {
7465
}
7566

7667
impl<'src> Attribute<'src> {
68+
fn check_option_name(
69+
parameter: &StringLiteral<'src>,
70+
literal: &StringLiteral<'src>,
71+
) -> CompileResult<'src> {
72+
if literal.cooked.contains('=') {
73+
return Err(
74+
literal
75+
.token
76+
.error(CompileErrorKind::OptionNameContainsEqualSign {
77+
parameter: parameter.cooked.clone(),
78+
}),
79+
);
80+
}
81+
82+
if literal.cooked.is_empty() {
83+
return Err(literal.token.error(CompileErrorKind::OptionNameEmpty {
84+
parameter: parameter.cooked.clone(),
85+
}));
86+
}
87+
88+
Ok(())
89+
}
90+
7791
pub(crate) fn new(
7892
name: Name<'src>,
79-
arguments: Vec<(Token<'src>, StringLiteral)>,
80-
mut keyword_arguments: BTreeMap<&'src str, (Name<'src>, Token<'src>, StringLiteral)>,
93+
arguments: Vec<StringLiteral<'src>>,
94+
mut keyword_arguments: BTreeMap<&'src str, (Name<'src>, StringLiteral<'src>)>,
8195
) -> CompileResult<'src, Self> {
8296
let discriminant = name
8397
.lexeme()
8498
.parse::<AttributeDiscriminant>()
85-
.ok()
86-
.ok_or_else(|| {
99+
.map_err(|_| {
87100
name.error(CompileErrorKind::UnknownAttribute {
88101
attribute: name.lexeme(),
89102
})
@@ -94,99 +107,68 @@ impl<'src> Attribute<'src> {
94107
if !range.contains(&found) {
95108
return Err(
96109
name.error(CompileErrorKind::AttributeArgumentCountMismatch {
97-
attribute: name.lexeme(),
110+
attribute: name,
98111
found,
99112
min: *range.start(),
100113
max: *range.end(),
101114
}),
102115
);
103116
}
104117

105-
let (tokens, arguments): (Vec<Token>, Vec<StringLiteral>) = arguments.into_iter().unzip();
106-
107118
let attribute = match discriminant {
108119
AttributeDiscriminant::Arg => {
109120
let name = arguments.into_iter().next().unwrap();
110-
let name_token = tokens.into_iter().next().unwrap();
111-
112-
let (long_token, long) =
113-
if let Some((_name, token, literal)) = keyword_arguments.remove("long") {
114-
if literal.cooked.contains('=') {
115-
return Err(token.error(CompileErrorKind::OptionNameContainsEqualSign {
116-
parameter: name.cooked,
117-
}));
118-
}
119-
120-
if literal.cooked.is_empty() {
121-
return Err(token.error(CompileErrorKind::OptionNameEmpty {
122-
parameter: name.cooked,
123-
}));
124-
}
125121

126-
(Some(token), Some(literal))
127-
} else {
128-
(None, None)
129-
};
130-
131-
let (short_token, short) =
132-
if let Some((_name, token, literal)) = keyword_arguments.remove("short") {
133-
if literal.cooked.contains('=') {
134-
return Err(token.error(CompileErrorKind::OptionNameContainsEqualSign {
135-
parameter: name.cooked,
136-
}));
137-
}
122+
let long = keyword_arguments
123+
.remove("long")
124+
.map(|(_name, literal)| {
125+
Self::check_option_name(&name, &literal)?;
126+
Ok(literal)
127+
})
128+
.transpose()?;
138129

139-
if literal.cooked.is_empty() {
140-
return Err(token.error(CompileErrorKind::OptionNameEmpty {
141-
parameter: name.cooked,
142-
}));
143-
}
130+
let short = keyword_arguments
131+
.remove("short")
132+
.map(|(_name, literal)| {
133+
Self::check_option_name(&name, &literal)?;
144134

145135
if literal.cooked.chars().count() != 1 {
146-
return Err(
147-
token.error(CompileErrorKind::ShortOptionWithMultipleCharacters {
148-
parameter: name.cooked,
149-
}),
150-
);
136+
return Err(literal.token.error(
137+
CompileErrorKind::ShortOptionWithMultipleCharacters {
138+
parameter: name.cooked.clone(),
139+
},
140+
));
151141
}
152142

153-
(Some(token), Some(literal))
154-
} else {
155-
(None, None)
156-
};
143+
Ok(literal)
144+
})
145+
.transpose()?;
157146

158-
let (pattern_literal, pattern) = keyword_arguments
147+
let pattern = keyword_arguments
159148
.remove("pattern")
160-
.map(|(_name, token, literal)| {
161-
let pattern = Pattern::new(token, &literal)?;
162-
Ok((Some(literal), Some(pattern)))
149+
.map(|(_name, literal)| Pattern::new(&literal))
150+
.transpose()?;
151+
152+
let value = keyword_arguments
153+
.remove("value")
154+
.map(|(name, literal)| {
155+
if long.is_none() && short.is_none() {
156+
return Err(name.error(CompileErrorKind::ArgAttributeValueRequiresOption));
157+
}
158+
Ok(literal)
163159
})
164-
.transpose()?
165-
.unwrap_or((None, None));
166-
167-
let value = if let Some((name, _token, literal)) = keyword_arguments.remove("value") {
168-
if long.is_none() && short.is_none() {
169-
return Err(name.error(CompileErrorKind::ArgAttributeValueRequiresOption));
170-
}
171-
Some(literal)
172-
} else {
173-
None
174-
};
160+
.transpose()?;
175161

176162
let help = keyword_arguments
177163
.remove("help")
178-
.map(|(_name, _token, literal)| literal);
164+
.map(|(_name, literal)| literal);
179165

180166
Self::Arg {
181167
help,
182168
long,
183-
long_token,
184169
name,
185-
name_token,
186170
pattern,
187-
pattern_literal,
188171
short,
189-
short_token,
190172
value,
191173
}
192174
}
@@ -220,7 +202,7 @@ impl<'src> Attribute<'src> {
220202
}
221203
};
222204

223-
if let Some((_name, (keyword_name, _token, _literal))) = keyword_arguments.into_iter().next() {
205+
if let Some((_name, (keyword_name, _literal))) = keyword_arguments.into_iter().next() {
224206
return Err(
225207
keyword_name.error(CompileErrorKind::UnknownAttributeKeyword {
226208
attribute: name.lexeme(),
@@ -256,13 +238,9 @@ impl Display for Attribute<'_> {
256238
Self::Arg {
257239
help,
258240
long,
259-
long_token: _,
260241
name,
261-
name_token: _,
262-
pattern: _,
263-
pattern_literal,
242+
pattern,
264243
short,
265-
short_token: _,
266244
value,
267245
} => {
268246
write!(f, "({name}")?;
@@ -275,8 +253,8 @@ impl Display for Attribute<'_> {
275253
write!(f, ", short={short}")?;
276254
}
277255

278-
if let Some(pattern) = pattern_literal {
279-
write!(f, ", pattern={pattern}")?;
256+
if let Some(pattern) = pattern {
257+
write!(f, ", pattern={}", pattern.token.lexeme())?;
280258
}
281259

282260
if let Some(value) = value {

src/compile_error_kind.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub(crate) enum CompileErrorKind<'src> {
77
source: regex::Error,
88
},
99
AttributeArgumentCountMismatch {
10-
attribute: &'src str,
10+
attribute: Name<'src>,
1111
found: usize,
1212
min: usize,
1313
max: usize,

src/compiler.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ impl Compiler {
7171
relative,
7272
absolute,
7373
optional,
74-
path,
7574
} => {
7675
let import = current
7776
.path
@@ -88,9 +87,11 @@ impl Compiler {
8887
});
8988
}
9089
*absolute = Some(import.clone());
91-
stack.push(current.import(import, path.offset));
90+
stack.push(current.import(import, relative.token.offset));
9291
} else if !*optional {
93-
return Err(Error::MissingImportFile { path: *path });
92+
return Err(Error::MissingImportFile {
93+
path: relative.token,
94+
});
9495
}
9596
}
9697
_ => {}

src/error.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub(crate) enum Error<'src> {
99
ArgumentPatternMismatch {
1010
argument: String,
1111
parameter: &'src str,
12-
pattern: Pattern,
12+
pattern: Box<Pattern<'src>>,
1313
recipe: &'src str,
1414
},
1515
Assert {
@@ -363,7 +363,8 @@ impl ColorDisplay for Error<'_> {
363363
} => {
364364
write!(
365365
f,
366-
"Argument `{argument}` passed to recipe `{recipe}` parameter `{parameter}` does not match pattern '{pattern}'",
366+
"Argument `{argument}` passed to recipe `{recipe}` parameter `{parameter}` does not match pattern '{}'",
367+
pattern.original(),
367368
)?;
368369
}
369370
Assert { message, .. } => {

src/expression.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ pub(crate) enum Expression<'src> {
3939
},
4040
// `f"format string"`
4141
FormatString {
42-
start: StringLiteral,
43-
expressions: Vec<(Expression<'src>, StringLiteral)>,
42+
start: StringLiteral<'src>,
43+
expressions: Vec<(Expression<'src>, StringLiteral<'src>)>,
4444
},
4545
/// `(contents)`
4646
Group { contents: Box<Expression<'src>> },
@@ -55,7 +55,7 @@ pub(crate) enum Expression<'src> {
5555
rhs: Box<Expression<'src>>,
5656
},
5757
/// `"string_literal"` or `'string_literal'`
58-
StringLiteral { string_literal: StringLiteral },
58+
StringLiteral { string_literal: StringLiteral<'src> },
5959
/// `variable`
6060
Variable { name: Name<'src> },
6161
}

src/item.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,15 @@ pub(crate) enum Item<'src> {
99
Import {
1010
absolute: Option<PathBuf>,
1111
optional: bool,
12-
path: Token<'src>,
13-
relative: StringLiteral,
12+
relative: StringLiteral<'src>,
1413
},
1514
Module {
1615
absolute: Option<PathBuf>,
1716
doc: Option<String>,
18-
groups: Vec<StringLiteral>,
17+
groups: Vec<StringLiteral<'src>>,
1918
name: Name<'src>,
2019
optional: bool,
21-
relative: Option<StringLiteral>,
20+
relative: Option<StringLiteral<'src>>,
2221
},
2322
Recipe(UnresolvedRecipe<'src>),
2423
Set(Set<'src>),

src/justfile.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub(crate) struct Justfile<'src> {
77
#[serde(rename = "first", serialize_with = "keyed::serialize_option")]
88
pub(crate) default: Option<Arc<Recipe<'src>>>,
99
pub(crate) doc: Option<String>,
10-
pub(crate) groups: Vec<StringLiteral>,
10+
pub(crate) groups: Vec<StringLiteral<'src>>,
1111
#[serde(skip)]
1212
pub(crate) loaded: Vec<PathBuf>,
1313
#[serde(skip)]

0 commit comments

Comments
 (0)