mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 12:14:43 +00:00
fix: bugs
This commit is contained in:
parent
33e1b776cb
commit
ced04e5d6a
8 changed files with 71 additions and 65 deletions
|
@ -28,11 +28,12 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
send_log("visitor not found")?;
|
||||
return Ok(None);
|
||||
};
|
||||
let Some(artifact) = self.artifacts.get(&uri) else {
|
||||
let Some(result) = self.artifacts.get(&uri) else {
|
||||
send_log("artifact not found")?;
|
||||
return Ok(None);
|
||||
};
|
||||
let warns = artifact
|
||||
let warns = result
|
||||
.artifact
|
||||
.warns
|
||||
.iter()
|
||||
.filter(|warn| warn.core.main_message.ends_with("is not used"))
|
||||
|
|
|
@ -24,8 +24,8 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
|
||||
fn send_trait_impls_lens(&mut self, uri: &NormalizedUrl) -> ELSResult<Vec<CodeLens>> {
|
||||
let mut result = vec![];
|
||||
if let Some(artifact) = self.artifacts.get(uri) {
|
||||
if let Some(hir) = &artifact.object {
|
||||
if let Some(analysis) = self.artifacts.get(uri) {
|
||||
if let Some(hir) = &analysis.artifact.object {
|
||||
for chunk in hir.module.iter() {
|
||||
match chunk {
|
||||
Expr::Def(def) if def.def_kind().is_trait() => {
|
||||
|
|
|
@ -4,12 +4,12 @@ use erg_common::style::*;
|
|||
use erg_common::traits::Stream;
|
||||
|
||||
use erg_compiler::artifact::BuildRunnable;
|
||||
use erg_compiler::erg_parser::Parser;
|
||||
use erg_compiler::error::CompileErrors;
|
||||
|
||||
use lsp_types::{Diagnostic, DiagnosticSeverity, Position, PublishDiagnosticsParams, Range, Url};
|
||||
|
||||
use crate::server::{send, send_log, DefaultFeatures, ELSResult, Server};
|
||||
use crate::diff::{ASTDiff, HIRDiff};
|
||||
use crate::server::{send, send_log, AnalysisResult, DefaultFeatures, ELSResult, Server};
|
||||
use crate::util::{self, NormalizedUrl};
|
||||
|
||||
impl<Checker: BuildRunnable> Server<Checker> {
|
||||
|
@ -36,7 +36,10 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
send_log(format!("{uri}, warns: {}", diags.len()))?;
|
||||
self.send_diagnostics(uri, diags)?;
|
||||
}
|
||||
self.artifacts.insert(uri.clone(), artifact.into());
|
||||
if let Some(module) = self.file_cache.get_ast(&uri) {
|
||||
self.artifacts
|
||||
.insert(uri.clone(), AnalysisResult::new(module, artifact.into()));
|
||||
}
|
||||
}
|
||||
Err(artifact) => {
|
||||
send_log(format!("found errors: {}", artifact.errors.len()))?;
|
||||
|
@ -55,7 +58,10 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
send_log(format!("{uri}, errs & warns: {}", diags.len()))?;
|
||||
self.send_diagnostics(uri, diags)?;
|
||||
}
|
||||
self.artifacts.insert(uri.clone(), artifact);
|
||||
if let Some(module) = self.file_cache.get_ast(&uri) {
|
||||
self.artifacts
|
||||
.insert(uri.clone(), AnalysisResult::new(module, artifact));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(module) = checker.pop_context() {
|
||||
|
@ -72,38 +78,26 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
}
|
||||
|
||||
pub(crate) fn quick_check_file(&mut self, uri: NormalizedUrl) -> ELSResult<()> {
|
||||
// send_log(format!("checking {uri}"))?;
|
||||
let Some(ts) = self.file_cache.get_token_stream(&uri) else {
|
||||
let Some(old) = self.artifacts.get(&uri).map(|r| &r.ast) else {
|
||||
crate::_log!("not found");
|
||||
return Ok(());
|
||||
};
|
||||
let mut parser = Parser::new(ts);
|
||||
let Ok(module) = parser.parse() else {
|
||||
let Some(new) = self.file_cache.get_ast(&uri) else {
|
||||
crate::_log!("not found");
|
||||
return Ok(());
|
||||
};
|
||||
let path = util::uri_to_path(&uri);
|
||||
let code = self.file_cache.get_entire_code(&uri)?;
|
||||
let mode = if path.to_string_lossy().ends_with(".d.er") {
|
||||
"declare"
|
||||
} else {
|
||||
"exec"
|
||||
};
|
||||
if let Some(mut lowerer) = self.get_lowerer(&path) {}
|
||||
let mut checker = self.get_checker(path);
|
||||
match checker.build(code, mode) {
|
||||
Ok(artifact) => {
|
||||
self.artifacts.insert(uri.clone(), artifact.into());
|
||||
let ast_diff = ASTDiff::diff(old, &new);
|
||||
crate::_log!("diff: {ast_diff:?}");
|
||||
if let Some(mut lowerer) = self.get_lowerer(&uri) {
|
||||
let hir = self
|
||||
.artifacts
|
||||
.get_mut(&uri)
|
||||
.and_then(|r| r.artifact.object.as_mut());
|
||||
if let Some((hir_diff, hir)) = HIRDiff::new(ast_diff, &mut lowerer).zip(hir) {
|
||||
crate::_log!("hir_diff: {hir_diff:?}");
|
||||
hir_diff.update(hir);
|
||||
}
|
||||
Err(artifact) => {
|
||||
self.artifacts.insert(uri.clone(), artifact);
|
||||
}
|
||||
}
|
||||
if let Some(module) = checker.pop_context() {
|
||||
self.modules.insert(uri.clone(), module);
|
||||
}
|
||||
let dependents = self.dependents_of(&uri);
|
||||
for dep in dependents {
|
||||
// _log!("dep: {dep}");
|
||||
self.quick_check_file(dep)?;
|
||||
self.restore_mod_ctx(&uri, lowerer.pop_mod_ctx().unwrap());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::cmp::Ordering::*;
|
|||
|
||||
use erg_common::traits::Stream;
|
||||
use erg_compiler::erg_parser::ast;
|
||||
use erg_compiler::erg_parser::ast::AST;
|
||||
use erg_compiler::erg_parser::ast::Module;
|
||||
use erg_compiler::hir;
|
||||
use erg_compiler::hir::HIR;
|
||||
use erg_compiler::lower::ASTLowerer;
|
||||
|
@ -23,30 +23,27 @@ pub enum ASTDiff {
|
|||
/// diff(old: {x, y, z}, new: {x, a, z}) => ASTDiff::Modification(1)
|
||||
/// diff(old: {x, y, z}, new: {x, y, z}) => ASTDiff::Nop
|
||||
impl ASTDiff {
|
||||
pub fn diff(old: AST, new: AST) -> ASTDiff {
|
||||
match old.module.len().cmp(&new.module.len()) {
|
||||
pub fn diff(old: &Module, new: &Module) -> ASTDiff {
|
||||
match old.len().cmp(&new.len()) {
|
||||
Less => {
|
||||
let idx = new
|
||||
.module
|
||||
.iter()
|
||||
.zip(old.module.iter())
|
||||
.zip(old.iter())
|
||||
.position(|(new, old)| new != old)
|
||||
.unwrap();
|
||||
Self::Addition(idx, new.module.get(idx).unwrap().clone())
|
||||
.unwrap_or(new.len() - 1);
|
||||
Self::Addition(idx, new.get(idx).unwrap().clone())
|
||||
}
|
||||
Greater => Self::Deletion(
|
||||
old.module
|
||||
.iter()
|
||||
.zip(new.module.iter())
|
||||
old.iter()
|
||||
.zip(new.iter())
|
||||
.position(|(old, new)| old != new)
|
||||
.unwrap(),
|
||||
.unwrap_or(old.len() - 1),
|
||||
),
|
||||
Equal => old
|
||||
.module
|
||||
.iter()
|
||||
.zip(new.module.iter())
|
||||
.zip(new.iter())
|
||||
.position(|(old, new)| old != new)
|
||||
.map(|idx| Self::Modification(idx, new.module.get(idx).unwrap().clone()))
|
||||
.map(|idx| Self::Modification(idx, new.get(idx).unwrap().clone()))
|
||||
.unwrap_or(Self::Nop),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
use erg_compiler::erg_parser::ast::Module;
|
||||
use erg_compiler::erg_parser::Parser;
|
||||
use lsp_types::{
|
||||
DidChangeTextDocumentParams, FileOperationFilter, FileOperationPattern,
|
||||
FileOperationPatternKind, FileOperationRegistrationOptions, OneOf, Position, Range,
|
||||
|
@ -126,6 +128,12 @@ impl FileCache {
|
|||
self.files.borrow_mut().get(uri)?.token_stream.clone()
|
||||
}
|
||||
|
||||
pub fn get_ast(&self, uri: &NormalizedUrl) -> Option<Module> {
|
||||
let ts = self.get_token_stream(uri)?;
|
||||
let mut parser = Parser::new(ts);
|
||||
parser.parse().ok()
|
||||
}
|
||||
|
||||
pub fn get_token(&self, uri: &NormalizedUrl, pos: Position) -> Option<Token> {
|
||||
let _ = self.load_once(uri);
|
||||
let ent = self.files.borrow_mut();
|
||||
|
|
|
@ -95,7 +95,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
let mut result = vec![];
|
||||
if let Some(IncompleteArtifact {
|
||||
object: Some(hir), ..
|
||||
}) = self.artifacts.get(&uri)
|
||||
}) = self.artifacts.get(&uri).map(|r| &r.artifact)
|
||||
{
|
||||
for chunk in hir.module.iter() {
|
||||
result.extend(self.get_expr_hint(chunk));
|
||||
|
|
|
@ -209,7 +209,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
let mut imports = vec![];
|
||||
if let Some(IncompleteArtifact {
|
||||
object: Some(hir), ..
|
||||
}) = self.artifacts.get(target)
|
||||
}) = self.artifacts.get(target).map(|r| &r.artifact)
|
||||
{
|
||||
for chunk in hir.module.iter() {
|
||||
imports.extend(Self::extract_import_symbols(chunk, needle_module_name));
|
||||
|
|
|
@ -3,11 +3,10 @@ use std::io;
|
|||
use std::io::{stdin, stdout, BufRead, Read, StdinLock, StdoutLock, Write};
|
||||
use std::ops::Not;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
|
||||
use erg_common::consts::PYTHON_MODE;
|
||||
use erg_compiler::error::{CompileErrors, CompileWarnings};
|
||||
use erg_compiler::erg_parser::ast::Module;
|
||||
use erg_compiler::lower::ASTLowerer;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
@ -188,6 +187,18 @@ pub(crate) fn send_invalid_req_error() -> ELSResult<()> {
|
|||
send_error(None, -32601, "received an invalid request")
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AnalysisResult {
|
||||
pub ast: Module,
|
||||
pub artifact: IncompleteArtifact,
|
||||
}
|
||||
|
||||
impl AnalysisResult {
|
||||
pub fn new(ast: Module, artifact: IncompleteArtifact) -> Self {
|
||||
Self { ast, artifact }
|
||||
}
|
||||
}
|
||||
|
||||
/// A Language Server, which can be used any object implementing `BuildRunnable` internally by passing it as a generic parameter.
|
||||
#[derive(Debug)]
|
||||
pub struct Server<Checker: BuildRunnable = HIRBuilder> {
|
||||
|
@ -200,7 +211,7 @@ pub struct Server<Checker: BuildRunnable = HIRBuilder> {
|
|||
pub(crate) file_cache: FileCache,
|
||||
pub(crate) comp_cache: CompletionCache,
|
||||
pub(crate) modules: Dict<NormalizedUrl, ModuleContext>,
|
||||
pub(crate) artifacts: Dict<NormalizedUrl, IncompleteArtifact>,
|
||||
pub(crate) artifacts: Dict<NormalizedUrl, AnalysisResult>,
|
||||
pub(crate) current_sig: Option<Expr>,
|
||||
pub(crate) _checker: std::marker::PhantomData<Checker>,
|
||||
}
|
||||
|
@ -541,24 +552,19 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_lowerer(&self, path: &Path) -> Option<ASTLowerer> {
|
||||
let module = Rc::get_mut(&mut self.get_shared().unwrap().mod_cache.get_mut(path)?.module)?;
|
||||
let module = std::mem::take(module);
|
||||
pub(crate) fn get_lowerer(&mut self, uri: &NormalizedUrl) -> Option<ASTLowerer> {
|
||||
let module = std::mem::take(self.modules.get_mut(uri)?);
|
||||
Some(ASTLowerer::new_with_ctx(module))
|
||||
}
|
||||
|
||||
pub(crate) fn restore_mod_ctx(&self, path: &Path, module: ModuleContext) {
|
||||
self.get_shared()
|
||||
.unwrap()
|
||||
.mod_cache
|
||||
.get_mut(path)
|
||||
.unwrap()
|
||||
.module = Rc::new(module);
|
||||
pub(crate) fn restore_mod_ctx(&mut self, uri: &NormalizedUrl, module: ModuleContext) {
|
||||
*self.modules.get_mut(uri).unwrap() = module;
|
||||
}
|
||||
|
||||
pub(crate) fn get_visitor(&self, uri: &NormalizedUrl) -> Option<HIRVisitor> {
|
||||
self.artifacts
|
||||
.get(uri)?
|
||||
.artifact
|
||||
.object
|
||||
.as_ref()
|
||||
.map(|hir| HIRVisitor::new(hir, &self.file_cache, uri.clone()))
|
||||
|
@ -611,7 +617,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
ctxs.extend(singular_ctxs);
|
||||
}
|
||||
} else {
|
||||
send_log("expr not found: {token}")?;
|
||||
_log!("expr not found: {token}");
|
||||
}
|
||||
}
|
||||
Ok(ctxs)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue