report errors in the header with correct source

This commit is contained in:
Folkert 2021-03-02 16:42:26 +01:00
parent b4dd5687e3
commit 27130c3172
2 changed files with 98 additions and 25 deletions

View file

@ -36,7 +36,14 @@ pub fn gen_from_mono_module(
let code_gen_start = SystemTime::now(); let code_gen_start = SystemTime::now();
for (home, (module_path, src)) in loaded.sources { for (home, (module_path, src)) in loaded.sources {
let src_lines: Vec<&str> = src.split('\n').collect(); let mut src_lines: Vec<&str> = Vec::new();
if let Some((_, header_src)) = loaded.header_sources.get(&home) {
src_lines.extend(header_src.split('\n'));
src_lines.extend(src.split('\n').skip(1));
} else {
src_lines.extend(src.split('\n'));
}
let palette = DEFAULT_PALETTE; let palette = DEFAULT_PALETTE;
// Report parsing and canonicalization problems // Report parsing and canonicalization problems

View file

@ -366,6 +366,7 @@ struct ModuleCache<'a> {
mono_problems: MutMap<ModuleId, Vec<roc_mono::ir::MonoProblem>>, mono_problems: MutMap<ModuleId, Vec<roc_mono::ir::MonoProblem>>,
sources: MutMap<ModuleId, (PathBuf, &'a str)>, sources: MutMap<ModuleId, (PathBuf, &'a str)>,
header_sources: MutMap<ModuleId, (PathBuf, &'a str)>,
} }
fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) -> Vec<BuildTask<'a>> { fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) -> Vec<BuildTask<'a>> {
@ -616,6 +617,7 @@ pub struct LoadedModule {
pub type_problems: MutMap<ModuleId, Vec<solve::TypeError>>, pub type_problems: MutMap<ModuleId, Vec<solve::TypeError>>,
pub declarations_by_id: MutMap<ModuleId, Vec<Declaration>>, pub declarations_by_id: MutMap<ModuleId, Vec<Declaration>>,
pub exposed_to_host: MutMap<Symbol, Variable>, pub exposed_to_host: MutMap<Symbol, Variable>,
pub header_sources: MutMap<ModuleId, (PathBuf, Box<str>)>,
pub sources: MutMap<ModuleId, (PathBuf, Box<str>)>, pub sources: MutMap<ModuleId, (PathBuf, Box<str>)>,
pub timings: MutMap<ModuleId, ModuleTiming>, pub timings: MutMap<ModuleId, ModuleTiming>,
pub documentation: MutMap<ModuleId, ModuleDocumentation>, pub documentation: MutMap<ModuleId, ModuleDocumentation>,
@ -639,6 +641,7 @@ struct ModuleHeader<'a> {
package_qualified_imported_modules: MutSet<PackageQualified<'a, ModuleId>>, package_qualified_imported_modules: MutSet<PackageQualified<'a, ModuleId>>,
exposes: Vec<Symbol>, exposes: Vec<Symbol>,
exposed_imports: MutMap<Ident, (Symbol, Region)>, exposed_imports: MutMap<Ident, (Symbol, Region)>,
header_src: &'a str,
src: &'a [u8], src: &'a [u8],
module_timing: ModuleTiming, module_timing: ModuleTiming,
} }
@ -698,6 +701,7 @@ pub struct MonomorphizedModule<'a> {
pub mono_problems: MutMap<ModuleId, Vec<roc_mono::ir::MonoProblem>>, pub mono_problems: MutMap<ModuleId, Vec<roc_mono::ir::MonoProblem>>,
pub procedures: MutMap<(Symbol, Layout<'a>), Proc<'a>>, pub procedures: MutMap<(Symbol, Layout<'a>), Proc<'a>>,
pub exposed_to_host: MutMap<Symbol, Variable>, pub exposed_to_host: MutMap<Symbol, Variable>,
pub header_sources: MutMap<ModuleId, (PathBuf, Box<str>)>,
pub sources: MutMap<ModuleId, (PathBuf, Box<str>)>, pub sources: MutMap<ModuleId, (PathBuf, Box<str>)>,
pub timings: MutMap<ModuleId, ModuleTiming>, pub timings: MutMap<ModuleId, ModuleTiming>,
} }
@ -1678,6 +1682,11 @@ fn update<'a>(
.exposed_symbols_by_module .exposed_symbols_by_module
.insert(home, exposed_symbols); .insert(home, exposed_symbols);
state
.module_cache
.header_sources
.insert(home, (header.module_path.clone(), header.header_src));
state state
.module_cache .module_cache
.imports .imports
@ -2115,6 +2124,7 @@ fn finish_specialization(
type_problems, type_problems,
can_problems, can_problems,
sources, sources,
header_sources,
.. ..
} = module_cache; } = module_cache;
@ -2123,6 +2133,11 @@ fn finish_specialization(
.map(|(id, (path, src))| (id, (path, src.into()))) .map(|(id, (path, src))| (id, (path, src.into())))
.collect(); .collect();
let header_sources: MutMap<ModuleId, (PathBuf, Box<str>)> = header_sources
.into_iter()
.map(|(id, (path, src))| (id, (path, src.into())))
.collect();
let path_to_platform = { let path_to_platform = {
use PlatformPath::*; use PlatformPath::*;
let package_or_path = match platform_path { let package_or_path = match platform_path {
@ -2224,6 +2239,7 @@ fn finish_specialization(
interns, interns,
procedures, procedures,
sources, sources,
header_sources,
timings: state.timings, timings: state.timings,
}) })
} }
@ -2251,6 +2267,13 @@ fn finish(
.map(|(id, (path, src))| (id, (path, src.into()))) .map(|(id, (path, src))| (id, (path, src.into())))
.collect(); .collect();
let header_sources = state
.module_cache
.header_sources
.into_iter()
.map(|(id, (path, src))| (id, (path, src.into())))
.collect();
LoadedModule { LoadedModule {
module_id: state.root_id, module_id: state.root_id,
interns, interns,
@ -2259,6 +2282,7 @@ fn finish(
type_problems: state.module_cache.type_problems, type_problems: state.module_cache.type_problems,
declarations_by_id: state.declarations_by_id, declarations_by_id: state.declarations_by_id,
exposed_to_host: exposed_vars_by_symbol.into_iter().collect(), exposed_to_host: exposed_vars_by_symbol.into_iter().collect(),
header_sources,
sources, sources,
timings: state.timings, timings: state.timings,
documentation, documentation,
@ -2468,41 +2492,63 @@ fn parse_header<'a>(
module_timing.parse_header = parse_header_duration; module_timing.parse_header = parse_header_duration;
match parsed { match parsed {
Ok((_, ast::Module::Interface { header }, parse_state)) => Ok(send_header( Ok((_, ast::Module::Interface { header }, parse_state)) => {
Located { let header_src = unsafe {
let chomped = src_bytes.len() - parse_state.bytes.len();
std::str::from_utf8_unchecked(&src_bytes[..chomped])
};
let info = HeaderInfo {
loc_name: Located {
region: header.name.region, region: header.name.region,
value: ModuleNameEnum::Interface(header.name.value), value: ModuleNameEnum::Interface(header.name.value),
}, },
filename, filename,
is_root_module, is_root_module,
opt_shorthand, opt_shorthand,
&[], header_src,
header.exposes.into_bump_slice(), packages: &[],
header.imports.into_bump_slice(), exposes: header.exposes.into_bump_slice(),
None, imports: header.imports.into_bump_slice(),
to_platform: None,
};
Ok(send_header(
info,
parse_state, parse_state,
module_ids, module_ids,
ident_ids_by_module, ident_ids_by_module,
module_timing, module_timing,
)), ))
}
Ok((_, ast::Module::App { header }, parse_state)) => { Ok((_, ast::Module::App { header }, parse_state)) => {
let mut pkg_config_dir = filename.clone(); let mut pkg_config_dir = filename.clone();
pkg_config_dir.pop(); pkg_config_dir.pop();
let header_src = unsafe {
let chomped = src_bytes.len() - parse_state.bytes.len();
std::str::from_utf8_unchecked(&src_bytes[..chomped])
};
let packages = header.packages.into_bump_slice(); let packages = header.packages.into_bump_slice();
let (module_id, app_module_header_msg) = send_header( let info = HeaderInfo {
Located { loc_name: Located {
region: header.name.region, region: header.name.region,
value: ModuleNameEnum::App(header.name.value), value: ModuleNameEnum::App(header.name.value),
}, },
filename, filename,
is_root_module, is_root_module,
opt_shorthand, opt_shorthand,
header_src,
packages, packages,
header.provides.into_bump_slice(), exposes: header.provides.into_bump_slice(),
header.imports.into_bump_slice(), imports: header.imports.into_bump_slice(),
Some(header.to.value.clone()), to_platform: Some(header.to.value.clone()),
};
let (module_id, app_module_header_msg) = send_header(
info,
parse_state, parse_state,
module_ids.clone(), module_ids.clone(),
ident_ids_by_module.clone(), ident_ids_by_module.clone(),
@ -2673,16 +2719,22 @@ enum ModuleNameEnum<'a> {
PkgConfig, PkgConfig,
} }
#[allow(clippy::too_many_arguments)] #[derive(Debug)]
fn send_header<'a>( struct HeaderInfo<'a> {
loc_name: Located<ModuleNameEnum<'a>>, loc_name: Located<ModuleNameEnum<'a>>,
filename: PathBuf, filename: PathBuf,
is_root_module: bool, is_root_module: bool,
opt_shorthand: Option<&'a str>, opt_shorthand: Option<&'a str>,
header_src: &'a str,
packages: &'a [Located<PackageEntry<'a>>], packages: &'a [Located<PackageEntry<'a>>],
exposes: &'a [Located<ExposesEntry<'a, &'a str>>], exposes: &'a [Located<ExposesEntry<'a, &'a str>>],
imports: &'a [Located<ImportsEntry<'a>>], imports: &'a [Located<ImportsEntry<'a>>],
to_platform: Option<To<'a>>, to_platform: Option<To<'a>>,
}
#[allow(clippy::too_many_arguments)]
fn send_header<'a>(
info: HeaderInfo<'a>,
parse_state: parser::State<'a>, parse_state: parser::State<'a>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>, module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>, ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
@ -2690,6 +2742,18 @@ fn send_header<'a>(
) -> (ModuleId, Msg<'a>) { ) -> (ModuleId, Msg<'a>) {
use ModuleNameEnum::*; use ModuleNameEnum::*;
let HeaderInfo {
loc_name,
filename,
is_root_module,
opt_shorthand,
packages,
exposes,
imports,
to_platform,
header_src,
} = info;
let declared_name: ModuleName = match &loc_name.value { let declared_name: ModuleName = match &loc_name.value {
PkgConfig => unreachable!(), PkgConfig => unreachable!(),
App(_) => ModuleName::APP.into(), App(_) => ModuleName::APP.into(),
@ -2872,6 +2936,7 @@ fn send_header<'a>(
package_qualified_imported_modules, package_qualified_imported_modules,
deps_by_name, deps_by_name,
exposes: exposed, exposes: exposed,
header_src,
src: parse_state.bytes, src: parse_state.bytes,
exposed_imports: scope, exposed_imports: scope,
module_timing, module_timing,
@ -3091,6 +3156,7 @@ fn send_header_two<'a>(
package_qualified_imported_modules, package_qualified_imported_modules,
deps_by_name, deps_by_name,
exposes: exposed, exposes: exposed,
header_src: "#builtin effect header",
src: parse_state.bytes, src: parse_state.bytes,
exposed_imports: scope, exposed_imports: scope,
module_timing, module_timing,