Skip to content

Commit

Permalink
fix: Properly deserialize ARM64, fix diagnostics behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
WillLillis committed Oct 30, 2024
1 parent 0a7fc13 commit 965e9b7
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 75 deletions.
53 changes: 25 additions & 28 deletions asm-lsp/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use asm_lsp::handle::{
handle_references_request, handle_signature_help_request,
};
use asm_lsp::{
get_compile_cmd_for_path, get_compile_cmds, get_completes, get_include_dirs, get_root_config,
CompletionItems, DocumentStore, NameToInfoMaps, RootConfig,
get_compile_cmd_for_req, get_compile_cmds_from_file, get_completes, get_include_dirs,
get_root_config, CompletionItems, DocumentStore, NameToInfoMaps, RootConfig,
};

use compile_commands::{CompilationDatabase, SourceFile};
Expand Down Expand Up @@ -179,8 +179,10 @@ pub fn main() -> Result<()> {
Some(CompletionItemKind::OPERATOR),
);

let compile_cmds = get_compile_cmds(&params).unwrap_or_default();
info!("Loaded compile commands: {:?}", compile_cmds);
let compile_cmds = get_compile_cmds_from_file(&params).unwrap_or_default();
if !compile_cmds.is_empty() {
info!("Loaded compile commands: {:?}", compile_cmds);
}
let include_dirs = get_include_dirs(&compile_cmds);

main_loop(
Expand Down Expand Up @@ -301,25 +303,22 @@ fn main_loop(
} else if let Ok((_id, params)) = cast_req::<DocumentDiagnosticRequest>(req.clone())
{
let project_config = config.get_config(&params.text_document.uri);
#[allow(clippy::option_if_let_else)]
let cmp_cmds = if let Some(cmd) =
get_compile_cmd_for_path(config, &params.text_document.uri)
{
// If the user provided a compiler invocation command in their config
// for the project config covering this file, use it
&vec![cmd]
} else {
// Otherwise pass the default compile commands object
compile_cmds
};

// Ok to unwrap, this should never be `None`
if project_config.opts.as_ref().unwrap().diagnostics.unwrap() {
let compile_cmds = get_compile_cmd_for_req(
config,
&params.text_document.uri,
compile_cmds,
);
info!(
"Selected compile command(s) for request: {:#?}",
compile_cmds
);
handle_diagnostics(
connection,
&params.text_document.uri,
project_config,
cmp_cmds,
&compile_cmds,
)?;
info!(
"Diagnostics request serviced in {}ms",
Expand Down Expand Up @@ -353,22 +352,20 @@ fn main_loop(
let project_config = config.get_config(&params.text_document.uri);
// Ok to unwrap, this should never be `None`
if project_config.opts.as_ref().unwrap().diagnostics.unwrap() {
#[allow(clippy::option_if_let_else)]
let cmp_cmds = if let Some(cmd) =
get_compile_cmd_for_path(config, &params.text_document.uri)
{
// If the user provided a compiler invocation command in their config
// for the project config covering this file, use it
&vec![cmd]
} else {
// Otherwise pass the default compile commands object
let compile_cmds = get_compile_cmd_for_req(
config,
&params.text_document.uri,
compile_cmds,
);
info!(
"Selected compile command(s) for request: {:#?}",
compile_cmds
};
);
handle_diagnostics(
connection,
&params.text_document.uri,
project_config,
cmp_cmds,
&compile_cmds,
)?;
info!(
"Published diagnostics on save in {}ms",
Expand Down
116 changes: 69 additions & 47 deletions asm-lsp/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ fn get_additional_include_dirs(compile_cmds: &CompilationDatabase) -> Vec<(Sourc
/// `CompilationDatabase` object
///
/// If both are present, `compile_commands.json` will override `compile_flags.txt`
pub fn get_compile_cmds(params: &InitializeParams) -> Option<CompilationDatabase> {
pub fn get_compile_cmds_from_file(params: &InitializeParams) -> Option<CompilationDatabase> {
if let Some(mut path) = get_project_root(params) {
// Check the project root directory first
let db = get_compilation_db_files(&path);
Expand Down Expand Up @@ -348,16 +348,28 @@ fn get_compilation_db_files(path: &Path) -> Option<CompilationDatabase> {
None
}

/// Attempts to find the user-provided compile command for `req_uri`, as specified within a
/// `project` field in `.asm-lsp.toml`
/// Returns the compile command associated with `uri` if it exists, or the default
/// one from `compile_cmds` otherwise
///
/// NOTE: The `directory` field is intentionally left empty. If this function is being used
/// in a new place, please reconsider this assumption
/// - If the user specified a `compiler` *and* flags in their config, use that
/// - If the user specified a `compiler` but no flags in their config (`None`,
/// *not* an empty `Vec`), try to find flags from `compile_flags.txt` in
/// `compile_cmds` and combine the two
/// - If the user didn't specify any compiler info in the relevant config, return
/// the default commands from `compile_cmds`
///
/// # Panics
///
/// Will panic if `req_uri` cannot be canonicalized
pub fn get_compile_cmd_for_path(config: &RootConfig, req_uri: &Uri) -> Option<CompileCommand> {
/// Will panic if `req_uri` can't be canonicalized
///
/// NOTE: Several fields within the returned `CompilationDatabase` are intentionally left
/// uninitialized to avoid unnecessary allocations. If you're using this function
/// in a new place, please reconsider this assumption
pub fn get_compile_cmd_for_req(
config: &RootConfig,
req_uri: &Uri,
compile_cmds: &CompilationDatabase,
) -> CompilationDatabase {
#[allow(irrefutable_let_patterns)]
let Ok(req_path) = PathBuf::from_str(req_uri.path().as_str()) else {
unreachable!()
Expand All @@ -366,51 +378,61 @@ pub fn get_compile_cmd_for_path(config: &RootConfig, req_uri: &Uri) -> Option<Co
Ok(path) => path,
Err(e) => panic!("Invalid request path: \"{}\" - {e}", req_path.display()),
};
// if the path is within a project configuration and that project specifies
// a compiler and/or compiler flags, use it
if let Some(project) = config.get_project(&request_path) {
match (
project.config.get_compiler(),
project.config.get_compile_flags_txt(),
) {
// Specify this as a full compiler command
(Some(compiler), Some(flags)) => {
let compiler_with_args = {
let mut compile_cmd = vec![];
compile_cmd.push(compiler.to_owned());
compile_cmd.extend(flags.to_owned());
if let Some(path) = request_path.to_str() {
// append the request path as the last compiler argument
compile_cmd.push(path.to_string());
}
compile_cmd
};
Some(CompileCommand {
file: SourceFile::File(request_path.clone()),
directory: PathBuf::new(),
arguments: Some(CompileArgs::Arguments(compiler_with_args)),
command: None,
output: None,
})
let config = config.get_config(req_uri);
match (config.get_compiler(), config.get_compile_flags_txt()) {
(Some(compiler), Some(flags)) => {
// Fill out the full command invocation
let mut args = vec![compiler.to_owned()];
args.append(&mut flags.clone());
args.push(request_path.to_str().unwrap_or_default().to_string());
vec![CompileCommand {
file: SourceFile::File(request_path),
directory: PathBuf::new(),
arguments: Some(CompileArgs::Arguments(args)),
command: None,
output: None,
}]
}
(Some(compiler), None) => {
// Fill out the full command invocation, check if `compile_cmds`
// has flags to tack on
let mut args = vec![compiler.to_owned()];
// Check if we have flags as the first compile command from files,
// `compile_flags.txt` files get loaded as a single `CompileCommand`
// object as structured in the below `if` block
if compile_cmds.len() == 1 {
if let CompileCommand {
arguments: Some(CompileArgs::Flags(flags)),
..
} = &compile_cmds[0]
{
args.append(&mut flags.clone());
}
}
// The default compilers will be added in `apply_compile_cmd`, just
// specify the flags
(None, Some(flags)) => Some(CompileCommand {
file: SourceFile::File(request_path.clone()),
args.push(request_path.to_str().unwrap_or_default().to_string());
vec![CompileCommand {
file: SourceFile::File(request_path),
directory: PathBuf::new(),
arguments: Some(CompileArgs::Flags(flags.to_owned())),
arguments: Some(CompileArgs::Arguments(args)),
command: None,
output: None,
}),
// - Do nothing if only `compiler` is specified, `get_default_compile_cmd`
// will generate a command with `compiler` in it
// - Do nothing if nothing is specified, a default compmand will be
// generated by `get_default_compile_cmd` in `handle_diagnostics`
(Some(_) | None, None) => None,
};
}]
}
(None, Some(flags)) => {
// Fill out flags, no compiler
vec![CompileCommand {
file: SourceFile::File(request_path),
directory: PathBuf::new(),
arguments: Some(CompileArgs::Flags(flags.clone())),
command: None,
output: None,
}]
}
(None, None) => {
// Grab the default command from `compile_cmds`
compile_cmds.clone()
}
}

None
}

/// Returns a default `CompileCommand` for the provided `uri`.
Expand Down
1 change: 1 addition & 0 deletions asm-lsp/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,7 @@ pub enum Arch {
#[serde(rename = "arm")]
ARM,
#[strum(serialize = "arm64")]
#[serde(rename = "arm64")]
ARM64,
#[strum(serialize = "riscv")]
#[serde(rename = "riscv")]
Expand Down

0 comments on commit 965e9b7

Please sign in to comment.