From aaca7d003bd969785be53d8f312b67bfa26f6272 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 27 Aug 2018 20:58:38 +0300 Subject: move scopes to file --- crates/libanalysis/src/lib.rs | 36 +++++++++++++++++++++++++++++++----- crates/libanalysis/src/module_map.rs | 5 +++++ crates/libanalysis/tests/tests.rs | 13 +++++++++++++ 3 files changed, 49 insertions(+), 5 deletions(-) (limited to 'crates/libanalysis') diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs index a3f721cc8..49c39e1f3 100644 --- a/crates/libanalysis/src/lib.rs +++ b/crates/libanalysis/src/lib.rs @@ -12,12 +12,9 @@ extern crate rayon; mod symbol_index; mod module_map; -use once_cell::sync::OnceCell; -use rayon::prelude::*; - use std::{ fmt, - path::{Path}, + path::{Path, PathBuf}, sync::{ Arc, atomic::{AtomicBool, Ordering::SeqCst}, @@ -26,13 +23,16 @@ use std::{ time::Instant, }; +use once_cell::sync::OnceCell; +use rayon::prelude::*; + use libsyntax2::{ File, TextUnit, TextRange, SmolStr, ast::{self, AstNode, NameOwner}, SyntaxKind::*, }; -use libeditor::{LineIndex, FileSymbol, find_node_at_offset}; +use libeditor::{Diagnostic, LineIndex, FileSymbol, find_node_at_offset}; use self::{ symbol_index::FileSymbols, @@ -130,6 +130,9 @@ impl WorldState { } } +pub enum QuickFix { + CreateFile(PathBuf), +} impl World { pub fn file_syntax(&self, file_id: FileId) -> Result { @@ -210,6 +213,29 @@ impl World { Ok(vec![]) } + pub fn diagnostics(&self, file_id: FileId) -> Result)>> { + let syntax = self.file_syntax(file_id)?; + let mut res = libeditor::diagnostics(&syntax) + .into_iter() + .map(|d| (d, None)) + .collect::>(); + for module in syntax.ast().modules() { + if module.has_semi() && self.resolve_module(file_id, module).is_empty() { + if let Some(name) = module.name() { + let d = Diagnostic { + range: name.syntax().range(), + msg: "unresolved module".to_string(), + }; + let quick_fix = self.data.module_map.suggested_child_mod_path(module) + .map(QuickFix::CreateFile); + + res.push((d, quick_fix)) + } + } + } + Ok(res) + } + fn index_resolve(&self, name_ref: ast::NameRef) -> Vec<(FileId, FileSymbol)> { let name = name_ref.text(); let mut query = Query::new(name.to_string()); diff --git a/crates/libanalysis/src/module_map.rs b/crates/libanalysis/src/module_map.rs index 6a9104d84..4f480591e 100644 --- a/crates/libanalysis/src/module_map.rs +++ b/crates/libanalysis/src/module_map.rs @@ -93,6 +93,11 @@ impl ModuleMap { res } + pub fn suggested_child_mod_path(&self, m: ast::Module) -> Option { + let name = m.name()?; + Some(PathBuf::from(format!("../{}.rs", name.text()))) + } + fn links( &self, file_resolver: &FileResolver, diff --git a/crates/libanalysis/tests/tests.rs b/crates/libanalysis/tests/tests.rs index 32abf9152..b3c357b02 100644 --- a/crates/libanalysis/tests/tests.rs +++ b/crates/libanalysis/tests/tests.rs @@ -44,6 +44,19 @@ fn test_resolve_module() { ); } +#[test] +fn test_unresolved_module_diagnostic() { + let mut world = WorldState::new(); + world.change_file(FileId(1), Some("mod foo;".to_string())); + + let snap = world.snapshot(|_id, _path| None); + let diagnostics = snap.diagnostics(FileId(1)).unwrap(); + assert_eq_dbg( + r#"[Diagnostic { range: [4; 7), msg: "unresolved module" }]"#, + &diagnostics, + ); +} + #[test] fn test_resolve_parent_module() { let mut world = WorldState::new(); -- cgit v1.2.3