aboutsummaryrefslogtreecommitdiff
path: root/crates/libeditor/src/completion.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libeditor/src/completion.rs')
-rw-r--r--crates/libeditor/src/completion.rs101
1 files changed, 85 insertions, 16 deletions
diff --git a/crates/libeditor/src/completion.rs b/crates/libeditor/src/completion.rs
index ec9388ee3..69c039e83 100644
--- a/crates/libeditor/src/completion.rs
+++ b/crates/libeditor/src/completion.rs
@@ -1,4 +1,7 @@
1use std::collections::HashMap; 1use std::{
2 fmt,
3 collections::HashMap,
4};
2 5
3use libsyntax2::{ 6use libsyntax2::{
4 File, TextUnit, AstNode, SyntaxNodeRef, SyntaxNode, SmolStr, 7 File, TextUnit, AstNode, SyntaxNodeRef, SyntaxNode, SmolStr,
@@ -49,33 +52,89 @@ fn compute_scopes(fn_def: ast::FnDef) -> FnScopes {
49 .filter_map(|it| it.pat()) 52 .filter_map(|it| it.pat())
50 .for_each(|it| scopes.add_bindings(root, it)); 53 .for_each(|it| scopes.add_bindings(root, it));
51 54
52 let mut scope = root;
53 if let Some(body) = fn_def.body() { 55 if let Some(body) = fn_def.body() {
54 for stmt in body.statements() { 56 compute_block_scopes(body, &mut scopes, root)
55 match stmt { 57 }
56 ast::Stmt::LetStmt(stmt) => { 58 scopes
57 scope = scopes.new_scope(scope); 59}
58 if let Some(pat) = stmt.pat() { 60
59 scopes.add_bindings(scope, pat); 61fn compute_block_scopes(block: ast::Block, scopes: &mut FnScopes, mut scope: ScopeId) {
60 } 62 for stmt in block.statements() {
61 if let Some(expr) = stmt.initializer() { 63 match stmt {
62 scopes.set_scope(expr.syntax(), scope) 64 ast::Stmt::LetStmt(stmt) => {
63 } 65 scope = scopes.new_scope(scope);
66 if let Some(pat) = stmt.pat() {
67 scopes.add_bindings(scope, pat);
64 } 68 }
65 ast::Stmt::ExprStmt(expr) => { 69 if let Some(expr) = stmt.initializer() {
66 scopes.set_scope(expr.syntax(), scope) 70 scopes.set_scope(expr.syntax(), scope)
67 } 71 }
68 } 72 }
73 ast::Stmt::ExprStmt(expr_stmt) => {
74 if let Some(expr) = expr_stmt.expr() {
75 scopes.set_scope(expr.syntax(), scope);
76 compute_expr_scopes(expr, scopes, scope);
77 }
78 }
79 }
80 }
81 if let Some(expr) = block.expr() {
82 scopes.set_scope(expr.syntax(), scope);
83 compute_expr_scopes(expr, scopes, scope);
84 }
85}
86
87fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) {
88 match expr {
89 ast::Expr::IfExpr(e) => {
90 let cond_scope = e.condition().and_then(|cond| {
91 compute_cond_scopes(cond, scopes, scope)
92 });
93 if let Some(block) = e.then_branch() {
94 compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope));
95 }
96 if let Some(block) = e.else_branch() {
97 compute_block_scopes(block, scopes, scope);
98 }
99 },
100 ast::Expr::WhileExpr(e) => {
101 let cond_scope = e.condition().and_then(|cond| {
102 compute_cond_scopes(cond, scopes, scope)
103 });
104 if let Some(block) = e.body() {
105 compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope));
106 }
107 },
108 ast::Expr::BlockExpr(e) => {
109 if let Some(block) = e.block() {
110 compute_block_scopes(block, scopes, scope);
111 }
69 } 112 }
70 if let Some(expr) = body.expr() { 113 // ForExpr(e) => TODO,
71 scopes.set_scope(expr.syntax(), scope) 114 _ => {
115 expr.syntax().children()
116 .filter_map(ast::Expr::cast)
117 .for_each(|expr| compute_expr_scopes(expr, scopes, scope))
118 }
119 };
120
121 fn compute_cond_scopes(cond: ast::Condition, scopes: &mut FnScopes, scope: ScopeId) -> Option<ScopeId> {
122 if let Some(expr) = cond.expr() {
123 compute_expr_scopes(expr, scopes, scope);
124 }
125 if let Some(pat) = cond.pat() {
126 let s = scopes.new_scope(scope);
127 scopes.add_bindings(s, pat);
128 Some(s)
129 } else {
130 None
72 } 131 }
73 } 132 }
74 scopes
75} 133}
76 134
77type ScopeId = usize; 135type ScopeId = usize;
78 136
137#[derive(Debug)]
79struct FnScopes { 138struct FnScopes {
80 scopes: Vec<ScopeData>, 139 scopes: Vec<ScopeData>,
81 scope_for: HashMap<SyntaxNode, ScopeId>, 140 scope_for: HashMap<SyntaxNode, ScopeId>,
@@ -120,6 +179,7 @@ impl FnScopes {
120 } 179 }
121} 180}
122 181
182#[derive(Debug)]
123struct ScopeData { 183struct ScopeData {
124 parent: Option<ScopeId>, 184 parent: Option<ScopeId>,
125 entries: Vec<ScopeEntry> 185 entries: Vec<ScopeEntry>
@@ -149,3 +209,12 @@ impl ScopeEntry {
149 .unwrap() 209 .unwrap()
150 } 210 }
151} 211}
212
213impl fmt::Debug for ScopeEntry {
214 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
215 f.debug_struct("ScopeEntry")
216 .field("name", &self.name())
217 .field("syntax", &self.syntax)
218 .finish()
219 }
220}