From d0d7c3c7d0676a1b7504cf690486987c5d2167d8 Mon Sep 17 00:00:00 2001 From: 0xSwapFeeder Date: Fri, 8 Dec 2023 11:54:11 -0500 Subject: [PATCH] fix(solidity/core/foundry-compiler-server): some windows specific issues --- libs/foundry-wrapper/src/compiler.rs | 7 ++-- libs/foundry-wrapper/src/types.rs | 7 ++-- libs/foundry-wrapper/src/utils/path.rs | 4 ++ .../foundry-compiler-server/src/main.rs | 39 +++++++++++-------- .../foundry-compiler-server/src/utils.rs | 16 ++++++++ .../solidity/extension/src/extension.ts | 5 +-- .../extension/src/foundry-compiler.ts | 6 ++- 7 files changed, 56 insertions(+), 28 deletions(-) diff --git a/libs/foundry-wrapper/src/compiler.rs b/libs/foundry-wrapper/src/compiler.rs index 21bda6c4..98094767 100644 --- a/libs/foundry-wrapper/src/compiler.rs +++ b/libs/foundry-wrapper/src/compiler.rs @@ -1,7 +1,7 @@ use crate::{ error::Error, types::ProjectCompileOutput, - utils::{check_executable_argument, find_forge_executable, find_projects_paths}, + utils::{check_executable_argument, find_forge_executable, find_projects_paths, normalize_path}, }; use std::process::Command; @@ -31,10 +31,11 @@ impl Compiler { } fn find_closest_workspace(&self, file_path: &str) -> Option { + let filepath = normalize_path(file_path); self.inner .workspaces .iter() - .filter(|path| file_path.starts_with(path.as_str())) + .filter(|path| filepath.starts_with(path.as_str())) .max_by_key(|path| path.len()) .map(|path| path.to_string()) } @@ -43,7 +44,7 @@ impl Compiler { let paths = find_projects_paths(&root_folder)?; for path in paths { if let Some(path) = path.to_str() { - self.inner.workspaces.push(path.to_string()); + self.inner.workspaces.push(normalize_path(path)); } } self.inner.root_path = root_folder; diff --git a/libs/foundry-wrapper/src/types.rs b/libs/foundry-wrapper/src/types.rs index f2dd707f..ff2bce40 100644 --- a/libs/foundry-wrapper/src/types.rs +++ b/libs/foundry-wrapper/src/types.rs @@ -84,14 +84,15 @@ pub struct Position { impl Position { pub fn from_index(idx: i32, source: &str) -> Option { let mut idx: usize = idx as usize; - for (i, l) in source.lines().enumerate() { - if idx < l.len() { + for (i, l) in source.split("\n").enumerate() { + let line_length = l.len() + if l.ends_with("\r") { 2 } else { 1 }; + if idx < line_length { return Some(Self { line: i as u32, column: idx as u32, }); } - idx -= l.len() + 1; + idx -= line_length } None } diff --git a/libs/foundry-wrapper/src/utils/path.rs b/libs/foundry-wrapper/src/utils/path.rs index 6a8999e6..53d79e0a 100644 --- a/libs/foundry-wrapper/src/utils/path.rs +++ b/libs/foundry-wrapper/src/utils/path.rs @@ -13,3 +13,7 @@ pub fn find_projects_paths(root_path: &str) -> Result, glob::Patter .map(|path| path.parent().unwrap().to_path_buf()) .collect()) } + +pub fn normalize_path(path: &str) -> String { + path.replace("\\", "/").replace("//", "/").replace("\\\\", "/") +} diff --git a/toolchains/solidity/core/crates/foundry-compiler-server/src/main.rs b/toolchains/solidity/core/crates/foundry-compiler-server/src/main.rs index 85a42309..60db0d72 100644 --- a/toolchains/solidity/core/crates/foundry-compiler-server/src/main.rs +++ b/toolchains/solidity/core/crates/foundry-compiler-server/src/main.rs @@ -7,7 +7,7 @@ use tower_lsp::jsonrpc::Result; use tower_lsp::lsp_types::*; use tower_lsp::{Client, LanguageServer, LspService, Server}; mod utils; -use utils::{convert_severity, get_root_path}; +use utils::{convert_severity, get_root_path, normalize_path, slashify_path}; mod affected_files_store; use affected_files_store::AffectedFilesStore; @@ -41,7 +41,7 @@ impl LanguageServer for Backend { ), ) .await; - self.load_workspace(path).await; + self.load_workspace(normalize_path(path.as_str())).await; } else { self.client .log_message( @@ -74,7 +74,10 @@ impl LanguageServer for Backend { format!("file opened!: {:}", params.text_document.uri), ) .await; - self.compile(params.text_document.uri.path().to_string()) + if params.text_document.uri.path().contains("forge-std") { + return; + } + self.compile(slashify_path(&normalize_path(params.text_document.uri.path()))) .await; } @@ -85,7 +88,7 @@ impl LanguageServer for Backend { format!("file changed!: {:}", params.text_document.uri), ) .await; - self.compile(params.text_document.uri.path().to_string()) + self.compile(slashify_path(&normalize_path(params.text_document.uri.path()))) .await; } @@ -164,7 +167,7 @@ impl Backend { .log_message(MessageType::INFO, format!("Compile errors: {:?}", output.get_errors())) .await;*/ drop(state); - self.publish_errors_diagnostics(project_path, filepath, output) + self.publish_errors_diagnostics(slashify_path(&project_path), filepath, output) .await; } Err(err) => { @@ -184,7 +187,7 @@ impl Backend { filepath: String, output: ProjectCompileOutput, ) { - let mut diagnostics = HashMap::>::new(); + let mut diagnostics = HashMap::>::new(); for error in output.get_errors() { eprintln!("error: {:?}", error); let (source_content_filepath, range) = @@ -212,11 +215,10 @@ impl Backend { tags: None, data: None, }; - let url = Url::parse(&format!( - "file://{}", - source_content_filepath.to_str().unwrap() - )) - .unwrap(); + let url = match source_content_filepath.to_str() { + Some(source_path) => slashify_path(source_path), + None => continue, + }; if !diagnostics.contains_key(&url) { diagnostics.insert(url.clone(), vec![diagnostic]); } else { @@ -227,9 +229,13 @@ impl Backend { self.add_not_affected_files(project_path, filepath, &mut diagnostics) .await; for (uri, diags) in diagnostics.iter() { - self.client - .publish_diagnostics(uri.clone(), diags.clone(), None) + if let Ok(url) = Url::parse(&format!("file://{}", &uri)) { + self.client + .publish_diagnostics(url, diags.clone(), None) .await; + } else { + self.client.log_message(MessageType::ERROR, "error, cannot parse file uri").await; + } } } @@ -285,7 +291,7 @@ impl Backend { &self, project_path: String, filepath: String, - files: &mut HashMap>, + raised_diagnostics: &mut HashMap>, ) { let mut state = self.state.lock().await; @@ -296,10 +302,11 @@ impl Backend { let affected_files = state.affected_files.get_affected_files(&project_path); drop(state); let mut without_diagnostics = vec![]; + for file in affected_files { - let url = Url::parse(&format!("file://{}", file)).unwrap(); + if !raised_diagnostics.contains_key(&file) { // if not potential not affected file is not in raised diags if let std::collections::hash_map::Entry::Vacant(e) = files.entry(url) { - e.insert(vec![]); + raised_diagnostics.insert(file.clone(), vec![]); without_diagnostics.push(file); } } diff --git a/toolchains/solidity/core/crates/foundry-compiler-server/src/utils.rs b/toolchains/solidity/core/crates/foundry-compiler-server/src/utils.rs index a53dd1bb..75a8a91b 100644 --- a/toolchains/solidity/core/crates/foundry-compiler-server/src/utils.rs +++ b/toolchains/solidity/core/crates/foundry-compiler-server/src/utils.rs @@ -17,3 +17,19 @@ pub fn convert_severity(severity: Severity) -> DiagnosticSeverity { Severity::Info => DiagnosticSeverity::INFORMATION, } } + +#[cfg(target_family = "windows")] +pub fn normalize_path(path: &str) -> String { + let mut path = path.replace("%3A/", "://"); + path.remove(0); + path.to_string() +} + +#[cfg(not(target_family = "windows"))] +pub fn normalize_path(path: &str) -> String { + path.to_string() +} + +pub fn slashify_path(path: &str) -> String { + path.replace("\\", "/").replace("\\\\", "/").replace("//", "/") +} \ No newline at end of file diff --git a/toolchains/solidity/extension/src/extension.ts b/toolchains/solidity/extension/src/extension.ts index 6f181ae7..e74c904d 100644 --- a/toolchains/solidity/extension/src/extension.ts +++ b/toolchains/solidity/extension/src/extension.ts @@ -5,12 +5,9 @@ import * as path from 'path'; import { workspace, ExtensionContext } from 'vscode'; - +[] import { LanguageClient, - LanguageClientOptions, - ServerOptions, - TransportKind } from 'vscode-languageclient/node'; import { createLinterClient } from './linter'; import { createFoundryCompilerClient } from './foundry-compiler'; diff --git a/toolchains/solidity/extension/src/foundry-compiler.ts b/toolchains/solidity/extension/src/foundry-compiler.ts index 16bc53ce..b43a9c27 100644 --- a/toolchains/solidity/extension/src/foundry-compiler.ts +++ b/toolchains/solidity/extension/src/foundry-compiler.ts @@ -6,15 +6,17 @@ import { ServerOptions, TransportKind } from 'vscode-languageclient/node'; +import * as os from 'os'; export function createFoundryCompilerClient(context: ExtensionContext): LanguageClient { // The server is implemented in node const serverBinary = context.asAbsolutePath( - path.join('dist', 'foundry-compiler-server') + path.join('dist', + os.platform().startsWith("win") ? 'foundry-compiler-server.exe' : 'foundry-compiler-server') ); // If the extension is launched in debug mode then the debug server options are used - // Otherwise the run options are used + // Otherwise the run options are used[] const serverOptions: ServerOptions = { run: { command: serverBinary, transport: TransportKind.stdio }, debug: {