diff options
Diffstat (limited to 'crates/ra_syntax/src/ast')
-rw-r--r-- | crates/ra_syntax/src/ast/edit.rs | 44 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 36 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/tokens.rs | 5 |
3 files changed, 56 insertions, 29 deletions
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index 24a1e1d91..29eb3fcb9 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs | |||
@@ -1,7 +1,10 @@ | |||
1 | //! This module contains functions for editing syntax trees. As the trees are | 1 | //! This module contains functions for editing syntax trees. As the trees are |
2 | //! immutable, all function here return a fresh copy of the tree, instead of | 2 | //! immutable, all function here return a fresh copy of the tree, instead of |
3 | //! doing an in-place modification. | 3 | //! doing an in-place modification. |
4 | use std::{iter, ops::RangeInclusive}; | 4 | use std::{ |
5 | fmt, iter, | ||
6 | ops::{self, RangeInclusive}, | ||
7 | }; | ||
5 | 8 | ||
6 | use arrayvec::ArrayVec; | 9 | use arrayvec::ArrayVec; |
7 | 10 | ||
@@ -437,6 +440,28 @@ impl From<u8> for IndentLevel { | |||
437 | } | 440 | } |
438 | } | 441 | } |
439 | 442 | ||
443 | impl fmt::Display for IndentLevel { | ||
444 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
445 | let spaces = " "; | ||
446 | let buf; | ||
447 | let len = self.0 as usize * 4; | ||
448 | let indent = if len <= spaces.len() { | ||
449 | &spaces[..len] | ||
450 | } else { | ||
451 | buf = iter::repeat(' ').take(len).collect::<String>(); | ||
452 | &buf | ||
453 | }; | ||
454 | fmt::Display::fmt(indent, f) | ||
455 | } | ||
456 | } | ||
457 | |||
458 | impl ops::Add<u8> for IndentLevel { | ||
459 | type Output = IndentLevel; | ||
460 | fn add(self, rhs: u8) -> IndentLevel { | ||
461 | IndentLevel(self.0 + rhs) | ||
462 | } | ||
463 | } | ||
464 | |||
440 | impl IndentLevel { | 465 | impl IndentLevel { |
441 | pub fn from_node(node: &SyntaxNode) -> IndentLevel { | 466 | pub fn from_node(node: &SyntaxNode) -> IndentLevel { |
442 | let first_token = match node.first_token() { | 467 | let first_token = match node.first_token() { |
@@ -453,6 +478,14 @@ impl IndentLevel { | |||
453 | IndentLevel(0) | 478 | IndentLevel(0) |
454 | } | 479 | } |
455 | 480 | ||
481 | /// XXX: this intentionally doesn't change the indent of the very first token. | ||
482 | /// Ie, in something like | ||
483 | /// ``` | ||
484 | /// fn foo() { | ||
485 | /// 92 | ||
486 | /// } | ||
487 | /// ``` | ||
488 | /// if you indent the block, the `{` token would stay put. | ||
456 | fn increase_indent(self, node: SyntaxNode) -> SyntaxNode { | 489 | fn increase_indent(self, node: SyntaxNode) -> SyntaxNode { |
457 | let mut rewriter = SyntaxRewriter::default(); | 490 | let mut rewriter = SyntaxRewriter::default(); |
458 | node.descendants_with_tokens() | 491 | node.descendants_with_tokens() |
@@ -463,12 +496,7 @@ impl IndentLevel { | |||
463 | text.contains('\n') | 496 | text.contains('\n') |
464 | }) | 497 | }) |
465 | .for_each(|ws| { | 498 | .for_each(|ws| { |
466 | let new_ws = make::tokens::whitespace(&format!( | 499 | let new_ws = make::tokens::whitespace(&format!("{}{}", ws.syntax(), self,)); |
467 | "{}{:width$}", | ||
468 | ws.syntax().text(), | ||
469 | "", | ||
470 | width = self.0 as usize * 4 | ||
471 | )); | ||
472 | rewriter.replace(ws.syntax(), &new_ws) | 500 | rewriter.replace(ws.syntax(), &new_ws) |
473 | }); | 501 | }); |
474 | rewriter.rewrite(&node) | 502 | rewriter.rewrite(&node) |
@@ -485,7 +513,7 @@ impl IndentLevel { | |||
485 | }) | 513 | }) |
486 | .for_each(|ws| { | 514 | .for_each(|ws| { |
487 | let new_ws = make::tokens::whitespace( | 515 | let new_ws = make::tokens::whitespace( |
488 | &ws.syntax().text().replace(&format!("\n{:1$}", "", self.0 as usize * 4), "\n"), | 516 | &ws.syntax().text().replace(&format!("\n{}", self), "\n"), |
489 | ); | 517 | ); |
490 | rewriter.replace(ws.syntax(), &new_ws) | 518 | rewriter.replace(ws.syntax(), &new_ws) |
491 | }); | 519 | }); |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index d0e960fb4..da0eb0926 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -1,5 +1,9 @@ | |||
1 | //! This module contains free-standing functions for creating AST fragments out | 1 | //! This module contains free-standing functions for creating AST fragments out |
2 | //! of smaller pieces. | 2 | //! of smaller pieces. |
3 | //! | ||
4 | //! Note that all functions here intended to be stupid constructors, which just | ||
5 | //! assemble a finish node from immediate children. If you want to do something | ||
6 | //! smarter than that, it probably doesn't belong in this module. | ||
3 | use itertools::Itertools; | 7 | use itertools::Itertools; |
4 | use stdx::format_to; | 8 | use stdx::format_to; |
5 | 9 | ||
@@ -95,6 +99,9 @@ pub fn expr_empty_block() -> ast::Expr { | |||
95 | pub fn expr_unimplemented() -> ast::Expr { | 99 | pub fn expr_unimplemented() -> ast::Expr { |
96 | expr_from_text("unimplemented!()") | 100 | expr_from_text("unimplemented!()") |
97 | } | 101 | } |
102 | pub fn expr_unreachable() -> ast::Expr { | ||
103 | expr_from_text("unreachable!()") | ||
104 | } | ||
98 | pub fn expr_todo() -> ast::Expr { | 105 | pub fn expr_todo() -> ast::Expr { |
99 | expr_from_text("todo!()") | 106 | expr_from_text("todo!()") |
100 | } | 107 | } |
@@ -264,10 +271,6 @@ pub fn token(kind: SyntaxKind) -> SyntaxToken { | |||
264 | .unwrap_or_else(|| panic!("unhandled token: {:?}", kind)) | 271 | .unwrap_or_else(|| panic!("unhandled token: {:?}", kind)) |
265 | } | 272 | } |
266 | 273 | ||
267 | pub fn unreachable_macro_call() -> ast::MacroCall { | ||
268 | ast_from_text(&format!("unreachable!()")) | ||
269 | } | ||
270 | |||
271 | pub fn param(name: String, ty: String) -> ast::Param { | 274 | pub fn param(name: String, ty: String) -> ast::Param { |
272 | ast_from_text(&format!("fn f({}: {}) {{ }}", name, ty)) | 275 | ast_from_text(&format!("fn f({}: {}) {{ }}", name, ty)) |
273 | } | 276 | } |
@@ -277,7 +280,12 @@ pub fn param_list(pats: impl IntoIterator<Item = ast::Param>) -> ast::ParamList | |||
277 | ast_from_text(&format!("fn f({}) {{ }}", args)) | 280 | ast_from_text(&format!("fn f({}) {{ }}", args)) |
278 | } | 281 | } |
279 | 282 | ||
283 | pub fn visibility_pub_crate() -> ast::Visibility { | ||
284 | ast_from_text("pub(crate) struct S") | ||
285 | } | ||
286 | |||
280 | pub fn fn_def( | 287 | pub fn fn_def( |
288 | visibility: Option<ast::Visibility>, | ||
281 | fn_name: ast::Name, | 289 | fn_name: ast::Name, |
282 | type_params: Option<ast::TypeParamList>, | 290 | type_params: Option<ast::TypeParamList>, |
283 | params: ast::ParamList, | 291 | params: ast::ParamList, |
@@ -285,21 +293,11 @@ pub fn fn_def( | |||
285 | ) -> ast::FnDef { | 293 | ) -> ast::FnDef { |
286 | let type_params = | 294 | let type_params = |
287 | if let Some(type_params) = type_params { format!("<{}>", type_params) } else { "".into() }; | 295 | if let Some(type_params) = type_params { format!("<{}>", type_params) } else { "".into() }; |
288 | ast_from_text(&format!("fn {}{}{} {}", fn_name, type_params, params, body)) | 296 | let visibility = match visibility { |
289 | } | 297 | None => String::new(), |
290 | 298 | Some(it) => format!("{} ", it), | |
291 | pub fn add_leading_newlines(amount_of_newlines: usize, t: impl AstNode) -> ast::SourceFile { | 299 | }; |
292 | let newlines = "\n".repeat(amount_of_newlines); | 300 | ast_from_text(&format!("{}fn {}{}{} {}", visibility, fn_name, type_params, params, body)) |
293 | ast_from_text(&format!("{}{}", newlines, t.syntax())) | ||
294 | } | ||
295 | |||
296 | pub fn add_trailing_newlines(amount_of_newlines: usize, t: impl AstNode) -> ast::SourceFile { | ||
297 | let newlines = "\n".repeat(amount_of_newlines); | ||
298 | ast_from_text(&format!("{}{}", t.syntax(), newlines)) | ||
299 | } | ||
300 | |||
301 | pub fn add_pub_crate_modifier(fn_def: ast::FnDef) -> ast::FnDef { | ||
302 | ast_from_text(&format!("pub(crate) {}", fn_def)) | ||
303 | } | 301 | } |
304 | 302 | ||
305 | fn ast_from_text<N: AstNode>(text: &str) -> N { | 303 | fn ast_from_text<N: AstNode>(text: &str) -> N { |
diff --git a/crates/ra_syntax/src/ast/tokens.rs b/crates/ra_syntax/src/ast/tokens.rs index 74906d8a6..3cd6d99c3 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 | }); |
@@ -498,7 +499,7 @@ impl HasFormatSpecifier for String { | |||
498 | let offset = self.text_range_between_quotes()?.start() - self.syntax().text_range().start(); | 499 | let offset = self.text_range_between_quotes()?.start() - self.syntax().text_range().start(); |
499 | 500 | ||
500 | let mut res = Vec::with_capacity(text.len()); | 501 | let mut res = Vec::with_capacity(text.len()); |
501 | rustc_lexer::unescape::unescape_str(text, &mut |range, unescaped_char| { | 502 | unescape_literal(text, Mode::Str, &mut |range, unescaped_char| { |
502 | res.push(( | 503 | res.push(( |
503 | TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()) | 504 | TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()) |
504 | + offset, | 505 | + offset, |