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