From 509d59e4c1b5b9c76d3576f2c5c111e81e404a21 Mon Sep 17 00:00:00 2001 From: hapeeeeee <623151737@qq.com> Date: Tue, 23 Jan 2024 13:43:11 +0800 Subject: [PATCH] cargo format project --- .../move-analyzer/src/analyzer_handler.rs | 3 +- .../src/bin/aptos-move-analyzer.rs | 73 ++-- language/move-analyzer/src/completion.rs | 120 ++--- language/move-analyzer/src/goto_definition.rs | 333 +++++++------- language/move-analyzer/src/hover.rs | 184 ++++---- language/move-analyzer/src/inlay_hints.rs | 411 ++++++++++-------- language/move-analyzer/src/item.rs | 20 +- language/move-analyzer/src/lib.rs | 15 +- .../move-analyzer/src/move_generate_spec.rs | 195 +++++---- .../src/move_generate_spec_file.rs | 132 +++--- .../src/move_generate_spec_sel.rs | 178 ++++---- .../src/move_generate_spec_utils.rs | 390 +++++++++-------- language/move-analyzer/src/multiproject.rs | 4 +- language/move-analyzer/src/project.rs | 24 +- language/move-analyzer/src/project_manager.rs | 56 ++- language/move-analyzer/src/references.rs | 152 ++++--- language/move-analyzer/src/symbols.rs | 146 ++++--- .../src/type_display_for_spec.rs | 29 +- language/move-analyzer/src/utils.rs | 90 ++-- .../tests/test_document_symbols.rs | 24 +- language/move-analyzer/tests/test_goto_def.rs | 37 +- language/move-analyzer/tests/test_hover.rs | 11 +- .../move-analyzer/tests/test_references.rs | 28 +- .../move-analyzer/tests/test_spec_file.rs | 17 +- language/move-analyzer/tests/test_spec_sel.rs | 134 +++--- 25 files changed, 1502 insertions(+), 1304 deletions(-) diff --git a/language/move-analyzer/src/analyzer_handler.rs b/language/move-analyzer/src/analyzer_handler.rs index d8fe01550a..e5b9095ca6 100644 --- a/language/move-analyzer/src/analyzer_handler.rs +++ b/language/move-analyzer/src/analyzer_handler.rs @@ -85,7 +85,7 @@ pub trait ItemOrAccessHandler: std::fmt::Display { _services: &dyn HandleItemService, _: &GlobalEnv, _: &Path, - _: String + _: String, ) { } } @@ -94,6 +94,7 @@ impl ItemOrAccessHandler for DummyHandler { fn finished(&self) -> bool { false } + fn visit_fun_or_spec_body(&self) -> bool { false } diff --git a/language/move-analyzer/src/bin/aptos-move-analyzer.rs b/language/move-analyzer/src/bin/aptos-move-analyzer.rs index 767559ba20..c73e16f07e 100644 --- a/language/move-analyzer/src/bin/aptos-move-analyzer.rs +++ b/language/move-analyzer/src/bin/aptos-move-analyzer.rs @@ -2,6 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 use anyhow::Result; +use aptos_move_analyzer::{ + analyzer_handler::ConvertLoc, + completion, + context::{Context, FileDiags}, + goto_definition, hover, inlay_hints, + inlay_hints::*, + move_generate_spec_file::on_generate_spec_file, + move_generate_spec_sel::on_generate_spec_sel, + multiproject::MultiProject, + references, symbols, + utils::*, +}; use clap::Parser; use crossbeam::channel::{bounded, select, Sender}; use log::{Level, Metadata, Record}; @@ -18,22 +30,6 @@ use std::{ path::{Path, PathBuf}, sync::{Arc, Mutex}, }; - -use aptos_move_analyzer::{ - analyzer_handler::ConvertLoc, - context::{Context, FileDiags}, - multiproject::MultiProject, - goto_definition, - references, - hover, - completion, - inlay_hints, - inlay_hints::*, - utils::*, - symbols, - move_generate_spec_file::on_generate_spec_file, - move_generate_spec_sel::on_generate_spec_sel, -}; use url::Url; struct SimpleLogger; @@ -41,11 +37,13 @@ impl log::Log for SimpleLogger { fn enabled(&self, metadata: &Metadata) -> bool { metadata.level() <= Level::Info } + fn log(&self, record: &Record) { if self.enabled(record.metadata()) { eprintln!("{} - {}", record.level(), record.args()); } } + fn flush(&self) {} } const LOGGER: SimpleLogger = SimpleLogger; @@ -189,31 +187,31 @@ fn on_request(context: &mut Context, request: &Request, inlay_hints_config: &mut }, lsp_types::request::References::METHOD => { references::on_references_request(context, request); - } + }, lsp_types::request::HoverRequest::METHOD => { hover::on_hover_request(context, request); - } + }, lsp_types::request::Completion::METHOD => { completion::on_completion_request(context, request); - } + }, lsp_types::request::InlayHintRequest::METHOD => { inlay_hints::on_inlay_hints(context, request, inlay_hints_config); - } + }, lsp_types::request::DocumentSymbolRequest::METHOD => { symbols::on_document_symbol_request(context, request); - } + }, "move/generate/spec/file" => { on_generate_spec_file(context, request, true); - } + }, "move/generate/spec/sel" => { on_generate_spec_sel(context, request); - } + }, "move/lsp/client/inlay_hints/config" => { let parameters = serde_json::from_value::(request.params.clone()) .expect("could not deserialize inlay hints request"); log::info!("call inlay_hints config {:?}", parameters); *inlay_hints_config = parameters; - } + }, _ => { log::error!("unsupported request: '{}' from client", request.method) }, @@ -239,14 +237,14 @@ fn report_diag(context: &mut Context, fpath: PathBuf) { let mut result: HashMap> = HashMap::new(); let diag_err = proj.err_diags.clone(); let tokens: Vec<&str> = diag_err.as_str().split("error").collect(); - for token in tokens { + for token in tokens { if token.lines().count() < 3 { - continue; + continue; } let err_msg = token.lines().next().unwrap_or_default(); let loc_str = match token.lines().nth(1) { Some(str) => str.to_string(), - None => "".to_string() + None => "".to_string(), }; let mut file_path = ""; @@ -286,12 +284,7 @@ fn report_diag(context: &mut Context, fpath: PathBuf) { end: pos, }, severity: Some(lsp_types::DiagnosticSeverity::ERROR), - message: format!( - "{}\n{}{:?}", - err_msg, - code_str, - "".to_string() - ), + message: format!("{}\n{}{:?}", err_msg, code_str, "".to_string()), ..Default::default() }; let url = url::Url::from_file_path(PathBuf::from(file_path).as_path()).unwrap(); @@ -421,9 +414,7 @@ fn on_notification(context: &mut Context, notification: &Notification, diag_send } } -fn get_package_compile_diagnostics( - pkg_path: &Path, -) -> Result { +fn get_package_compile_diagnostics(pkg_path: &Path) -> Result { use anyhow::*; use move_package::compilation::build_plan::BuildPlan; use tempfile::tempdir; @@ -439,8 +430,10 @@ fn get_package_compile_diagnostics( let build_plan = BuildPlan::create(resolution_graph)?; let mut diagnostics = None; let compile_cfg: move_package::CompilerConfig = Default::default(); - build_plan.compile_with_driver(&mut std::io::sink(), &compile_cfg, - |compiler| { + build_plan.compile_with_driver( + &mut std::io::sink(), + &compile_cfg, + |compiler| { let (_, compilation_result) = compiler.run::()?; match compilation_result { std::result::Result::Ok(_) => {}, @@ -451,9 +444,7 @@ fn get_package_compile_diagnostics( }; Ok(Default::default()) }, - |_compiler| { - Ok(Default::default()) - } + |_compiler| Ok(Default::default()), )?; match diagnostics { Some(x) => Ok(x), diff --git a/language/move-analyzer/src/completion.rs b/language/move-analyzer/src/completion.rs index dfaba81aa2..184078cc86 100644 --- a/language/move-analyzer/src/completion.rs +++ b/language/move-analyzer/src/completion.rs @@ -1,19 +1,15 @@ // Copyright (c) The BitsLab.MoveBit Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::{ - context::*, - utils::path_concat, -}; -use lsp_server::*; -use move_model::model::GlobalEnv; -use std::vec; -use lsp_server::Request; +use crate::{context::*, utils::path_concat}; +use lsp_server::{Request, *}; use lsp_types::{CompletionItem, CompletionItemKind, CompletionParams, Position}; use move_command_line_common::files::FileHash; use move_compiler::parser::{ keywords::{BUILTINS, CONTEXTUAL_KEYWORDS, KEYWORDS, PRIMITIVE_TYPES}, lexer::{Lexer, Tok}, }; +use move_model::model::GlobalEnv; +use std::vec; /// Constructs an `lsp_types::CompletionItem` with the given `label` and `kind`. fn completion_item(label: &str, kind: CompletionItemKind) -> CompletionItem { @@ -85,8 +81,8 @@ fn get_cursor_token(buffer: &str, position: &Position) -> Option { } else { Some(Tok::Colon) } - } - _ => None, + }, + _ => None, } } @@ -122,7 +118,7 @@ fn lexer_for_buffer(buffer: &str, is_dedup: bool) -> Vec<&str> { if lexer.advance().is_err() { return ids; } - + while lexer.peek() != Tok::EOF { // Some tokens, such as "phantom", are contextual keywords that are only reserved in // certain contexts. Since for now this language server doesn't analyze semantic context, @@ -130,8 +126,10 @@ fn lexer_for_buffer(buffer: &str, is_dedup: bool) -> Vec<&str> { // these keywords to the user twice in the case that the token "phantom" is present in the // source program (once as a keyword, and once as an identifier), we filter out any // identifier token that has the same text as a keyword. - if (lexer.peek() == Tok::Identifier && !KEYWORDS.contains(&lexer.content())) - || lexer.peek() == Tok::ColonColon || lexer.peek() == Tok::Period { + if (lexer.peek() == Tok::Identifier && !KEYWORDS.contains(&lexer.content())) + || lexer.peek() == Tok::ColonColon + || lexer.peek() == Tok::Period + { // The completion item kind "text" indicates the item is not based on any semantic // context of the request cursor's position. if !(is_dedup && ids.contains(&lexer.content())) { @@ -145,57 +143,73 @@ fn lexer_for_buffer(buffer: &str, is_dedup: bool) -> Vec<&str> { ids } -fn handle_identifiers_for_coloncolon(string_tokens: &Vec<&str>, env: &GlobalEnv) -> Vec { +fn handle_identifiers_for_coloncolon( + string_tokens: &Vec<&str>, + env: &GlobalEnv, +) -> Vec { let mut result = vec![]; if string_tokens.len() <= 1 { return result; } - let prefix_token_string = string_tokens.get(string_tokens.len() - 2).unwrap().to_string(); + let prefix_token_string = string_tokens + .get(string_tokens.len() - 2) + .unwrap() + .to_string(); for module_env in env.get_modules() { if prefix_token_string == module_env.get_name().display(env).to_string() { for func_env in module_env.get_functions() { - result.push(completion_item(func_env.get_name_str().as_str(), CompletionItemKind::FUNCTION)); + result.push(completion_item( + func_env.get_name_str().as_str(), + CompletionItemKind::FUNCTION, + )); } for struct_env in module_env.get_structs() { - result.push(completion_item(&struct_env.get_name().display(env.symbol_pool()).to_string(), CompletionItemKind::STRUCT)); + result.push(completion_item( + &struct_env.get_name().display(env.symbol_pool()).to_string(), + CompletionItemKind::STRUCT, + )); } } } result } -fn handle_identifiers_for_coloncolon_item(string_tokens: &Vec<&str>, env: &GlobalEnv) -> Vec { +fn handle_identifiers_for_coloncolon_item( + string_tokens: &Vec<&str>, + env: &GlobalEnv, +) -> Vec { let mut result = vec![]; if string_tokens.len() <= 2 { return result; } - let prefix_token_string = string_tokens.get(string_tokens.len() - 3).unwrap().to_string(); + let prefix_token_string = string_tokens + .get(string_tokens.len() - 3) + .unwrap() + .to_string(); let wanted_token_string = string_tokens.last().unwrap(); for module_env in env.get_modules() { if prefix_token_string == module_env.get_name().display(env).to_string() { for func_env in module_env.get_functions() { if func_env.get_name_str().contains(wanted_token_string) { - result.push( - completion_item( + result.push(completion_item( func_env.get_name_str().as_str(), - CompletionItemKind::FUNCTION) - ); + CompletionItemKind::FUNCTION, + )); } } - + for struct_env in module_env.get_structs() { if struct_env .get_name() .display(env.symbol_pool()) .to_string() - .contains(wanted_token_string) + .contains(wanted_token_string) { - result.push( - completion_item( + result.push(completion_item( &struct_env.get_name().display(env.symbol_pool()).to_string(), - CompletionItemKind::STRUCT) - ); + CompletionItemKind::STRUCT, + )); } } } @@ -203,8 +217,10 @@ fn handle_identifiers_for_coloncolon_item(string_tokens: &Vec<&str>, env: &Globa result } - -fn handle_file_identifiers(cursor_tokens: &str, file_tokens_string: &mut Vec<&str>) -> Vec { +fn handle_file_identifiers( + cursor_tokens: &str, + file_tokens_string: &mut Vec<&str>, +) -> Vec { let mut result = vec![]; file_tokens_string.dedup(); for &token_str in file_tokens_string.iter() { @@ -239,20 +255,22 @@ pub fn on_completion_request(context: &Context, request: &Request) -> lsp_server }; }, }; - + let file_buffer_str = current_project.current_modifing_file_content.as_str(); let buffer = Some(file_buffer_str); // The completion items we provide depend upon where the user's cursor is positioned. let cursor = buffer.and_then(|buf| get_cursor_token(buf, ¶meters.text_document_position.position)); - let cursor_line = + let cursor_line = buffer.and_then(|buf| get_cursor_line(buf, ¶meters.text_document_position.position)); if cursor_line.is_none() { log::error!("could not found code string from cursor line"); return Response { id: "".to_string().into(), - result: Some(serde_json::json!({"msg": "Could not found code string from cursor line"})), + result: Some( + serde_json::json!({"msg": "Could not found code string from cursor line"}), + ), error: None, }; } @@ -265,7 +283,9 @@ pub fn on_completion_request(context: &Context, request: &Request) -> lsp_server log::error!("could not found code string from cursor line"); return Response { id: "".to_string().into(), - result: Some(serde_json::json!({"msg": "Could not found code string from cursor line"})), + result: Some( + serde_json::json!({"msg": "Could not found code string from cursor line"}), + ), error: None, }; } @@ -274,11 +294,11 @@ pub fn on_completion_request(context: &Context, request: &Request) -> lsp_server match cursor { Some(Tok::Colon) => { items.extend_from_slice(&primitive_types()); - } + }, Some(Tok::ColonColon) => { // `.` or `::` must be followed by identifiers, which are added to the completion items. - let module_items - = handle_identifiers_for_coloncolon(&cursor_line_tokens, ¤t_project.global_env); + let module_items = + handle_identifiers_for_coloncolon(&cursor_line_tokens, ¤t_project.global_env); items.extend_from_slice(&module_items); }, Some(Tok::Period) => { @@ -293,26 +313,25 @@ pub fn on_completion_request(context: &Context, request: &Request) -> lsp_server let &cursor_token_str = cursor_line_tokens.last().unwrap(); let mut may_coloncolon = ""; if cursor_line_tokens.len() > 1 { - may_coloncolon = cursor_line_tokens.get(cursor_line_tokens.len() - 2).unwrap(); + may_coloncolon = cursor_line_tokens + .get(cursor_line_tokens.len() - 2) + .unwrap(); } if may_coloncolon == "::" { - let module_items - = handle_identifiers_for_coloncolon_item(&cursor_line_tokens, ¤t_project.global_env); + let module_items = handle_identifiers_for_coloncolon_item( + &cursor_line_tokens, + ¤t_project.global_env, + ); items.extend_from_slice(&module_items); } else { let mut token_str_in_file = lexer_for_buffer(file_buffer_str, true); - let file_items - = handle_file_identifiers(cursor_token_str, &mut token_str_in_file); + let file_items = handle_file_identifiers(cursor_token_str, &mut token_str_in_file); items.extend_from_slice(&file_items); } - } + }, } - - - - // if let Some(cursor_line_buffer) = &cursor_line { // let identifiers = identifiers(cursor_line_buffer.as_str(), ¤t_project.global_env, &fpath); // // log::info!("identifiers = {:?}", identifiers); @@ -322,7 +341,10 @@ pub fn on_completion_request(context: &Context, request: &Request) -> lsp_server let result = serde_json::to_value(items).expect("could not serialize completion response"); let response = lsp_server::Response::new_ok(request.id.clone(), result); let ret_response = response.clone(); - log::trace!("------------------------------------\nret_response = {:?}\n\n", ret_response); + log::trace!( + "------------------------------------\nret_response = {:?}\n\n", + ret_response + ); if let Err(err) = context .connection .sender diff --git a/language/move-analyzer/src/goto_definition.rs b/language/move-analyzer/src/goto_definition.rs index 815a29e63d..c086f551f3 100644 --- a/language/move-analyzer/src/goto_definition.rs +++ b/language/move-analyzer/src/goto_definition.rs @@ -6,16 +6,18 @@ use crate::{ context::*, utils::{path_concat, FileRange}, }; -use std::{collections::HashMap, ops::Deref}; use lsp_server::*; use lsp_types::*; - use move_model::{ - ast::{ExpData::*, Operation::*, Spec, SpecBlockTarget, Pattern as MoveModelPattern}, - model::{FunId, GlobalEnv ,ModuleId, StructId, NodeId, ModuleEnv}, + ast::{ExpData::*, Operation::*, Pattern as MoveModelPattern, Spec, SpecBlockTarget}, + model::{FunId, GlobalEnv, ModuleEnv, ModuleId, NodeId, StructId}, symbol::Symbol, }; -use std::path::{Path, PathBuf}; +use std::{ + collections::HashMap, + ops::Deref, + path::{Path, PathBuf}, +}; /// Handles go-to-def request of the language server. pub fn on_go_to_def_request(context: &Context, request: &Request) -> lsp_server::Response { @@ -47,7 +49,7 @@ pub fn on_go_to_def_request(context: &Context, request: &Request) -> lsp_server: let mut handler = Handler::new(fpath.clone(), line, col); handler.addrname_2_addrnum = project.addrname_2_addrnum.clone(); project.run_visitor_for_file(&mut handler, &fpath, String::default()); - + handler.remove_not_in_loc(&project.global_env); let locations = handler.convert_to_locations(); @@ -97,28 +99,26 @@ impl Handler { } } - fn check_move_model_loc_contains_mouse_pos(&self, env: &GlobalEnv, loc: &move_model::model::Loc) -> bool { - if let Some(obj_first_col) = env.get_location(& - move_model::model::Loc::new( + fn check_move_model_loc_contains_mouse_pos( + &self, + env: &GlobalEnv, + loc: &move_model::model::Loc, + ) -> bool { + if let Some(obj_first_col) = env.get_location(&move_model::model::Loc::new( + loc.file_id(), + codespan::Span::new( + loc.span().start(), + loc.span().start() + codespan::ByteOffset(1), + ), + )) { + if let Some(obj_last_col) = env.get_location(&move_model::model::Loc::new( loc.file_id(), - codespan::Span::new( - loc.span().start(), - loc.span().start() + codespan::ByteOffset(1), - ) - ) - ) { - if let Some(obj_last_col) = env.get_location(& - move_model::model::Loc::new( - loc.file_id(), - codespan::Span::new( - loc.span().end(), - loc.span().end() + codespan::ByteOffset(1), - ) - ) - ) { - if u32::from(obj_first_col.line) == self.line && - u32::from(obj_first_col.column) < self.col && - self.col < u32::from(obj_last_col.column) { + codespan::Span::new(loc.span().end(), loc.span().end() + codespan::ByteOffset(1)), + )) { + if u32::from(obj_first_col.line) == self.line + && u32::from(obj_first_col.column) < self.col + && self.col < u32::from(obj_last_col.column) + { return true; } } @@ -136,9 +136,13 @@ impl Handler { let mut ret = Vec::with_capacity(2); if let Some(x) = self.result.as_ref() { ret.push(x.mk_location()); - log::info!("goto definition result path = {}, line = {}", x.path.display(), x.line_start); + log::info!( + "goto definition result path = {}, line = {}", + x.path.display(), + x.line_start + ); } - + self.capture_items_span.clear(); self.result_candidates.clear(); ret @@ -174,7 +178,7 @@ impl Handler { mouse_line_first_col.span().end() + codespan::ByteOffset(1), ), ); - + mouse_loc = env.get_location(&mouse_line_last_col).unwrap(); // locate to self.line first column while mouse_loc.column.0 < self.col && mouse_loc.line.0 == self.line { @@ -196,7 +200,10 @@ impl Handler { ), )); log::info!("get mouse_source = {:?}", mouse_source); - self.mouse_span = codespan::Span::new(mouse_line_first_col.span().start(), mouse_line_last_col.span().start()); + self.mouse_span = codespan::Span::new( + mouse_line_first_col.span().start(), + mouse_line_last_col.span().start(), + ); } fn remove_not_in_loc(&mut self, env: &GlobalEnv) { @@ -204,18 +211,17 @@ impl Handler { let mut res_result_candidates = vec![]; let mut indexes_to_retain = vec![]; for index in 0..self.capture_items_span.len() { - if let Some(file_id) = crate::utils::get_file_id_by_fpath_in_all_modules(env, &self.filepath) { + if let Some(file_id) = + crate::utils::get_file_id_by_fpath_in_all_modules(env, &self.filepath) + { let capture_span = self.capture_items_span.get(index).unwrap(); let span_loc = move_model::model::Loc::new( file_id, - codespan::Span::new( - capture_span.start(), - capture_span.end(), - ), + codespan::Span::new(capture_span.start(), capture_span.end()), ); if crate::move_generate_spec_sel::ReqParametersPath::is_linecol_in_loc( - self.line, self.col, &span_loc, env + self.line, self.col, &span_loc, env, ) { indexes_to_retain.push(index) } @@ -246,12 +252,15 @@ impl Handler { let mut found_usedecl_same_line = false; let mut capture_items_loc = move_model::model::Loc::default(); let mut addrnum_with_module_name = Default::default(); - + for use_decl in target_module.get_use_decls() { if !self.check_move_model_loc_contains_mouse_pos(env, &use_decl.loc) { continue; } - log::info!("find use decl module, line: {}", use_decl.loc.span().start()); + log::info!( + "find use decl module, line: {}", + use_decl.loc.span().start() + ); let used_module_name = use_decl.module_name.display_full(env).to_string(); let before_after = used_module_name.split("::").collect::>(); @@ -265,18 +274,17 @@ impl Handler { None => { log::error!("could not convert addrname to addrnum, please check you use decl"); continue; - } + }, }; addrnum_with_module_name = addrnum.clone() + "::" + before_after[1]; found_usedecl_same_line = true; capture_items_loc = use_decl.loc.clone(); - + if !use_decl.members.is_empty() { for (member_loc, name, _alias_name) in use_decl.members.clone().into_iter() { log::trace!("member_loc = {:?} ---", env.get_location(&member_loc)); if self.check_move_model_loc_contains_mouse_pos(env, &member_loc) { - target_stct_or_fn = name.display(spool).to_string(); found_target_stct_or_fn = true; capture_items_loc = member_loc; @@ -293,14 +301,14 @@ impl Handler { if !found_target_stct_or_fn && !found_usedecl_same_line { return; } - + let mut option_use_module: Option> = None; for mo_env in env.get_modules() { let mo_name_str = mo_env.get_name().display_full(env).to_string(); if addrnum_with_module_name.len() != mo_name_str.len() { continue; } - + if mo_name_str.to_lowercase() == addrnum_with_module_name.to_lowercase() { option_use_module = Some(mo_env); break; @@ -315,7 +323,11 @@ impl Handler { if found_target_stct_or_fn { log::info!("finding use decl module member..."); for stct in use_decl_module.get_structs() { - log::trace!("per_struct_name = {:?}, target_struct: {}", stct.get_full_name_str(), target_stct_or_fn); + log::trace!( + "per_struct_name = {:?}, target_struct: {}", + stct.get_full_name_str(), + target_stct_or_fn + ); if stct.get_full_name_str().contains(&target_stct_or_fn) { log::info!("stct.get_full_name_str() = {:?}", stct.get_full_name_str()); let (type_struct_file, type_struct_pos) = @@ -333,7 +345,11 @@ impl Handler { } } for func in use_decl_module.get_functions() { - log::trace!("per_fun_name = {:?}, target_fun: {}", func.get_full_name_str(), target_stct_or_fn); + log::trace!( + "per_fun_name = {:?}, target_fun: {}", + func.get_full_name_str(), + target_stct_or_fn + ); if func.get_name_str().contains(&target_stct_or_fn) { log::info!("func.get_name_str() = {:?}", func.get_name_str()); let (use_fun_file, use_fun_line) = @@ -352,11 +368,12 @@ impl Handler { } } } - + if found_usedecl_same_line { log::info!("find use decl module..."); - let (module_file, module_pos) = - env.get_file_and_location(&use_decl_module.get_loc()).unwrap(); + let (module_file, module_pos) = env + .get_file_and_location(&use_decl_module.get_loc()) + .unwrap(); let result = FileRange { path: PathBuf::from(module_file), line_start: module_pos.line.0, @@ -384,9 +401,13 @@ impl Handler { codespan::Span::new(this_fun_loc.span().end(), this_fun_loc.span().end()), )) .unwrap(); - + if func_start_pos.line.0 <= self.line && self.line < func_end_pos.line.0 { - log::info!("get target function: func_start_pos = {:?}, func_end_pos = {:?}", func_start_pos, func_end_pos); + log::info!( + "get target function: func_start_pos = {:?}, func_end_pos = {:?}", + func_start_pos, + func_end_pos + ); target_fun_id = fun.get_id(); found_target_fun = true; break; @@ -404,8 +425,7 @@ impl Handler { self.process_parameter(); self.process_return_type(); - - if let Some(exp) = target_fun.get_def().deref() { + if let Some(exp) = target_fun.get_def().deref() { self.process_expr(env, exp); }; } @@ -414,6 +434,7 @@ impl Handler { /// As a result, it is unable to compare positions with user-clicked addresses. /// Parameters and return types in function signatures are currently not supported for navigation. fn process_parameter(&mut self) {} + fn process_return_type(&mut self) {} fn process_spec_func(&mut self, env: &GlobalEnv) { @@ -437,12 +458,13 @@ impl Handler { codespan::Span::new( spec_block_info.loc.span().end(), spec_block_info.loc.span().end() + codespan::ByteOffset(1), - ) + ), ); - + if let Some(s_loc) = env.get_location(&span_first_col) { if let Some(e_loc) = env.get_location(&span_last_col) { - if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) { + if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) + { target_fun_id = fun_id; found_target_fun = true; spec_fn_span_loc = spec_block_info.loc.clone(); @@ -460,8 +482,7 @@ impl Handler { let target_fn = target_module.get_function(target_fun_id); let target_fn_spec = target_fn.get_spec(); - log::info!("target_fun's spec = {}", - env.display(&*target_fn_spec)); + log::info!("target_fun's spec = {}", env.display(&*target_fn_spec)); self.get_mouse_loc(env, &spec_fn_span_loc); for cond in target_fn_spec.conditions.clone() { for exp in cond.all_exps() { @@ -493,12 +514,12 @@ impl Handler { if !found_target_struct { return; } - + let target_module = env.get_module(self.target_module_id); let target_struct = target_module.get_struct(target_struct_id); let target_struct_loc = target_struct.get_loc(); self.get_mouse_loc(env, &target_struct_loc); - + for field_env in target_struct.get_fields() { let field_name = field_env.get_name(); let field_name_str = field_name.display(env.symbol_pool()); @@ -526,8 +547,7 @@ impl Handler { ); let atomic_field_source = env.get_source(&atomic_field_loc); if atomic_field_loc.span().end() < self.mouse_span.end() - || atomic_field_loc.span().start() - > self.mouse_span.end() + || atomic_field_loc.span().start() > self.mouse_span.end() { continue; } @@ -562,12 +582,13 @@ impl Handler { codespan::Span::new( spec_block_info.loc.span().end(), spec_block_info.loc.span().end() + codespan::ByteOffset(1), - ) + ), ); - + if let Some(s_loc) = env.get_location(&span_first_col) { if let Some(e_loc) = env.get_location(&span_last_col) { - if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) { + if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) + { target_stct_id = stct_id; found_target_spec_stct = true; spec_stct_span_loc = spec_block_info.loc.clone(); @@ -585,8 +606,7 @@ impl Handler { let target_stct = target_module.get_struct(target_stct_id); let target_stct_spec = target_stct.get_spec(); - log::info!("target_stct's spec = {}", - env.display(target_stct_spec)); + log::info!("target_stct's spec = {}", env.display(target_stct_spec)); self.get_mouse_loc(env, &spec_stct_span_loc); for cond in target_stct_spec.conditions.clone() { for exp in cond.all_exps() { @@ -594,15 +614,10 @@ impl Handler { } } } - - fn process_expr( - &mut self, - env: &GlobalEnv, - exp: &move_model::ast::Exp, - ) { - + + fn process_expr(&mut self, env: &GlobalEnv, exp: &move_model::ast::Exp) { log::trace!("process_expr -------------------------\n"); - + exp.visit_post_order(&mut |e| { match e { Value(node_id, _) => { @@ -613,9 +628,14 @@ impl Handler { if let Ok(capture_value_str) = env.get_source(&value_loc) { value_str = capture_value_str.to_string(); } - for named_const in env.get_module(self.target_module_id).get_named_constants() { + for named_const in + env.get_module(self.target_module_id).get_named_constants() + { let spool = env.symbol_pool(); - log::trace!("named_const.get_name() = {}", named_const.get_name().display(spool)); + log::trace!( + "named_const.get_name() = {}", + named_const.get_name().display(spool) + ); let named_const_str = named_const.get_name().display(spool).to_string(); if value_str.contains(&named_const_str) { let (def_file, def_line) = @@ -628,7 +648,7 @@ impl Handler { col_end: def_line.column.0, }; self.capture_items_span.push(value_loc.span()); - self.result_candidates.push(result); + self.result_candidates.push(result); } } } @@ -636,9 +656,9 @@ impl Handler { }, LocalVar(node_id, localvar_symbol) => { let localvar_loc = env.get_node_loc(*node_id); - + if localvar_loc.span().start() > self.mouse_span.end() - || localvar_loc.span().end() < self.mouse_span.end() + || localvar_loc.span().end() < self.mouse_span.end() { return true; } @@ -648,7 +668,9 @@ impl Handler { ); if let Some(pattern_id) = self.symbol_2_pattern_id.get(localvar_symbol) { let pattern_loc = env.get_node_loc(*pattern_id); - if let Some((def_file, def_location)) = env.get_file_and_location(&pattern_loc) { + if let Some((def_file, def_location)) = + env.get_file_and_location(&pattern_loc) + { let result = FileRange { path: PathBuf::from(def_file), line_start: def_location.line.0, @@ -657,18 +679,18 @@ impl Handler { col_end: def_location.column.0, }; self.capture_items_span.push(localvar_loc.span()); - self.result_candidates.push(result); + self.result_candidates.push(result); } } true }, Temporary(node_id, _) => { let tmpvar_loc = env.get_node_loc(*node_id); - if let Ok(x) = env.get_source(&tmpvar_loc) { - log::trace!("temp_source = {}", x) + if let Ok(x) = env.get_source(&tmpvar_loc) { + log::trace!("temp_source = {}", x) } - if tmpvar_loc.span().start() > self.mouse_span.end() { + if tmpvar_loc.span().start() > self.mouse_span.end() { log::trace!("tmpvar_loc.span().start() > self.mouse_span.end()"); return true; } @@ -684,7 +706,7 @@ impl Handler { true }, Call(..) => { - log::trace!("lll >> exp.visit Call", ); + log::trace!("lll >> exp.visit Call",); self.process_call_spec_func(env, e); self.process_call(env, e); true @@ -703,7 +725,7 @@ impl Handler { self.process_spec_block(env, &env.get_node_loc(*node_id), spec); true }, - Block(_,pat,left_exp, right_exp) => { + Block(_, pat, left_exp, right_exp) => { self.collect_local_var_in_pattern(pat); self.process_pattern(env, pat); @@ -722,11 +744,7 @@ impl Handler { log::trace!("\nlll << process_expr ^^^^^^^^^^^^^^^^^^^^^^^^^\n"); } - fn process_call_spec_func( - &mut self, - env: &GlobalEnv, - expdata: &move_model::ast::ExpData, - ) { + fn process_call_spec_func(&mut self, env: &GlobalEnv, expdata: &move_model::ast::ExpData) { if let Call(node_id, SpecFunction(mid, fid, _), _) = expdata { let this_call_loc = env.get_node_loc(*node_id); log::trace!( @@ -761,11 +779,13 @@ impl Handler { let mut generic_ty_loc = this_call_loc.clone(); let capture_call_source = env.get_source(&this_call_loc); if let Ok(capture_call_source_str) = capture_call_source { - if let Some(index) = capture_call_source_str.find("<".to_string().as_str()) { + if let Some(index) = capture_call_source_str.find("<".to_string().as_str()) + { generic_ty_loc = move_model::model::Loc::new( this_call_loc.file_id(), codespan::Span::new( - this_call_loc.span().start() + codespan::ByteOffset(index.try_into().unwrap()), + this_call_loc.span().start() + + codespan::ByteOffset(index.try_into().unwrap()), this_call_loc.span().end(), ), ); @@ -784,7 +804,7 @@ impl Handler { if this_call_loc.span().start() < self.mouse_span.end() && self.mouse_span.end() < this_call_loc.span().end() { - log::trace!("lll >> exp.visit Exists exist_exp = {:?}", exp_vec); + log::trace!("lll >> exp.visit Exists exist_exp = {:?}", exp_vec); for exist_exp in exp_vec { self.process_expr(env, exist_exp); } @@ -792,12 +812,7 @@ impl Handler { } } - fn process_call( - &mut self, - env: &GlobalEnv, - expdata: &move_model::ast::ExpData, - ) - { + fn process_call(&mut self, env: &GlobalEnv, expdata: &move_model::ast::ExpData) { log::trace!("lll >> process_call"); if let Call(node_id, MoveFunction(mid, fid), _) = expdata { let this_call_loc = env.get_node_loc(*node_id); @@ -823,8 +838,7 @@ impl Handler { line_start: called_fun_line.line.0, col_start: called_fun_line.column.0, line_end: called_fun_line.line.0, - col_end: called_fun_line.column.0 - + called_fun.get_full_name_str().len() as u32, + col_end: called_fun_line.column.0 + called_fun.get_full_name_str().len() as u32, }; self.result_candidates.push(result); self.capture_items_span.push(this_call_loc.span()); @@ -834,11 +848,13 @@ impl Handler { let mut generic_ty_loc = this_call_loc.clone(); let capture_call_source = env.get_source(&this_call_loc); if let Ok(capture_call_source_str) = capture_call_source { - if let Some(index) = capture_call_source_str.find("<".to_string().as_str()) { + if let Some(index) = capture_call_source_str.find("<".to_string().as_str()) + { generic_ty_loc = move_model::model::Loc::new( this_call_loc.file_id(), codespan::Span::new( - this_call_loc.span().start() + codespan::ByteOffset(index.try_into().unwrap()), + this_call_loc.span().start() + + codespan::ByteOffset(index.try_into().unwrap()), this_call_loc.span().end(), ), ); @@ -860,7 +876,7 @@ impl Handler { { let inst_vec = &env.get_node_instantiation(*node_id); for inst in inst_vec { - log::info!("lll >> inst = {:?}", inst); + log::info!("lll >> inst = {:?}", inst); self.process_type(env, &this_call_loc, inst); } } @@ -890,9 +906,7 @@ impl Handler { let called_struct_loc = called_struct.get_loc(); let call_struct_source = env.get_source(&called_struct_loc); if let Ok(call_struct_str) = call_struct_source { - if let Some(index) = - call_struct_str.find(field_name_str.to_string().as_str()) - { + if let Some(index) = call_struct_str.find(field_name_str.to_string().as_str()) { let field_start = called_struct_loc.span().start() + codespan::ByteOffset(index.try_into().unwrap()); let field_len = field_name_str.to_string().len(); @@ -919,31 +933,27 @@ impl Handler { } } } - + if let Call(node_id, Pack(mid, sid), _) = expdata { let this_call_loc = env.get_node_loc(*node_id); log::trace!( "lll >> exp.visit this_call_loc = {:?}", env.get_location(&this_call_loc) - ); if this_call_loc.span().start() > self.mouse_span.end() - || self.mouse_span.end() > this_call_loc.span().end() + || self.mouse_span.end() > this_call_loc.span().end() { return; } let pack_module = env.get_module(*mid); let pack_struct = pack_module.get_struct(*sid); - log::trace!( - "lll >> pack_struct = {:?}", - pack_struct.get_full_name_str() - ); + log::trace!("lll >> pack_struct = {:?}", pack_struct.get_full_name_str()); let pack_struct_loc = pack_struct.get_loc(); let (pack_struct_file, pack_struct_location) = env.get_file_and_location(&pack_struct_loc).unwrap(); - + let path_buf = PathBuf::from(pack_struct_file); let result = FileRange { path: path_buf, @@ -958,7 +968,7 @@ impl Handler { } log::trace!("lll << process_call"); } - + fn collect_local_var_in_pattern(&mut self, pattern: &MoveModelPattern) { for (node_id, sym) in pattern.vars().iter() { self.symbol_2_pattern_id.insert(*sym, *node_id); @@ -966,31 +976,26 @@ impl Handler { } fn process_pattern(&mut self, env: &GlobalEnv, pattern: &MoveModelPattern) { - if let MoveModelPattern::Struct(node_id, q_id, _) = pattern { let this_call_loc = env.get_node_loc(*node_id); log::trace!( "lll >> exp.visit this_call_loc = {:?}", env.get_location(&this_call_loc) - ); if this_call_loc.span().start() > self.mouse_span.end() - || self.mouse_span.end() > this_call_loc.span().end() + || self.mouse_span.end() > this_call_loc.span().end() { return; } let pattern_module = env.get_module(q_id.module_id); let pattern_struct = pattern_module.get_struct(q_id.id); - log::info!( - "pattern_struct = {:?}", - pattern_struct.get_full_name_str() - ); + log::info!("pattern_struct = {:?}", pattern_struct.get_full_name_str()); let pattern_struct_loc = pattern_struct.get_loc(); let (pattern_struct_file, pattern_struct_location) = env.get_file_and_location(&pattern_struct_loc).unwrap(); - + let path_buf = PathBuf::from(pattern_struct_file); let result = FileRange { path: path_buf, @@ -1012,8 +1017,11 @@ impl Handler { _speck_block: &Spec, ) { log::trace!("\n\n"); - - log::trace!("lll >> process_spec_block loc = {:?}", env.get_file_and_location(capture_items_loc)); + + log::trace!( + "lll >> process_spec_block loc = {:?}", + env.get_file_and_location(capture_items_loc) + ); log::trace!("lll << process_spec_block loc"); } @@ -1060,23 +1068,40 @@ impl Handler { let generic_struct_ty_symbol = generic_struct_ty.0.get_name(); let capture_generic_ty_source = env.get_source(capture_items_loc); if let Ok(capture_generic_ty_str) = capture_generic_ty_source { - let generic_struct_ty_symbol_display = generic_struct_ty_symbol.display(env.symbol_pool()); - if let Some(index) = capture_generic_ty_str.find(generic_struct_ty_symbol_display.to_string().as_str()) { - let capture_generic_ty_str_len = generic_struct_ty_symbol_display.to_string().len(); - let capture_generic_ty_start = - (*capture_items_loc).span().start() + codespan::ByteOffset(index.try_into().unwrap()); - let capture_generic_ty_end = - capture_generic_ty_start + codespan::ByteOffset(capture_generic_ty_str_len.try_into().unwrap()); + let generic_struct_ty_symbol_display = + generic_struct_ty_symbol.display(env.symbol_pool()); + if let Some(index) = capture_generic_ty_str + .find(generic_struct_ty_symbol_display.to_string().as_str()) + { + let capture_generic_ty_str_len = + generic_struct_ty_symbol_display.to_string().len(); + let capture_generic_ty_start = (*capture_items_loc).span().start() + + codespan::ByteOffset(index.try_into().unwrap()); + let capture_generic_ty_end = capture_generic_ty_start + + codespan::ByteOffset( + capture_generic_ty_str_len.try_into().unwrap(), + ); let capture_generic_ty_loc = move_model::model::Loc::new( (*capture_items_loc).file_id(), - codespan::Span::new(capture_generic_ty_start, capture_generic_ty_end), + codespan::Span::new( + capture_generic_ty_start, + capture_generic_ty_end, + ), + ); + log::trace!( + "capture_generic_ty_str = {:?}", + env.get_source(&capture_generic_ty_loc) ); - log::trace!("capture_generic_ty_str = {:?}", env.get_source(&capture_generic_ty_loc)); - let capture_line = env.get_location(&capture_generic_ty_loc).unwrap(); - let (generic_struct_belong_file, generic_struct_belong_pos) = env.get_file_and_location(&generic_struct_ty.0.get_loc()).unwrap(); - if self.line.eq(&capture_line.line.0) && - capture_generic_ty_loc.span().start() <= self.mouse_span.end() && - self.mouse_span.end() <= capture_generic_ty_loc.span().end() { + let capture_line = + env.get_location(&capture_generic_ty_loc).unwrap(); + let (generic_struct_belong_file, generic_struct_belong_pos) = env + .get_file_and_location(&generic_struct_ty.0.get_loc()) + .unwrap(); + if self.line.eq(&capture_line.line.0) + && capture_generic_ty_loc.span().start() + <= self.mouse_span.end() + && self.mouse_span.end() <= capture_generic_ty_loc.span().end() + { let result = FileRange { path: PathBuf::from(generic_struct_belong_file).clone(), line_start: generic_struct_belong_pos.line.0, @@ -1120,16 +1145,9 @@ impl Handler { } } - fn run_move_model_visitor_internal( - &mut self, - env: &GlobalEnv, - move_file_path: &Path - ) { - let candidate_modules - = crate::utils::get_modules_by_fpath_in_all_modules( - env, - &PathBuf::from(move_file_path) - ); + fn run_move_model_visitor_internal(&mut self, env: &GlobalEnv, move_file_path: &Path) { + let candidate_modules = + crate::utils::get_modules_by_fpath_in_all_modules(env, &PathBuf::from(move_file_path)); if candidate_modules.is_empty() { log::error!("cannot get target module\n"); return; @@ -1143,7 +1161,7 @@ impl Handler { } else { self.process_use_decl(env); self.process_func(env); - self.process_struct(env); + self.process_struct(env); } } } @@ -1154,7 +1172,10 @@ impl Handler { let capture_loc = env.get_location(span_loc).unwrap(); let a = env.get_source(span_loc).unwrap(); eprintln!("capture str: {}", a); - eprintln!("capture loc: {}, {}", capture_loc.line.0, capture_loc.column.0); + eprintln!( + "capture loc: {}, {}", + capture_loc.line.0, capture_loc.column.0 + ); eprintln!("moutse loc: {}, {}", self.line, self.col); } } @@ -1173,7 +1194,7 @@ impl ItemOrAccessHandler for Handler { _services: &dyn HandleItemService, env: &GlobalEnv, move_file_path: &Path, - _: String + _: String, ) { self.run_move_model_visitor_internal(env, move_file_path); } @@ -1192,7 +1213,7 @@ impl std::fmt::Display for Handler { pub fn find_smallest_length_index(spans: &[codespan::Span]) -> Option { let mut smallest_length = i64::MAX; let mut smallest_index = None; - + for (index, span) in spans.iter().enumerate() { let length = span.end() - span.start(); if length.0 < smallest_length { diff --git a/language/move-analyzer/src/hover.rs b/language/move-analyzer/src/hover.rs index a8dc4aa4d3..6d43d95ef3 100644 --- a/language/move-analyzer/src/hover.rs +++ b/language/move-analyzer/src/hover.rs @@ -1,18 +1,17 @@ // Copyright (c) The BitsLab.MoveBit Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::{ - analyzer_handler::*, - context::*, - utils::path_concat, -}; +use crate::{analyzer_handler::*, context::*, utils::path_concat}; use lsp_server::*; use lsp_types::*; use move_model::{ ast::{ExpData::*, Operation::*, SpecBlockTarget}, model::{FunId, GlobalEnv, ModuleId, StructId}, }; -use std::{path::{Path, PathBuf}, ops::Deref}; +use std::{ + ops::Deref, + path::{Path, PathBuf}, +}; /// Handles on_hover_request of the language server. pub fn on_hover_request(context: &Context, request: &Request) -> lsp_server::Response { @@ -44,9 +43,15 @@ pub fn on_hover_request(context: &Context, request: &Request) -> lsp_server::Res } .run_visitor_for_file(&mut handler, &fpath, String::default()); - let r = Response::new_ok(request.id.clone(), serde_json::to_value(handler.get_result()).unwrap()); + let r = Response::new_ok( + request.id.clone(), + serde_json::to_value(handler.get_result()).unwrap(), + ); let ret_response = r.clone(); - log::info!("------------------------------------\nret_response = \n{:?}\n\n", ret_response); + log::info!( + "------------------------------------\nret_response = \n{:?}\n\n", + ret_response + ); context .connection .sender @@ -80,28 +85,26 @@ impl Handler { } } - fn check_move_model_loc_contains_mouse_pos(&self, env: &GlobalEnv, loc: &move_model::model::Loc) -> bool { - if let Some(obj_first_col) = env.get_location(& - move_model::model::Loc::new( + fn check_move_model_loc_contains_mouse_pos( + &self, + env: &GlobalEnv, + loc: &move_model::model::Loc, + ) -> bool { + if let Some(obj_first_col) = env.get_location(&move_model::model::Loc::new( + loc.file_id(), + codespan::Span::new( + loc.span().start(), + loc.span().start() + codespan::ByteOffset(1), + ), + )) { + if let Some(obj_last_col) = env.get_location(&move_model::model::Loc::new( loc.file_id(), - codespan::Span::new( - loc.span().start(), - loc.span().start() + codespan::ByteOffset(1), - ) - ) - ) { - if let Some(obj_last_col) = env.get_location(& - move_model::model::Loc::new( - loc.file_id(), - codespan::Span::new( - loc.span().end(), - loc.span().end() + codespan::ByteOffset(1), - ) - ) - ) { - if u32::from(obj_first_col.line) == self.line && - u32::from(obj_first_col.column) < self.col && - self.col < u32::from(obj_last_col.column) { + codespan::Span::new(loc.span().end(), loc.span().end() + codespan::ByteOffset(1)), + )) { + if u32::from(obj_first_col.line) == self.line + && u32::from(obj_first_col.column) < self.col + && self.col < u32::from(obj_last_col.column) + { return true; } } @@ -115,8 +118,8 @@ impl Handler { most_clost_item_idx = item_idx; } - if !self.result_candidates.is_empty() && - most_clost_item_idx < self.result_candidates.len() { + if !self.result_candidates.is_empty() && most_clost_item_idx < self.result_candidates.len() + { let ret_str = self.result_candidates[most_clost_item_idx].clone(); self.capture_items_span.clear(); self.result_candidates.clear(); @@ -133,7 +136,6 @@ impl Handler { contents: HoverContents::Scalar(MarkedString::String("null".to_string())), range: None, } - } fn get_mouse_loc(&mut self, env: &GlobalEnv, target_fn_or_struct_loc: &move_model::model::Loc) { @@ -177,7 +179,7 @@ impl Handler { ); mouse_loc = env.get_location(&mouse_line_last_col).unwrap(); } - + let mouse_source = env.get_source(&move_model::model::Loc::new( target_fn_or_struct_loc.file_id(), codespan::Span::new( @@ -186,8 +188,11 @@ impl Handler { ), )); log::info!(" mouse_source = {:?}", mouse_source); - - self.mouse_span = codespan::Span::new(mouse_line_first_col.span().start(), mouse_line_last_col.span().start()); + + self.mouse_span = codespan::Span::new( + mouse_line_first_col.span().start(), + mouse_line_last_col.span().start(), + ); } fn process_use_decl(&mut self, env: &GlobalEnv) { @@ -203,8 +208,11 @@ impl Handler { continue; } } - log::trace!("use_decl.loc = {:?}, use_decl.loc.len = {:?}", - use_decl.loc, use_decl.loc.span().end() - use_decl.loc.span().start()); + log::trace!( + "use_decl.loc = {:?}, use_decl.loc.len = {:?}", + use_decl.loc, + use_decl.loc.span().end() - use_decl.loc.span().start() + ); if !use_decl.members.is_empty() { for (member_loc, name, _) in use_decl.members.clone().into_iter() { @@ -306,12 +314,13 @@ impl Handler { codespan::Span::new( spec_block_info.loc.span().end(), spec_block_info.loc.span().end() + codespan::ByteOffset(1), - ) + ), ); - + if let Some(s_loc) = env.get_location(&span_first_col) { if let Some(e_loc) = env.get_location(&span_last_col) { - if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) { + if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) + { target_fun_id = fun_id; found_target_fun = true; spec_fn_span_loc = spec_block_info.loc.clone(); @@ -357,17 +366,17 @@ impl Handler { break; } } - + if !found_target_struct { log::warn!(" not found_target_struct"); return; } - + let target_module = env.get_module(self.target_module_id); let target_struct = target_module.get_struct(target_struct_id); let target_struct_loc = target_struct.get_loc(); self.get_mouse_loc(env, &target_struct_loc); - + for field_env in target_struct.get_fields() { let field_name = field_env.get_name(); let field_name_str = field_name.display(env.symbol_pool()); @@ -394,8 +403,7 @@ impl Handler { ); if atomic_field_loc.span().end() < self.mouse_span.end() - || atomic_field_loc.span().start() - > self.mouse_span.end() + || atomic_field_loc.span().start() > self.mouse_span.end() { continue; } @@ -407,7 +415,7 @@ impl Handler { } } } - + fn process_spec_struct(&mut self, env: &GlobalEnv) { let mut found_target_spec_stct = false; let mut target_stct_id = StructId::new(env.symbol_pool().make("name")); @@ -428,12 +436,13 @@ impl Handler { codespan::Span::new( spec_block_info.loc.span().end(), spec_block_info.loc.span().end() + codespan::ByteOffset(1), - ) + ), ); - + if let Some(s_loc) = env.get_location(&span_first_col) { if let Some(e_loc) = env.get_location(&span_last_col) { - if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) { + if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) + { target_stct_id = stct_id; found_target_spec_stct = true; spec_stct_span_loc = spec_block_info.loc.clone(); @@ -451,8 +460,7 @@ impl Handler { let target_stct = target_module.get_struct(target_stct_id); let target_stct_spec = target_stct.get_spec(); - log::info!("target_stct's spec = {}", - env.display(target_stct_spec)); + log::info!("target_stct's spec = {}", env.display(target_stct_spec)); self.get_mouse_loc(env, &spec_stct_span_loc); for cond in target_stct_spec.conditions.clone() { for exp in cond.all_exps() { @@ -461,11 +469,7 @@ impl Handler { } } - fn process_expr( - &mut self, - env: &GlobalEnv, - exp: &move_model::ast::Exp, - ) { + fn process_expr(&mut self, env: &GlobalEnv, exp: &move_model::ast::Exp) { exp.visit_post_order(&mut |e| { match e { Value(node_id, _v) => { @@ -476,12 +480,15 @@ impl Handler { if let Ok(capture_value_str) = env.get_source(&value_loc) { value_str = capture_value_str.to_string(); } - for named_const in env.get_module(self.target_module_id).get_named_constants() { + for named_const in + env.get_module(self.target_module_id).get_named_constants() + { let spool = env.symbol_pool(); let named_const_str = named_const.get_name().display(spool).to_string(); if value_str.contains(&named_const_str) { self.capture_items_span.push(value_loc.span()); - self.result_candidates.push(env.display(&named_const.get_value()).to_string()); + self.result_candidates + .push(env.display(&named_const.get_value()).to_string()); } } } @@ -493,22 +500,28 @@ impl Handler { }, LocalVar(node_id, localvar_symbol) => { let localvar_loc = env.get_node_loc(*node_id); - + if localvar_loc.span().start() > self.mouse_span.end() || self.mouse_span.end() > localvar_loc.span().end() { return true; } - // The variable names "__update_iter_flag" and "__upper_bound_value" seem to be special, + // The variable names "__update_iter_flag" and "__upper_bound_value" seem to be special, // causing hover errors in a "for (i 1..10)" loop. Handling this issue accordingly. - if localvar_symbol.display(env.symbol_pool()).to_string() == "__update_iter_flag" - || localvar_symbol.display(env.symbol_pool()).to_string() == "__upper_bound_value" { + if localvar_symbol.display(env.symbol_pool()).to_string() + == "__update_iter_flag" + || localvar_symbol.display(env.symbol_pool()).to_string() + == "__upper_bound_value" + { return true; } - log::trace!("local val symbol: {}", localvar_symbol.display(env.symbol_pool()).to_string()); - + log::trace!( + "local val symbol: {}", + localvar_symbol.display(env.symbol_pool()).to_string() + ); + if let Some(node_type) = env.get_node_type_opt(*node_id) { self.process_type(env, &localvar_loc, &node_type); } @@ -521,7 +534,7 @@ impl Handler { { return true; } - + if let Some(node_type) = env.get_node_type_opt(*node_id) { self.process_type(env, &tmpvar_loc, &node_type); } @@ -531,7 +544,7 @@ impl Handler { for (sym_node_id, _) in pattern.vars() { let sym_loc = env.get_node_loc(sym_node_id); if sym_loc.span().start() > self.mouse_span.end() - || self.mouse_span.end() > sym_loc.span().end() + || self.mouse_span.end() > sym_loc.span().end() { return true; } @@ -547,12 +560,7 @@ impl Handler { }); } - fn process_call( - &mut self, - env: &GlobalEnv, - expdata: &move_model::ast::ExpData, - ) - { + fn process_call(&mut self, env: &GlobalEnv, expdata: &move_model::ast::ExpData) { if let Call(node_id, MoveFunction(mid, fid), _) = expdata { let this_call_loc = env.get_node_loc(*node_id); @@ -573,7 +581,7 @@ impl Handler { { return; } - + let called_module = env.get_module(*mid); let called_struct = called_module.get_struct(*sid); let called_field = called_struct.get_field(*fid); @@ -589,18 +597,21 @@ impl Handler { let called_module = env.get_module(*mid); let spec_fun = called_module.get_spec_fun(*fid); self.capture_items_span.push(this_call_loc.span()); - self.result_candidates.push(spec_fun.name.display(env.symbol_pool()).to_string()); + self.result_candidates + .push(spec_fun.name.display(env.symbol_pool()).to_string()); let inst_vec = &env.get_node_instantiation(*node_id); for inst in inst_vec { let mut generic_ty_loc = this_call_loc.clone(); let capture_call_source = env.get_source(&this_call_loc); if let Ok(capture_call_source_str) = capture_call_source { - if let Some(index) = capture_call_source_str.find("<".to_string().as_str()) { + if let Some(index) = capture_call_source_str.find("<".to_string().as_str()) + { generic_ty_loc = move_model::model::Loc::new( this_call_loc.file_id(), codespan::Span::new( - this_call_loc.span().start() + codespan::ByteOffset(index.try_into().unwrap()), + this_call_loc.span().start() + + codespan::ByteOffset(index.try_into().unwrap()), this_call_loc.span().end(), ), ); @@ -610,11 +621,11 @@ impl Handler { } } } - + if let Call(node_id, Pack(_, _), _) = expdata { let op_loc = env.get_node_loc(*node_id); if op_loc.span().start() < self.mouse_span.end() - && self.mouse_span.end() < op_loc.span().end() + && self.mouse_span.end() < op_loc.span().end() { if let Some(node_type) = env.get_node_type_opt(*node_id) { self.process_type(env, &op_loc, &node_type); @@ -636,16 +647,9 @@ impl Handler { self.result_candidates.push(type_display.to_string()); } - fn run_move_model_visitor_internal( - &mut self, - env: &GlobalEnv, - move_file_path: &Path - ) { - let candidate_modules - = crate::utils::get_modules_by_fpath_in_all_modules( - env, - &PathBuf::from(move_file_path) - ); + fn run_move_model_visitor_internal(&mut self, env: &GlobalEnv, move_file_path: &Path) { + let candidate_modules = + crate::utils::get_modules_by_fpath_in_all_modules(env, &PathBuf::from(move_file_path)); if candidate_modules.is_empty() { log::info!("cannot get target module\n"); return; @@ -659,7 +663,7 @@ impl Handler { } else { self.process_use_decl(env); self.process_func(env); - self.process_struct(env); + self.process_struct(env); } } } @@ -680,7 +684,7 @@ impl ItemOrAccessHandler for Handler { _services: &dyn HandleItemService, env: &GlobalEnv, move_file_path: &Path, - _: String + _: String, ) { self.run_move_model_visitor_internal(env, move_file_path); } diff --git a/language/move-analyzer/src/inlay_hints.rs b/language/move-analyzer/src/inlay_hints.rs index b711b37ef2..9bea3b6cb4 100644 --- a/language/move-analyzer/src/inlay_hints.rs +++ b/language/move-analyzer/src/inlay_hints.rs @@ -1,29 +1,29 @@ // Copyright (c) The BitsLab.MoveBit Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::{ - analyzer_handler::*, - context::*, - utils::*, -}; +use crate::{analyzer_handler::*, context::*, utils::*}; use lsp_server::*; use lsp_types::*; use move_model::{ ast::{ExpData::*, Operation::*, SpecBlockTarget}, - model::{GlobalEnv, FunctionEnv, ModuleId}, + model::{FunctionEnv, GlobalEnv, ModuleId}, +}; +use std::{ + ops::Deref, + path::{Path, PathBuf}, }; -use std::{path::{Path, PathBuf}, ops::Deref}; /// Handles inlay_hints request of the language server. -pub fn on_inlay_hints(context: &Context, request: &Request, inlay_hints_config: &InlayHintsConfig) -> lsp_server::Response { +pub fn on_inlay_hints( + context: &Context, + request: &Request, + inlay_hints_config: &InlayHintsConfig, +) -> lsp_server::Response { log::info!("on_inlay_hints request = {:?}", request); let parameters = serde_json::from_value::(request.params.clone()) .expect("could not deserialize go-to-def request"); let fpath = parameters.text_document.uri.to_file_path().unwrap(); - let fpath = path_concat( - std::env::current_dir().unwrap().as_path(), - fpath.as_path(), - ); + let fpath = path_concat(std::env::current_dir().unwrap().as_path(), fpath.as_path()); if !inlay_hints_config.enable { log::info!("inlay-hints is not enabled."); @@ -44,7 +44,7 @@ pub fn on_inlay_hints(context: &Context, request: &Request, inlay_hints_config: result: Some(serde_json::json!({"msg": "No available project"})), error: None, }; - } + }, } .run_visitor_for_file(&mut handler, &fpath, String::default()); @@ -66,9 +66,7 @@ pub struct InlayHintsConfig { impl Default for InlayHintsConfig { fn default() -> Self { - Self { - enable: true, - } + Self { enable: true } } } @@ -105,7 +103,9 @@ impl Handler { )) .unwrap(); - if self.range.line_start <= func_start_pos.line.0 && func_end_pos.line.0 <= self.range.line_end { + if self.range.line_start <= func_start_pos.line.0 + && func_end_pos.line.0 <= self.range.line_end + { if let Some(exp) = fun.get_def().deref() { log::trace!("process funcation: {}", fun.get_name_string()); self.process_expr(env, &fun, exp); @@ -122,14 +122,21 @@ impl Handler { let (_, block_end_pos) = env .get_file_and_location(&move_model::model::Loc::new( spec_block_info.loc.file_id(), - codespan::Span::new(spec_block_info.loc.span().end(), spec_block_info.loc.span().end()), + codespan::Span::new( + spec_block_info.loc.span().end(), + spec_block_info.loc.span().end(), + ), )) .unwrap(); - if self.range.line_start <= block_start_pos.line.0 && block_end_pos.line.0 <= self.range.line_end { + if self.range.line_start <= block_start_pos.line.0 + && block_end_pos.line.0 <= self.range.line_end + { let target_fn = target_module.get_function(fun_id); let target_fn_spec = target_fn.get_spec(); - log::info!(" -- target_fun's spec = {}", - env.display(&*target_fn_spec)); + log::info!( + " -- target_fun's spec = {}", + env.display(&*target_fn_spec) + ); for cond in target_fn_spec.conditions.clone() { for exp in cond.all_exps() { self.process_expr(env, &target_fn, exp); @@ -137,16 +144,21 @@ impl Handler { } } } - + if let SpecBlockTarget::FunctionCode(_, fun_id, _) = spec_block_info.target { let (_, block_start_pos) = env.get_file_and_location(&spec_block_info.loc).unwrap(); let (_, block_end_pos) = env .get_file_and_location(&move_model::model::Loc::new( spec_block_info.loc.file_id(), - codespan::Span::new(spec_block_info.loc.span().end(), spec_block_info.loc.span().end()), + codespan::Span::new( + spec_block_info.loc.span().end(), + spec_block_info.loc.span().end(), + ), )) .unwrap(); - if self.range.line_start <= block_start_pos.line.0 && block_end_pos.line.0 <= self.range.line_end { + if self.range.line_start <= block_start_pos.line.0 + && block_end_pos.line.0 <= self.range.line_end + { let target_fn = target_module.get_function(fun_id); let target_fn_spec = target_fn.get_spec(); for cond in target_fn_spec.conditions.clone() { @@ -156,167 +168,209 @@ impl Handler { } } } - + if let SpecBlockTarget::Schema(_, _, _) = spec_block_info.target { let (_, block_start_pos) = env.get_file_and_location(&spec_block_info.loc).unwrap(); let (_, block_end_pos) = env .get_file_and_location(&move_model::model::Loc::new( spec_block_info.loc.file_id(), - codespan::Span::new(spec_block_info.loc.span().end(), spec_block_info.loc.span().end()), + codespan::Span::new( + spec_block_info.loc.span().end(), + spec_block_info.loc.span().end(), + ), )) .unwrap(); - if self.range.line_start <= block_start_pos.line.0 && block_end_pos.line.0 <= self.range.line_end { - log::info!(" -- SpecBlockTarget::Schema, spec_block_info.loc = {:?}", env - .get_file_and_location(&spec_block_info.loc.clone())); + if self.range.line_start <= block_start_pos.line.0 + && block_end_pos.line.0 <= self.range.line_end + { + log::info!( + " -- SpecBlockTarget::Schema, spec_block_info.loc = {:?}", + env.get_file_and_location(&spec_block_info.loc.clone()) + ); } } } } - - fn process_expr( - &mut self, - env: &GlobalEnv, - fun: &FunctionEnv, - exp: &move_model::ast::Exp, - ) { + + fn process_expr(&mut self, env: &GlobalEnv, fun: &FunctionEnv, exp: &move_model::ast::Exp) { let mut is_visited = vec![]; - exp.visit_post_order(&mut |e| { - match e { - Call(..) => { - self.process_call(env, e); - true - }, - LocalVar(node_id, localvar_symbol) => { - let mut localvar_loc = env.get_node_loc(*node_id); - localvar_loc = move_model::model::Loc::new( - localvar_loc.file_id(), - codespan::Span::new( - localvar_loc.span().start(), - localvar_loc.span().end() + codespan::ByteOffset((2).try_into().unwrap()) - ) - ); - if localvar_symbol.display(env.symbol_pool()).to_string() == "__update_iter_flag" - || localvar_symbol.display(env.symbol_pool()).to_string() == "__upper_bound_value" { - return true; - } + exp.visit_post_order(&mut |e| match e { + Call(..) => { + self.process_call(env, e); + true + }, + LocalVar(node_id, localvar_symbol) => { + let mut localvar_loc = env.get_node_loc(*node_id); + localvar_loc = move_model::model::Loc::new( + localvar_loc.file_id(), + codespan::Span::new( + localvar_loc.span().start(), + localvar_loc.span().end() + codespan::ByteOffset((2).try_into().unwrap()), + ), + ); + if localvar_symbol.display(env.symbol_pool()).to_string() == "__update_iter_flag" + || localvar_symbol.display(env.symbol_pool()).to_string() + == "__upper_bound_value" + { + return true; + } - if is_visited.contains(&localvar_loc.span().start().0) { - return true; + if is_visited.contains(&localvar_loc.span().start().0) { + return true; + } + is_visited.push(localvar_loc.span().start().0); + + log::trace!( + "lll >> exp.visit localvar_loc = {:?}", + env.get_location(&localvar_loc) + ); + log::trace!( + "lll >> exp.visit localvar_symbol = {}", + localvar_symbol.display(env.symbol_pool()).to_string() + ); + if let Some(node_type) = env.get_node_type_opt(*node_id) { + if let Ok(local_var_str) = env.get_source(&localvar_loc) { + if let Some(index) = local_var_str.find( + localvar_symbol + .display(env.symbol_pool()) + .to_string() + .as_str(), + ) { + let inlay_hint_pos = move_model::model::Loc::new( + localvar_loc.file_id(), + codespan::Span::new( + localvar_loc.span().start() + + codespan::ByteOffset( + (index + + localvar_symbol + .display(env.symbol_pool()) + .to_string() + .len()) + .try_into() + .unwrap(), + ), + localvar_loc.span().end(), + ), + ); + let next_char = local_var_str.chars().nth( + index + + localvar_symbol.display(env.symbol_pool()).to_string().len(), + ); + match next_char { + Some('.') => return true, + Some(':') => return true, + _ => { + log::trace!( + "local_var_str[{:?}] inlay_hint_pos = {:?}", + local_var_str, + inlay_hint_pos + ); + self.process_type(env, &inlay_hint_pos, &node_type); + }, + } + } } - is_visited.push(localvar_loc.span().start().0); - - log::trace!( - "lll >> exp.visit localvar_loc = {:?}", - env.get_location(&localvar_loc) - ); - log::trace!( - "lll >> exp.visit localvar_symbol = {}", - localvar_symbol.display(env.symbol_pool()).to_string() - ); - if let Some(node_type) = env.get_node_type_opt(*node_id) { - if let Ok(local_var_str) = env.get_source(&localvar_loc) { - if let Some(index) = local_var_str.find(localvar_symbol.display(env.symbol_pool()).to_string().as_str()) { - let inlay_hint_pos = move_model::model::Loc::new( - localvar_loc.file_id(), - codespan::Span::new( - localvar_loc.span().start() + - codespan::ByteOffset((index + localvar_symbol.display(env.symbol_pool()).to_string().len()).try_into().unwrap()), - localvar_loc.span().end())); - let next_char = local_var_str.chars().nth(index + localvar_symbol.display(env.symbol_pool()).to_string().len()); - match next_char { - Some('.') => return true, - Some(':') => return true, - _ => { - log::trace!("local_var_str[{:?}] inlay_hint_pos = {:?}", local_var_str, inlay_hint_pos); - self.process_type(env, &inlay_hint_pos, &node_type); - } - } + } + true + }, + Temporary(node_id, idx) => { + let mut tmpvar_loc = env.get_node_loc(*node_id); + tmpvar_loc = move_model::model::Loc::new( + tmpvar_loc.file_id(), + codespan::Span::new( + tmpvar_loc.span().start(), + tmpvar_loc.span().end() + codespan::ByteOffset((2).try_into().unwrap()), + ), + ); + + let mut tmp_var_name_str = "".to_string(); + if let Some(name) = fun.get_parameters().get(*idx).map(|p| p.0) { + tmp_var_name_str = name.display(env.symbol_pool()).to_string(); + } + if let Some(node_type) = env.get_node_type_opt(*node_id) { + if let Ok(tmp_var_str) = env.get_source(&tmpvar_loc) { + if let Some(index) = tmp_var_str.find(tmp_var_name_str.as_str()) { + let inlay_hint_pos = move_model::model::Loc::new( + tmpvar_loc.file_id(), + codespan::Span::new( + tmpvar_loc.span().start() + + codespan::ByteOffset( + (index + tmp_var_name_str.len()).try_into().unwrap(), + ), + tmpvar_loc.span().end(), + ), + ); + let next_char = tmp_var_str.chars().nth(index + tmp_var_name_str.len()); + match next_char { + Some('.') => return true, + Some(':') => return true, + _ => { + self.process_type(env, &inlay_hint_pos, &node_type); + }, } } } - true - }, - Temporary(node_id, idx) => { - let mut tmpvar_loc = env.get_node_loc(*node_id); - tmpvar_loc = move_model::model::Loc::new( - tmpvar_loc.file_id(), + } + true + }, + Block(_, pattern, _, _) => { + for (sym_node_id, sym_symbol) in pattern.vars() { + let mut sym_loc = env.get_node_loc(sym_node_id); + sym_loc = move_model::model::Loc::new( + sym_loc.file_id(), codespan::Span::new( - tmpvar_loc.span().start(), - tmpvar_loc.span().end() + codespan::ByteOffset((2).try_into().unwrap()))); + sym_loc.span().start(), + sym_loc.span().end() + codespan::ByteOffset((2).try_into().unwrap()), + ), + ); - let mut tmp_var_name_str = "".to_string(); - if let Some(name) = fun.get_parameters().get(*idx).map(|p| p.0) - { - tmp_var_name_str = name.display(env.symbol_pool()).to_string(); - } - if let Some(node_type) = env.get_node_type_opt(*node_id) { - if let Ok(tmp_var_str) = env.get_source(&tmpvar_loc) { - if let Some(index) = tmp_var_str.find(tmp_var_name_str.as_str()) { + if let Some(node_type) = env.get_node_type_opt(sym_node_id) { + if let Ok(pattern_sym_str) = env.get_source(&sym_loc) { + if let Some(index) = pattern_sym_str + .find(sym_symbol.display(env.symbol_pool()).to_string().as_str()) + { let inlay_hint_pos = move_model::model::Loc::new( - tmpvar_loc.file_id(), + sym_loc.file_id(), codespan::Span::new( - tmpvar_loc.span().start() + - codespan::ByteOffset((index + tmp_var_name_str.len()).try_into().unwrap()), - tmpvar_loc.span().end())); - let next_char = tmp_var_str.chars().nth(index + tmp_var_name_str.len()); + sym_loc.span().start() + + codespan::ByteOffset( + (index + + sym_symbol + .display(env.symbol_pool()) + .to_string() + .len()) + .try_into() + .unwrap(), + ), + sym_loc.span().end(), + ), + ); + let next_char = pattern_sym_str.chars().nth( + index + sym_symbol.display(env.symbol_pool()).to_string().len(), + ); match next_char { Some('.') => return true, Some(':') => return true, _ => { + log::trace!( + "pattern sym [{:?}] inlay_hint_pos = {:?}", + pattern_sym_str, + inlay_hint_pos + ); self.process_type(env, &inlay_hint_pos, &node_type); - } - } - } - } - } - true - }, - Block(_, pattern, _, _) => { - for (sym_node_id, sym_symbol) in pattern.vars() { - let mut sym_loc = env.get_node_loc(sym_node_id); - sym_loc = move_model::model::Loc::new( - sym_loc.file_id(), - codespan::Span::new( - sym_loc.span().start(), - sym_loc.span().end() + codespan::ByteOffset((2).try_into().unwrap()) - ) - ); - - if let Some(node_type) = env.get_node_type_opt(sym_node_id) { - if let Ok(pattern_sym_str) = env.get_source(&sym_loc) { - if let Some(index) = pattern_sym_str.find(sym_symbol.display(env.symbol_pool()).to_string().as_str()) { - let inlay_hint_pos = move_model::model::Loc::new( - sym_loc.file_id(), - codespan::Span::new( - sym_loc.span().start() + - codespan::ByteOffset((index + sym_symbol.display(env.symbol_pool()).to_string().len()).try_into().unwrap()), - sym_loc.span().end())); - let next_char = pattern_sym_str.chars().nth(index + sym_symbol.display(env.symbol_pool()).to_string().len()); - match next_char { - Some('.') => return true, - Some(':') => return true, - _ => { - log::trace!("pattern sym [{:?}] inlay_hint_pos = {:?}", pattern_sym_str, inlay_hint_pos); - self.process_type(env, &inlay_hint_pos, &node_type); - } - } + }, } } } } - true - }, - _ => true, - } + } + true + }, + _ => true, }); } - fn process_call( - &mut self, - env: &GlobalEnv, - expdata: &move_model::ast::ExpData, - ) - { + fn process_call(&mut self, env: &GlobalEnv, expdata: &move_model::ast::ExpData) { if let Call(node_id, Select(mid, sid, fid), _) = expdata { let this_call_loc = env.get_node_loc(*node_id); let called_module = env.get_module(*mid); @@ -325,20 +379,27 @@ impl Handler { let field_type = called_field.get_type(); if let Ok(link_access_source) = env.get_source(&this_call_loc) { - let called_field_name = ".".to_string() + called_field.get_name().display(env.symbol_pool()).to_string().as_str(); + let called_field_name = ".".to_string() + + called_field + .get_name() + .display(env.symbol_pool()) + .to_string() + .as_str(); if let Some(index) = link_access_source.find(called_field_name.as_str()) { let dis = index + called_field_name.len(); let inlay_hint_pos = move_model::model::Loc::new( this_call_loc.file_id(), codespan::Span::new( - this_call_loc.span().start() + codespan::ByteOffset((dis).try_into().unwrap()), - this_call_loc.span().end() - )); - self.process_type(env, &inlay_hint_pos, &field_type); + this_call_loc.span().start() + + codespan::ByteOffset((dis).try_into().unwrap()), + this_call_loc.span().end(), + ), + ); + self.process_type(env, &inlay_hint_pos, &field_type); } } - } + } } fn process_type( @@ -365,13 +426,13 @@ impl Handler { match unpack_ty { move_model::ty::Type::Reference(_, _) => { unpack_ty = ty.skip_reference().clone(); - } + }, move_model::ty::Type::Vector(_) => { unpack_ty = ty.get_vector_element_type().unwrap(); - } - _ => {} + }, + _ => {}, } - + if let move_model::ty::Type::Struct(mid, sid, _) = unpack_ty { let module_env = env.get_module(mid); let struct_env = module_env.get_struct(sid); @@ -383,7 +444,7 @@ impl Handler { definition_pos.line_end = def_loc.line.0; definition_pos.col_end = def_loc.column.0; } - } + } self.reuslts.push(mk_inlay_hits( Position { @@ -395,17 +456,9 @@ impl Handler { )); } - fn run_move_model_visitor_internal( - &mut self, - env: &GlobalEnv, - move_file_path: &Path - ) { - - let candidate_modules - = crate::utils::get_modules_by_fpath_in_all_modules( - env, - &PathBuf::from(move_file_path) - ); + fn run_move_model_visitor_internal(&mut self, env: &GlobalEnv, move_file_path: &Path) { + let candidate_modules = + crate::utils::get_modules_by_fpath_in_all_modules(env, &PathBuf::from(move_file_path)); if candidate_modules.is_empty() { log::info!("cannot get target module\n"); return; @@ -437,7 +490,7 @@ impl ItemOrAccessHandler for Handler { _services: &dyn HandleItemService, env: &GlobalEnv, move_file_path: &Path, - _: String + _: String, ) { self.run_move_model_visitor_internal(env, move_file_path); } @@ -445,10 +498,7 @@ impl ItemOrAccessHandler for Handler { impl std::fmt::Display for Handler { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "inlay hints" - ) + write!(f, "inlay hints") } } @@ -474,7 +524,6 @@ fn para_inlay_hints_parts(name: &str, label_pos: FileRange) -> InlayHintLabel { }]) } - fn mk_command(label_pos: FileRange) -> Option { Some(MoveAnalyzerClientCommands::GotoDefinition(label_pos.mk_location()).to_lsp_command()) -} \ No newline at end of file +} diff --git a/language/move-analyzer/src/item.rs b/language/move-analyzer/src/item.rs index acb73607f9..5bb22189d7 100644 --- a/language/move-analyzer/src/item.rs +++ b/language/move-analyzer/src/item.rs @@ -3,8 +3,7 @@ use enum_iterator::Sequence; #[derive(Clone)] -pub struct ItemStruct { -} +pub struct ItemStruct {} impl std::fmt::Display for ItemStruct { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -45,17 +44,13 @@ pub struct ItemUseItem { } #[derive(Clone)] -pub struct ItemModuleName { -} +pub struct ItemModuleName {} #[derive(Clone)] -pub struct ItemStructNameRef { - -} +pub struct ItemStructNameRef {} #[derive(Clone)] -pub struct ItemFun { -} +pub struct ItemFun {} #[derive(Clone, Copy, PartialEq, Eq)] pub enum AttrTest { @@ -71,8 +66,7 @@ impl Default for Item { } #[derive(Clone)] -pub struct ItemConst { -} +pub struct ItemConst {} #[derive(Clone)] pub enum Access { @@ -81,9 +75,7 @@ pub enum Access { } #[derive(Clone)] -pub struct AccessFiled { - -} +pub struct AccessFiled {} #[derive(Clone)] pub enum ItemOrAccess { diff --git a/language/move-analyzer/src/lib.rs b/language/move-analyzer/src/lib.rs index b9714906e1..841abdfdbe 100644 --- a/language/move-analyzer/src/lib.rs +++ b/language/move-analyzer/src/lib.rs @@ -7,7 +7,7 @@ extern crate move_ir_types; #[macro_export] macro_rules! impl_convert_loc { - ($struct_name : ident) => { + ($struct_name:ident) => { impl ConvertLoc for $struct_name { fn convert_file_hash_filepath(&self, hash: &FileHash) -> Option { self.hash_file @@ -16,6 +16,7 @@ macro_rules! impl_convert_loc { .get_path(hash) .map(|x| x.clone()) } + fn convert_loc_range(&self, loc: &Loc) -> Option { self.convert_file_hash_filepath(&loc.file_hash()) .map(|file| { @@ -32,22 +33,22 @@ macro_rules! impl_convert_loc { } pub mod analyzer_handler; +pub mod completion; pub mod context; pub mod diagnostics; pub mod goto_definition; +pub mod hover; +pub mod inlay_hints; pub mod item; pub mod multiproject; pub mod project; pub mod project_manager; -pub mod utils; pub mod references; -pub mod hover; -pub mod completion; -pub mod inlay_hints; +pub mod utils; pub mod move_generate_spec; +pub mod move_generate_spec_file; pub mod move_generate_spec_sel; pub mod move_generate_spec_utils; -pub mod move_generate_spec_file; pub mod symbols; -pub mod type_display_for_spec; \ No newline at end of file +pub mod type_display_for_spec; diff --git a/language/move-analyzer/src/move_generate_spec.rs b/language/move-analyzer/src/move_generate_spec.rs index a989ce849a..474d86595e 100644 --- a/language/move-analyzer/src/move_generate_spec.rs +++ b/language/move-analyzer/src/move_generate_spec.rs @@ -1,17 +1,20 @@ // Copyright (c) The BitsLab.MoveBit Contributors // SPDX-License-Identifier: Apache-2.0 -use std::{collections::HashMap, ops::Deref}; +use crate::{ + move_generate_spec_utils::{BinOPReason, SpecExpItem}, + type_display_for_spec::TypeDisplayForSpec, +}; use move_model::{ - model::{GlobalEnv, ModuleEnv, FunctionEnv, StructEnv}, - ty::{TypeDisplayContext, Type as MoveModelType}, ast::{ - Exp as MoveModelExp, ExpData as MoveModelExpData, - Operation as MoveModelOperation, ModuleName - }, symbol::Symbol, + Exp as MoveModelExp, ExpData as MoveModelExpData, ModuleName, + Operation as MoveModelOperation, + }, + model::{FunctionEnv, GlobalEnv, ModuleEnv, StructEnv}, + symbol::Symbol, + ty::{Type as MoveModelType, TypeDisplayContext}, }; -use crate::type_display_for_spec::TypeDisplayForSpec; -use crate::move_generate_spec_utils::{SpecExpItem, BinOPReason}; +use std::{collections::HashMap, ops::Deref}; #[derive(Default)] pub struct StructSpecGenerator { @@ -22,13 +25,19 @@ impl StructSpecGenerator { pub(crate) fn new() -> Self { Self::default() } + pub(crate) fn get_result_string(self) -> String { self.result } + pub(crate) fn generate(&mut self, x: &StructEnv) { - self.result - .push_str(format!("{}spec {}", indent(1), - x.get_name().display(x.symbol_pool())).as_str() + self.result.push_str( + format!( + "{}spec {}", + indent(1), + x.get_name().display(x.symbol_pool()) + ) + .as_str(), ); self.result.push_str("{\n"); self.result.push_str(format!("{}}}\n", indent(1)).as_str()) @@ -41,15 +50,14 @@ pub struct FunSpecGenerator { } pub fn generate_fun_spec_zx( - global_env: &GlobalEnv, + global_env: &GlobalEnv, module_env: &ModuleEnv, - f: &FunctionEnv, + f: &FunctionEnv, using_module_map: &HashMap>, ) -> String { let mut g = FunSpecGenerator::new(); g.generate_zx(global_env, module_env, f, using_module_map); g.get_result_string() - } pub fn genrate_struct_spec(s: &StructEnv) -> String { @@ -62,19 +70,18 @@ impl FunSpecGenerator { pub(crate) fn new() -> Self { Self::default() } + pub(crate) fn get_result_string(self) -> String { self.result } pub(crate) fn generate_zx( - &mut self, - global_env: &GlobalEnv, + &mut self, + global_env: &GlobalEnv, module_env: &ModuleEnv, - f: &FunctionEnv, + f: &FunctionEnv, using_module_map: &HashMap>, ) { - - let display_context = f.get_type_display_ctx(); self.result .push_str(format!("{}spec {}", indent(1), f.get_name_str()).as_str()); @@ -82,13 +89,12 @@ impl FunSpecGenerator { let generics = if !f.get_type_parameters().is_empty() { format!( "<{}>", - f.get_type_parameters() + f.get_type_parameters() .iter() .map(|p| p.0.display(f.symbol_pool()).to_string()) .collect::>() - .join(",") - ) + ) } else { "".to_owned() }; @@ -98,7 +104,8 @@ impl FunSpecGenerator { let para_len = f.get_parameter_count(); if para_len > 0 { for (index, para) in f.get_parameters().iter().enumerate() { - self.result.push_str(para.0.display(f.symbol_pool()).to_string().as_str()); + self.result + .push_str(para.0.display(f.symbol_pool()).to_string().as_str()); self.result.push_str(": "); let display_context_para = TypeDisplayForSpec { type_: ¶.1, @@ -114,7 +121,7 @@ impl FunSpecGenerator { } } self.result.push(')'); - + let return_type = f.get_result_type(); let display_context_return = TypeDisplayForSpec { type_: &return_type, @@ -123,7 +130,7 @@ impl FunSpecGenerator { using_module_map, }; let mut return_type_string = display_context_return.to_string(); - + return_type_string.insert_str(0, ": "); if let MoveModelType::Tuple(_) = return_type { // ": ()" len is 4 @@ -138,15 +145,10 @@ impl FunSpecGenerator { self.result.push_str(format!("{}}}\n", indent(1)).as_str()); } - fn generate_body_zx(&self, f: &FunctionEnv, global_env: &GlobalEnv) -> String { + fn generate_body_zx(&self, f: &FunctionEnv, global_env: &GlobalEnv) -> String { let mut statements = String::new(); if let Some(exp) = f.get_def().deref() { - FunSpecGenerator::try_emit_exp_zx( - self, - &mut statements, - exp, - global_env, - ); + FunSpecGenerator::try_emit_exp_zx(self, &mut statements, exp, global_env); } else { log::trace!("body is none"); return statements; @@ -157,24 +159,23 @@ impl FunSpecGenerator { } impl FunSpecGenerator { - fn try_emit_exp_zx( - &self, - statements: &mut String, - exp: &MoveModelExp, - env: &GlobalEnv, - ) { - let items = FunSpecGenerator::collect_spec_exp_zx(self, exp, env); + fn try_emit_exp_zx(&self, statements: &mut String, exp: &MoveModelExp, env: &GlobalEnv) { + let items = FunSpecGenerator::collect_spec_exp_zx(self, exp, env); let display_context = &TypeDisplayContext::new(env); for item in items.iter() { match item { - SpecExpItem::BinOP { reason, left, right } => { + SpecExpItem::BinOP { + reason, + left, + right, + } => { let _left_node_id = left.as_ref().node_id(); let _right_node_id = right.as_ref().node_id(); let _left_node_loc = env.get_node_loc(_left_node_id); let _right_node_loc = env.get_node_loc(_right_node_id); let _left_node_type = env.get_node_type(_left_node_id); let _right_node_type = env.get_node_type(_right_node_id); - + let _left_exp_str = match env.get_source(&_left_node_loc) { Ok(x) => x, Err(_) => continue, @@ -185,44 +186,46 @@ impl FunSpecGenerator { Err(_) => continue, }; - if *reason != BinOPReason::DivByZero - && !FunSpecGenerator::is_support_exp(left, env) + if *reason != BinOPReason::DivByZero + && !FunSpecGenerator::is_support_exp(left, env) { - continue; + continue; } - if !FunSpecGenerator::is_support_exp(right , env) { + if !FunSpecGenerator::is_support_exp(right, env) { continue; } match reason { - BinOPReason::OverFlowADD - | BinOPReason::OverFlowMUL + BinOPReason::OverFlowADD + | BinOPReason::OverFlowMUL | BinOPReason::OverFlowSHL => { - let over_type = format!("MAX_{}", _left_node_type.display(display_context).to_string().to_uppercase()); + let over_type = format!( + "MAX_{}", + _left_node_type + .display(display_context) + .to_string() + .to_uppercase() + ); let statements_abort_if = format!( - "{}aborts_if {} {} {} > {};\n", - indent(2), - _left_exp_str, - match reason { - BinOPReason::OverFlowADD => "+", - BinOPReason::OverFlowMUL => "*", - BinOPReason::OverFlowSHL => "<<", - _ => unreachable!(), - }, - _right_exp_str, - over_type - ); + "{}aborts_if {} {} {} > {};\n", + indent(2), + _left_exp_str, + match reason { + BinOPReason::OverFlowADD => "+", + BinOPReason::OverFlowMUL => "*", + BinOPReason::OverFlowSHL => "<<", + _ => unreachable!(), + }, + _right_exp_str, + over_type + ); statements.push_str(statements_abort_if.as_str()); }, BinOPReason::DivByZero => { statements.push_str( - format!( - "{}aborts_if {} == 0;\n", - indent(2), - _right_exp_str, - ) - .as_str(), + format!("{}aborts_if {} == 0;\n", indent(2), _right_exp_str,) + .as_str(), ); }, BinOPReason::UnderFlow => { @@ -238,19 +241,26 @@ impl FunSpecGenerator { }, }; }, - SpecExpItem::MarcoAbort{if_exp, abort_exp} => { - if let MoveModelExpData::Call(_, op, _) = if_exp.as_ref() { + SpecExpItem::MarcoAbort { if_exp, abort_exp } => { + if let MoveModelExpData::Call(_, op, _) = if_exp.as_ref() { match op { - MoveModelOperation::Eq | MoveModelOperation::Neq | - MoveModelOperation::Lt | MoveModelOperation::Gt | - MoveModelOperation::Le | MoveModelOperation::Ge => { - FunSpecGenerator::handle_binop_exp(statements, if_exp, op, abort_exp, env); - } + MoveModelOperation::Eq + | MoveModelOperation::Neq + | MoveModelOperation::Lt + | MoveModelOperation::Gt + | MoveModelOperation::Le + | MoveModelOperation::Ge => { + FunSpecGenerator::handle_binop_exp( + statements, if_exp, op, abort_exp, env, + ); + }, MoveModelOperation::MoveFunction(_, _) => { - FunSpecGenerator::handle_funcop_exp(statements, if_exp, abort_exp, env); - } - _ => {} - } + FunSpecGenerator::handle_funcop_exp( + statements, if_exp, abort_exp, env, + ); + }, + _ => {}, + } } }, SpecExpItem::PatternLet { left, right } => { @@ -260,10 +270,10 @@ impl FunSpecGenerator { Ok(x) => x, Err(_) => continue, }; - + statements.push_str(format!("{}let ", indent(2)).as_str()); statements.push_str(_left_exp_str); - + statements.push_str(" = "); let _right_node_id = right.as_ref().node_id(); let _right_node_loc = env.get_node_loc(_right_node_id); @@ -273,16 +283,21 @@ impl FunSpecGenerator { }; statements.push_str(_right_exp_str); statements.push_str(";\n"); - }, SpecExpItem::BorrowGlobalMut { .. } => {}, SpecExpItem::TypeName { .. } => {}, - SpecExpItem::TypeOf { .. } => {} + SpecExpItem::TypeOf { .. } => {}, } } } - fn handle_binop_exp(statements: &mut String, if_exp: &MoveModelExp, op: &MoveModelOperation, abort_exp: &MoveModelExp, env: &GlobalEnv) { + fn handle_binop_exp( + statements: &mut String, + if_exp: &MoveModelExp, + op: &MoveModelOperation, + abort_exp: &MoveModelExp, + env: &GlobalEnv, + ) { fn inverse_binop_zx(op: &MoveModelOperation) -> (String, String) { match op { MoveModelOperation::Eq => (String::from("=="), String::from("!=")), @@ -294,16 +309,16 @@ impl FunSpecGenerator { _ => (String::from("_"), String::from("_")), } } - + let op2 = inverse_binop_zx(op); - + let if_exp_node_id = if_exp.as_ref().node_id(); let if_exp_node_loc = env.get_node_loc(if_exp_node_id); let if_exp_str = match env.get_source(&if_exp_node_loc) { Ok(x) => x, Err(_) => return, }; - + #[allow(unused_assignments)] let mut if_exp_inverse_str = String::new(); if if_exp_str.contains(op2.0.as_str()) { @@ -330,7 +345,12 @@ impl FunSpecGenerator { ); } - fn handle_funcop_exp(statements: &mut String, if_exp: &MoveModelExp, abort_exp: &MoveModelExp, env: &GlobalEnv) { + fn handle_funcop_exp( + statements: &mut String, + if_exp: &MoveModelExp, + abort_exp: &MoveModelExp, + env: &GlobalEnv, + ) { let if_exp_node_id = if_exp.as_ref().node_id(); let if_exp_node_loc = env.get_node_loc(if_exp_node_id); let if_exp_str = match env.get_source(&if_exp_node_loc) { @@ -360,6 +380,3 @@ impl FunSpecGenerator { pub(crate) fn indent(num: usize) -> String { " ".to_string().repeat(num) } - - - diff --git a/language/move-analyzer/src/move_generate_spec_file.rs b/language/move-analyzer/src/move_generate_spec_file.rs index 1af88b4ab4..88546e2d35 100644 --- a/language/move-analyzer/src/move_generate_spec_file.rs +++ b/language/move-analyzer/src/move_generate_spec_file.rs @@ -1,18 +1,25 @@ // Copyright (c) The BitsLab.MoveBit Contributors // SPDX-License-Identifier: Apache-2.0 -use std::{collections::HashMap, path::PathBuf, str::FromStr, path::Path}; use super::move_generate_spec::*; -use lsp_server::*; -use serde::Deserialize; - use crate::{ - utils::{get_modules_by_fpath_in_target_modules, collect_use_decl}, context::Context, + utils::{collect_use_decl, get_modules_by_fpath_in_target_modules}, +}; +use lsp_server::*; +use move_model::model::{FunctionEnv, StructEnv}; +use serde::Deserialize; +use std::{ + collections::HashMap, + path::{Path, PathBuf}, + str::FromStr, }; -use move_model::model::{StructEnv, FunctionEnv}; -pub fn on_generate_spec_file<'a>(context: &Context, request: &Request, is_generate: bool) -> Response +pub fn on_generate_spec_file<'a>( + context: &Context, + request: &Request, + is_generate: bool, +) -> Response where 'a: 'static, { @@ -46,13 +53,17 @@ where result: Some(serde_json::json!({"msg": "project not found."})), error: None, }; - } + }, }; - + let addrname_2_addrnum = &project.addrname_2_addrnum; let mut result = ModuleSpecBuilder::new(); for module_env in get_modules_by_fpath_in_target_modules(&project.global_env, &fpath) { - let using_module_map = collect_use_decl(&project.addrname_2_addrnum, &module_env, &project.global_env); + let using_module_map = collect_use_decl( + &project.addrname_2_addrnum, + &module_env, + &project.global_env, + ); log::info!("generate spec module: {}", module_env.get_full_name_str()); // find module_env's namespace @@ -61,47 +72,51 @@ where let addr = module_env_full_name[0..addr_end].to_string(); let addr_name_default = String::from("0x0"); let addr_name = addrname_2_addrnum.get(&addr).unwrap_or(&addr_name_default); - let module_name = module_env_full_name[addr_end+2..].to_string(); + let module_name = module_env_full_name[addr_end + 2..].to_string(); // find all available StructEnv and FunctionEnv let mut env_item_list: Vec = module_env - .get_functions() - .filter(|fun_env| !fun_env.is_test_only()) - .map(|fun_env| EnvItem { - struct_env: None, - function_env: Some(fun_env.clone()), - line: fun_env.get_loc().span().start().0, - }) - .chain( - module_env - .get_structs() - .filter(|struct_env| !struct_env.is_test_only()) - .map(|struct_env| EnvItem { - struct_env: Some(struct_env.clone()), - function_env: None, - line: struct_env.get_loc().span().start().0, - }), - ) - .collect(); - + .get_functions() + .filter(|fun_env| !fun_env.is_test_only()) + .map(|fun_env| EnvItem { + struct_env: None, + function_env: Some(fun_env.clone()), + line: fun_env.get_loc().span().start().0, + }) + .chain( + module_env + .get_structs() + .filter(|struct_env| !struct_env.is_test_only()) + .map(|struct_env| EnvItem { + struct_env: Some(struct_env.clone()), + function_env: None, + line: struct_env.get_loc().span().start().0, + }), + ) + .collect(); + env_item_list.sort_by(|a, b| a.line.cmp(&b.line)); for item in env_item_list { let spec = match item { - EnvItem { struct_env: Some(struct_env), function_env: None, .. } => { - genrate_struct_spec(&struct_env) - } - EnvItem { struct_env: None, function_env: Some(f_env), .. } => { - generate_fun_spec_zx( - &project.global_env, - &module_env, - &f_env, - &using_module_map, - ) - } + EnvItem { + struct_env: Some(struct_env), + function_env: None, + .. + } => genrate_struct_spec(&struct_env), + EnvItem { + struct_env: None, + function_env: Some(f_env), + .. + } => generate_fun_spec_zx( + &project.global_env, + &module_env, + &f_env, + &using_module_map, + ), _ => continue, }; - + result.insert( AddrAndModuleName::new(addr_name.clone(), module_name.clone()), spec, @@ -112,7 +127,7 @@ where let file_content = result.get_result_string(); if is_generate { match std::fs::write(result_file_path.clone(), file_content.clone()) { - Ok(_) => {} + Ok(_) => {}, Err(err) => { send_err(context, format!("write to file failed,err:{:?}", err)); return lsp_server::Response { @@ -120,10 +135,9 @@ where result: Some(serde_json::json!({"msg": "write to file failed"})), error: None, }; - } + }, }; } - let r = Response::new_ok( request.id.clone(), @@ -138,10 +152,7 @@ where .send(Message::Response(r)) .unwrap(); - Response::new_ok( - request.id.clone(), - serde_json::json!(file_content) - ) + Response::new_ok(request.id.clone(), serde_json::json!(file_content)) } #[derive(Debug, Clone)] @@ -159,14 +170,13 @@ impl<'a> PartialEq for EnvItem<'a> { impl<'a> Eq for EnvItem<'a> {} - impl<'a> Ord for EnvItem<'a> { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.line.cmp(&other.line) } } -impl<'a> PartialOrd for EnvItem<'a> { +impl<'a> PartialOrd for EnvItem<'a> { fn partial_cmp(&self, other: &Self) -> Option { Some(self.line.cmp(&other.line)) } @@ -181,6 +191,7 @@ impl ModuleSpecBuilder { fn new() -> Self { Self::default() } + fn insert(&mut self, k: AddrAndModuleName, v: String) { if let Some(x) = self.results.get_mut(&k) { x.push(v); @@ -188,16 +199,18 @@ impl ModuleSpecBuilder { self.results.insert(k, vec![v]); } } + fn get_result_string(self) -> String { let mut ret = String::new(); for (k, vv) in self.results.into_iter() { let mut x = String::default(); x.push_str( - format!("spec {}::{} {{\n\n", - &k.addr_name.as_str(), + format!( + "spec {}::{} {{\n\n", + &k.addr_name.as_str(), &k.module_name.as_str() ) - .as_str() + .as_str(), ); x.push_str(format!("{}spec module {{\n", indent(1)).as_str()); x.push_str(format!("{}pragma verify = true;\n", indent(2)).as_str()); @@ -221,7 +234,10 @@ pub struct AddrAndModuleName { impl AddrAndModuleName { fn new(addr_name: String, module_name: String) -> Self { - Self { addr_name, module_name } + Self { + addr_name, + module_name, + } } } #[derive(Clone, Deserialize)] @@ -246,11 +262,7 @@ impl Resp { let index = b.as_str().rfind('.').unwrap(); x.pop(); let mut ret = x.clone(); - ret.push(format!( - "{}{}", - &b.as_str()[0..index], - ".spec.move" - )); + ret.push(format!("{}{}", &b.as_str()[0..index], ".spec.move")); ret } } diff --git a/language/move-analyzer/src/move_generate_spec_sel.rs b/language/move-analyzer/src/move_generate_spec_sel.rs index 00e2487bad..9707777892 100644 --- a/language/move-analyzer/src/move_generate_spec_sel.rs +++ b/language/move-analyzer/src/move_generate_spec_sel.rs @@ -2,35 +2,36 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - utils::{GetPosition, get_modules_by_fpath_in_target_modules, collect_use_decl}, - project::Project, context::Context, - move_generate_spec::{genrate_struct_spec, generate_fun_spec_zx}, - + move_generate_spec::{generate_fun_spec_zx, genrate_struct_spec}, + project::Project, + utils::{collect_use_decl, get_modules_by_fpath_in_target_modules, GetPosition}, }; -use move_model::model::{ModuleEnv, GlobalEnv, Loc}; -use std::{path::PathBuf, str::FromStr, collections::HashMap}; -use serde::{Deserialize, Serialize}; -use lsp_server::{*, Message, Request, Response}; use codespan::Location; -use move_model::ast::ModuleName; -use move_model::symbol::Symbol as SpecSymbol; +use lsp_server::{Message, Request, Response, *}; +use move_model::{ + ast::ModuleName, + model::{GlobalEnv, Loc, ModuleEnv}, + symbol::Symbol as SpecSymbol, +}; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, path::PathBuf, str::FromStr}; pub fn on_generate_spec_sel(context: &mut Context, request: &Request) -> Response { log::info!("on_generate_spec_sel request = {:?}", request); let parameters = serde_json::from_value::(request.params.clone()) .expect("could not deserialize generate spec request"); - + let parameters = match ReqParametersPath::try_from(parameters) { Ok(p) => p, Err(_) => { - send_err(context, request,"not a valid path".to_string()); + send_err(context, request, "not a valid path".to_string()); return lsp_server::Response { id: "".to_string().into(), result: Some(serde_json::json!({"msg": "not a valid path"})), error: None, }; - } + }, }; let project = match context.projects.get_project(¶meters.fpath) { @@ -42,24 +43,34 @@ pub fn on_generate_spec_sel(context: &mut Context, request: &Request) -> Respons result: Some(serde_json::json!({"msg": "No available project"})), error: None, }; - } + }, }; - let mut insert_pos: (u32, u32) = (0,0); - let mut result_string :String = String::new(); + let mut insert_pos: (u32, u32) = (0, 0); + let mut result_string: String = String::new(); let mut is_find = false; - for module_env in get_modules_by_fpath_in_target_modules(&project.global_env, ¶meters.fpath) { + for module_env in get_modules_by_fpath_in_target_modules(&project.global_env, ¶meters.fpath) + { log::info!("collect_use_decl"); - let using_module_map = collect_use_decl(&project.addrname_2_addrnum, &module_env, &project.global_env); + let using_module_map = collect_use_decl( + &project.addrname_2_addrnum, + &module_env, + &project.global_env, + ); - if handle_struct(project, &module_env, ¶meters, &mut insert_pos, &mut result_string) - || handle_function( - project, + if handle_struct( + project, + &module_env, + ¶meters, + &mut insert_pos, + &mut result_string, + ) || handle_function( + project, &module_env, using_module_map, ¶meters, &mut insert_pos, - &mut result_string + &mut result_string, ) { is_find = true; break; @@ -67,7 +78,7 @@ pub fn on_generate_spec_sel(context: &mut Context, request: &Request) -> Respons } if !is_find { - send_err(context, request,"spec target not found.".to_string()); + send_err(context, request, "spec target not found.".to_string()); return lsp_server::Response { id: "".to_string().into(), result: Some(serde_json::json!({"msg": "spec target not found"})), @@ -75,11 +86,11 @@ pub fn on_generate_spec_sel(context: &mut Context, request: &Request) -> Respons }; } - let result = Some(Resp {line: insert_pos.0, - col: insert_pos.1, - content: result_string.clone(), - } - ); + let result = Some(Resp { + line: insert_pos.0, + col: insert_pos.1, + content: result_string.clone(), + }); let r = Response::new_ok(request.id.clone(), serde_json::to_value(result).unwrap()); context @@ -99,21 +110,30 @@ fn send_err(context: &Context, requset: &Request, msg: String) { .unwrap(); } -fn handle_struct(project :&Project, module_env : &ModuleEnv, - parameters: &ReqParametersPath, insert_pos: &mut(u32, u32), - result_string: &mut String) -> bool -{ +fn handle_struct( + project: &Project, + module_env: &ModuleEnv, + parameters: &ReqParametersPath, + insert_pos: &mut (u32, u32), + result_string: &mut String, +) -> bool { for struct_env in module_env.get_structs() { if struct_env.is_test_only() { continue; } - - if !ReqParametersPath::is_linecol_in_loc(parameters.line, parameters.col, - &struct_env.get_loc(), &project.global_env) - { + + if !ReqParametersPath::is_linecol_in_loc( + parameters.line, + parameters.col, + &struct_env.get_loc(), + &project.global_env, + ) { continue; } - let end_location = match ReqParametersPath::get_loc_end_location(&struct_env.get_loc(), &project.global_env) { + let end_location = match ReqParametersPath::get_loc_end_location( + &struct_env.get_loc(), + &project.global_env, + ) { Some(x) => x, None => return false, }; @@ -124,39 +144,46 @@ fn handle_struct(project :&Project, module_env : &ModuleEnv, insert_pos.0 = end_location.line.0; insert_pos.1 = 4; - if ReqParametersPath::is_linecol_in_loc(new_parameters.line, new_parameters.col, - &module_env.get_loc(), &project.global_env) - { + if ReqParametersPath::is_linecol_in_loc( + new_parameters.line, + new_parameters.col, + &module_env.get_loc(), + &project.global_env, + ) { insert_pos.0 += 1; } result_string.push_str(genrate_struct_spec(&struct_env).as_str()); - + return true; } false } fn handle_function( - project :&Project, - module_env : &ModuleEnv, + project: &Project, + module_env: &ModuleEnv, using_module_map: HashMap>, - parameters: &ReqParametersPath, - insert_pos: &mut(u32, u32), - result_string: &mut String -) -> bool -{ + parameters: &ReqParametersPath, + insert_pos: &mut (u32, u32), + result_string: &mut String, +) -> bool { for func_env in module_env.get_functions() { - if !ReqParametersPath::is_linecol_in_loc(parameters.line, parameters.col, - &func_env.get_loc(), &project.global_env) - { + if !ReqParametersPath::is_linecol_in_loc( + parameters.line, + parameters.col, + &func_env.get_loc(), + &project.global_env, + ) { continue; } - let end_location = match ReqParametersPath::get_loc_end_location(&func_env.get_loc(), &project.global_env) { - Some(x) => x, - None => return false, - }; + let end_location = + match ReqParametersPath::get_loc_end_location(&func_env.get_loc(), &project.global_env) + { + Some(x) => x, + None => return false, + }; let mut new_parameters = parameters.clone(); new_parameters.line = end_location.line.0 + 1; @@ -165,27 +192,29 @@ fn handle_function( insert_pos.0 = end_location.line.0; insert_pos.1 = end_location.column.0; - if ReqParametersPath::is_linecol_in_loc(new_parameters.line, new_parameters.col, - &module_env.get_loc(), &project.global_env) - { + if ReqParametersPath::is_linecol_in_loc( + new_parameters.line, + new_parameters.col, + &module_env.get_loc(), + &project.global_env, + ) { insert_pos.0 += 1; } - + result_string.push_str( generate_fun_spec_zx( - &project.global_env, + &project.global_env, module_env, - &func_env, + &func_env, &using_module_map, - ).as_str() + ) + .as_str(), ); return true; } false } - - #[derive(Clone, Deserialize)] pub struct ReqParameters { fpath: String, @@ -202,6 +231,7 @@ pub struct ReqParametersPath { impl TryFrom for ReqParametersPath { type Error = core::convert::Infallible; + fn try_from(value: ReqParameters) -> Result { match PathBuf::from_str(value.fpath.as_str()) { Ok(x) => Ok(Self { @@ -221,7 +251,7 @@ impl GetPosition for ReqParametersPath { } impl ReqParametersPath { - pub fn is_linecol_in_loc(line :u32, col :u32, loc : &Loc, env:&GlobalEnv) -> bool { + pub fn is_linecol_in_loc(line: u32, col: u32, loc: &Loc, env: &GlobalEnv) -> bool { let start_location = match env.get_location(loc) { Some(x) => x, None => return false, @@ -232,7 +262,6 @@ impl ReqParametersPath { None => return false, }; - if line < start_location.line.0 { return false; } @@ -250,23 +279,16 @@ impl ReqParametersPath { } fn get_loc_end_location(loc: &Loc, env: &GlobalEnv) -> Option { - env.get_location( - &move_model::model::Loc::new( - loc.file_id(), - codespan::Span::new( - loc.span().end(), - loc.span().end() - ) - ) - ) + env.get_location(&move_model::model::Loc::new( + loc.file_id(), + codespan::Span::new(loc.span().end(), loc.span().end()), + )) } } - - #[derive(Clone, Serialize)] pub struct Resp { pub line: u32, pub col: u32, pub content: String, -} \ No newline at end of file +} diff --git a/language/move-analyzer/src/move_generate_spec_utils.rs b/language/move-analyzer/src/move_generate_spec_utils.rs index 3afcb7442d..384b35ec0e 100644 --- a/language/move-analyzer/src/move_generate_spec_utils.rs +++ b/language/move-analyzer/src/move_generate_spec_utils.rs @@ -1,18 +1,18 @@ // Copyright (c) The BitsLab.MoveBit Contributors // SPDX-License-Identifier: Apache-2.0 -use std::collections::HashMap; +use super::move_generate_spec::FunSpecGenerator; use im::HashSet; use move_model::{ + ast::{ + Address as MoveModelAddress, Exp as MoveModelExp, ExpData as MoveModelExpData, ModuleName, + Operation, Pattern as MoveModelPattern, Value as MoveModelValue, + }, + model::{FunctionEnv, GlobalEnv, NodeId}, symbol::Symbol, - ast::{ModuleName, Operation}, - model::{GlobalEnv, NodeId, FunctionEnv}, - ast::{Exp as MoveModelExp, ExpData as MoveModelExpData, Value as MoveModelValue, - Address as MoveModelAddress, Pattern as MoveModelPattern}, ty::Type as MoveModelType, }; - -use super::move_generate_spec::FunSpecGenerator; +use std::collections::HashMap; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct ShadowItemUseItem { @@ -38,7 +38,6 @@ pub struct ShadowItemLocal { pub index: NodeId, } - pub enum ShadowItem { Use(ShadowItemUse), Local(ShadowItemLocal), @@ -86,31 +85,30 @@ pub fn get_shadows(exp: &MoveModelExp, env: &GlobalEnv, shadows: &mut ShadowItem }, MoveModelExpData::Invoke(_, _, _) => {}, MoveModelExpData::Lambda(_, _, _) => {}, - MoveModelExpData::Quant(_,_,_,_,_,_) => {}, - MoveModelExpData::Block(_,p,s,exp) => { + MoveModelExpData::Quant(_, _, _, _, _, _) => {}, + MoveModelExpData::Block(_, p, s, exp) => { handle_expdata_block_parren(p, shadows); if let Some(op_exp) = s { get_shadows(op_exp, env, shadows); } get_shadows(exp, env, shadows) }, - MoveModelExpData::IfElse(_,if_exp,if_do_exp,else_do_exp) => { + MoveModelExpData::IfElse(_, if_exp, if_do_exp, else_do_exp) => { get_shadows(if_exp, env, shadows); get_shadows(if_do_exp, env, shadows); get_shadows(else_do_exp, env, shadows); }, - MoveModelExpData::Return(_,_) => {}, - MoveModelExpData::Sequence(_,vec_exp) => { - + MoveModelExpData::Return(_, _) => {}, + MoveModelExpData::Sequence(_, vec_exp) => { for exp in vec_exp.iter() { get_shadows(exp, env, shadows); } }, - MoveModelExpData::Loop(_,_) => {}, - MoveModelExpData::LoopCont(_,_) => {}, - MoveModelExpData::Assign(_,_,_) => {}, - MoveModelExpData::Mutate(_,_,_) => {}, - MoveModelExpData::SpecBlock(_,_) => {}, + MoveModelExpData::Loop(_, _) => {}, + MoveModelExpData::LoopCont(_, _) => {}, + MoveModelExpData::Assign(_, _, _) => {}, + MoveModelExpData::Mutate(_, _, _) => {}, + MoveModelExpData::SpecBlock(_, _) => {}, } } @@ -138,23 +136,15 @@ pub fn handle_expdata_value(v: &MoveModelValue, env: &GlobalEnv) { #[allow(unused_variables)] pub fn handle_expdata_value_address(addr: &MoveModelAddress, env: &GlobalEnv) { match addr { - MoveModelAddress::Numerical(_) => { - }, - MoveModelAddress::Symbolic(_) => { - }, + MoveModelAddress::Numerical(_) => {}, + MoveModelAddress::Symbolic(_) => {}, } } -pub fn handle_expdata_block_parren( - p: &MoveModelPattern, - shadows: &mut ShadowItems -) { +pub fn handle_expdata_block_parren(p: &MoveModelPattern, shadows: &mut ShadowItems) { let vec_sym = p.vars(); for (node_id, sym) in vec_sym.iter() { - shadows.insert( - *sym, - ShadowItem::Local(ShadowItemLocal { index:*node_id }) - ); + shadows.insert(*sym, ShadowItem::Local(ShadowItemLocal { index: *node_id })); } } @@ -181,12 +171,11 @@ pub(crate) enum SpecExpItem { right: MoveModelExp, }, MarcoAbort { - if_exp:MoveModelExp, + if_exp: MoveModelExp, abort_exp: MoveModelExp, - } + }, } - #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub(crate) enum BinOPReason { OverFlowADD, @@ -198,9 +187,9 @@ pub(crate) enum BinOPReason { impl FunSpecGenerator { fn collect_spec_exp_op_movefunc( - &self, + &self, ret: &mut Vec, - func_env: &FunctionEnv, + func_env: &FunctionEnv, vec_exp: &Vec, ) { const TYPE_OF: &str = "type_of"; @@ -209,33 +198,26 @@ impl FunSpecGenerator { match func_env.get_name_str().as_str() { "borrow_global_mut" if !para.is_empty() && !vec_exp.is_empty() => { ret.push(SpecExpItem::BorrowGlobalMut { - ty: para.get(0).unwrap().1.clone(), - addr: vec_exp.get(0).unwrap().clone(), - } - ) - }, - TYPE_OF if !para.is_empty() => { - ret.push(SpecExpItem::TypeOf { - ty: para.get(0).unwrap().1.clone(), - } - ) - }, - TYPE_NAME if !para.is_empty() => { - ret.push(SpecExpItem::TypeName { - ty: para.get(0).unwrap().1.clone(), - } - ) + ty: para.get(0).unwrap().1.clone(), + addr: vec_exp.get(0).unwrap().clone(), + }) }, - _ => {} + TYPE_OF if !para.is_empty() => ret.push(SpecExpItem::TypeOf { + ty: para.get(0).unwrap().1.clone(), + }), + TYPE_NAME if !para.is_empty() => ret.push(SpecExpItem::TypeName { + ty: para.get(0).unwrap().1.clone(), + }), + _ => {}, } } fn collect_spec_exp_op( - &self, - ret: &mut Vec, + &self, + ret: &mut Vec, op: &Operation, vec_exp: &Vec, - env: &GlobalEnv + env: &GlobalEnv, ) { match op { Operation::Add => { @@ -243,66 +225,60 @@ impl FunSpecGenerator { self.collect_spec_exp_(ret, exp, env); } ret.push(SpecExpItem::BinOP { - reason: BinOPReason::OverFlowADD, - left: vec_exp[0].clone(), - right: vec_exp[1].clone(), - } - ); + reason: BinOPReason::OverFlowADD, + left: vec_exp[0].clone(), + right: vec_exp[1].clone(), + }); }, Operation::Sub => { for exp in vec_exp.iter() { self.collect_spec_exp_(ret, exp, env); } ret.push(SpecExpItem::BinOP { - reason: BinOPReason::UnderFlow, - left: vec_exp[0].clone(), - right: vec_exp[1].clone(), - } - ); + reason: BinOPReason::UnderFlow, + left: vec_exp[0].clone(), + right: vec_exp[1].clone(), + }); }, Operation::Mul => { for exp in vec_exp.iter() { self.collect_spec_exp_(ret, exp, env); } ret.push(SpecExpItem::BinOP { - reason: BinOPReason::OverFlowMUL, - left: vec_exp[0].clone(), - right: vec_exp[1].clone(), - } - ); + reason: BinOPReason::OverFlowMUL, + left: vec_exp[0].clone(), + right: vec_exp[1].clone(), + }); }, Operation::Mod => { for exp in vec_exp.iter() { self.collect_spec_exp_(ret, exp, env); } ret.push(SpecExpItem::BinOP { - reason: BinOPReason::DivByZero, - left:vec_exp[0].clone(), - right: vec_exp[1].clone(), - } - ); + reason: BinOPReason::DivByZero, + left: vec_exp[0].clone(), + right: vec_exp[1].clone(), + }); }, Operation::Div => { for exp in vec_exp.iter() { self.collect_spec_exp_(ret, exp, env); } ret.push(SpecExpItem::BinOP { - reason: BinOPReason::DivByZero, - left:vec_exp[0].clone(), - right: vec_exp[1].clone(), - } - ); + reason: BinOPReason::DivByZero, + left: vec_exp[0].clone(), + right: vec_exp[1].clone(), + }); }, Operation::Shl => { for exp in vec_exp.iter() { self.collect_spec_exp_(ret, exp, env); } ret.push(SpecExpItem::BinOP { - reason: BinOPReason::OverFlowSHL, - left: vec_exp[0].clone(), - right: vec_exp[1].clone(), - } - ); + reason: BinOPReason::OverFlowSHL, + left: vec_exp[0].clone(), + right: vec_exp[1].clone(), + }); }, Operation::Cast => { for exp in vec_exp.iter() { @@ -313,12 +289,12 @@ impl FunSpecGenerator { for exp in vec_exp.iter() { self.collect_spec_exp_(ret, exp, env); } - } + }, Operation::Pack(_, _) => { for exp in vec_exp.iter() { self.collect_spec_exp_(ret, exp, env); } - } + }, Operation::Vector => { for exp in vec_exp.iter() { self.collect_spec_exp_(ret, exp, env); @@ -344,53 +320,51 @@ impl FunSpecGenerator { self.collect_spec_exp_(ret, exp, env); } }, - Operation::MoveFunction(module_id, func_id) => { + Operation::MoveFunction(module_id, func_id) => { self.collect_spec_exp_op_movefunc( - ret, + ret, &env.get_function(module_id.qualified(*func_id)), - vec_exp + vec_exp, ); - } + }, Operation::Tuple => { for exp in vec_exp.iter() { self.collect_spec_exp_(ret, exp, env); - } - } + } + }, _ => {}, } } fn collect_spec_exp_(&self, ret: &mut Vec, e: &MoveModelExp, env: &GlobalEnv) { - // The issue of multiple accesses exists in the current version with the "for (i in 0.. n) {}" syntax. + // The issue of multiple accesses exists in the current version with the "for (i in 0.. n) {}" syntax. // Filter the for syntax through specific keywords. let exp_source = e.display(env).to_string(); if exp_source.contains("__upper_bound_value") { - return ; - } + return; + } if exp_source.contains("__update_iter_flag") { - return ; - } - + return; + } + match e.as_ref() { MoveModelExpData::Block(_, p, assign_exp, exp) => { - if let MoveModelPattern::Var(_, _) = p { + if let MoveModelPattern::Var(_, _) = p { match assign_exp { Some(x) => { if FunSpecGenerator::is_support_exp(x, env) { - ret.push( - SpecExpItem::PatternLet { - left: p.clone(), - right: assign_exp.clone().unwrap(), - } - ); + ret.push(SpecExpItem::PatternLet { + left: p.clone(), + right: assign_exp.clone().unwrap(), + }); } }, - None => {} - } + None => {}, + } } match assign_exp { Some(x) => self.collect_spec_exp_(ret, x, env), - None => {} + None => {}, } self.collect_spec_exp_(ret, exp, env); }, @@ -412,29 +386,39 @@ impl FunSpecGenerator { MoveModelExpData::IfElse(_, if_exp, if_do_exp, else_do_exp) => { // if if_do_exp is null and else_do_exp is abort, the source code is assert!() if let MoveModelExpData::Call(_, _, if_do_args) = if_do_exp.as_ref() { - if !if_do_args.is_empty() {return ;} + if !if_do_args.is_empty() { + return; + } if let MoveModelExpData::Call(_, oper, abort_exp) = else_do_exp.as_ref() { if oper == &Operation::Abort { - if abort_exp.len() != 1 {return ;} - if !FunSpecGenerator::is_support_exp(if_exp, env) {return ;} - for ve_exp in abort_exp { - if !FunSpecGenerator::is_support_exp(ve_exp, env) {return ;} + if abort_exp.len() != 1 { + return; } - ret.push( - SpecExpItem::MarcoAbort { - if_exp: if_exp.clone(), - abort_exp: abort_exp.get(0).unwrap().clone(), + if !FunSpecGenerator::is_support_exp(if_exp, env) { + return; + } + for ve_exp in abort_exp { + if !FunSpecGenerator::is_support_exp(ve_exp, env) { + return; } - ); + } + ret.push(SpecExpItem::MarcoAbort { + if_exp: if_exp.clone(), + abort_exp: abort_exp.get(0).unwrap().clone(), + }); } } } - } - _ => {} + }, + _ => {}, } } - pub(crate) fn collect_spec_exp_zx(&self, exp: &MoveModelExp, env: &GlobalEnv) -> Vec { + pub(crate) fn collect_spec_exp_zx( + &self, + exp: &MoveModelExp, + env: &GlobalEnv, + ) -> Vec { let mut ret: Vec = Vec::new(); self.collect_spec_exp_(&mut ret, exp, env); let (ret_after, _) = FunSpecGenerator::handle_unused_pattern(&ret, env); @@ -444,7 +428,7 @@ impl FunSpecGenerator { pub fn is_support_exp(e: &MoveModelExp, _env: &GlobalEnv) -> bool { let exp_data = e.as_ref(); match exp_data { - MoveModelExpData::Invalid(_) => {return false}, + MoveModelExpData::Invalid(_) => return false, MoveModelExpData::Call(_, op, args) => { if !FunSpecGenerator::is_support_operation(op) { return false; @@ -455,7 +439,7 @@ impl FunSpecGenerator { } } }, - MoveModelExpData::Block(_, _, s,exp) => { + MoveModelExpData::Block(_, _, s, exp) => { if let Some(op_exp) = s { if !FunSpecGenerator::is_support_exp(op_exp, _env) { return false; @@ -464,77 +448,86 @@ impl FunSpecGenerator { if !FunSpecGenerator::is_support_exp(exp, _env) { return false; } - }, - MoveModelExpData::IfElse(_,_,_,_) => {}, - MoveModelExpData::Return(_,_) => {}, - MoveModelExpData::Sequence(_,vec_exp) => { - for a in vec_exp.iter() { - if !FunSpecGenerator::is_support_exp(a, _env) { - return false; - } + MoveModelExpData::IfElse(_, _, _, _) => {}, + MoveModelExpData::Return(_, _) => {}, + MoveModelExpData::Sequence(_, vec_exp) => { + for a in vec_exp.iter() { + if !FunSpecGenerator::is_support_exp(a, _env) { + return false; } + } }, - _ => {} + _ => {}, } true } - fn handle_unused_pattern(items: &[SpecExpItem], env: &GlobalEnv) -> (Vec, bool){ + fn handle_unused_pattern(items: &[SpecExpItem], env: &GlobalEnv) -> (Vec, bool) { log::info!("handle unused pattern"); let mut is_change = false; let mut ret = items.to_owned(); - let mut used_local_var:HashSet = HashSet::new(); + let mut used_local_var: HashSet = HashSet::new(); for item in items.iter().rev() { match item { - SpecExpItem::BinOP {reason:_, left, right } => { + SpecExpItem::BinOP { + reason: _, + left, + right, + } => { let left_vars = left.free_vars(); let right_vars = right.free_vars(); - left_vars.iter().for_each(|sym| { - used_local_var.insert(*sym); + left_vars.iter().for_each(|sym| { + used_local_var.insert(*sym); }); right_vars.iter().for_each(|sym| { - - used_local_var.insert(*sym); + used_local_var.insert(*sym); }); }, - SpecExpItem::MarcoAbort{if_exp, abort_exp} => { + SpecExpItem::MarcoAbort { if_exp, abort_exp } => { let left_vars = if_exp.free_vars(); let right_vars = abort_exp.free_vars(); - - left_vars.iter().for_each(|sym| { used_local_var.insert(*sym); }); - right_vars.iter().for_each(|sym| { used_local_var.insert(*sym); }); + + left_vars.iter().for_each(|sym| { + used_local_var.insert(*sym); + }); + right_vars.iter().for_each(|sym| { + used_local_var.insert(*sym); + }); }, SpecExpItem::PatternLet { left, right } => { let _left_node_id = left.node_id(); let _left_node_loc = env.get_node_loc(_left_node_id); let _left_exp_str = env.get_source(&_left_node_loc).unwrap_or("err"); - + let mut is_use = false; for (_, var_in_pattern) in left.vars() { if used_local_var.contains(&var_in_pattern) { let right_vars = right.free_vars(); - right_vars.iter().for_each(|sym| { used_local_var.insert(*sym); }); + right_vars.iter().for_each(|sym| { + used_local_var.insert(*sym); + }); is_use = true; break; - } + } } - + if is_use { continue; } let _left_node_id = left.node_id(); let _left_node_loc = env.get_node_loc(_left_node_id); let _left_exp_str = env.get_source(&_left_node_loc).unwrap_or("err"); - ret.retain(|x| { - match x { - SpecExpItem::PatternLet { left: l_iter, right: _ } => left.node_id() != l_iter.node_id(), - _ => true, - } + ret.retain(|x| match x { + SpecExpItem::PatternLet { + left: l_iter, + right: _, + } => left.node_id() != l_iter.node_id(), + _ => true, }); is_change = true; }, - _ => {} + _ => {}, } } @@ -542,13 +535,20 @@ impl FunSpecGenerator { } #[allow(unused)] - fn handle_exp_without_pattern(items: &[SpecExpItem], env: &GlobalEnv) -> (Vec, bool){ + fn handle_exp_without_pattern( + items: &[SpecExpItem], + env: &GlobalEnv, + ) -> (Vec, bool) { let mut is_change = false; let mut ret = items.to_owned(); - let mut used_local_var:HashSet = HashSet::new(); + let mut used_local_var: HashSet = HashSet::new(); for item in items.iter() { match item { - SpecExpItem::BinOP { reason, left, right } => { + SpecExpItem::BinOP { + reason, + left, + right, + } => { let mut with_pattern = true; for exp_sym in left.free_vars() { if !used_local_var.contains(&exp_sym) { @@ -563,23 +563,25 @@ impl FunSpecGenerator { break; } } - + if with_pattern { continue; } - ret.retain(|x| { - match x { - SpecExpItem::BinOP { reason:_, left: l_iter, right: r_iter } =>{ - !(left.node_id() == l_iter.node_id() || right.node_id() == r_iter.node_id()) - } - _ => true, - } + ret.retain(|x| match x { + SpecExpItem::BinOP { + reason: _, + left: l_iter, + right: r_iter, + } => { + !(left.node_id() == l_iter.node_id() + || right.node_id() == r_iter.node_id()) + }, + _ => true, }); is_change = true; }, - SpecExpItem::MarcoAbort{if_exp, abort_exp} => { - + SpecExpItem::MarcoAbort { if_exp, abort_exp } => { let mut with_pattern = true; for exp_sym in if_exp.free_vars() { if !used_local_var.contains(&exp_sym) { @@ -594,17 +596,20 @@ impl FunSpecGenerator { break; } } - + if with_pattern { continue; } - - ret.retain(|x| { - match x { - SpecExpItem::MarcoAbort { if_exp: l_iter, abort_exp: r_iter } => - !(if_exp.node_id() == l_iter.node_id() && abort_exp.node_id() == r_iter.node_id()), - _ => true, - } + + ret.retain(|x| match x { + SpecExpItem::MarcoAbort { + if_exp: l_iter, + abort_exp: r_iter, + } => { + !(if_exp.node_id() == l_iter.node_id() + && abort_exp.node_id() == r_iter.node_id()) + }, + _ => true, }); is_change = true; }, @@ -619,11 +624,12 @@ impl FunSpecGenerator { } if !with_pattern { - ret.retain(|x| { - match x { - SpecExpItem::PatternLet { left: l_iter, right: _ } => left.node_id() != l_iter.node_id(), - _ => true, - } + ret.retain(|x| match x { + SpecExpItem::PatternLet { + left: l_iter, + right: _, + } => left.node_id() != l_iter.node_id(), + _ => true, }); is_change = true; continue; @@ -635,23 +641,23 @@ impl FunSpecGenerator { }; used_local_var.insert(*pat_sym); }, - _ => {} + _ => {}, } } (ret, is_change) } - fn is_support_operation(op:&Operation) -> bool { - !matches!(op, Operation::BorrowGlobal(_) - | Operation::Borrow(_) - | Operation::Deref - | Operation::MoveTo - | Operation::MoveFrom - | Operation::Freeze - | Operation::Vector + fn is_support_operation(op: &Operation) -> bool { + !matches!( + op, + Operation::BorrowGlobal(_) + | Operation::Borrow(_) + | Operation::Deref + | Operation::MoveTo + | Operation::MoveFrom + | Operation::Freeze + | Operation::Vector ) } } - - diff --git a/language/move-analyzer/src/multiproject.rs b/language/move-analyzer/src/multiproject.rs index a5bbf20175..59b2157619 100644 --- a/language/move-analyzer/src/multiproject.rs +++ b/language/move-analyzer/src/multiproject.rs @@ -105,7 +105,6 @@ impl MultiProject { ret } - fn get_projects_mut(&mut self, x: &Path) -> Vec<&mut Project> { let (manifest, _) = match super::utils::discover_manifest_and_kind(x) { Some(x) => x, @@ -121,8 +120,7 @@ impl MultiProject { } pub fn update_defs(&mut self, file_path: PathBuf, content: String) { - match super::utils::discover_manifest_and_kind(file_path.as_path()) - { + match super::utils::discover_manifest_and_kind(file_path.as_path()) { Some(_) => {}, None => { log::error!("file_path {:?} not found", file_path.as_path()); diff --git a/language/move-analyzer/src/project.rs b/language/move-analyzer/src/project.rs index 33e228c430..4405010208 100644 --- a/language/move-analyzer/src/project.rs +++ b/language/move-analyzer/src/project.rs @@ -3,6 +3,7 @@ use super::utils::*; use crate::analyzer_handler::*; +use move_compiler::shared::PackagePaths; use std::{ cell::RefCell, collections::{HashMap, HashSet}, @@ -10,7 +11,6 @@ use std::{ rc::Rc, time::SystemTime, }; -use move_compiler::shared::PackagePaths; /// Project pub struct Project { @@ -30,23 +30,21 @@ pub struct Project { pub(crate) targets: Vec>, pub(crate) dependents: Vec>, pub(crate) addrname_2_addrnum: std::collections::HashMap, - pub err_diags: String, + pub err_diags: String, } impl Project { pub fn loc_to_range(&self, loc: &move_model::model::Loc) -> lsp_types::Range { let location_start = self.global_env.get_location(loc).unwrap(); - let location_end = self.global_env.get_location( - &move_model::model::Loc::new( - loc.file_id(), - codespan::Span::new( - loc.span().end(), - loc.span().end() - ) - ) - ).unwrap(); + let location_end = self + .global_env + .get_location(&move_model::model::Loc::new( + loc.file_id(), + codespan::Span::new(loc.span().end(), loc.span().end()), + )) + .unwrap(); lsp_types::Range { - start: lsp_types::Position { + start: lsp_types::Position { line: location_start.line.0, character: location_start.column.0, }, @@ -56,4 +54,4 @@ impl Project { }, } } -} \ No newline at end of file +} diff --git a/language/move-analyzer/src/project_manager.rs b/language/move-analyzer/src/project_manager.rs index 5a35328b2d..ad8f14375e 100644 --- a/language/move-analyzer/src/project_manager.rs +++ b/language/move-analyzer/src/project_manager.rs @@ -4,27 +4,24 @@ use super::utils::*; use crate::{analyzer_handler::*, project::Project}; use anyhow::{Ok, Result}; +use codespan_reporting::diagnostic::Severity; use move_compiler::shared::{NumericalAddress, PackagePaths}; use move_core_types::account_address::*; +use move_model::{options::ModelBuilderOptions, run_model_builder_with_options}; use move_package::source_package::{layout::SourcePackageLayout, manifest_parser::*}; +use num_bigint::BigUint; use std::{ cell::RefCell, cmp::Ordering, - collections::{ BTreeSet, BTreeMap }, + collections::{BTreeMap, BTreeSet, HashMap}, path::{Path, PathBuf}, rc::Rc, }; -use walkdir::WalkDir; -use move_model::{options::ModelBuilderOptions, run_model_builder_with_options}; -use std::collections::HashMap; -use num_bigint::BigUint; use tempfile::tempdir; -use codespan_reporting::diagnostic::Severity; +use walkdir::WalkDir; // Determines the base of the number literal, depending on the prefix -pub(crate) fn determine_num_text_and_base( - s: &str, -) -> (&str, move_compiler::shared::NumberFormat) { +pub(crate) fn determine_num_text_and_base(s: &str) -> (&str, move_compiler::shared::NumberFormat) { for c in s.chars() { if c.is_alphabetic() { return (s, move_compiler::shared::NumberFormat::Hex); @@ -40,14 +37,13 @@ pub fn parse_addr_str_to_number( [u8; AccountAddress::LENGTH], move_compiler::shared::NumberFormat, )> { - let (txt, base) = determine_num_text_and_base(s); let parsed = match base { move_compiler::shared::NumberFormat::Hex => BigUint::parse_bytes(txt[2..].as_bytes(), 16), move_compiler::shared::NumberFormat::Decimal => BigUint::parse_bytes(txt.as_bytes(), 10), }?; - + let bytes = parsed.to_bytes_be(); if bytes.len() > AccountAddress::LENGTH { return None; @@ -75,11 +71,15 @@ pub fn parse_named_address_item(s: &str) -> anyhow::Result<(String, NumericalAdd if let Some(addr) = parse_addr_str(before_after[1]) { Ok((name, addr)) } else { - Ok((name, NumericalAddress::new(AccountAddress::from_hex_literal("0x0") - .unwrap() - .into_bytes(), - move_compiler::shared::NumberFormat::Hex)) - ) + Ok(( + name, + NumericalAddress::new( + AccountAddress::from_hex_literal("0x0") + .unwrap() + .into_bytes(), + move_compiler::shared::NumberFormat::Hex, + ), + )) } } @@ -187,7 +187,10 @@ impl Project { &attributes, ) .expect("Failed to create GlobalEnv!"); - log::info!("env.get_module_count() = {:?}", &new_project.global_env.get_module_count()); + log::info!( + "env.get_module_count() = {:?}", + &new_project.global_env.get_module_count() + ); use codespan_reporting::term::termcolor::Buffer; let mut error_writer = Buffer::no_color(); @@ -197,7 +200,9 @@ impl Project { } new_project.addrname_2_addrnum = helper; - new_project.global_env.report_diag(&mut error_writer, Severity::Error); + new_project + .global_env + .report_diag(&mut error_writer, Severity::Error); new_project.err_diags = String::from_utf8_lossy(&error_writer.into_inner()).to_string(); Ok(new_project) } @@ -210,10 +215,10 @@ impl Project { None => { log::error!("not move project."); return; - } + }, }; - let new_project = match Project::new(root_dir, |msg| {log::info!("{}", msg)}) { + let new_project = match Project::new(root_dir, |msg| log::info!("{}", msg)) { Ok(x) => x, Err(_) => { log::error!("reload project failed"); @@ -226,10 +231,14 @@ impl Project { self.dependents = new_project.dependents.clone(); self.global_env = new_project.global_env; - log::info!("env.get_module_count() = {:?}", &self.global_env.get_module_count()); + log::info!( + "env.get_module_count() = {:?}", + &self.global_env.get_module_count() + ); use codespan_reporting::term::termcolor::Buffer; let mut error_writer = Buffer::no_color(); - self.global_env.report_diag(&mut error_writer, Severity::Error); + self.global_env + .report_diag(&mut error_writer, Severity::Error); self.err_diags = String::from_utf8_lossy(&error_writer.into_inner()).to_string(); } @@ -351,7 +360,6 @@ impl Project { } log::debug!("load source file {:?}", file.path()); ret_paths.push(file.path().to_path_buf()); - } } Ok(ret_paths) @@ -377,7 +385,7 @@ impl Project { &self, visitor: &mut dyn ItemOrAccessHandler, filepath: &Path, - source_str: String + source_str: String, ) { visitor.handle_project_env(self, &self.global_env, filepath, source_str); } diff --git a/language/move-analyzer/src/references.rs b/language/move-analyzer/src/references.rs index 278643af54..a56104c21b 100644 --- a/language/move-analyzer/src/references.rs +++ b/language/move-analyzer/src/references.rs @@ -12,7 +12,11 @@ use move_model::{ ast::{ExpData::*, Operation::*, SpecBlockTarget}, model::{FunId, GlobalEnv, ModuleEnv, ModuleId, StructId}, }; -use std::{path::{Path, PathBuf}, collections::BTreeSet, ops::Deref}; +use std::{ + collections::BTreeSet, + ops::Deref, + path::{Path, PathBuf}, +}; /// Handles on_references_request of the language server. pub fn on_references_request(context: &Context, request: &Request) -> lsp_server::Response { @@ -49,7 +53,10 @@ pub fn on_references_request(context: &Context, request: &Request) -> lsp_server serde_json::to_value(GotoDefinitionResponse::Array(locations)).unwrap(), ); let ret_response = r.clone(); - log::info!("------------------------------------\nret_response = \n{:?}\n\n", ret_response); + log::info!( + "------------------------------------\nret_response = \n{:?}\n\n", + ret_response + ); context .connection .sender @@ -91,8 +98,9 @@ impl Handler { most_clost_item_idx = item_idx; } - if !self.result_ref_candidates.is_empty() && - most_clost_item_idx < self.result_ref_candidates.len() { + if !self.result_ref_candidates.is_empty() + && most_clost_item_idx < self.result_ref_candidates.len() + { let mut ret = Vec::with_capacity(self.result_ref_candidates.len()); for item in &self.result_ref_candidates[most_clost_item_idx] { ret.push(item.mk_location()); @@ -136,7 +144,7 @@ impl Handler { mouse_line_first_col.span().start() + codespan::ByteOffset(2), ), ); - + mouse_loc = env.get_location(&mouse_line_last_col).unwrap(); // locate to self.line first column while mouse_loc.column.0 < self.col && mouse_loc.line.0 == self.line { @@ -149,7 +157,7 @@ impl Handler { ); mouse_loc = env.get_location(&mouse_line_last_col).unwrap(); } - + let mouse_source = env.get_source(&move_model::model::Loc::new( target_fn_or_struct_loc.file_id(), codespan::Span::new( @@ -158,12 +166,20 @@ impl Handler { ), )); log::info!(" -- mouse_source = {:?}", mouse_source); - - self.mouse_span = codespan::Span::new(mouse_line_first_col.span().start(), mouse_line_last_col.span().start()); + + self.mouse_span = codespan::Span::new( + mouse_line_first_col.span().start(), + mouse_line_last_col.span().start(), + ); } - - fn get_which_modules_used_target_module(&mut self, env: &GlobalEnv, target_module: &ModuleEnv) -> BTreeSet { - env.get_modules().filter_map(|module_env| { + + fn get_which_modules_used_target_module( + &mut self, + env: &GlobalEnv, + target_module: &ModuleEnv, + ) -> BTreeSet { + env.get_modules() + .filter_map(|module_env| { let target_module_name_symbol = target_module.get_name().name(); let target_module_name_dis = target_module_name_symbol.display(env.symbol_pool()); let target_module_name_str = target_module_name_dis.to_string(); @@ -225,7 +241,7 @@ impl Handler { self.process_expr(env, exp); }; } - + fn process_spec_func(&mut self, env: &GlobalEnv) { let mut found_target_fun = false; let mut target_fun_id = FunId::new(env.symbol_pool().make("name")); @@ -246,12 +262,13 @@ impl Handler { codespan::Span::new( spec_block_info.loc.span().end(), spec_block_info.loc.span().end() + codespan::ByteOffset(1), - ) + ), ); - + if let Some(s_loc) = env.get_location(&span_first_col) { if let Some(e_loc) = env.get_location(&span_last_col) { - if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) { + if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) + { target_fun_id = fun_id; found_target_fun = true; spec_fn_span_loc = spec_block_info.loc.clone(); @@ -269,8 +286,7 @@ impl Handler { let target_fn = target_module.get_function(target_fun_id); let target_fn_spec = target_fn.get_spec(); - log::info!("target_fun's spec = {}", - env.display(&*target_fn_spec)); + log::info!("target_fun's spec = {}", env.display(&*target_fn_spec)); self.get_mouse_loc(env, &spec_fn_span_loc); for cond in target_fn_spec.conditions.clone() { for exp in cond.all_exps() { @@ -298,7 +314,7 @@ impl Handler { break; } } - + if !found_target_struct { log::info!(" -- not in struct!\n"); return; @@ -308,7 +324,7 @@ impl Handler { let target_struct = target_module.get_struct(target_struct_id); let target_struct_loc = target_struct.get_loc(); self.get_mouse_loc(env, &target_struct_loc); - + for field_env in target_struct.get_fields() { let field_name = field_env.get_name(); let field_name_str = field_name.display(env.symbol_pool()); @@ -337,8 +353,7 @@ impl Handler { let atomic_field_source = env.get_source(&atomic_field_loc); // todo: should check mouse_last_col between in scope by atomic_field_loc if atomic_field_loc.span().end() < self.mouse_span.end() - || atomic_field_loc.span().start() - > self.mouse_span.end() + || atomic_field_loc.span().start() > self.mouse_span.end() { continue; } @@ -351,7 +366,7 @@ impl Handler { } } } - + fn process_spec_struct(&mut self, env: &GlobalEnv) { let mut found_target_spec_stct = false; let mut target_stct_id = StructId::new(env.symbol_pool().make("name")); @@ -372,12 +387,13 @@ impl Handler { codespan::Span::new( spec_block_info.loc.span().end(), spec_block_info.loc.span().end() + codespan::ByteOffset(1), - ) + ), ); - + if let Some(s_loc) = env.get_location(&span_first_col) { if let Some(e_loc) = env.get_location(&span_last_col) { - if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) { + if u32::from(s_loc.line) <= self.line && self.line <= u32::from(e_loc.line) + { target_stct_id = stct_id; found_target_spec_stct = true; spec_stct_span_loc = spec_block_info.loc.clone(); @@ -395,8 +411,7 @@ impl Handler { let target_stct = target_module.get_struct(target_stct_id); let target_stct_spec = target_stct.get_spec(); - log::info!("target_stct's spec = {}", - env.display(target_stct_spec)); + log::info!("target_stct's spec = {}", env.display(target_stct_spec)); self.get_mouse_loc(env, &spec_stct_span_loc); for cond in target_stct_spec.conditions.clone() { for exp in cond.all_exps() { @@ -404,29 +419,18 @@ impl Handler { } } } - - fn process_expr( - &mut self, - env: &GlobalEnv, - exp: &move_model::ast::Exp, - ) { - exp.visit_post_order(&mut |e| { - match e { - Call(..) => { - self.process_call(env, e); - true - }, - _ => true, - } + + fn process_expr(&mut self, env: &GlobalEnv, exp: &move_model::ast::Exp) { + exp.visit_post_order(&mut |e| match e { + Call(..) => { + self.process_call(env, e); + true + }, + _ => true, }); } - fn process_call( - &mut self, - env: &GlobalEnv, - expdata: &move_model::ast::ExpData, - ) - { + fn process_call(&mut self, env: &GlobalEnv, expdata: &move_model::ast::ExpData) { if let Call(node_id, MoveFunction(mid, fid), _) = expdata { let this_call_loc = env.get_node_loc(*node_id); if this_call_loc.span().start() < self.mouse_span.end() @@ -447,13 +451,18 @@ impl Handler { // need locate called_fun.get_full_name_str() in f's body source let f_source = env.get_source(&caller_fun_loc); if let Ok(f_source_str) = f_source { - if let Some(index) = f_source_str.find(called_fun.get_name_str().as_str()) { + if let Some(index) = + f_source_str.find(called_fun.get_name_str().as_str()) + { let target_len: usize = called_fun.get_name_str().len(); let start = caller_fun_loc.span().start() + codespan::ByteOffset(index.try_into().unwrap()); - let end = start + codespan::ByteOffset((target_len).try_into().unwrap()); + let end = + start + codespan::ByteOffset((target_len).try_into().unwrap()); caller_fun_loc = move_model::model::Loc::new( - caller_fun_loc.file_id(), codespan::Span::new(start, end)); + caller_fun_loc.file_id(), + codespan::Span::new(start, end), + ); } } let (caller_fun_file, caller_fun_line) = @@ -514,7 +523,7 @@ impl Handler { ty: &move_model::ty::Type, ) { use move_model::ty::Type::*; - + if let Struct(mid, stid, _) = ty { let stc_def_module = env.get_module(*mid); let type_struct = stc_def_module.get_struct(*stid); @@ -523,18 +532,26 @@ impl Handler { let mouse_capture_ty_symbol_str = mouse_capture_ty_symbol_dis.to_string(); let mut result_candidates: Vec = Vec::new(); - for reference_module_id in self.get_which_modules_used_target_module(env, &stc_def_module) { + for reference_module_id in + self.get_which_modules_used_target_module(env, &stc_def_module) + { let stc_ref_module = env.get_module(reference_module_id); for stc_ref_fn in stc_ref_module.get_functions() { let mut stc_ref_fn_loc = stc_ref_fn.get_loc(); while let Ok(stc_ref_fn_source) = env.get_source(&stc_ref_fn_loc) { - if let Some(index) = stc_ref_fn_source.find(mouse_capture_ty_symbol_str.as_str()) { - let capture_ref_ty_start = stc_ref_fn_loc.span().start() + codespan::ByteOffset(index.try_into().unwrap()); - let capture_ref_ty_end = capture_ref_ty_start + codespan::ByteOffset((mouse_capture_ty_symbol_str.len()).try_into().unwrap()); + if let Some(index) = + stc_ref_fn_source.find(mouse_capture_ty_symbol_str.as_str()) + { + let capture_ref_ty_start = stc_ref_fn_loc.span().start() + + codespan::ByteOffset(index.try_into().unwrap()); + let capture_ref_ty_end = capture_ref_ty_start + + codespan::ByteOffset( + (mouse_capture_ty_symbol_str.len()).try_into().unwrap(), + ); let result_loc = move_model::model::Loc::new( stc_ref_fn_loc.file_id(), - codespan::Span::new(capture_ref_ty_start, capture_ref_ty_end) + codespan::Span::new(capture_ref_ty_start, capture_ref_ty_end), ); let (ref_ty_file, ref_ty_pos) = @@ -551,7 +568,11 @@ impl Handler { stc_ref_fn_loc = move_model::model::Loc::new( stc_ref_fn_loc.file_id(), - codespan::Span::new(capture_ref_ty_end, stc_ref_fn_loc.span().end())); + codespan::Span::new( + capture_ref_ty_end, + stc_ref_fn_loc.span().end(), + ), + ); } else { break; } @@ -563,16 +584,9 @@ impl Handler { } } - fn run_move_model_visitor_internal( - &mut self, - env: &GlobalEnv, - move_file_path: &Path - ) { - let candidate_modules - = crate::utils::get_modules_by_fpath_in_all_modules( - env, - &PathBuf::from(move_file_path) - ); + fn run_move_model_visitor_internal(&mut self, env: &GlobalEnv, move_file_path: &Path) { + let candidate_modules = + crate::utils::get_modules_by_fpath_in_all_modules(env, &PathBuf::from(move_file_path)); if candidate_modules.is_empty() { log::info!("cannot get target module\n"); return; @@ -585,7 +599,7 @@ impl Handler { self.process_spec_struct(env); } else { self.process_func(env); - self.process_struct(env); + self.process_struct(env); } } } @@ -606,7 +620,7 @@ impl ItemOrAccessHandler for Handler { _services: &dyn HandleItemService, env: &GlobalEnv, move_file_path: &Path, - _: String + _: String, ) { self.run_move_model_visitor_internal(env, move_file_path); } diff --git a/language/move-analyzer/src/symbols.rs b/language/move-analyzer/src/symbols.rs index 548be390ab..37e8582c4c 100644 --- a/language/move-analyzer/src/symbols.rs +++ b/language/move-analyzer/src/symbols.rs @@ -46,18 +46,14 @@ //! definitions, the symbolicator builds a scope stack, entering encountered definitions and //! matching uses to a definition in the innermost scope. -use crate::{ - context::Context, - utils::get_modules_by_fpath_in_all_modules, project::Project, -}; +use crate::{context::Context, project::Project, utils::get_modules_by_fpath_in_all_modules}; use lsp_server::Request; use lsp_types::{DocumentSymbol, DocumentSymbolParams, SymbolKind}; use move_model::{ - model::{ModuleEnv, StructEnv}, ast::SpecBlockTarget, + model::{ModuleEnv, StructEnv}, }; - /// Handles document symbol request of the language server #[allow(deprecated)] pub fn on_document_symbol_request(context: &Context, request: &Request) -> lsp_server::Response { @@ -66,7 +62,7 @@ pub fn on_document_symbol_request(context: &Context, request: &Request) -> lsp_s .expect("could not deserialize document symbol request"); let fpath = parameters.text_document.uri.to_file_path().unwrap(); - + let mut may_target_modules = Default::default(); let mut may_project = Default::default(); let projects = context.projects.get_projects(&fpath); @@ -77,38 +73,50 @@ pub fn on_document_symbol_request(context: &Context, request: &Request) -> lsp_s may_project = Some(project); break; } - } let project = match may_project { - Some(x) => x, + Some(x) => x, None => { - log::error!("coule not found project from file path, fpath = {:?}", fpath.as_path()); + log::error!( + "coule not found project from file path, fpath = {:?}", + fpath.as_path() + ); return lsp_server::Response { id: "".to_string().into(), result: Some(serde_json::json!({"msg": "coule not found project from file path"})), error: None, }; - } - }; + }, + }; let module_envs = match may_target_modules { - Some(x) => x, + Some(x) => x, None => { - log::error!("coule not found module from file path, fpath = {:?}", fpath.as_path()); + log::error!( + "coule not found module from file path, fpath = {:?}", + fpath.as_path() + ); return lsp_server::Response { id: "".to_string().into(), result: Some(serde_json::json!({"msg": "coule not found module from file path"})), error: None, }; - } - }; + }, + }; let mut result_vec_document_symbols: Vec = vec![]; for module_env in module_envs { - log::info!("start handle module env name: {:?}", module_env.get_full_name_str()); + log::info!( + "start handle module env name: {:?}", + module_env.get_full_name_str() + ); let module_range = project.loc_to_range(&module_env.get_loc()); - let module_name = module_env.get_name().display(&project.global_env).to_string().clone(); + let module_name = module_env + .get_name() + .display(&project.global_env) + .to_string() + .clone(); let module_detail = Some(module_name.clone()); let module_kind = SymbolKind::MODULE; @@ -119,7 +127,7 @@ pub fn on_document_symbol_request(context: &Context, request: &Request) -> lsp_s handle_document_symbols_const(project, &module_env, &mut children); handle_document_symbols_struct(project, &module_env, &mut children); - result_vec_document_symbols.push( DocumentSymbol{ + result_vec_document_symbols.push(DocumentSymbol { name: module_name, detail: module_detail, kind: module_kind, @@ -129,12 +137,15 @@ pub fn on_document_symbol_request(context: &Context, request: &Request) -> lsp_s tags: Some(vec![]), deprecated: Some(false), }); - log::trace!("end handle module env name: {:?}", module_env.get_full_name_str()); + log::trace!( + "end handle module env name: {:?}", + module_env.get_full_name_str() + ); } - + let response = lsp_server::Response::new_ok( - request.id.clone(), - serde_json::json!(&result_vec_document_symbols) + request.id.clone(), + serde_json::json!(&result_vec_document_symbols), ); if context .connection @@ -153,88 +164,109 @@ pub fn on_document_symbol_request(context: &Context, request: &Request) -> lsp_s /// Helper function to handle Spec function in the document symbols #[allow(deprecated)] -fn handle_document_symbols_spec_function(project: &Project, module_env :&ModuleEnv, children: &mut Vec) { +fn handle_document_symbols_spec_function( + project: &Project, + module_env: &ModuleEnv, + children: &mut Vec, +) { for spec_info in module_env.get_spec_block_infos() { match project.global_env.get_file_and_location(&spec_info.loc) { Some((_, _)) => {}, None => { - log::error!("could not get file and location from spec info, spec: {:?}", spec_info); + log::error!( + "could not get file and location from spec info, spec: {:?}", + spec_info + ); continue; - } + }, }; - let (spec_name, spec_range) = match spec_info.target { + let (spec_name, spec_range) = match spec_info.target { SpecBlockTarget::Function(_, fid) => { let f_env = module_env.get_function(fid); (f_env.get_name_str(), project.loc_to_range(&spec_info.loc)) }, SpecBlockTarget::Struct(_, sid) => { let s_env = module_env.get_struct(sid); - (s_env.get_name().display(project.global_env.symbol_pool()).to_string(), project.loc_to_range(&spec_info.loc)) + ( + s_env + .get_name() + .display(project.global_env.symbol_pool()) + .to_string(), + project.loc_to_range(&spec_info.loc), + ) }, _ => continue, }; children.push(DocumentSymbol { name: spec_name, - detail:None, + detail: None, kind: SymbolKind::FUNCTION, range: spec_range, selection_range: spec_range, children: None, tags: Some(vec![]), deprecated: Some(false), - }); + }); } } - /// Helper function to handle function in the document symbols #[allow(deprecated)] -fn handle_document_symbols_function(project: &Project, module_env :&ModuleEnv, children: &mut Vec) { +fn handle_document_symbols_function( + project: &Project, + module_env: &ModuleEnv, + children: &mut Vec, +) { for function_env in module_env.get_functions() { let func_range = project.loc_to_range(&function_env.get_loc()); - + children.push(DocumentSymbol { name: function_env.get_name_str().to_string(), - detail:None, + detail: None, kind: SymbolKind::FUNCTION, range: func_range, selection_range: func_range, children: None, tags: Some(vec![]), deprecated: Some(false), - }); + }); } } /// Helper function to handle constants in the document symbols #[allow(deprecated)] -fn handle_document_symbols_const(project: &Project, - module_env :&ModuleEnv, - children: &mut Vec +fn handle_document_symbols_const( + project: &Project, + module_env: &ModuleEnv, + children: &mut Vec, ) { for const_env in module_env.get_named_constants() { let const_range = project.loc_to_range(&const_env.get_loc()); - + children.push(DocumentSymbol { - name: const_env.get_name().display(project.global_env.symbol_pool()).to_string(), - detail:None, + name: const_env + .get_name() + .display(project.global_env.symbol_pool()) + .to_string(), + detail: None, kind: SymbolKind::CONSTANT, range: const_range, selection_range: const_range, children: None, tags: Some(vec![]), deprecated: Some(false), - }); + }); } } /// Helper function to handle sturct in the document symbols #[allow(deprecated)] -fn handle_document_symbols_struct(project: &Project, - module_env :&ModuleEnv, - children: &mut Vec +fn handle_document_symbols_struct( + project: &Project, + module_env: &ModuleEnv, + children: &mut Vec, ) { for struct_env in module_env.get_structs() { let struct_range = project.loc_to_range(&struct_env.get_loc()); @@ -243,15 +275,18 @@ fn handle_document_symbols_struct(project: &Project, handle_document_symbols_struct_fields(project, &struct_env, &mut fields); children.push(DocumentSymbol { - name: struct_env.get_name().display(struct_env.symbol_pool()).to_string(), - detail:None, + name: struct_env + .get_name() + .display(struct_env.symbol_pool()) + .to_string(), + detail: None, kind: SymbolKind::CONSTANT, range: struct_range, selection_range: struct_range, children: Some(fields), tags: Some(vec![]), deprecated: Some(false), - }); + }); } } @@ -259,21 +294,24 @@ fn handle_document_symbols_struct(project: &Project, #[allow(deprecated)] fn handle_document_symbols_struct_fields( project: &Project, - struct_env :&StructEnv, - children: &mut Vec + struct_env: &StructEnv, + children: &mut Vec, ) { for field_env in struct_env.get_fields() { let field_range = project.loc_to_range(field_env.get_loc()); children.push(DocumentSymbol { - name: field_env.get_name().display(struct_env.symbol_pool()).to_string(), - detail:None, + name: field_env + .get_name() + .display(struct_env.symbol_pool()) + .to_string(), + detail: None, kind: SymbolKind::FIELD, range: field_range, selection_range: field_range, children: None, tags: Some(vec![]), deprecated: Some(false), - }); + }); } -} \ No newline at end of file +} diff --git a/language/move-analyzer/src/type_display_for_spec.rs b/language/move-analyzer/src/type_display_for_spec.rs index a6b292f9d9..4085ccd429 100644 --- a/language/move-analyzer/src/type_display_for_spec.rs +++ b/language/move-analyzer/src/type_display_for_spec.rs @@ -7,26 +7,17 @@ //! for structs within this module. For structs from other modules, it prints in the form //! "module_name::struct_name" instead of displaying all structs as "module_name::struct_name". - use move_model::{ - model:: { - StructId, ModuleId, ModuleEnv - }, - ty::{Type, TypeDisplayContext, ReferenceKind}, ast::ModuleName, + model::{ModuleEnv, ModuleId, StructId}, symbol::Symbol, + ty::{ReferenceKind, Type, TypeDisplayContext}, }; - -use std::{ - fmt, - fmt::Formatter, -}; - -use std::collections::HashMap; +use std::{collections::HashMap, fmt, fmt::Formatter}; pub struct TypeDisplayForSpec<'a> { pub type_: &'a Type, pub context: &'a TypeDisplayContext<'a>, - pub using_module_map: &'a HashMap>, + pub using_module_map: &'a HashMap>, pub module_env: &'a ModuleEnv<'a>, } @@ -39,7 +30,7 @@ impl<'a> TypeDisplayForSpec<'a> { using_module_map: self.using_module_map, } } -} +} impl<'a> fmt::Display for TypeDisplayForSpec<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -139,16 +130,16 @@ impl<'a> TypeDisplayForSpec<'a> { if let Some(members) = self.using_module_map.get(struct_module_env_name) { let a = members.iter().find(|&&x| x == struct_env_name); - if let Some(x) = a { - return x.display(env.symbol_pool()).to_string(); + if let Some(x) = a { + return x.display(env.symbol_pool()).to_string(); } - } + } - format!("{}::{}", + format!( + "{}::{}", struct_module_env_name.display(env), struct_env_name.display(env.symbol_pool()) ) } } } - diff --git a/language/move-analyzer/src/utils.rs b/language/move-analyzer/src/utils.rs index 12782a24c5..182faf5675 100644 --- a/language/move-analyzer/src/utils.rs +++ b/language/move-analyzer/src/utils.rs @@ -1,16 +1,15 @@ // Copyright (c) The BitsLab.MoveBit Contributors // SPDX-License-Identifier: Apache-2.0 -use codespan_reporting::files::{Files, SimpleFiles}; use codespan::FileId; +use codespan_reporting::files::{Files, SimpleFiles}; use lsp_types::{Command, Location, Position}; use move_command_line_common::files::FileHash; use move_ir_types::location::*; +use move_model::{ast::ModuleName, symbol::Symbol as SpecSymbol}; use move_package::source_package::layout::SourcePackageLayout; use move_symbol_pool::Symbol; use std::{collections::HashMap, path::*, vec}; -use move_model::ast::ModuleName; -use move_model::symbol::Symbol as SpecSymbol; /// Converts a location from the byte index format to the line/character (Position) format, where /// line/character are 0-based. @@ -56,6 +55,7 @@ impl PathBufHashMap { self.path_2_hash.insert(path.clone(), hash); self.hash_2_path.insert(hash, path); } + pub(crate) fn get_path(&self, hash: &FileHash) -> Option<&'_ PathBuf> { self.hash_2_path.get(hash) } @@ -68,9 +68,7 @@ pub struct FileLineMapping { impl FileLineMapping { pub fn new() -> FileLineMapping { - Self { - m: HashMap::new() - } + Self { m: HashMap::new() } } pub fn update(&mut self, filepath: PathBuf, content: String) { @@ -188,14 +186,16 @@ pub fn path_concat(p1: &Path, p2: &Path) -> PathBuf { Component::RootDir | Component::Prefix(_) ); let mut p1: Vec<_> = p1.components().collect(); - normal_path_components(if is_abs { - &p2 - } else { - { - p1.extend(p2); - &p1 - } - }) + normal_path_components( + if is_abs { + &p2 + } else { + { + p1.extend(p2); + &p1 + } + }, + ) } /// concat Move.toml file. @@ -361,7 +361,11 @@ impl From<&Location> for PathAndRange { pub const PROJECT_FILE_NAME: &str = "Move.toml"; use move_model::model::{GlobalEnv, ModuleId}; -pub fn get_target_module(env: &GlobalEnv, move_file_path: &Path, target_module_id: &mut ModuleId) -> bool { +pub fn get_target_module( + env: &GlobalEnv, + move_file_path: &Path, + target_module_id: &mut ModuleId, +) -> bool { let mut move_file_str: &str = "null_move_file"; if let Some(file_stem) = move_file_path.file_stem() { if let Some(file_stem_str) = file_stem.to_str() { @@ -388,9 +392,9 @@ pub fn fpath_str_is_equal(s1: &String, s2: &String) -> bool { if s1.len() != s2.len() { return false; } - + for (c1, c2) in s1.chars().zip(s2.chars()) { - if c1 == c2|| (c1 == '\\' && c2 == '/') || (c1 == '/' && c2 == '\\') { + if c1 == c2 || (c1 == '\\' && c2 == '/') || (c1 == '/' && c2 == '\\') { continue; } else { return false; @@ -400,15 +404,24 @@ pub fn fpath_str_is_equal(s1: &String, s2: &String) -> bool { } use move_model::model::ModuleEnv; -pub fn get_modules_by_fpath_in_target_modules<'a>(env: &'a GlobalEnv, fpath: &Path) -> Vec> { +pub fn get_modules_by_fpath_in_target_modules<'a>( + env: &'a GlobalEnv, + fpath: &Path, +) -> Vec> { log::trace!("get target module by path"); let mut result_vec_modules: Vec = vec![]; for module_env in env.get_target_modules() { - - log::info!("{}", env.get_file(module_env.get_loc().file_id()).to_string_lossy().to_string()); + log::info!( + "{}", + env.get_file(module_env.get_loc().file_id()) + .to_string_lossy() + .to_string() + ); if !fpath_str_is_equal( - &env.get_file(module_env.get_loc().file_id()).to_string_lossy().to_string(), - &fpath.to_string_lossy().to_string() + &env.get_file(module_env.get_loc().file_id()) + .to_string_lossy() + .to_string(), + &fpath.to_string_lossy().to_string(), ) { continue; } @@ -417,12 +430,17 @@ pub fn get_modules_by_fpath_in_target_modules<'a>(env: &'a GlobalEnv, fpath: &Pa result_vec_modules } -pub fn get_modules_by_fpath_in_all_modules<'a>(env: &'a GlobalEnv, fpath: &Path) -> Vec> { +pub fn get_modules_by_fpath_in_all_modules<'a>( + env: &'a GlobalEnv, + fpath: &Path, +) -> Vec> { let mut result_vec_modules: Vec = vec![]; for module_env in env.get_modules() { if !fpath_str_is_equal( - &env.get_file(module_env.get_loc().file_id()).to_string_lossy().to_string(), - &fpath.to_string_lossy().to_string() + &env.get_file(module_env.get_loc().file_id()) + .to_string_lossy() + .to_string(), + &fpath.to_string_lossy().to_string(), ) { continue; } @@ -435,22 +453,26 @@ pub fn get_file_id_by_fpath_in_all_modules(env: &GlobalEnv, fpath: &Path) -> Opt let mut result_file_id = Default::default(); for module_env in env.get_modules() { if fpath_str_is_equal( - &env.get_file(module_env.get_loc().file_id()).to_string_lossy().to_string(), - &fpath.to_string_lossy().to_string() + &env.get_file(module_env.get_loc().file_id()) + .to_string_lossy() + .to_string(), + &fpath.to_string_lossy().to_string(), ) { result_file_id = Some(module_env.get_loc().file_id()); } - } result_file_id } - -pub fn collect_use_decl(addrname_2_addrnum :&std::collections::HashMap, module_env: &ModuleEnv, global_env: &GlobalEnv) -> HashMap> { +pub fn collect_use_decl( + addrname_2_addrnum: &std::collections::HashMap, + module_env: &ModuleEnv, + global_env: &GlobalEnv, +) -> HashMap> { let mut result: HashMap> = Default::default(); for using_decl in module_env.get_use_decls() { let using_decl_name = using_decl.module_name.display_full(global_env).to_string(); - + let before_after = using_decl_name.split("::").collect::>(); if before_after.len() != 2 { log::error!("use decl module name len should be 2"); @@ -467,16 +489,16 @@ pub fn collect_use_decl(addrname_2_addrnum :&std::collections::HashMap = vec![]; for (_, acc_symbol, may_sym) in using_decl.members.clone().into_iter() { match may_sym { Some(x) => using_decl_member.push(x), - None => using_decl_member.push(acc_symbol), + None => using_decl_member.push(acc_symbol), } } result.insert(addr_addrnum_with_module_name, using_decl_member); } result } - diff --git a/language/move-analyzer/tests/test_document_symbols.rs b/language/move-analyzer/tests/test_document_symbols.rs index 9374600b4a..584aba44ed 100644 --- a/language/move-analyzer/tests/test_document_symbols.rs +++ b/language/move-analyzer/tests/test_document_symbols.rs @@ -6,14 +6,13 @@ mod tests { use aptos_move_analyzer::{ context::*, - utils::{path_concat,discover_manifest_and_kind}, multiproject::MultiProject, - symbols::on_document_symbol_request + symbols::on_document_symbol_request, + utils::{discover_manifest_and_kind, path_concat}, }; use lsp_server::*; - - use std::path::PathBuf; use serde_json::json; + use std::path::PathBuf; // use itertools::Itertools; fn prepare_project(context: &mut Context, fpath: PathBuf) { @@ -67,7 +66,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -115,7 +114,7 @@ mod tests { } }, "tags": [ - + ] } ], @@ -143,7 +142,7 @@ mod tests { } }, "tags": [ - + ] } ], @@ -172,10 +171,10 @@ mod tests { } }, "tags": [ - + ] } - ] + ] ), ); // // std::thread::sleep(Duration::new(1, 0)); @@ -186,7 +185,6 @@ mod tests { log::info!("\n------------------------------\n"); assert_eq!(actual_r.result, expect_r.result); } - /// Document Symbol 2 #[test] @@ -209,7 +207,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -383,7 +381,7 @@ mod tests { }] ), ); - + assert_eq!(actual_r.result, expect_r.result); } -} \ No newline at end of file +} diff --git a/language/move-analyzer/tests/test_goto_def.rs b/language/move-analyzer/tests/test_goto_def.rs index 3fa1409ea3..06e6e3d4b2 100644 --- a/language/move-analyzer/tests/test_goto_def.rs +++ b/language/move-analyzer/tests/test_goto_def.rs @@ -6,13 +6,13 @@ mod tests { use aptos_move_analyzer::{ context::*, - utils::{path_concat,discover_manifest_and_kind}, + goto_definition::on_go_to_def_request, multiproject::MultiProject, - goto_definition::on_go_to_def_request + utils::{discover_manifest_and_kind, path_concat}, }; use lsp_server::*; - use std::path::PathBuf; use serde_json::json; + use std::path::PathBuf; // use itertools::Itertools; fn prepare_project(context: &mut Context, fpath: PathBuf) { @@ -45,8 +45,7 @@ mod tests { context.projects.insert_project(p); } - - /// Testing whether local variables in a test function + /// Testing whether local variables in a test function /// can goto definition in this function #[test] fn test_on_go_to_def_request_001() { @@ -68,7 +67,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -102,7 +101,7 @@ mod tests { } }, "uri": "file://".to_string() + fpath.to_str().unwrap() - + }]), ); // std::thread::sleep(Duration::new(1, 0)); @@ -113,7 +112,7 @@ mod tests { log::trace!("\n------------------------------\n"); assert_eq!(actual_r.result, expect_r.result); } - + /// Test whether references to structs in the same file can get definition. #[test] fn test_on_go_to_def_request_002() { @@ -135,7 +134,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -200,7 +199,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -265,7 +264,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -330,7 +329,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -362,8 +361,8 @@ mod tests { "character":42, }, }, - "uri": - "file://".to_string() + "uri": + "file://".to_string() + path_concat( std::env::current_dir().unwrap().as_path(), PathBuf::from("tests/v1-core/Swap/sources/swap_library.move").as_path(), @@ -379,7 +378,7 @@ mod tests { assert_eq!(actual_r.result, expect_r.result); } - /// Test goto definition for use decl + /// Test goto definition for use decl #[test] fn test_on_go_to_def_request_006() { let (connection, _) = Connection::stdio(); @@ -400,7 +399,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -432,8 +431,8 @@ mod tests { "character":4, }, }, - "uri": - "file://".to_string() + "uri": + "file://".to_string() + path_concat( std::env::current_dir().unwrap().as_path(), PathBuf::from("tests/v1-core/LPCoin/sources/LPCoin.move").as_path(), @@ -442,4 +441,4 @@ mod tests { ); assert_eq!(actual_r.result, expect_r.result); } -} \ No newline at end of file +} diff --git a/language/move-analyzer/tests/test_hover.rs b/language/move-analyzer/tests/test_hover.rs index a3296829d0..76315bfe60 100644 --- a/language/move-analyzer/tests/test_hover.rs +++ b/language/move-analyzer/tests/test_hover.rs @@ -3,18 +3,15 @@ #[cfg(test)] mod tests { - use lsp_server::{Connection, Request, Response}; use aptos_move_analyzer::{ context::{Context, FileDiags}, - multiproject::MultiProject, hover, + multiproject::MultiProject, utils::*, }; + use lsp_server::{Connection, Request, Response}; use serde_json::json; - use std::{ - path::PathBuf, - time::Duration, - }; + use std::{path::PathBuf, time::Duration}; fn prepare_project(context: &mut Context, fpath: PathBuf) { eprintln!(" -- prepare_project -- fpath = {:?}", fpath.to_str()); @@ -345,6 +342,4 @@ mod tests { eprintln!("\n------------------------------\n"); assert_eq!(actual_r.result, expect_r.result); } - - } diff --git a/language/move-analyzer/tests/test_references.rs b/language/move-analyzer/tests/test_references.rs index 32459a2355..1ecd5952a8 100644 --- a/language/move-analyzer/tests/test_references.rs +++ b/language/move-analyzer/tests/test_references.rs @@ -3,18 +3,15 @@ #[cfg(test)] mod tests { - use lsp_server::{Connection, Request, Response}; use aptos_move_analyzer::{ context::{Context, FileDiags}, multiproject::MultiProject, references, utils::*, }; + use lsp_server::{Connection, Request, Response}; use serde_json::json; - use std::{ - path::PathBuf, - time::Duration, - }; + use std::{path::PathBuf, time::Duration}; fn prepare_project(context: &mut Context, fpath: PathBuf) { eprintln!(" -- prepare_project -- fpath = {:?}", fpath.to_str()); @@ -132,8 +129,14 @@ mod tests { if let Some(serde_json::Value::Array(expect_r_result)) = expect_r.result.clone() { for expect_r_value in expect_r_result { if actual_r_value.eq(&expect_r_value) { - eprintln!("actual_r_value = {:?}", serde_json::to_string(&actual_r_value)); - eprintln!("expect_r_value = {:?}", serde_json::to_string(&expect_r_value)); + eprintln!( + "actual_r_value = {:?}", + serde_json::to_string(&actual_r_value) + ); + eprintln!( + "expect_r_value = {:?}", + serde_json::to_string(&expect_r_value) + ); found_same_item = true; break; } @@ -315,8 +318,14 @@ mod tests { if let Some(serde_json::Value::Array(expect_r_result)) = expect_r.result.clone() { for expect_r_value in expect_r_result { if actual_r_value.eq(&expect_r_value) { - eprintln!("actual_r_value = {:?}", serde_json::to_string(&actual_r_value)); - eprintln!("expect_r_value = {:?}", serde_json::to_string(&expect_r_value)); + eprintln!( + "actual_r_value = {:?}", + serde_json::to_string(&actual_r_value) + ); + eprintln!( + "expect_r_value = {:?}", + serde_json::to_string(&expect_r_value) + ); found_same_item = true; break; } @@ -326,5 +335,4 @@ mod tests { } } } - } diff --git a/language/move-analyzer/tests/test_spec_file.rs b/language/move-analyzer/tests/test_spec_file.rs index 04c5600ee5..5cf85efb51 100644 --- a/language/move-analyzer/tests/test_spec_file.rs +++ b/language/move-analyzer/tests/test_spec_file.rs @@ -6,14 +6,13 @@ mod tests { use aptos_move_analyzer::{ context::*, - utils::{path_concat,discover_manifest_and_kind}, + move_generate_spec_file::on_generate_spec_file, multiproject::MultiProject, - move_generate_spec_file::on_generate_spec_file + utils::{discover_manifest_and_kind, path_concat}, }; use lsp_server::*; - - use std::path::PathBuf; use serde_json::json; + use std::path::PathBuf; // use itertools::Itertools; fn prepare_project(context: &mut Context, fpath: PathBuf) { @@ -67,7 +66,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -116,7 +115,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -131,7 +130,6 @@ mod tests { let actual_r = on_generate_spec_file(&context, &request, false); let ex = Some( String::from("spec 0x0::M3 {\n\n spec module {\n pragma verify = true;\n pragma aborts_if_is_strict;\n }\n spec create_u128(a: u128, b: u128): u128{\n aborts_if a + b > MAX_U128;\n }\n spec test_may_overflow(var_u64: u64, var_u128: u128, var_u256: u256): u64{\n let var_local_u64 = var_u64 + 1;\n aborts_if var_u64 + 1 > MAX_U64;\n let var_local_u128 = var_u128 * 2;\n aborts_if var_u128 * 2 > MAX_U128;\n let var_local_u256 = var_u256 << 3;\n aborts_if var_u256 << 3 > MAX_U256;\n aborts_if (var_local_u64 as u128) + var_local_u128 > MAX_U128;\n aborts_if (((var_local_u64 as u128) + var_local_u128) as u256) * var_local_u256 > MAX_U256;\n aborts_if ((((var_local_u64 as u128) + var_local_u128) as u256) * var_local_u256) << 3 > MAX_U256;\n }\n spec test_may_underflow(var_u64: u64, var_u128: u128, var_u256: u256): u64{\n aborts_if var_u64 - 1 < 0;\n let var_local_u128 = (var_u128 * 2) - 1000;\n aborts_if var_u128 * 2 > MAX_U128;\n aborts_if (var_u128 * 2) - 1000 < 0;\n aborts_if var_local_u128 <= 0 with 0;\n }\n spec test_may_div_zero(var_u64: u64, var_u128: u128, var_u256: u256): u64{\n aborts_if 100 + var_u64 > MAX_U64;\n aborts_if var_u64 == 0;\n aborts_if var_u256 == 0;\n aborts_if ((var_u128 as u256) / var_u256) == 0;\n }\n}\n\n") - ); let expect_r = Response::new_ok( "generate_spec_file_request_002".to_string().into(), @@ -145,7 +143,4 @@ mod tests { log::info!("\n------------------------------\n"); assert_eq!(actual_r.result, expect_r.result); } - - - -} \ No newline at end of file +} diff --git a/language/move-analyzer/tests/test_spec_sel.rs b/language/move-analyzer/tests/test_spec_sel.rs index f32ff7662a..13df8001aa 100644 --- a/language/move-analyzer/tests/test_spec_sel.rs +++ b/language/move-analyzer/tests/test_spec_sel.rs @@ -6,13 +6,13 @@ mod tests { use aptos_move_analyzer::{ context::*, - utils::{path_concat,discover_manifest_and_kind}, + move_generate_spec_sel::{on_generate_spec_sel, Resp}, multiproject::MultiProject, - move_generate_spec_sel::{on_generate_spec_sel,Resp}, + utils::{discover_manifest_and_kind, path_concat}, }; use lsp_server::*; - use std::path::PathBuf; use serde_json::json; + use std::path::PathBuf; // use itertools::Itertools; fn prepare_project(context: &mut Context, fpath: PathBuf) { @@ -66,7 +66,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -81,13 +81,11 @@ mod tests { }; let actual_r = on_generate_spec_sel(&mut context, &request); - let ex = Some( - Resp { - line: 11, - col: 4, - content: String::from(" spec CapabilityStorage{\n }\n") - } - ); + let ex = Some(Resp { + line: 11, + col: 4, + content: String::from(" spec CapabilityStorage{\n }\n"), + }); let expect_r = Response::new_ok( "generate_spec_request_001".to_string().into(), serde_json::to_value(ex).unwrap(), @@ -100,7 +98,6 @@ mod tests { log::info!("\n------------------------------\n"); assert_eq!(actual_r.result, expect_r.result); } - /// Generate Spec for Operators which may Overflow in a Function. #[test] @@ -123,7 +120,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -140,7 +137,7 @@ mod tests { let actual_r = on_generate_spec_sel(&mut context, &request); let ex = Some( Resp { - line: 15, + line: 15, col: 5, content: String::from(" spec test_may_overflow(var_u64: u64, var_u128: u128, var_u256: u256): u64{\n let var_local_u64 = var_u64 + 1;\n aborts_if var_u64 + 1 > MAX_U64;\n let var_local_u128 = var_u128 * 2;\n aborts_if var_u128 * 2 > MAX_U128;\n let var_local_u256 = var_u256 << 3;\n aborts_if var_u256 << 3 > MAX_U256;\n aborts_if (var_local_u64 as u128) + var_local_u128 > MAX_U128;\n aborts_if (((var_local_u64 as u128) + var_local_u128) as u256) * var_local_u256 > MAX_U256;\n aborts_if ((((var_local_u64 as u128) + var_local_u128) as u256) * var_local_u256) << 3 > MAX_U256;\n }\n") } @@ -179,7 +176,7 @@ mod tests { None => { log::error!("project '{:?}' not found.", fpath.as_path()); return; - } + }, }; let params_json = json!({ @@ -196,7 +193,7 @@ mod tests { let actual_r = on_generate_spec_sel(&mut context, &request); let ex = Some( Resp { - line: 25, + line: 25, col: 5, content: String::from(" spec test_may_underflow(var_u64: u64, var_u128: u128, var_u256: u256): u64{\n aborts_if var_u64 - 1 < 0;\n let var_local_u128 = (var_u128 * 2) - 1000;\n aborts_if var_u128 * 2 > MAX_U128;\n aborts_if (var_u128 * 2) - 1000 < 0;\n aborts_if var_local_u128 <= 0 with 0;\n }\n") } @@ -212,62 +209,61 @@ mod tests { // log::trace!("expect_r = {:?}", expect_r); log::info!("\n------------------------------\n"); assert_eq!(actual_r.result, expect_r.result); - } + } - /// Generate Spec for Operators which may Div Zero in a Function. - #[test] - fn test_generate_spec_request_004() { - let (connection, _) = Connection::stdio(); - let mut context = Context { - projects: MultiProject::new(), - connection, - diag_version: FileDiags::new(), - }; - - let fpath = path_concat( - std::env::current_dir().unwrap().as_path(), - PathBuf::from("tests/symbols/sources/SpecTest.move").as_path(), - ); - prepare_project(&mut context, fpath.clone()); - - let _ = match context.projects.get_project(&fpath) { - Some(x) => x, - None => { - log::error!("project '{:?}' not found.", fpath.as_path()); - return; - } - }; - - let params_json = json!({ - "col": 5, - "line": 33, - "fpath": fpath.to_string_lossy().to_string() - }); - let request = Request { - id: "generate_spec_request_004".to_string().into(), - method: String::from("move/generate/spec/sel"), - params: params_json, - }; - - let actual_r = on_generate_spec_sel(&mut context, &request); - let ex = Some( + /// Generate Spec for Operators which may Div Zero in a Function. + #[test] + fn test_generate_spec_request_004() { + let (connection, _) = Connection::stdio(); + let mut context = Context { + projects: MultiProject::new(), + connection, + diag_version: FileDiags::new(), + }; + + let fpath = path_concat( + std::env::current_dir().unwrap().as_path(), + PathBuf::from("tests/symbols/sources/SpecTest.move").as_path(), + ); + prepare_project(&mut context, fpath.clone()); + + let _ = match context.projects.get_project(&fpath) { + Some(x) => x, + None => { + log::error!("project '{:?}' not found.", fpath.as_path()); + return; + }, + }; + + let params_json = json!({ + "col": 5, + "line": 33, + "fpath": fpath.to_string_lossy().to_string() + }); + let request = Request { + id: "generate_spec_request_004".to_string().into(), + method: String::from("move/generate/spec/sel"), + params: params_json, + }; + + let actual_r = on_generate_spec_sel(&mut context, &request); + let ex = Some( Resp { - line: 34, + line: 34, col: 5, content: String::from(" spec test_may_div_zero(var_u64: u64, var_u128: u128, var_u256: u256): u64{\n aborts_if 100 + var_u64 > MAX_U64;\n aborts_if var_u64 == 0;\n aborts_if var_u256 == 0;\n aborts_if ((var_u128 as u256) / var_u256) == 0;\n }\n") } ); - let expect_r = Response::new_ok( - "generate_spec_request_004".to_string().into(), - serde_json::to_value(ex).unwrap(), - ); - // // std::thread::sleep(Duration::new(1, 0)); - // log::info!("\n------------------------------\n"); - eprintln!("actual_r = {:?}", actual_r.result); - eprintln!("\n\n\n"); - // log::trace!("expect_r = {:?}", expect_r); - log::info!("\n------------------------------\n"); - assert_eq!(actual_r.result, expect_r.result); - } - -} \ No newline at end of file + let expect_r = Response::new_ok( + "generate_spec_request_004".to_string().into(), + serde_json::to_value(ex).unwrap(), + ); + // // std::thread::sleep(Duration::new(1, 0)); + // log::info!("\n------------------------------\n"); + eprintln!("actual_r = {:?}", actual_r.result); + eprintln!("\n\n\n"); + // log::trace!("expect_r = {:?}", expect_r); + log::info!("\n------------------------------\n"); + assert_eq!(actual_r.result, expect_r.result); + } +}