forked from argotorg/fe
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpath.rs
More file actions
129 lines (117 loc) · 4.17 KB
/
Copy pathpath.rs
File metadata and controls
129 lines (117 loc) · 4.17 KB
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
use crate::{ParseError, SyntaxKind, TextRange, TextSize};
use super::{
Parser, define_scope,
expr::{is_lshift, is_lt_eq},
param::{GenericArgListScope, TraitRefScope},
token_stream::TokenStream,
type_::parse_type,
};
define_scope! {
#[doc(hidden)]
pub PathScope { is_expr: bool },
Path,
(Colon2)
}
impl super::Parse for PathScope {
type Error = ParseError;
fn parse<S: TokenStream>(&mut self, parser: &mut Parser<S>) -> Result<(), Self::Error> {
parser.set_newline_as_trivia(false);
parser.parse(PathSegmentScope::new(self.is_expr))?;
while parser.bump_if(SyntaxKind::Colon2) {
parser.parse(PathSegmentScope::default())?;
}
Ok(())
}
}
define_scope! { PathSegmentScope { is_expr: bool }, PathSegment }
impl super::Parse for PathSegmentScope {
type Error = ParseError;
fn parse<S: TokenStream>(&mut self, parser: &mut Parser<S>) -> Result<(), Self::Error> {
match parser.current_kind() {
Some(SyntaxKind::Lt) if is_qualified_type(parser) => {
parser.parse(QualifiedTypeScope::default())
}
Some(kind) if is_path_segment(kind) => {
parser.bump();
let is_turbofish = parser.current_kind_same_line() == Some(SyntaxKind::Colon2)
&& parser.peek_two() == (Some(SyntaxKind::Colon2), Some(SyntaxKind::Lt));
if (is_turbofish
|| (parser.current_kind_same_line() == Some(SyntaxKind::Lt)
&& !(is_lt_eq(parser) || is_lshift(parser))))
&& parser.dry_run(|parser| {
parser.bump_if(SyntaxKind::Colon2);
parser.parses_without_error(GenericArgListScope::new(self.is_expr))
})
{
if is_turbofish {
parser.bump_trivias();
parser.add_error(ParseError::Unexpected(
"unexpected turbofish syntax `::<`; remove the double colons".into(),
TextRange::at(parser.current_pos, TextSize::from(3)),
));
parser.bump_expected(SyntaxKind::Colon2);
}
parser
.parse(GenericArgListScope::new(self.is_expr))
.expect("dry_run suggests this will succeed");
}
Ok(())
}
_ => Err(ParseError::expected(
&[SyntaxKind::PathSegment],
None,
parser.end_of_prev_token,
)),
}
}
}
define_scope! { QualifiedTypeScope, QualifiedType }
impl super::Parse for QualifiedTypeScope {
type Error = ParseError;
fn parse<S: TokenStream>(&mut self, parser: &mut Parser<S>) -> Result<(), Self::Error> {
parser.bump_expected(SyntaxKind::Lt);
match parse_type(parser, None) {
Ok(_) => {}
Err(_) => {
return Err(ParseError::expected(
&[SyntaxKind::PathType],
None,
parser.end_of_prev_token,
));
}
}
parser.bump_expected(SyntaxKind::AsKw);
parser.parse(TraitRefScope::default())?;
if parser.bump_if(SyntaxKind::Gt) {
Ok(())
} else {
Err(ParseError::expected(
&[SyntaxKind::Gt],
None,
parser.end_of_prev_token,
))
}
}
}
pub(super) fn is_qualified_type<S: TokenStream>(parser: &mut Parser<S>) -> bool {
parser
.dry_run(|parser| {
if !parser.bump_if(SyntaxKind::Lt) {
return None;
}
parse_type(parser, None).ok()?;
(parser.current_kind() == Some(SyntaxKind::AsKw)).then_some(())
})
.is_some()
}
pub(super) fn is_path_segment(kind: SyntaxKind) -> bool {
matches!(
kind,
SyntaxKind::SelfTypeKw
| SyntaxKind::SelfKw
| SyntaxKind::IngotKw
| SyntaxKind::SuperKw
| SyntaxKind::Ident
| SyntaxKind::Lt
)
}