diff options
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated/nodes.rs | 4 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/tokens.rs | 10 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/traits.rs | 13 | ||||
-rw-r--r-- | crates/ra_syntax/src/syntax_node.rs | 4 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation.rs | 20 |
6 files changed, 30 insertions, 23 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 1876afe95..eddc807d5 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -75,7 +75,7 @@ impl<N> AstChildren<N> { | |||
75 | impl<N: AstNode> Iterator for AstChildren<N> { | 75 | impl<N: AstNode> Iterator for AstChildren<N> { |
76 | type Item = N; | 76 | type Item = N; |
77 | fn next(&mut self) -> Option<N> { | 77 | fn next(&mut self) -> Option<N> { |
78 | self.inner.by_ref().find_map(N::cast) | 78 | self.inner.find_map(N::cast) |
79 | } | 79 | } |
80 | } | 80 | } |
81 | 81 | ||
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index cf6067e57..cb430ca01 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs | |||
@@ -1081,6 +1081,7 @@ pub struct BlockExpr { | |||
1081 | impl ast::AttrsOwner for BlockExpr {} | 1081 | impl ast::AttrsOwner for BlockExpr {} |
1082 | impl ast::ModuleItemOwner for BlockExpr {} | 1082 | impl ast::ModuleItemOwner for BlockExpr {} |
1083 | impl BlockExpr { | 1083 | impl BlockExpr { |
1084 | pub fn label(&self) -> Option<Label> { support::child(&self.syntax) } | ||
1084 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | 1085 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } |
1085 | pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } | 1086 | pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } |
1086 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | 1087 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } |
@@ -1235,6 +1236,8 @@ impl CastExpr { | |||
1235 | /// ``` | 1236 | /// ``` |
1236 | /// ❰ &foo ❱; | 1237 | /// ❰ &foo ❱; |
1237 | /// ❰ &mut bar ❱; | 1238 | /// ❰ &mut bar ❱; |
1239 | /// ❰ &raw const bar ❱; | ||
1240 | /// ❰ &raw mut bar ❱; | ||
1238 | /// ``` | 1241 | /// ``` |
1239 | /// | 1242 | /// |
1240 | /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators) | 1243 | /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators) |
@@ -1247,6 +1250,7 @@ impl RefExpr { | |||
1247 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } | 1250 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } |
1248 | pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) } | 1251 | pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) } |
1249 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | 1252 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } |
1253 | pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } | ||
1250 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | 1254 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } |
1251 | } | 1255 | } |
1252 | /// Prefix operator call. This is either `!` or `*` or `-`. | 1256 | /// Prefix operator call. This is either `!` or `*` or `-`. |
diff --git a/crates/ra_syntax/src/ast/tokens.rs b/crates/ra_syntax/src/ast/tokens.rs index 74906d8a6..04b0a4480 100644 --- a/crates/ra_syntax/src/ast/tokens.rs +++ b/crates/ra_syntax/src/ast/tokens.rs | |||
@@ -6,6 +6,7 @@ use crate::{ | |||
6 | ast::{AstToken, Comment, RawString, String, Whitespace}, | 6 | ast::{AstToken, Comment, RawString, String, Whitespace}, |
7 | TextRange, TextSize, | 7 | TextRange, TextSize, |
8 | }; | 8 | }; |
9 | use rustc_lexer::unescape::{unescape_literal, Mode}; | ||
9 | 10 | ||
10 | impl Comment { | 11 | impl Comment { |
11 | pub fn kind(&self) -> CommentKind { | 12 | pub fn kind(&self) -> CommentKind { |
@@ -147,7 +148,7 @@ impl HasStringValue for String { | |||
147 | 148 | ||
148 | let mut buf = std::string::String::with_capacity(text.len()); | 149 | let mut buf = std::string::String::with_capacity(text.len()); |
149 | let mut has_error = false; | 150 | let mut has_error = false; |
150 | rustc_lexer::unescape::unescape_str(text, &mut |_, unescaped_char| match unescaped_char { | 151 | unescape_literal(text, Mode::Str, &mut |_, unescaped_char| match unescaped_char { |
151 | Ok(c) => buf.push(c), | 152 | Ok(c) => buf.push(c), |
152 | Err(_) => has_error = true, | 153 | Err(_) => has_error = true, |
153 | }); | 154 | }); |
@@ -417,14 +418,9 @@ pub trait HasFormatSpecifier: AstToken { | |||
417 | 418 | ||
418 | let mut cloned = chars.clone().take(2); | 419 | let mut cloned = chars.clone().take(2); |
419 | let first = cloned.next().and_then(|next| next.1.as_ref().ok()).copied(); | 420 | let first = cloned.next().and_then(|next| next.1.as_ref().ok()).copied(); |
420 | let second = cloned.next().and_then(|next| next.1.as_ref().ok()).copied(); | ||
421 | if first != Some('}') { | 421 | if first != Some('}') { |
422 | continue; | 422 | continue; |
423 | } | 423 | } |
424 | if second == Some('}') { | ||
425 | // Escaped format end specifier, `}}` | ||
426 | continue; | ||
427 | } | ||
428 | skip_char_and_emit(&mut chars, FormatSpecifier::Close, &mut callback); | 424 | skip_char_and_emit(&mut chars, FormatSpecifier::Close, &mut callback); |
429 | } | 425 | } |
430 | _ => { | 426 | _ => { |
@@ -498,7 +494,7 @@ impl HasFormatSpecifier for String { | |||
498 | let offset = self.text_range_between_quotes()?.start() - self.syntax().text_range().start(); | 494 | let offset = self.text_range_between_quotes()?.start() - self.syntax().text_range().start(); |
499 | 495 | ||
500 | let mut res = Vec::with_capacity(text.len()); | 496 | let mut res = Vec::with_capacity(text.len()); |
501 | rustc_lexer::unescape::unescape_str(text, &mut |range, unescaped_char| { | 497 | unescape_literal(text, Mode::Str, &mut |range, unescaped_char| { |
502 | res.push(( | 498 | res.push(( |
503 | TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()) | 499 | TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()) |
504 | + offset, | 500 | + offset, |
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs index bfc05e08b..a8f2454fd 100644 --- a/crates/ra_syntax/src/ast/traits.rs +++ b/crates/ra_syntax/src/ast/traits.rs | |||
@@ -83,13 +83,22 @@ pub trait DocCommentsOwner: AstNode { | |||
83 | CommentIter { iter: self.syntax().children_with_tokens() } | 83 | CommentIter { iter: self.syntax().children_with_tokens() } |
84 | } | 84 | } |
85 | 85 | ||
86 | fn doc_comment_text(&self) -> Option<String> { | ||
87 | self.doc_comments().doc_comment_text() | ||
88 | } | ||
89 | } | ||
90 | |||
91 | impl CommentIter { | ||
92 | pub fn from_syntax_node(syntax_node: &ast::SyntaxNode) -> CommentIter { | ||
93 | CommentIter { iter: syntax_node.children_with_tokens() } | ||
94 | } | ||
95 | |||
86 | /// Returns the textual content of a doc comment block as a single string. | 96 | /// Returns the textual content of a doc comment block as a single string. |
87 | /// That is, strips leading `///` (+ optional 1 character of whitespace), | 97 | /// That is, strips leading `///` (+ optional 1 character of whitespace), |
88 | /// trailing `*/`, trailing whitespace and then joins the lines. | 98 | /// trailing `*/`, trailing whitespace and then joins the lines. |
89 | fn doc_comment_text(&self) -> Option<String> { | 99 | pub fn doc_comment_text(self) -> Option<String> { |
90 | let mut has_comments = false; | 100 | let mut has_comments = false; |
91 | let docs = self | 101 | let docs = self |
92 | .doc_comments() | ||
93 | .filter(|comment| comment.kind().doc.is_some()) | 102 | .filter(|comment| comment.kind().doc.is_some()) |
94 | .map(|comment| { | 103 | .map(|comment| { |
95 | has_comments = true; | 104 | has_comments = true; |
diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs index e566af7e8..9650b8781 100644 --- a/crates/ra_syntax/src/syntax_node.rs +++ b/crates/ra_syntax/src/syntax_node.rs | |||
@@ -48,11 +48,11 @@ impl SyntaxTreeBuilder { | |||
48 | 48 | ||
49 | pub fn finish(self) -> Parse<SyntaxNode> { | 49 | pub fn finish(self) -> Parse<SyntaxNode> { |
50 | let (green, errors) = self.finish_raw(); | 50 | let (green, errors) = self.finish_raw(); |
51 | let node = SyntaxNode::new_root(green); | ||
52 | if cfg!(debug_assertions) { | 51 | if cfg!(debug_assertions) { |
52 | let node = SyntaxNode::new_root(green.clone()); | ||
53 | crate::validation::validate_block_structure(&node); | 53 | crate::validation::validate_block_structure(&node); |
54 | } | 54 | } |
55 | Parse::new(node.green().clone(), errors) | 55 | Parse::new(green, errors) |
56 | } | 56 | } |
57 | 57 | ||
58 | pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) { | 58 | pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) { |
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index d68cf0a82..fdec48fb0 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs | |||
@@ -2,15 +2,15 @@ | |||
2 | 2 | ||
3 | mod block; | 3 | mod block; |
4 | 4 | ||
5 | use std::convert::TryFrom; | ||
6 | |||
7 | use rustc_lexer::unescape; | ||
8 | |||
9 | use crate::{ | 5 | use crate::{ |
10 | ast, match_ast, AstNode, SyntaxError, | 6 | ast, match_ast, AstNode, SyntaxError, |
11 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST_DEF, FN_DEF, INT_NUMBER, STRING, TYPE_ALIAS_DEF}, | 7 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST_DEF, FN_DEF, INT_NUMBER, STRING, TYPE_ALIAS_DEF}, |
12 | SyntaxNode, SyntaxToken, TextSize, T, | 8 | SyntaxNode, SyntaxToken, TextSize, T, |
13 | }; | 9 | }; |
10 | use rustc_lexer::unescape::{ | ||
11 | self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode, | ||
12 | }; | ||
13 | use std::convert::TryFrom; | ||
14 | 14 | ||
15 | fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> &'static str { | 15 | fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> &'static str { |
16 | use unescape::EscapeError as EE; | 16 | use unescape::EscapeError as EE; |
@@ -81,10 +81,8 @@ fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> &'static str { | |||
81 | 81 | ||
82 | pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { | 82 | pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { |
83 | // FIXME: | 83 | // FIXME: |
84 | // * Add validation of character literal containing only a single char | 84 | // * Add unescape validation of raw string literals and raw byte string literals |
85 | // * Add validation of `crate` keyword not appearing in the middle of the symbol path | ||
86 | // * Add validation of doc comments are being attached to nodes | 85 | // * Add validation of doc comments are being attached to nodes |
87 | // * Remove validation of unterminated literals (it is already implemented in `tokenize()`) | ||
88 | 86 | ||
89 | let mut errors = Vec::new(); | 87 | let mut errors = Vec::new(); |
90 | for node in root.descendants() { | 88 | for node in root.descendants() { |
@@ -121,18 +119,18 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) { | |||
121 | 119 | ||
122 | match token.kind() { | 120 | match token.kind() { |
123 | BYTE => { | 121 | BYTE => { |
124 | if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape::unescape_byte) { | 122 | if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) { |
125 | push_err(2, e); | 123 | push_err(2, e); |
126 | } | 124 | } |
127 | } | 125 | } |
128 | CHAR => { | 126 | CHAR => { |
129 | if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape::unescape_char) { | 127 | if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape_char) { |
130 | push_err(1, e); | 128 | push_err(1, e); |
131 | } | 129 | } |
132 | } | 130 | } |
133 | BYTE_STRING => { | 131 | BYTE_STRING => { |
134 | if let Some(without_quotes) = unquote(text, 2, '"') { | 132 | if let Some(without_quotes) = unquote(text, 2, '"') { |
135 | unescape::unescape_byte_str(without_quotes, &mut |range, char| { | 133 | unescape_byte_literal(without_quotes, Mode::ByteStr, &mut |range, char| { |
136 | if let Err(err) = char { | 134 | if let Err(err) = char { |
137 | push_err(2, (range.start, err)); | 135 | push_err(2, (range.start, err)); |
138 | } | 136 | } |
@@ -141,7 +139,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) { | |||
141 | } | 139 | } |
142 | STRING => { | 140 | STRING => { |
143 | if let Some(without_quotes) = unquote(text, 1, '"') { | 141 | if let Some(without_quotes) = unquote(text, 1, '"') { |
144 | unescape::unescape_str(without_quotes, &mut |range, char| { | 142 | unescape_literal(without_quotes, Mode::Str, &mut |range, char| { |
145 | if let Err(err) = char { | 143 | if let Err(err) = char { |
146 | push_err(1, (range.start, err)); | 144 | push_err(1, (range.start, err)); |
147 | } | 145 | } |