Add StateMap
This commit is contained in:
parent
5706fd99e3
commit
d27ec2bb70
@ -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() {
|
||||||
|
@ -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(¶ms.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(¶ms.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;
|
||||||
|
Loading…
Reference in New Issue
Block a user