use std::path::{Path, PathBuf}; use ropey::RopeSlice; use tower_lsp::lsp_types::{GotoDefinitionResponse, LocationLink, Position, Range, Url}; /// 跳转到定义 pub fn goto_include_definition(uri: &Url, line: &RopeSlice, pos: Position) -> Option { let line_text = line.as_str().unwrap_or(""); if line_text.trim().starts_with("`include") { let character = pos.character as usize; let first_quote_idx = line_text.find("\""); let last_quote_idx = line_text.rfind("\""); if first_quote_idx.is_none() || last_quote_idx.is_none() { return None; } let first_quote_idx = first_quote_idx.unwrap(); let last_quote_idx = last_quote_idx.unwrap(); if character >= first_quote_idx && character <= last_quote_idx { let mut path_string = &line_text[(first_quote_idx + 1) .. last_quote_idx]; if path_string.starts_with("./") || path_string.starts_with(".\\") { path_string = &path_string[2 ..]; } // 此处得到路径,根据是否为绝对路径进行判断 let path = Path::new(path_string); let mut abs_path: PathBuf; if path.is_absolute() { abs_path = PathBuf::from(path); } else { let base = Path::new(uri.path()).parent()?; abs_path = base.join(path); } if abs_path.exists() { let target_uri = match Url::from_file_path(abs_path.as_path()) { Ok(uri) => uri, Err(_) => return None }; let origin_selection_range = Range::new( Position { line: pos.line, character: first_quote_idx as u32 }, Position { line: pos.line, character: last_quote_idx as u32 } ); let target_position = Position { line: 0, character: 0 }; let target_range = Range::new(target_position, target_position); let link = vec![LocationLink { target_uri, origin_selection_range: Some(origin_selection_range), target_range, target_selection_range: target_range }]; let links = GotoDefinitionResponse::Link(link); return Some(links); } } } None }