Add StateMap

This commit is contained in:
Sofia 2025-08-03 22:44:00 +03:00
parent 5706fd99e3
commit d27ec2bb70
2 changed files with 43 additions and 27 deletions

View File

@ -127,6 +127,8 @@ pub struct AnalysisState {
types: HashMap<TypeKind, SymbolId>, types: HashMap<TypeKind, SymbolId>,
} }
pub type StateMap = HashMap<SourceModuleId, AnalysisState>;
impl AnalysisState { impl AnalysisState {
pub fn get_symbol(&self, id: SymbolId) -> &Symbol { pub fn get_symbol(&self, id: SymbolId) -> &Symbol {
self.symbol_table.get(id.0).unwrap() self.symbol_table.get(id.0).unwrap()
@ -208,12 +210,14 @@ pub struct AnalysisScope<'a> {
state: &'a mut AnalysisState, state: &'a mut AnalysisState,
tokens: &'a Vec<FullToken>, tokens: &'a Vec<FullToken>,
variables: HashMap<String, SymbolId>, variables: HashMap<String, SymbolId>,
map: &'a StateMap,
} }
impl<'a> AnalysisScope<'a> { impl<'a> AnalysisScope<'a> {
pub fn inner(&mut self) -> AnalysisScope { pub fn inner(&mut self) -> AnalysisScope {
AnalysisScope { AnalysisScope {
state: self.state, state: self.state,
map: self.map,
tokens: self.tokens, tokens: self.tokens,
variables: self.variables.clone(), variables: self.variables.clone(),
} }
@ -308,6 +312,7 @@ pub fn analyze(
tokens: Vec<FullToken>, tokens: Vec<FullToken>,
path: PathBuf, path: PathBuf,
map: &mut ErrorModules, map: &mut ErrorModules,
state_map: &StateMap,
) -> Result<Option<StaticAnalysis>, ReidError> { ) -> Result<Option<StaticAnalysis>, ReidError> {
let (module, mut parse_error) = match compile_module(module_id, tokens, map, Some(path.clone()), true)? { let (module, mut parse_error) = match compile_module(module_id, tokens, map, Some(path.clone()), true)? {
Ok(module) => (module, None), Ok(module) => (module, None),
@ -331,12 +336,17 @@ pub fn analyze(
if module.module_id != module_id { if module.module_id != module_id {
continue; continue;
} }
return Ok(Some(analyze_context(&context, &module, parse_error))); return Ok(Some(analyze_context(&context, &module, parse_error, state_map)));
} }
return Ok(None); return Ok(None);
} }
pub fn analyze_context(context: &mir::Context, module: &mir::Module, error: Option<ReidError>) -> StaticAnalysis { pub fn analyze_context(
context: &mir::Context,
module: &mir::Module,
error: Option<ReidError>,
map: &StateMap,
) -> StaticAnalysis {
let mut state = AnalysisState { let mut state = AnalysisState {
map: HashMap::new(), map: HashMap::new(),
symbol_table: Vec::new(), symbol_table: Vec::new(),
@ -351,6 +361,7 @@ pub fn analyze_context(context: &mir::Context, module: &mir::Module, error: Opti
state: &mut state, state: &mut state,
tokens: &module.tokens, tokens: &module.tokens,
variables: HashMap::new(), variables: HashMap::new(),
map,
}; };
for (i, token) in module.tokens.iter().enumerate() { for (i, token) in module.tokens.iter().enumerate() {

View File

@ -26,9 +26,9 @@ mod analysis;
#[derive(Debug)] #[derive(Debug)]
struct Backend { struct Backend {
client: Client, client: Client,
analysis: DashMap<String, StaticAnalysis>, analysis: DashMap<PathBuf, StaticAnalysis>,
module_to_url: DashMap<SourceModuleId, PathBuf>, module_to_url: DashMap<SourceModuleId, PathBuf>,
url_to_module: DashMap<PathBuf, SourceModuleId>, path_to_module: DashMap<PathBuf, SourceModuleId>,
module_id_counter: Mutex<SourceModuleId>, module_id_counter: Mutex<SourceModuleId>,
} }
@ -102,8 +102,7 @@ impl LanguageServer for Backend {
async fn completion(&self, params: CompletionParams) -> jsonrpc::Result<Option<CompletionResponse>> { async fn completion(&self, params: CompletionParams) -> jsonrpc::Result<Option<CompletionResponse>> {
let path = PathBuf::from(params.text_document_position.text_document.uri.path()); let path = PathBuf::from(params.text_document_position.text_document.uri.path());
let file_name = path.file_name().unwrap().to_str().unwrap().to_owned(); let analysis = self.analysis.get(&path);
let analysis = self.analysis.get(&file_name);
let position = params.text_document_position.position; let position = params.text_document_position.position;
let token = if let Some(analysis) = &analysis { let token = if let Some(analysis) = &analysis {
@ -119,7 +118,7 @@ impl LanguageServer for Backend {
// dbg!(position, token); // dbg!(position, token);
let list = if let Some((idx, _)) = token { let list = if let Some((idx, _)) = token {
if let Some(analysis) = self.analysis.get(&file_name).unwrap().state.map.get(&idx) { if let Some(analysis) = self.analysis.get(&path).unwrap().state.map.get(&idx) {
analysis analysis
.autocomplete .autocomplete
.iter() .iter()
@ -138,8 +137,7 @@ impl LanguageServer for Backend {
async fn hover(&self, params: HoverParams) -> jsonrpc::Result<Option<Hover>> { async fn hover(&self, params: HoverParams) -> jsonrpc::Result<Option<Hover>> {
let path = PathBuf::from(params.text_document_position_params.text_document.uri.path()); let path = PathBuf::from(params.text_document_position_params.text_document.uri.path());
let file_name = path.file_name().unwrap().to_str().unwrap().to_owned(); let analysis = self.analysis.get(&path);
let analysis = self.analysis.get(&file_name);
let position = params.text_document_position_params.position; let position = params.text_document_position_params.position;
let token = if let Some(analysis) = &analysis { let token = if let Some(analysis) = &analysis {
@ -153,7 +151,7 @@ impl LanguageServer for Backend {
}; };
let (range, ty) = if let Some((idx, token)) = token { let (range, ty) = if let Some((idx, token)) = token {
if let Some(analysis) = self.analysis.get(&file_name).unwrap().state.map.get(&idx) { if let Some(analysis) = self.analysis.get(&path).unwrap().state.map.get(&idx) {
let start = token.position; let start = token.position;
let end = token.position.add(token.token.len() as u32); let end = token.position.add(token.token.len() as u32);
let range = Range { let range = Range {
@ -211,8 +209,7 @@ impl LanguageServer for Backend {
params: SemanticTokensParams, params: SemanticTokensParams,
) -> jsonrpc::Result<Option<SemanticTokensResult>> { ) -> jsonrpc::Result<Option<SemanticTokensResult>> {
let path = PathBuf::from(params.text_document.uri.path()); let path = PathBuf::from(params.text_document.uri.path());
let file_name = path.file_name().unwrap().to_str().unwrap().to_owned(); let analysis = self.analysis.get(&path);
let analysis = self.analysis.get(&file_name);
let mut semantic_tokens = Vec::new(); let mut semantic_tokens = Vec::new();
if let Some(analysis) = analysis { if let Some(analysis) = analysis {
@ -257,8 +254,7 @@ impl LanguageServer for Backend {
async fn goto_definition(&self, params: GotoDefinitionParams) -> jsonrpc::Result<Option<GotoDefinitionResponse>> { async fn goto_definition(&self, params: GotoDefinitionParams) -> jsonrpc::Result<Option<GotoDefinitionResponse>> {
let path = PathBuf::from(params.text_document_position_params.text_document.uri.path()); let path = PathBuf::from(params.text_document_position_params.text_document.uri.path());
let file_name = path.file_name().unwrap().to_str().unwrap().to_owned(); let analysis = self.analysis.get(&path);
let analysis = self.analysis.get(&file_name);
let position = params.text_document_position_params.position; let position = params.text_document_position_params.position;
if let Some(analysis) = &analysis { if let Some(analysis) = &analysis {
@ -283,8 +279,7 @@ impl LanguageServer for Backend {
async fn references(&self, params: ReferenceParams) -> jsonrpc::Result<Option<Vec<Location>>> { async fn references(&self, params: ReferenceParams) -> jsonrpc::Result<Option<Vec<Location>>> {
let path = PathBuf::from(params.text_document_position.text_document.uri.path()); let path = PathBuf::from(params.text_document_position.text_document.uri.path());
let file_name = path.file_name().unwrap().to_str().unwrap().to_owned(); let analysis = self.analysis.get(&path);
let analysis = self.analysis.get(&file_name);
let position = params.text_document_position.position; let position = params.text_document_position.position;
if let Some(analysis) = &analysis { if let Some(analysis) = &analysis {
@ -322,7 +317,7 @@ impl LanguageServer for Backend {
async fn rename(&self, params: RenameParams) -> jsonrpc::Result<Option<WorkspaceEdit>> { async fn rename(&self, params: RenameParams) -> jsonrpc::Result<Option<WorkspaceEdit>> {
let path = PathBuf::from(params.text_document_position.text_document.uri.path()); let path = PathBuf::from(params.text_document_position.text_document.uri.path());
let file_name = path.file_name().unwrap().to_str().unwrap().to_owned(); let file_name = path.file_name().unwrap().to_str().unwrap().to_owned();
let analysis = self.analysis.get(&file_name); let analysis = self.analysis.get(&path);
let position = params.text_document_position.position; let position = params.text_document_position.position;
if let Some(analysis) = &analysis { if let Some(analysis) = &analysis {
@ -379,11 +374,10 @@ fn token_to_range(token: &FullToken) -> lsp_types::Range {
impl Backend { impl Backend {
async fn recompile(&self, params: TextDocumentItem) { async fn recompile(&self, params: TextDocumentItem) {
let path = PathBuf::from(params.uri.clone().path()); let file_path = PathBuf::from(params.uri.clone().path());
let file_name = path.file_name().unwrap().to_str().unwrap().to_owned();
let mut map: ErrorModules = Default::default(); let mut map: ErrorModules = Default::default();
for url_module in self.url_to_module.iter() { for url_module in self.path_to_module.iter() {
let (url, module) = url_module.pair(); let (url, module) = url_module.pair();
map.add_module( map.add_module(
url.file_name().unwrap().to_str().unwrap().to_owned(), url.file_name().unwrap().to_str().unwrap().to_owned(),
@ -392,20 +386,31 @@ impl Backend {
); );
} }
let module_id = if let Some(module_id) = self.url_to_module.get(&path) { let module_id = if let Some(module_id) = self.path_to_module.get(&file_path) {
*module_id *module_id
} else { } else {
let mut lock = self.module_id_counter.lock().await; let mut lock = self.module_id_counter.lock().await;
let module_id = lock.increment(); let module_id = lock.increment();
drop(lock); drop(lock);
self.url_to_module.insert(path.clone(), module_id); self.path_to_module.insert(file_path.clone(), module_id);
self.module_to_url.insert(module_id, path.clone()); self.module_to_url.insert(module_id, file_path.clone());
module_id module_id
}; };
let parse_res = parse(&params.text, path.clone(), &mut map, module_id); let mut state_map = HashMap::new();
for path_state in self.analysis.iter() {
let (path, state) = path_state.pair();
if let Some(module_id) = self.path_to_module.get(path) {
state_map.insert(*module_id, state.state.clone());
}
}
let parse_res = parse(&params.text, file_path.clone(), &mut map, module_id);
let (tokens, result) = match parse_res { let (tokens, result) = match parse_res {
Ok((module_id, tokens)) => (tokens.clone(), analyze(module_id, tokens, path, &mut map)), Ok((module_id, tokens)) => (
tokens.clone(),
analyze(module_id, tokens, file_path.clone(), &mut map, &state_map),
),
Err(e) => (Vec::new(), Err(e)), Err(e) => (Vec::new(), Err(e)),
}; };
@ -425,7 +430,7 @@ impl Backend {
self.client.log_message(MessageType::INFO, format!("{}", error)).await; self.client.log_message(MessageType::INFO, format!("{}", error)).await;
} }
} }
self.analysis.insert(file_name.clone(), analysis); self.analysis.insert(file_path, analysis);
} }
Ok(_) => {} Ok(_) => {}
Err(mut reid_error) => { Err(mut reid_error) => {
@ -498,7 +503,7 @@ async fn main() {
client, client,
analysis: DashMap::new(), analysis: DashMap::new(),
module_to_url: DashMap::new(), module_to_url: DashMap::new(),
url_to_module: DashMap::new(), path_to_module: DashMap::new(),
module_id_counter: Mutex::new(SourceModuleId(0)), module_id_counter: Mutex::new(SourceModuleId(0)),
}); });
Server::new(stdin, stdout, socket).serve(service).await; Server::new(stdin, stdout, socket).serve(service).await;