From aaca7d003bd969785be53d8f312b67bfa26f6272 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 27 Aug 2018 20:58:38 +0300 Subject: move scopes to file --- crates/libeditor/scope.rs | 0 crates/libeditor/src/completion.rs | 187 +------------------------------------ crates/libeditor/src/lib.rs | 1 + crates/libeditor/src/scope.rs | 183 ++++++++++++++++++++++++++++++++++++ 4 files changed, 187 insertions(+), 184 deletions(-) create mode 100644 crates/libeditor/scope.rs create mode 100644 crates/libeditor/src/scope.rs (limited to 'crates/libeditor') diff --git a/crates/libeditor/scope.rs b/crates/libeditor/scope.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/libeditor/src/completion.rs b/crates/libeditor/src/completion.rs index 69c039e83..242a3a434 100644 --- a/crates/libeditor/src/completion.rs +++ b/crates/libeditor/src/completion.rs @@ -1,20 +1,14 @@ -use std::{ - fmt, - collections::HashMap, -}; - use libsyntax2::{ - File, TextUnit, AstNode, SyntaxNodeRef, SyntaxNode, SmolStr, - ast::{self, NameOwner}, + File, TextUnit, AstNode, + ast::self, algo::{ ancestors, - walk::preorder, - generate, }, }; use { AtomEdit, find_node_at_offset, + scope::{FnScopes, compute_scopes}, }; #[derive(Debug)] @@ -43,178 +37,3 @@ fn complete(name_ref: ast::NameRef, scopes: &FnScopes) -> Vec { }) .collect() } - -fn compute_scopes(fn_def: ast::FnDef) -> FnScopes { - let mut scopes = FnScopes::new(); - let root = scopes.root_scope(); - fn_def.param_list().into_iter() - .flat_map(|it| it.params()) - .filter_map(|it| it.pat()) - .for_each(|it| scopes.add_bindings(root, it)); - - if let Some(body) = fn_def.body() { - compute_block_scopes(body, &mut scopes, root) - } - scopes -} - -fn compute_block_scopes(block: ast::Block, scopes: &mut FnScopes, mut scope: ScopeId) { - for stmt in block.statements() { - match stmt { - ast::Stmt::LetStmt(stmt) => { - scope = scopes.new_scope(scope); - if let Some(pat) = stmt.pat() { - scopes.add_bindings(scope, pat); - } - if let Some(expr) = stmt.initializer() { - scopes.set_scope(expr.syntax(), scope) - } - } - ast::Stmt::ExprStmt(expr_stmt) => { - if let Some(expr) = expr_stmt.expr() { - scopes.set_scope(expr.syntax(), scope); - compute_expr_scopes(expr, scopes, scope); - } - } - } - } - if let Some(expr) = block.expr() { - scopes.set_scope(expr.syntax(), scope); - compute_expr_scopes(expr, scopes, scope); - } -} - -fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { - match expr { - ast::Expr::IfExpr(e) => { - let cond_scope = e.condition().and_then(|cond| { - compute_cond_scopes(cond, scopes, scope) - }); - if let Some(block) = e.then_branch() { - compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope)); - } - if let Some(block) = e.else_branch() { - compute_block_scopes(block, scopes, scope); - } - }, - ast::Expr::WhileExpr(e) => { - let cond_scope = e.condition().and_then(|cond| { - compute_cond_scopes(cond, scopes, scope) - }); - if let Some(block) = e.body() { - compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope)); - } - }, - ast::Expr::BlockExpr(e) => { - if let Some(block) = e.block() { - compute_block_scopes(block, scopes, scope); - } - } - // ForExpr(e) => TODO, - _ => { - expr.syntax().children() - .filter_map(ast::Expr::cast) - .for_each(|expr| compute_expr_scopes(expr, scopes, scope)) - } - }; - - fn compute_cond_scopes(cond: ast::Condition, scopes: &mut FnScopes, scope: ScopeId) -> Option { - if let Some(expr) = cond.expr() { - compute_expr_scopes(expr, scopes, scope); - } - if let Some(pat) = cond.pat() { - let s = scopes.new_scope(scope); - scopes.add_bindings(s, pat); - Some(s) - } else { - None - } - } -} - -type ScopeId = usize; - -#[derive(Debug)] -struct FnScopes { - scopes: Vec, - scope_for: HashMap, -} - -impl FnScopes { - fn new() -> FnScopes { - FnScopes { - scopes: vec![], - scope_for: HashMap::new(), - } - } - fn root_scope(&mut self) -> ScopeId { - let res = self.scopes.len(); - self.scopes.push(ScopeData { parent: None, entries: vec![] }); - res - } - fn new_scope(&mut self, parent: ScopeId) -> ScopeId { - let res = self.scopes.len(); - self.scopes.push(ScopeData { parent: Some(parent), entries: vec![] }); - res - } - fn add_bindings(&mut self, scope: ScopeId, pat: ast::Pat) { - let entries = preorder(pat.syntax()) - .filter_map(ast::BindPat::cast) - .filter_map(ScopeEntry::new); - self.scopes[scope].entries.extend(entries); - } - fn set_scope(&mut self, node: SyntaxNodeRef, scope: ScopeId) { - self.scope_for.insert(node.owned(), scope); - } - fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { - &self.scopes[scope].entries - } - fn scope_for(&self, node: SyntaxNodeRef) -> Option { - ancestors(node) - .filter_map(|it| self.scope_for.get(&it.owned()).map(|&scope| scope)) - .next() - } - fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator + 'a { - generate(self.scope_for(node), move |&scope| self.scopes[scope].parent) - } -} - -#[derive(Debug)] -struct ScopeData { - parent: Option, - entries: Vec -} - -struct ScopeEntry { - syntax: SyntaxNode -} - -impl ScopeEntry { - fn new(pat: ast::BindPat) -> Option { - if pat.name().is_some() { - Some(ScopeEntry { syntax: pat.syntax().owned() }) - } else { - None - } - } - - fn name(&self) -> SmolStr { - self.ast().name() - .unwrap() - .text() - } - - fn ast(&self) -> ast::BindPat { - ast::BindPat::cast(self.syntax.borrowed()) - .unwrap() - } -} - -impl fmt::Debug for ScopeEntry { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("ScopeEntry") - .field("name", &self.name()) - .field("syntax", &self.syntax) - .finish() - } -} diff --git a/crates/libeditor/src/lib.rs b/crates/libeditor/src/lib.rs index 60489f7e3..d39e56d81 100644 --- a/crates/libeditor/src/lib.rs +++ b/crates/libeditor/src/lib.rs @@ -9,6 +9,7 @@ mod edit; mod code_actions; mod typing; mod completion; +mod scope; use libsyntax2::{ File, TextUnit, TextRange, SyntaxNodeRef, diff --git a/crates/libeditor/src/scope.rs b/crates/libeditor/src/scope.rs new file mode 100644 index 000000000..1fec0b24e --- /dev/null +++ b/crates/libeditor/src/scope.rs @@ -0,0 +1,183 @@ +use std::{ + fmt, + collections::HashMap, +}; + +use libsyntax2::{ + SyntaxNodeRef, SyntaxNode, SmolStr, AstNode, + ast::{self, NameOwner}, + algo::{ancestors, generate, walk::preorder} +}; + +pub fn compute_scopes(fn_def: ast::FnDef) -> FnScopes { + let mut scopes = FnScopes::new(); + let root = scopes.root_scope(); + fn_def.param_list().into_iter() + .flat_map(|it| it.params()) + .filter_map(|it| it.pat()) + .for_each(|it| scopes.add_bindings(root, it)); + + if let Some(body) = fn_def.body() { + compute_block_scopes(body, &mut scopes, root) + } + scopes +} + +fn compute_block_scopes(block: ast::Block, scopes: &mut FnScopes, mut scope: ScopeId) { + for stmt in block.statements() { + match stmt { + ast::Stmt::LetStmt(stmt) => { + scope = scopes.new_scope(scope); + if let Some(pat) = stmt.pat() { + scopes.add_bindings(scope, pat); + } + if let Some(expr) = stmt.initializer() { + scopes.set_scope(expr.syntax(), scope) + } + } + ast::Stmt::ExprStmt(expr_stmt) => { + if let Some(expr) = expr_stmt.expr() { + scopes.set_scope(expr.syntax(), scope); + compute_expr_scopes(expr, scopes, scope); + } + } + } + } + if let Some(expr) = block.expr() { + scopes.set_scope(expr.syntax(), scope); + compute_expr_scopes(expr, scopes, scope); + } +} + +fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { + match expr { + ast::Expr::IfExpr(e) => { + let cond_scope = e.condition().and_then(|cond| { + compute_cond_scopes(cond, scopes, scope) + }); + if let Some(block) = e.then_branch() { + compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope)); + } + if let Some(block) = e.else_branch() { + compute_block_scopes(block, scopes, scope); + } + }, + ast::Expr::WhileExpr(e) => { + let cond_scope = e.condition().and_then(|cond| { + compute_cond_scopes(cond, scopes, scope) + }); + if let Some(block) = e.body() { + compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope)); + } + }, + ast::Expr::BlockExpr(e) => { + if let Some(block) = e.block() { + compute_block_scopes(block, scopes, scope); + } + } + // ForExpr(e) => TODO, + _ => { + expr.syntax().children() + .filter_map(ast::Expr::cast) + .for_each(|expr| compute_expr_scopes(expr, scopes, scope)) + } + }; + + fn compute_cond_scopes(cond: ast::Condition, scopes: &mut FnScopes, scope: ScopeId) -> Option { + if let Some(expr) = cond.expr() { + compute_expr_scopes(expr, scopes, scope); + } + if let Some(pat) = cond.pat() { + let s = scopes.new_scope(scope); + scopes.add_bindings(s, pat); + Some(s) + } else { + None + } + } +} + +type ScopeId = usize; + +#[derive(Debug)] +pub struct FnScopes { + scopes: Vec, + scope_for: HashMap, +} + +impl FnScopes { + fn new() -> FnScopes { + FnScopes { + scopes: vec![], + scope_for: HashMap::new(), + } + } + pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { + &self.scopes[scope].entries + } + pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator + 'a { + generate(self.scope_for(node), move |&scope| self.scopes[scope].parent) + } + fn root_scope(&mut self) -> ScopeId { + let res = self.scopes.len(); + self.scopes.push(ScopeData { parent: None, entries: vec![] }); + res + } + fn new_scope(&mut self, parent: ScopeId) -> ScopeId { + let res = self.scopes.len(); + self.scopes.push(ScopeData { parent: Some(parent), entries: vec![] }); + res + } + fn add_bindings(&mut self, scope: ScopeId, pat: ast::Pat) { + let entries = preorder(pat.syntax()) + .filter_map(ast::BindPat::cast) + .filter_map(ScopeEntry::new); + self.scopes[scope].entries.extend(entries); + } + fn set_scope(&mut self, node: SyntaxNodeRef, scope: ScopeId) { + self.scope_for.insert(node.owned(), scope); + } + fn scope_for(&self, node: SyntaxNodeRef) -> Option { + ancestors(node) + .filter_map(|it| self.scope_for.get(&it.owned()).map(|&scope| scope)) + .next() + } +} + +#[derive(Debug)] +struct ScopeData { + parent: Option, + entries: Vec +} + +pub struct ScopeEntry { + syntax: SyntaxNode +} + +impl ScopeEntry { + fn new(pat: ast::BindPat) -> Option { + if pat.name().is_some() { + Some(ScopeEntry { syntax: pat.syntax().owned() }) + } else { + None + } + } + pub fn name(&self) -> SmolStr { + self.ast().name() + .unwrap() + .text() + } + fn ast(&self) -> ast::BindPat { + ast::BindPat::cast(self.syntax.borrowed()) + .unwrap() + } +} + +impl fmt::Debug for ScopeEntry { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ScopeEntry") + .field("name", &self.name()) + .field("syntax", &self.syntax) + .finish() + } +} -- cgit v1.2.3