Skip to content

Commit

Permalink
Store paths in 'compilation_data.files'.
Browse files Browse the repository at this point in the history
  • Loading branch information
InsertCreativityHere committed Feb 14, 2024
1 parent b3a00b7 commit 122db1c
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 68 deletions.
6 changes: 5 additions & 1 deletion server/src/configuration_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
use crate::slice_config::{compute_slice_options, ServerConfig, SliceConfig};
use crate::utils::sanitize_path;
use std::collections::HashMap;
use std::path::PathBuf;
use slicec::slice_options::SliceOptions;
use slicec::{ast::Ast, diagnostics::Diagnostic, slice_file::SliceFile};
use slicec::compilation_state::CompilationState;

#[derive(Debug, Default)]
pub struct CompilationData {
pub ast: Ast,
pub files: HashMap<String, SliceFile>,
pub files: HashMap<PathBuf, SliceFile>,
}

// Necessary for using `CompilationData` within async functions.
Expand Down Expand Up @@ -61,6 +62,9 @@ impl ConfigurationSet {
// Process the diagnostics (filter out allowed lints, and update diagnostic levels as necessary).
let updated_diagnostics = diagnostics.into_updated(&ast, &files, slice_options);

// Convert the stringified paths returned by `slicec` to actual PathBuf objects.
let files = files.into_iter().map(|(k, v)| (PathBuf::from(k), v)).collect();

// Store the data we got from compiling, then return the diagnostics so they can be published.
self.compilation_data = CompilationData { ast, files };
updated_diagnostics
Expand Down
11 changes: 5 additions & 6 deletions server/src/diagnostic_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::configuration_set::ConfigurationSet;
use crate::session::Session;
use crate::utils::convert_slice_url_to_uri;
use crate::utils::convert_slice_path_to_uri;
use crate::{notifications, show_popup};

use slicec::diagnostics::{Diagnostic, DiagnosticLevel, Note};
Expand All @@ -27,7 +27,7 @@ pub async fn publish_diagnostics_for_set(
.compilation_data
.files
.keys()
.filter_map(|uri| Some((convert_slice_url_to_uri(uri)?, vec![])))
.filter_map(|uri| Some((convert_slice_path_to_uri(uri)?, vec![])))
.collect::<HashMap<Url, Vec<tower_lsp::lsp_types::Diagnostic>>>();

// Process the diagnostics and populate the map.
Expand Down Expand Up @@ -87,7 +87,7 @@ pub fn process_diagnostics(
let file = span
.expect("If the span was empty, try_into_lsp_diagnostic should have hit the error case")
.file;
let uri = convert_slice_url_to_uri(&file)?;
let uri = convert_slice_path_to_uri(file)?;
Some((uri, lsp_diagnostic))
}
Err(diagnostic) => {
Expand All @@ -114,8 +114,7 @@ pub async fn clear_diagnostics(client: &Client, configuration_sets: &Mutex<Vec<C
.compilation_data
.files
.keys()
.cloned()
.filter_map(|uri| convert_slice_url_to_uri(&uri))
.filter_map(convert_slice_path_to_uri)
.for_each(|uri| {
all_tracked_files.insert(uri);
});
Expand Down Expand Up @@ -181,7 +180,7 @@ fn try_into_lsp_diagnostic_related_information(
note: &Note,
) -> Option<tower_lsp::lsp_types::DiagnosticRelatedInformation> {
let span = note.span.as_ref()?;
let file_path = convert_slice_url_to_uri(&span.file)?;
let file_path = convert_slice_path_to_uri(&span.file)?;
let start_position = Position::new((span.start.row - 1) as u32, (span.start.col - 1) as u32);
let end_position = Position::new((span.end.row - 1) as u32, (span.end.col - 1) as u32);

Expand Down
57 changes: 26 additions & 31 deletions server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::session::Session;
use crate::slice_config::compute_slice_options;
use std::{collections::HashMap, path::Path};
use tower_lsp::{jsonrpc::Error, lsp_types::*, Client, LanguageServer, LspService, Server};
use utils::{convert_slice_url_to_uri, url_to_sanitized_file_path, FindFile};
use utils::{convert_slice_path_to_uri, url_to_sanitized_file_path};

mod configuration_set;
mod diagnostic_ext;
Expand Down Expand Up @@ -71,9 +71,9 @@ impl Backend {
}
}

async fn handle_file_change(&self, file_name: &str) {
async fn handle_file_change(&self, file_path: &Path) {
self.client
.log_message(MessageType::INFO, format!("File '{file_name}' changed"))
.log_message(MessageType::INFO, format!("File '{}' changed", file_path.display()))
.await;

let mut configuration_sets = self.session.configuration_sets.lock().await;
Expand All @@ -89,7 +89,6 @@ impl Backend {
.into_iter()
.any(|f| {
let key_path = Path::new(&f);
let file_path = Path::new(file_name);
key_path == file_path || file_path.starts_with(key_path)
})
}) {
Expand All @@ -101,7 +100,7 @@ impl Backend {
set.compilation_data
.files
.keys()
.filter_map(|uri| convert_slice_url_to_uri(uri))
.filter_map(convert_slice_path_to_uri)
.map(|uri| (uri, vec![])),
);
}
Expand Down Expand Up @@ -189,31 +188,28 @@ impl LanguageServer for Backend {

// Find the configuration set that contains the file
let configuration_sets = self.session.configuration_sets.lock().await;
let compilation_data = configuration_sets.iter().find_file(&file_path);

// Get the definition span and convert it to a GotoDefinitionResponse
compilation_data
.and_then(|data| {
let file = data.files.get(&file_path).expect("mismatch in file name occurred during goto request");
get_definition_span(file, position)
})
.and_then(|location| {
let start = Position {
line: (location.start.row - 1) as u32,
character: (location.start.col - 1) as u32,
};
let end = Position {
line: (location.end.row - 1) as u32,
character: (location.end.col - 1) as u32,
};
convert_slice_url_to_uri(&location.file).map(|uri| {
Ok(configuration_sets.iter().find_map(|set| {
let files = &set.compilation_data.files;
files
.get(&file_path)
.and_then(|file| get_definition_span(file, position))
.map(|location| {
let start = Position {
line: (location.start.row - 1) as u32,
character: (location.start.col - 1) as u32,
};
let end = Position {
line: (location.end.row - 1) as u32,
character: (location.end.col - 1) as u32,
};
GotoDefinitionResponse::Scalar(Location {
uri,
uri: uri.clone(),
range: Range::new(start, end),
})
})
})
.map_or(Ok(None), |resp| Ok(Some(resp)))
}))
}

async fn hover(&self, params: HoverParams) -> tower_lsp::jsonrpc::Result<Option<Hover>> {
Expand All @@ -226,13 +222,12 @@ impl LanguageServer for Backend {
// Find the configuration set that contains the file and get the hover info
let configuration_sets = self.session.configuration_sets.lock().await;

Ok(configuration_sets
.iter()
.find_file(&file_path)
.and_then(|data| {
let file = data.files.get(&file_path).expect("mismatch in file name occurred during hover request");
try_into_hover_result(file, position).ok()
}))
Ok(configuration_sets.iter().find_map(|set| {
let files = &set.compilation_data.files;
files
.get(&file_path)
.and_then(|file| try_into_hover_result(file, position).ok())
}))
}

async fn did_open(&self, params: DidOpenTextDocumentParams) {
Expand Down
2 changes: 0 additions & 2 deletions server/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
use crate::configuration_set::ConfigurationSet;
use crate::slice_config::ServerConfig;
use crate::utils::{sanitize_path, url_to_sanitized_file_path};
use std::path::PathBuf;
use tokio::sync::{Mutex, RwLock};
use tower_lsp::lsp_types::DidChangeConfigurationParams;

Expand Down Expand Up @@ -31,7 +30,6 @@ impl Session {
let workspace_root_path = params
.root_uri
.and_then(|uri| url_to_sanitized_file_path(&uri))
.map(PathBuf::from)
.map(|path| path.display().to_string())
.expect("`root_uri` was not sent by the client, or was malformed");

Expand Down
34 changes: 6 additions & 28 deletions server/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,18 @@
// Copyright (c) ZeroC, Inc.

use crate::configuration_set::{CompilationData, ConfigurationSet};
use std::path::Path;
use std::path::{Path, PathBuf};
use tower_lsp::lsp_types::Url;

// A helper trait that allows us to find a file in an iterator of ConfigurationSet.
pub trait FindFile<'a> {
fn find_file(self, file_name: &str) -> Option<&'a CompilationData>;
}

impl<'a, I> FindFile<'a> for I
where
I: Iterator<Item = &'a ConfigurationSet>,
{
fn find_file(mut self, file_name: &str) -> Option<&'a CompilationData> {
self.find(|set| {
set.compilation_data.files.keys().any(|f| {
let key_path = Path::new(f);
let file_path = Path::new(file_name);
key_path == file_path || file_path.starts_with(key_path)
})
})
.map(|set| &set.compilation_data)
}
}

// This helper function converts a Url from tower_lsp into a string that can be used to
// This helper function converts a Url from tower_lsp into a path that can be used to
// retrieve a file from the compilation state from slicec.
pub fn url_to_sanitized_file_path(url: &Url) -> Option<String> {
pub fn url_to_sanitized_file_path(url: &Url) -> Option<PathBuf> {
let path = url.to_file_path().ok()?;
let path_string = path.to_str()?;
Some(sanitize_path(path_string))
Some(PathBuf::from(sanitize_path(path_string)))
}

pub fn convert_slice_url_to_uri(url: &str) -> Option<Url> {
Url::from_file_path(url).ok()
pub fn convert_slice_path_to_uri(path: impl AsRef<Path>) -> Option<Url> {
Url::from_file_path(path).ok()
}

#[cfg(target_os = "windows")]
Expand Down

0 comments on commit 122db1c

Please sign in to comment.