mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 19:58:18 +00:00
Merge pull request #6361 from faldor20/fix-lang-server-hang
Fix hang from bad imports
This commit is contained in:
commit
07ddd272e2
4 changed files with 127 additions and 8 deletions
|
@ -2174,6 +2174,38 @@ fn report_unused_imported_modules(
|
|||
}
|
||||
}
|
||||
|
||||
///Generates an errorfor modules that are imported from packages that don't exist
|
||||
///TODO. This is temporary. Remove this once module params is implemented
|
||||
fn check_for_missing_package_shorthand_in_cache<'a>(
|
||||
header: &ModuleHeader,
|
||||
shorthands: &Arc<Mutex<MutMap<&'a str, ShorthandPath>>>,
|
||||
) -> Result<(), LoadingProblem<'a>> {
|
||||
header.package_qualified_imported_modules
|
||||
.iter()
|
||||
.find_map(|pqim| match pqim {
|
||||
PackageQualified::Unqualified(_) => None,
|
||||
PackageQualified::Qualified(shorthand, _) => {
|
||||
if!(shorthands.lock().iter().any(|(short,_)|short==shorthand)){
|
||||
let module_path=header.module_path.to_str().unwrap_or("");
|
||||
Some(LoadingProblem::FormattedReport(
|
||||
match header.header_type {
|
||||
HeaderType::Hosted { ..} |
|
||||
HeaderType::Builtin {..} |
|
||||
HeaderType::Interface {..} =>
|
||||
{
|
||||
let mod_type= header.header_type.to_string();
|
||||
format!("The package shorthand '{shorthand}' that you are using in the 'imports' section of the header of module '{module_path}' doesn't exist.\nCheck that package shorthand is correct or reference the package in an 'app' or 'package' header.\nThis module is an {mod_type}, because of a bug in the compiler we are unable to directly typecheck {mod_type} modules with package imports so this error may not be correct. Please start checking at an app, package or platform file that imports this file.")
|
||||
},
|
||||
_=>
|
||||
format!("The package shorthand '{shorthand}' that you are using in the 'imports' section of the header of module '{module_path}' doesn't exist.\nCheck that package shorthand is correct or reference the package in an 'app' or 'package' header.")
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}).map_or(Ok(()),Err)
|
||||
}
|
||||
|
||||
fn extend_header_with_builtin(header: &mut ModuleHeader, module: ModuleId) {
|
||||
header
|
||||
.package_qualified_imported_modules
|
||||
|
@ -2257,7 +2289,9 @@ fn update<'a>(
|
|||
|
||||
#[cfg(target_family = "wasm")]
|
||||
{
|
||||
panic!("Specifying packages via URLs is curently unsupported in wasm.");
|
||||
panic!(
|
||||
"Specifying packages via URLs is currently unsupported in wasm."
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// This wasn't a URL, so it must be a filesystem path.
|
||||
|
@ -2387,6 +2421,7 @@ fn update<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
check_for_missing_package_shorthand_in_cache(&header, &state.arc_shorthands)?;
|
||||
// store an ID to name mapping, so we know the file to read when fetching dependencies' headers
|
||||
for (name, id) in header.deps_by_name.iter() {
|
||||
state.module_cache.module_names.insert(*id, name.clone());
|
||||
|
@ -3936,6 +3971,11 @@ fn parse_header<'a>(
|
|||
} else {
|
||||
&[]
|
||||
};
|
||||
let imports = if let Some(imports) = header.imports {
|
||||
unspace(arena, imports.item.items)
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
|
||||
let mut provides = bumpalo::collections::Vec::new_in(arena);
|
||||
|
||||
|
@ -3955,11 +3995,7 @@ fn parse_header<'a>(
|
|||
is_root_module,
|
||||
opt_shorthand,
|
||||
packages,
|
||||
imports: if let Some(imports) = header.imports {
|
||||
unspace(arena, imports.item.items)
|
||||
} else {
|
||||
&[]
|
||||
},
|
||||
imports,
|
||||
header_type: HeaderType::App {
|
||||
provides: provides.into_bump_slice(),
|
||||
output_name: header.name.value,
|
||||
|
@ -4143,7 +4179,7 @@ fn load_packages<'a>(
|
|||
|
||||
#[cfg(target_family = "wasm")]
|
||||
{
|
||||
panic!("Specifying packages via URLs is curently unsupported in wasm.");
|
||||
panic!("Specifying packages via URLs is currently unsupported in wasm.");
|
||||
}
|
||||
} else {
|
||||
cwd.join(src)
|
||||
|
|
22
crates/compiler/load_internal/src/file/reporting.rs
Normal file
22
crates/compiler/load_internal/src/file/reporting.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
fn report_missing_package_shorthand2<'a>(
|
||||
packages: &[Loc<PackageEntry>],
|
||||
imports: &[Loc<ImportsEntry>],
|
||||
) -> Option<LoadingProblem<'a>> {
|
||||
imports.iter().find_map(|i| match i.value {
|
||||
ImportsEntry::Module(_, _) | ImportsEntry::IngestedFile(_, _) => None,
|
||||
ImportsEntry::Package(shorthand, name, _) => {
|
||||
let name=name.as_str();
|
||||
if packages
|
||||
.iter()
|
||||
.find(|p| p.value.shorthand == shorthand)
|
||||
.is_none()
|
||||
{
|
||||
Some(
|
||||
LoadingProblem::FormattedReport(
|
||||
format!("The package shorthand '{shorthand}' that you are importing the module '{name}' from in '{shorthand}.{name}', doesn't exist in this module.\nImport it in the \"packages\" section of the header.")))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
|
@ -1058,7 +1058,6 @@ fn module_cyclic_import_itself() {
|
|||
err
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn module_cyclic_import_transitive() {
|
||||
let modules = vec![
|
||||
|
@ -1148,3 +1147,55 @@ fn nested_module_has_incorrect_name() {
|
|||
err
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn module_interface_with_qualified_import() {
|
||||
let modules = vec![(
|
||||
"A",
|
||||
indoc!(
|
||||
r"
|
||||
interface A exposes [] imports [b.T]
|
||||
"
|
||||
),
|
||||
)];
|
||||
|
||||
let err = multiple_modules("module_interface_with_qualified_import", modules).unwrap_err();
|
||||
assert_eq!(
|
||||
err,
|
||||
indoc!(
|
||||
r#"
|
||||
The package shorthand 'b' that you are using in the 'imports' section of the header of module 'tmp/module_interface_with_qualified_import/A' doesn't exist.
|
||||
Check that package shorthand is correct or reference the package in an 'app' or 'package' header.
|
||||
This module is an interface, because of a bug in the compiler we are unable to directly typecheck interface modules with package imports so this error may not be correct. Please start checking at an app, package or platform file that imports this file."#
|
||||
),
|
||||
"\n{}",
|
||||
err
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn app_missing_package_import() {
|
||||
let modules = vec![(
|
||||
"Main",
|
||||
indoc!(
|
||||
r#"
|
||||
app "example"
|
||||
packages { pack: "./package/main.roc" }
|
||||
imports [notpack.Mod]
|
||||
provides [] to pack
|
||||
|
||||
main = ""
|
||||
"#
|
||||
),
|
||||
)];
|
||||
|
||||
let err = multiple_modules("app_missing_package_import", modules).unwrap_err();
|
||||
assert_eq!(
|
||||
err,
|
||||
indoc!(
|
||||
r#"
|
||||
The package shorthand 'notpack' that you are using in the 'imports' section of the header of module 'tmp/app_missing_package_import/Main' doesn't exist.
|
||||
Check that package shorthand is correct or reference the package in an 'app' or 'package' header."#
|
||||
),
|
||||
"\n{}",
|
||||
err
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue