diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 40 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide_api/src/expand_macro.rs | 64 | ||||
-rw-r--r-- | crates/ra_ide_api/src/typing.rs | 34 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/lib.rs | 24 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main.rs | 3 | ||||
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 68 |
8 files changed, 215 insertions, 20 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index c42ceabdf..797f90d50 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -131,6 +131,7 @@ pub struct ReferenceDescriptor { | |||
131 | } | 131 | } |
132 | 132 | ||
133 | pub struct Expansion { | 133 | pub struct Expansion { |
134 | macro_file_kind: MacroFileKind, | ||
134 | macro_call_id: MacroCallId, | 135 | macro_call_id: MacroCallId, |
135 | } | 136 | } |
136 | 137 | ||
@@ -145,7 +146,7 @@ impl Expansion { | |||
145 | } | 146 | } |
146 | 147 | ||
147 | pub fn file_id(&self) -> HirFileId { | 148 | pub fn file_id(&self) -> HirFileId { |
148 | self.macro_call_id.as_file(MacroFileKind::Items) | 149 | self.macro_call_id.as_file(self.macro_file_kind) |
149 | } | 150 | } |
150 | } | 151 | } |
151 | 152 | ||
@@ -439,7 +440,10 @@ impl SourceAnalyzer { | |||
439 | db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), | 440 | db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), |
440 | ); | 441 | ); |
441 | let macro_call_loc = MacroCallLoc { def, ast_id }; | 442 | let macro_call_loc = MacroCallLoc { def, ast_id }; |
442 | Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) }) | 443 | Some(Expansion { |
444 | macro_call_id: db.intern_macro(macro_call_loc), | ||
445 | macro_file_kind: to_macro_file_kind(macro_call.value), | ||
446 | }) | ||
443 | } | 447 | } |
444 | 448 | ||
445 | #[cfg(test)] | 449 | #[cfg(test)] |
@@ -538,3 +542,35 @@ fn adjust( | |||
538 | }) | 542 | }) |
539 | .map(|(_ptr, scope)| *scope) | 543 | .map(|(_ptr, scope)| *scope) |
540 | } | 544 | } |
545 | |||
546 | /// Given a `ast::MacroCall`, return what `MacroKindFile` it belongs to. | ||
547 | /// FIXME: Not completed | ||
548 | fn to_macro_file_kind(macro_call: &ast::MacroCall) -> MacroFileKind { | ||
549 | let syn = macro_call.syntax(); | ||
550 | let parent = match syn.parent() { | ||
551 | Some(it) => it, | ||
552 | None => { | ||
553 | // FIXME: | ||
554 | // If it is root, which means the parent HirFile | ||
555 | // MacroKindFile must be non-items | ||
556 | // return expr now. | ||
557 | return MacroFileKind::Expr; | ||
558 | } | ||
559 | }; | ||
560 | |||
561 | match parent.kind() { | ||
562 | MACRO_ITEMS | SOURCE_FILE => MacroFileKind::Items, | ||
563 | LET_STMT => { | ||
564 | // FIXME: Handle Pattern | ||
565 | MacroFileKind::Expr | ||
566 | } | ||
567 | EXPR_STMT => MacroFileKind::Statements, | ||
568 | BLOCK => MacroFileKind::Statements, | ||
569 | ARG_LIST => MacroFileKind::Expr, | ||
570 | TRY_EXPR => MacroFileKind::Expr, | ||
571 | _ => { | ||
572 | // Unknown , Just guess it is `Items` | ||
573 | MacroFileKind::Items | ||
574 | } | ||
575 | } | ||
576 | } | ||
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 3c11c8a22..e1d93a8ef 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs | |||
@@ -151,6 +151,7 @@ pub(crate) fn parse_macro( | |||
151 | let fragment_kind = match macro_file.macro_file_kind { | 151 | let fragment_kind = match macro_file.macro_file_kind { |
152 | MacroFileKind::Items => FragmentKind::Items, | 152 | MacroFileKind::Items => FragmentKind::Items, |
153 | MacroFileKind::Expr => FragmentKind::Expr, | 153 | MacroFileKind::Expr => FragmentKind::Expr, |
154 | MacroFileKind::Statements => FragmentKind::Statements, | ||
154 | }; | 155 | }; |
155 | let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?; | 156 | let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?; |
156 | Some((parse, Arc::new(rev_token_map))) | 157 | Some((parse, Arc::new(rev_token_map))) |
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 1389f64ce..126d12fbb 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -109,6 +109,7 @@ pub struct MacroFile { | |||
109 | pub enum MacroFileKind { | 109 | pub enum MacroFileKind { |
110 | Items, | 110 | Items, |
111 | Expr, | 111 | Expr, |
112 | Statements, | ||
112 | } | 113 | } |
113 | 114 | ||
114 | /// `MacroCallId` identifies a particular macro invocation, like | 115 | /// `MacroCallId` identifies a particular macro invocation, like |
diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide_api/src/expand_macro.rs index 7f39262dc..7dbf33a16 100644 --- a/crates/ra_ide_api/src/expand_macro.rs +++ b/crates/ra_ide_api/src/expand_macro.rs | |||
@@ -84,24 +84,19 @@ fn insert_whitespaces(syn: SyntaxNode) -> String { | |||
84 | }; | 84 | }; |
85 | 85 | ||
86 | res += &match token.kind() { | 86 | res += &match token.kind() { |
87 | k @ _ | 87 | k @ _ if is_text(k) && is_next(|it| !it.is_punct(), true) => { |
88 | if (k.is_keyword() || k.is_literal() || k == IDENT) | ||
89 | && is_next(|it| !it.is_punct(), true) => | ||
90 | { | ||
91 | token.text().to_string() + " " | 88 | token.text().to_string() + " " |
92 | } | 89 | } |
93 | L_CURLY if is_next(|it| it != R_CURLY, true) => { | 90 | L_CURLY if is_next(|it| it != R_CURLY, true) => { |
94 | indent += 1; | 91 | indent += 1; |
95 | format!(" {{\n{}", " ".repeat(indent)) | 92 | let leading_space = if is_last(|it| is_text(it), false) { " " } else { "" }; |
93 | format!("{}{{\n{}", leading_space, " ".repeat(indent)) | ||
96 | } | 94 | } |
97 | R_CURLY if is_last(|it| it != L_CURLY, true) => { | 95 | R_CURLY if is_last(|it| it != L_CURLY, true) => { |
98 | indent = indent.checked_sub(1).unwrap_or(0); | 96 | indent = indent.checked_sub(1).unwrap_or(0); |
99 | format!("\n}}{}", " ".repeat(indent)) | 97 | format!("\n{}}}", " ".repeat(indent)) |
100 | } | ||
101 | R_CURLY => { | ||
102 | indent = indent.checked_sub(1).unwrap_or(0); | ||
103 | format!("}}\n{}", " ".repeat(indent)) | ||
104 | } | 98 | } |
99 | R_CURLY => format!("}}\n{}", " ".repeat(indent)), | ||
105 | T![;] => format!(";\n{}", " ".repeat(indent)), | 100 | T![;] => format!(";\n{}", " ".repeat(indent)), |
106 | T![->] => " -> ".to_string(), | 101 | T![->] => " -> ".to_string(), |
107 | T![=] => " = ".to_string(), | 102 | T![=] => " = ".to_string(), |
@@ -112,7 +107,11 @@ fn insert_whitespaces(syn: SyntaxNode) -> String { | |||
112 | last = Some(token.kind()); | 107 | last = Some(token.kind()); |
113 | } | 108 | } |
114 | 109 | ||
115 | res | 110 | return res; |
111 | |||
112 | fn is_text(k: SyntaxKind) -> bool { | ||
113 | k.is_keyword() || k.is_literal() || k == IDENT | ||
114 | } | ||
116 | } | 115 | } |
117 | 116 | ||
118 | #[cfg(test)] | 117 | #[cfg(test)] |
@@ -175,4 +174,47 @@ fn some_thing() -> u32 { | |||
175 | } | 174 | } |
176 | "###); | 175 | "###); |
177 | } | 176 | } |
177 | |||
178 | #[test] | ||
179 | fn macro_expand_match_ast() { | ||
180 | let res = check_expand_macro( | ||
181 | r#" | ||
182 | //- /lib.rs | ||
183 | macro_rules! match_ast { | ||
184 | (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; | ||
185 | |||
186 | (match ($node:expr) { | ||
187 | $( ast::$ast:ident($it:ident) => $res:block, )* | ||
188 | _ => $catch_all:expr $(,)? | ||
189 | }) => {{ | ||
190 | $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )* | ||
191 | { $catch_all } | ||
192 | }}; | ||
193 | } | ||
194 | |||
195 | fn main() { | ||
196 | mat<|>ch_ast! { | ||
197 | match container { | ||
198 | ast::TraitDef(it) => {}, | ||
199 | ast::ImplBlock(it) => {}, | ||
200 | _ => { continue }, | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | "#, | ||
205 | ); | ||
206 | |||
207 | assert_eq!(res.name, "match_ast"); | ||
208 | assert_snapshot!(res.expansion, @r###" | ||
209 | { | ||
210 | if let Some(it) = ast::TraitDef::cast(container.clone()){} | ||
211 | else if let Some(it) = ast::ImplBlock::cast(container.clone()){} | ||
212 | else { | ||
213 | { | ||
214 | continue | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | "###); | ||
219 | } | ||
178 | } | 220 | } |
diff --git a/crates/ra_ide_api/src/typing.rs b/crates/ra_ide_api/src/typing.rs index d51132f73..21e5be9b3 100644 --- a/crates/ra_ide_api/src/typing.rs +++ b/crates/ra_ide_api/src/typing.rs | |||
@@ -40,9 +40,13 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour | |||
40 | } | 40 | } |
41 | 41 | ||
42 | let prefix = comment.prefix(); | 42 | let prefix = comment.prefix(); |
43 | if position.offset | 43 | let comment_range = comment.syntax().text_range(); |
44 | < comment.syntax().text_range().start() + TextUnit::of_str(prefix) + TextUnit::from(1) | 44 | if position.offset < comment_range.start() + TextUnit::of_str(prefix) + TextUnit::from(1) { |
45 | { | 45 | return None; |
46 | } | ||
47 | |||
48 | // Continuing non-doc line comments (like this one :) ) is annoying | ||
49 | if prefix == "//" && comment_range.end() == position.offset { | ||
46 | return None; | 50 | return None; |
47 | } | 51 | } |
48 | 52 | ||
@@ -247,6 +251,30 @@ impl S { | |||
247 | } | 251 | } |
248 | ", | 252 | ", |
249 | ); | 253 | ); |
254 | do_check( | ||
255 | r" | ||
256 | fn main() { | ||
257 | // Fix<|> me | ||
258 | let x = 1 + 1; | ||
259 | } | ||
260 | ", | ||
261 | r" | ||
262 | fn main() { | ||
263 | // Fix | ||
264 | // <|> me | ||
265 | let x = 1 + 1; | ||
266 | } | ||
267 | ", | ||
268 | ); | ||
269 | do_check_noop( | ||
270 | r" | ||
271 | fn main() { | ||
272 | // Fix me<|> | ||
273 | let x = 1 + 1; | ||
274 | } | ||
275 | ", | ||
276 | ); | ||
277 | |||
250 | do_check_noop(r"<|>//! docz"); | 278 | do_check_noop(r"<|>//! docz"); |
251 | } | 279 | } |
252 | 280 | ||
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index 0e5dbbbd5..9c36402b0 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs | |||
@@ -1,6 +1,26 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Implementation of the LSP for rust-analyzer. |
2 | 2 | //! | |
3 | //! This crate takes Rust-specific analysis results from ra_ide_api and | ||
4 | //! translates into LSP types. | ||
5 | //! | ||
6 | //! It also is the root of all state. `world` module defines the bulk of the | ||
7 | //! state, and `main_loop` module defines the rules for modifying it. | ||
3 | #![recursion_limit = "512"] | 8 | #![recursion_limit = "512"] |
9 | |||
10 | #[allow(unused)] | ||
11 | macro_rules! println { | ||
12 | ($($tt:tt)*) => { | ||
13 | compile_error!("stdout is locked, use eprintln") | ||
14 | }; | ||
15 | } | ||
16 | |||
17 | #[allow(unused)] | ||
18 | macro_rules! print { | ||
19 | ($($tt:tt)*) => { | ||
20 | compile_error!("stdout is locked, use eprint") | ||
21 | }; | ||
22 | } | ||
23 | |||
4 | mod caps; | 24 | mod caps; |
5 | mod cargo_target_spec; | 25 | mod cargo_target_spec; |
6 | mod conv; | 26 | mod conv; |
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index 7d9a1d054..e13c8ca14 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs | |||
@@ -1,8 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! `ra_lsp_server` binary |
2 | 2 | ||
3 | use flexi_logger::{Duplicate, Logger}; | 3 | use flexi_logger::{Duplicate, Logger}; |
4 | use lsp_server::Connection; | 4 | use lsp_server::Connection; |
5 | |||
6 | use ra_lsp_server::{show_message, Result, ServerConfig}; | 5 | use ra_lsp_server::{show_message, Result, ServerConfig}; |
7 | use ra_prof; | 6 | use ra_prof; |
8 | 7 | ||
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index d1c49c0b3..1de399fee 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -5,6 +5,7 @@ use ra_syntax::{ | |||
5 | ast, AstNode, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode, | 5 | ast, AstNode, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode, |
6 | SyntaxTreeBuilder, TextRange, TextUnit, T, | 6 | SyntaxTreeBuilder, TextRange, TextUnit, T, |
7 | }; | 7 | }; |
8 | use std::iter::successors; | ||
8 | use tt::buffer::{Cursor, TokenBuffer}; | 9 | use tt::buffer::{Cursor, TokenBuffer}; |
9 | 10 | ||
10 | use crate::subtree_source::SubtreeTokenSource; | 11 | use crate::subtree_source::SubtreeTokenSource; |
@@ -160,6 +161,31 @@ impl Convertor { | |||
160 | 161 | ||
161 | let first_child = tt.first_child_or_token()?; | 162 | let first_child = tt.first_child_or_token()?; |
162 | let last_child = tt.last_child_or_token()?; | 163 | let last_child = tt.last_child_or_token()?; |
164 | |||
165 | // ignore trivial first_child and last_child | ||
166 | let first_child = successors(Some(first_child), |it| { | ||
167 | if it.kind().is_trivia() { | ||
168 | it.next_sibling_or_token() | ||
169 | } else { | ||
170 | None | ||
171 | } | ||
172 | }) | ||
173 | .last() | ||
174 | .unwrap(); | ||
175 | if first_child.kind().is_trivia() { | ||
176 | return Some(tt::Subtree { token_trees: vec![], delimiter: tt::Delimiter::None }); | ||
177 | } | ||
178 | |||
179 | let last_child = successors(Some(last_child), |it| { | ||
180 | if it.kind().is_trivia() { | ||
181 | it.prev_sibling_or_token() | ||
182 | } else { | ||
183 | None | ||
184 | } | ||
185 | }) | ||
186 | .last() | ||
187 | .unwrap(); | ||
188 | |||
163 | let (delimiter, skip_first) = match (first_child.kind(), last_child.kind()) { | 189 | let (delimiter, skip_first) = match (first_child.kind(), last_child.kind()) { |
164 | (T!['('], T![')']) => (tt::Delimiter::Parenthesis, true), | 190 | (T!['('], T![')']) => (tt::Delimiter::Parenthesis, true), |
165 | (T!['{'], T!['}']) => (tt::Delimiter::Brace, true), | 191 | (T!['{'], T!['}']) => (tt::Delimiter::Brace, true), |
@@ -363,6 +389,7 @@ mod tests { | |||
363 | use super::*; | 389 | use super::*; |
364 | use crate::tests::{create_rules, expand}; | 390 | use crate::tests::{create_rules, expand}; |
365 | use ra_parser::TokenSource; | 391 | use ra_parser::TokenSource; |
392 | use ra_syntax::algo::{insert_children, InsertPosition}; | ||
366 | 393 | ||
367 | #[test] | 394 | #[test] |
368 | fn convert_tt_token_source() { | 395 | fn convert_tt_token_source() { |
@@ -423,4 +450,45 @@ mod tests { | |||
423 | let expansion = expand(&rules, "stmts!();"); | 450 | let expansion = expand(&rules, "stmts!();"); |
424 | assert!(token_tree_to_syntax_node(&expansion, FragmentKind::Expr).is_err()); | 451 | assert!(token_tree_to_syntax_node(&expansion, FragmentKind::Expr).is_err()); |
425 | } | 452 | } |
453 | |||
454 | #[test] | ||
455 | fn test_token_tree_last_child_is_white_space() { | ||
456 | let source_file = ast::SourceFile::parse("f!({} );").ok().unwrap(); | ||
457 | let macro_call = source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); | ||
458 | let token_tree = macro_call.token_tree().unwrap(); | ||
459 | |||
460 | // Token Tree now is : | ||
461 | // TokenTree | ||
462 | // - T!['('] | ||
463 | // - TokenTree | ||
464 | // - T!['{'] | ||
465 | // - T!['}'] | ||
466 | // - WHITE_SPACE | ||
467 | // - T![')'] | ||
468 | |||
469 | let rbrace = | ||
470 | token_tree.syntax().descendants_with_tokens().find(|it| it.kind() == T!['}']).unwrap(); | ||
471 | let space = token_tree | ||
472 | .syntax() | ||
473 | .descendants_with_tokens() | ||
474 | .find(|it| it.kind() == SyntaxKind::WHITESPACE) | ||
475 | .unwrap(); | ||
476 | |||
477 | // reorder th white space, such that the white is inside the inner token-tree. | ||
478 | let token_tree = insert_children( | ||
479 | &rbrace.parent().unwrap(), | ||
480 | InsertPosition::Last, | ||
481 | &mut std::iter::once(space), | ||
482 | ); | ||
483 | |||
484 | // Token Tree now is : | ||
485 | // TokenTree | ||
486 | // - T!['{'] | ||
487 | // - T!['}'] | ||
488 | // - WHITE_SPACE | ||
489 | let token_tree = ast::TokenTree::cast(token_tree).unwrap(); | ||
490 | let tt = ast_to_token_tree(&token_tree).unwrap().0; | ||
491 | |||
492 | assert_eq!(tt.delimiter, tt::Delimiter::Brace); | ||
493 | } | ||
426 | } | 494 | } |