Skip to content

Commit

Permalink
Compile between messages if edits have been made
Browse files Browse the repository at this point in the history
  • Loading branch information
Riley-Kilgore committed Sep 13, 2024
1 parent 16e222e commit 8a959e4
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 12 deletions.
19 changes: 11 additions & 8 deletions crates/aiken-lsp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,17 @@ pub fn start() -> Result<(), Error> {
fn capabilities() -> lsp_types::ServerCapabilities {
lsp_types::ServerCapabilities {
// THIS IS STILL WEIRD, ONLY ENABLE IF DEVELOPING
// completion_provider: Some(lsp_types::CompletionOptions {
// resolve_provider: None,
// trigger_characters: Some(vec![".".into(), " ".into()]),
// all_commit_characters: None,
// work_done_progress_options: lsp_types::WorkDoneProgressOptions {
// work_done_progress: None,
// },
// }),
completion_provider: Some(lsp_types::CompletionOptions {
resolve_provider: None,
trigger_characters: Some(vec![".".into(), " ".into()]),
completion_item: Some(lsp_types::CompletionOptionsCompletionItem {
label_details_support: Some(true),
}),
all_commit_characters: None,
work_done_progress_options: lsp_types::WorkDoneProgressOptions {
work_done_progress: None,
},
}),
code_action_provider: Some(lsp_types::CodeActionProviderCapability::Simple(true)),
document_formatting_provider: Some(lsp_types::OneOf::Left(true)),
definition_provider: Some(lsp_types::OneOf::Left(true)),
Expand Down
49 changes: 48 additions & 1 deletion crates/aiken-lsp/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use std::{
collections::{HashMap, HashSet},
fs,
path::{Path, PathBuf},
time::{Duration, Instant},
};

pub mod lsp_project;
Expand Down Expand Up @@ -71,6 +72,10 @@ pub struct Server {

/// An instance of a LspProject
compiler: Option<LspProject>,

last_change: Instant,
compile_scheduled: bool,
debounce_duration: Duration,
}

impl Server {
Expand Down Expand Up @@ -98,10 +103,21 @@ impl Server {

/// Compile the project if we are in one. Otherwise do nothing.
fn compile(&mut self, connection: &Connection) -> Result<(), ServerError> {
self.compile_with_edits(connection, false)
}

/// Helper function used by compile and by the LSP to generate code completions.
fn compile_with_edits(
&mut self,
connection: &Connection,
use_edits: bool,
) -> Result<(), ServerError> {
self.notify_client_of_compilation_start(connection)?;

let edited = if use_edits { Some(&self.edited) } else { None };

if let Some(compiler) = self.compiler.as_mut() {
let result = compiler.compile();
let result = compiler.compile_with_edits(edited);

for warning in compiler.project.warnings() {
self.process_diagnostic(warning)?;
Expand Down Expand Up @@ -219,6 +235,10 @@ impl Server {
self.edited.insert(path, changes.text);
}

self.last_change = Instant::now();
self.compile_scheduled = true;
dbg!("Modified Document");

Ok(())
}

Expand Down Expand Up @@ -588,11 +608,35 @@ impl Server {
self.handle_notification(&connection, notification)?
}
}
// Check if it's time to compile after processing each message
self.check_compile(&connection)?;
}

Ok(())
}

fn check_compile(&mut self, connection: &Connection) -> Result<(), ServerError> {
if self.compile_scheduled && self.last_change.elapsed() >= self.debounce_duration {
dbg!("Entered check_compile (after initial check)");
self.compile_scheduled = false;
if let Ok(config) = Config::load(&self.root) {
dbg!("Config Okay");
self.config = Some(config);
self.create_new_compiler();
self.compile_with_edits(connection, true)?;
dbg!("after compile_with_edits");
} else {
dbg!("Failed to reload aiken.toml");
self.stored_messages.push(lsp_types::ShowMessageParams {
typ: lsp_types::MessageType::ERROR,
message: "Failed to reload aiken.toml".to_string(),
});
}
self.publish_stored_diagnostics(connection)?;
}
Ok(())
}

pub fn new(
initialize_params: InitializeParams,
config: Option<config::Config>,
Expand All @@ -607,6 +651,9 @@ impl Server {
stored_diagnostics: HashMap::new(),
stored_messages: Vec::new(),
compiler: None,
last_change: Instant::now(),
compile_scheduled: false,
debounce_duration: Duration::from_millis(300),
};

server.create_new_compiler();
Expand Down
10 changes: 9 additions & 1 deletion crates/aiken-lsp/src/server/lsp_project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,16 @@ impl LspProject {
}

pub fn compile(&mut self) -> Result<(), Vec<ProjectError>> {
self.compile_with_edits(None)
}

pub fn compile_with_edits(
&mut self,
edited: Option<&HashMap<String, String>>,
) -> Result<(), Vec<ProjectError>> {
let checkpoint = self.project.checkpoint();

let result = self.project.check(
let result = self.project.check_with_edits(
true,
None,
false,
Expand All @@ -38,6 +45,7 @@ impl LspProject {
PropertyTest::DEFAULT_MAX_SUCCESS,
Tracing::silent(),
None,
edited,
);

self.project.restore(checkpoint);
Expand Down
64 changes: 64 additions & 0 deletions crates/aiken-project/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ where
code_gen_mode: CodeGenMode::Build(uplc),
tracing,
env,
edited: None,
};

self.compile(options)
Expand Down Expand Up @@ -267,6 +268,32 @@ where
property_max_success: usize,
tracing: Tracing,
env: Option<String>,
) -> Result<(), Vec<Error>> {
self.check_with_edits(
skip_tests,
match_tests,
verbose,
exact_match,
seed,
property_max_success,
tracing,
env,
None,
)
}

#[allow(clippy::too_many_arguments)]
pub fn check_with_edits(
&mut self,
skip_tests: bool,
match_tests: Option<Vec<String>>,
verbose: bool,
exact_match: bool,
seed: u32,
property_max_success: usize,
tracing: Tracing,
env: Option<String>,
edited: Option<&HashMap<String, String>>,
) -> Result<(), Vec<Error>> {
let options = Options {
tracing,
Expand All @@ -282,6 +309,7 @@ where
property_max_success,
}
},
edited: edited,
};

self.compile(options)
Expand Down Expand Up @@ -353,6 +381,42 @@ where

let mut modules = self.parse_sources(self.config.name.clone())?;

if let Some(edited) = options.edited {
for (module_name, edited_content) in edited {
if let Some(module) = modules.get_mut(module_name) {
// Parse the edited content
match aiken_lang::parser::module(&edited_content, module.kind) {
Ok((mut ast, extra)) => {
ast.name.clone_from(&module.name);
*module = ParsedModule {
kind: module.kind,
ast,
code: edited_content.to_string(),
name: module.name.clone(),
path: module.path.clone(),
extra,
package: module.package.clone(),
};
}
Err(errs) => {
return Err(errs
.into_iter()
.map(|e| Error::Parse {
path: module.path.clone(),
src: edited_content.to_string(),
named: Box::new(NamedSource::new(
module.path.display().to_string(),
edited_content.to_string(),
)),
error: Box::new(e),
})
.collect());
}
}
}
}
}

self.type_check(&mut modules, options.tracing, env, true)?;

match options.code_gen_mode {
Expand Down
8 changes: 6 additions & 2 deletions crates/aiken-project/src/options.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
use std::collections::HashMap;

use aiken_lang::ast::Tracing;

pub struct Options {
pub struct Options<'a> {
pub code_gen_mode: CodeGenMode,
pub tracing: Tracing,
pub env: Option<String>,
pub edited: Option<&'a HashMap<String, String>>,
}

impl Default for Options {
impl<'a> Default for Options<'a> {
fn default() -> Self {
Self {
code_gen_mode: CodeGenMode::NoOp,
tracing: Tracing::silent(),
env: None,
edited: None,
}
}
}
Expand Down

0 comments on commit 8a959e4

Please sign in to comment.