From 97a5c3a65eb27f385eabc8da062b3359e3984964 Mon Sep 17 00:00:00 2001 From: sofia Date: Sat, 2 Aug 2025 21:46:45 +0300 Subject: [PATCH] Optimize LSP analysis a Lot --- reid-lsp/src/analysis.rs | 309 ++++++++++++++++----------------------- reid-lsp/src/main.rs | 11 +- 2 files changed, 129 insertions(+), 191 deletions(-) diff --git a/reid-lsp/src/analysis.rs b/reid-lsp/src/analysis.rs index fc0fe41..fc9280a 100644 --- a/reid-lsp/src/analysis.rs +++ b/reid-lsp/src/analysis.rs @@ -1,6 +1,5 @@ use std::{collections::HashMap, path::PathBuf}; -use dashmap::DashMap; use reid::{ ast::lexer::FullToken, compile_module, @@ -9,12 +8,12 @@ use reid::{ perform_all_passes, }; -use crate::CompileResult; +type TokenAnalysisMap = HashMap; #[derive(Debug, Clone)] pub struct StaticAnalysis { pub tokens: Vec, - pub token_analysis: HashMap, + pub token_analysis: TokenAnalysisMap, pub error: Option, } @@ -29,8 +28,6 @@ pub fn analyze( path: PathBuf, map: &mut ErrorModules, ) -> Result, ReidError> { - let mut token_analysis = HashMap::new(); - let (module, error) = match compile_module(module_id, tokens, map, Some(path.clone()), true)? { Ok(module) => (module, None), Err((m, err)) => (m.process(module_id), Some(err)), @@ -40,255 +37,203 @@ pub fn analyze( let mut context = Context::from(vec![module], path.parent().unwrap().to_owned()); perform_all_passes(&mut context, map)?; - for module in context.modules.into_values() { + for module in context.modules.values() { if module.module_id != module_id { continue; } - for idx in 0..module.tokens.len() { - token_analysis.insert( - idx, - SemanticAnalysis { - ty: find_type_in_context(&module, idx), - }, - ); - } - - return Ok(Some(StaticAnalysis { - tokens: module.tokens, - token_analysis: token_analysis, - error, - })); + return Ok(Some(analyze_context(&context, &module, error))); } return Ok(None); } -pub fn find_type_in_context(module: &mir::Module, token_idx: usize) -> Option { - for import in &module.imports { - if import.1.contains(token_idx) { - return Some(TypeKind::CustomType(mir::CustomTypeKey( - "d".to_owned(), - SourceModuleId(1), - ))); - } +pub fn set_tokens(map: &mut TokenAnalysisMap, meta: &mir::Metadata, analysis: SemanticAnalysis) { + for token in meta.range.start..meta.range.end { + map.insert(token, analysis.clone()); } - for typedef in &module.typedefs { - if !typedef.meta.contains(token_idx) { - continue; - } +} +pub fn analyze_context(context: &mir::Context, module: &mir::Module, error: Option) -> StaticAnalysis { + let mut map = HashMap::new(); + for import in &module.imports { + set_tokens(&mut map, &import.1, SemanticAnalysis { ty: None }); + } + + for typedef in &module.typedefs { match &typedef.kind { mir::TypeDefinitionKind::Struct(StructType(fields)) => { for field in fields { - if field.2.contains(token_idx) { - return Some(field.1.clone()); - } + set_tokens( + &mut map, + &field.2, + SemanticAnalysis { + ty: Some(field.1.clone()), + }, + ); } } } } for binop in &module.binop_defs { - if let Some(meta) = binop.block_meta() { - if !meta.contains(token_idx) { - continue; - } - } else { - continue; - } - - return match &binop.fn_kind { - mir::FunctionDefinitionKind::Local(block, _) => find_type_in_block(&block, module.module_id, token_idx), - mir::FunctionDefinitionKind::Extern(_) => None, - mir::FunctionDefinitionKind::Intrinsic(_) => None, + match &binop.fn_kind { + mir::FunctionDefinitionKind::Local(block, _) => analyze_block(context, module, block, &mut map), + mir::FunctionDefinitionKind::Extern(_) => {} + mir::FunctionDefinitionKind::Intrinsic(_) => {} }; } for (_, function) in &module.associated_functions { - if !(function.signature() + function.block_meta()).contains(token_idx) { - continue; - } - for param in &function.parameters { - if param.meta.contains(token_idx) { - return Some(param.ty.clone()); - } + set_tokens( + &mut map, + ¶m.meta, + SemanticAnalysis { + ty: Some(param.ty.clone()), + }, + ); } - return match &function.kind { - mir::FunctionDefinitionKind::Local(block, _) => find_type_in_block(&block, module.module_id, token_idx), - mir::FunctionDefinitionKind::Extern(_) => None, - mir::FunctionDefinitionKind::Intrinsic(_) => None, + match &function.kind { + mir::FunctionDefinitionKind::Local(block, _) => analyze_block(context, module, block, &mut map), + mir::FunctionDefinitionKind::Extern(_) => {} + mir::FunctionDefinitionKind::Intrinsic(_) => {} }; } for function in &module.functions { - if !(function.signature() + function.block_meta()).contains(token_idx) { - continue; - } - for param in &function.parameters { - if param.meta.contains(token_idx) { - return Some(param.ty.clone()); - } + set_tokens( + &mut map, + ¶m.meta, + SemanticAnalysis { + ty: Some(param.ty.clone()), + }, + ); } - return match &function.kind { - mir::FunctionDefinitionKind::Local(block, _) => find_type_in_block(&block, module.module_id, token_idx), - mir::FunctionDefinitionKind::Extern(_) => None, - mir::FunctionDefinitionKind::Intrinsic(_) => None, + match &function.kind { + mir::FunctionDefinitionKind::Local(block, _) => analyze_block(context, module, block, &mut map), + mir::FunctionDefinitionKind::Extern(_) => {} + mir::FunctionDefinitionKind::Intrinsic(_) => {} }; } - None + + StaticAnalysis { + tokens: module.tokens.clone(), + token_analysis: map, + error, + } } -pub fn find_type_in_block(block: &mir::Block, module_id: SourceModuleId, token_idx: usize) -> Option { - if !block.meta.contains(token_idx) { - return Some(TypeKind::Bool); - } - +pub fn analyze_block( + context: &mir::Context, + source_module: &mir::Module, + block: &mir::Block, + map: &mut TokenAnalysisMap, +) { for statement in &block.statements { - if !statement.1.contains(token_idx) { - continue; - } match &statement.0 { mir::StmtKind::Let(named_variable_ref, _, expression) => { - if named_variable_ref.2.contains(token_idx) { - return expression - .return_type(&Default::default(), module_id) - .ok() - .map(|(_, ty)| ty); - } else { - return find_type_in_expr(&expression, module_id, token_idx); - } + set_tokens( + map, + &named_variable_ref.2, + SemanticAnalysis { + ty: expression + .return_type(&Default::default(), source_module.module_id) + .ok() + .map(|(_, ty)| ty), + }, + ); + // return analyze_in_expr(&expression, module_id, token_idx); } mir::StmtKind::Set(lhs, rhs) => { - return find_type_in_expr(lhs, module_id, token_idx).or(find_type_in_expr(rhs, module_id, token_idx)); + analyze_expr(context, source_module, lhs, map); + analyze_expr(context, source_module, rhs, map); } mir::StmtKind::Import(_) => {} - mir::StmtKind::Expression(expression) => return find_type_in_expr(expression, module_id, token_idx), + mir::StmtKind::Expression(expression) => { + analyze_expr(context, source_module, expression, map); + } mir::StmtKind::While(WhileStatement { condition, block, .. }) => { - return find_type_in_expr(condition, module_id, token_idx) - .or(find_type_in_block(block, module_id, token_idx)); + analyze_expr(context, source_module, condition, map); + analyze_block(context, source_module, block, map); } } } if let Some((_, Some(return_exp))) = &block.return_expression { - if let Some(ty) = find_type_in_expr(return_exp, module_id, token_idx) { - return Some(ty); - } + analyze_expr(context, source_module, return_exp, map) } - - None } -pub fn find_type_in_expr(expr: &mir::Expression, module_id: SourceModuleId, token_idx: usize) -> Option { - if !expr.1.contains(token_idx) { - return None; - } +pub fn analyze_expr( + context: &mir::Context, + source_module: &mir::Module, + expr: &mir::Expression, + map: &mut TokenAnalysisMap, +) { + set_tokens( + map, + &expr.1, + SemanticAnalysis { + ty: expr + .return_type(&Default::default(), source_module.module_id) + .ok() + .map(|(_, t)| t), + }, + ); match &expr.0 { - mir::ExprKind::Variable(named_variable_ref) => Some(named_variable_ref.0.clone()), - mir::ExprKind::Indexed(value, type_kind, index_expr) => Some( - find_type_in_expr(&value, module_id, token_idx) - .or(find_type_in_expr(&index_expr, module_id, token_idx)) - .unwrap_or(type_kind.clone()), - ), - mir::ExprKind::Accessed(expression, type_kind, _, meta) => { - if meta.contains(token_idx) { - Some(type_kind.clone()) - } else { - find_type_in_expr(&expression, module_id, token_idx) - } + mir::ExprKind::Variable(_) => {} + mir::ExprKind::Indexed(value, _, index_expr) => { + analyze_expr(context, source_module, &value, map); + analyze_expr(context, source_module, &index_expr, map); + } + mir::ExprKind::Accessed(expression, ..) => { + analyze_expr(context, source_module, &expression, map); } mir::ExprKind::Array(expressions) => { for expr in expressions { - if let Some(ty) = find_type_in_expr(expr, module_id, token_idx) { - return Some(ty); - } + analyze_expr(context, source_module, expr, map); } - None } - mir::ExprKind::Struct(name, items) => { - for (_, expr, meta) in items { - if meta.contains(token_idx) { - return expr.return_type(&Default::default(), module_id).map(|(_, t)| t).ok(); - } - if let Some(ty) = find_type_in_expr(expr, module_id, token_idx) { - return Some(ty); - } + mir::ExprKind::Struct(_, items) => { + for (_, expr, _) in items { + analyze_expr(context, source_module, expr, map); } - Some(TypeKind::CustomType(mir::CustomTypeKey(name.clone(), module_id))) } - mir::ExprKind::Literal(literal) => Some(literal.as_type()), - mir::ExprKind::BinOp(_, lhs, rhs, type_kind) => { - if let Some(ty) = find_type_in_expr(lhs, module_id, token_idx) { - return Some(ty); - } - if let Some(ty) = find_type_in_expr(rhs, module_id, token_idx) { - return Some(ty); - } - Some(type_kind.clone()) + mir::ExprKind::Literal(_) => {} + mir::ExprKind::BinOp(_, lhs, rhs, _) => { + analyze_expr(context, source_module, &lhs, map); + analyze_expr(context, source_module, &rhs, map); } - mir::ExprKind::FunctionCall(FunctionCall { - return_type, - parameters, - .. - }) => { + mir::ExprKind::FunctionCall(FunctionCall { parameters, .. }) => { for expr in parameters { - if let Some(ty) = find_type_in_expr(expr, module_id, token_idx) { - return Some(ty); - } + analyze_expr(context, source_module, expr, map); } - Some(return_type.clone()) } - mir::ExprKind::AssociatedFunctionCall( - _, - FunctionCall { - return_type, - parameters, - .. - }, - ) => { + mir::ExprKind::AssociatedFunctionCall(_, FunctionCall { parameters, .. }) => { for expr in parameters { - if let Some(ty) = find_type_in_expr(expr, module_id, token_idx) { - return Some(ty); - } + analyze_expr(context, source_module, expr, map); } - Some(return_type.clone()) } - mir::ExprKind::If(IfExpression(cond, then_e, else_e)) => find_type_in_expr(&cond, module_id, token_idx) - .or(find_type_in_expr(&then_e, module_id, token_idx)) - .or(else_e.clone().and_then(|e| find_type_in_expr(&e, module_id, token_idx))), - mir::ExprKind::Block(block) => find_type_in_block(block, module_id, token_idx), - mir::ExprKind::Borrow(expression, mutable) => { - if let Some(ty) = find_type_in_expr(&expression, module_id, token_idx) { - return Some(ty); - } - if let Ok(inner) = expression.return_type(&Default::default(), module_id).map(|(_, ty)| ty) { - Some(TypeKind::Borrow(Box::new(inner.clone()), *mutable)) - } else { - None + mir::ExprKind::If(IfExpression(cond, then_e, else_e)) => { + analyze_expr(context, source_module, &cond, map); + analyze_expr(context, source_module, &then_e, map); + if let Some(else_e) = else_e.as_ref() { + analyze_expr(context, source_module, &else_e, map); } } + mir::ExprKind::Block(block) => analyze_block(context, source_module, block, map), + mir::ExprKind::Borrow(expression, _) => { + analyze_expr(context, source_module, &expression, map); + } mir::ExprKind::Deref(expression) => { - if let Some(ty) = find_type_in_expr(&expression, module_id, token_idx) { - return Some(ty); - } - if let Ok(TypeKind::Borrow(inner, _)) = - expression.return_type(&Default::default(), module_id).map(|(_, ty)| ty) - { - Some(*inner.clone()) - } else { - Some(TypeKind::CustomType(mir::CustomTypeKey( - "รค".to_owned(), - SourceModuleId(1), - ))) - } + analyze_expr(context, source_module, &expression, map); } - mir::ExprKind::CastTo(expression, type_kind) => { - Some(find_type_in_expr(&expression, module_id, token_idx).unwrap_or(type_kind.clone())) + mir::ExprKind::CastTo(expression, _) => { + analyze_expr(context, source_module, &expression, map); } - mir::ExprKind::GlobalRef(_, type_kind) => Some(type_kind.clone()), + mir::ExprKind::GlobalRef(_, _) => {} } } diff --git a/reid-lsp/src/main.rs b/reid-lsp/src/main.rs index 7312f2c..6603e54 100644 --- a/reid-lsp/src/main.rs +++ b/reid-lsp/src/main.rs @@ -22,7 +22,6 @@ mod analysis; struct Backend { client: Client, analysis: DashMap, - ast: DashMap, } #[tower_lsp::async_trait] @@ -91,7 +90,7 @@ impl LanguageServer for Backend { }; let (range, ty) = if let Some((idx, token)) = token { - if let Some(possible_ty) = self.analysis.get(&file_name).unwrap().token_analysis.get(&idx) { + if let Some(analysis) = self.analysis.get(&file_name).unwrap().token_analysis.get(&idx) { let start = token.position; let end = token.position.add(token.token.len() as u32); let range = Range { @@ -104,7 +103,7 @@ impl LanguageServer for Backend { character: (end.0 as i32 - 1).max(0) as u32, }, }; - if let Some(ty) = possible_ty.ty.clone() { + if let Some(ty) = analysis.ty.clone() { (Some(range), format!("{}", ty)) } else { (Some(range), String::from("None type")) @@ -220,11 +219,6 @@ fn reid_error_into_diagnostic(error: &error_raporting::ErrorKind, tokens: &Vec, - types: DashMap>, -} - fn parse(source: &str, path: PathBuf, map: &mut ErrorModules) -> Result<(SourceModuleId, Vec), ReidError> { let file_name = path.file_name().unwrap().to_str().unwrap().to_owned(); @@ -238,7 +232,6 @@ async fn main() { let (service, socket) = LspService::new(|client| Backend { client, - ast: DashMap::new(), analysis: DashMap::new(), }); Server::new(stdin, stdout, socket).serve(service).await;