mirror of
https://github.com/tweag/nickel.git
synced 2024-10-05 15:47:33 +03:00
Guess input format based on extension similarly like in multiple input case.
This commit is contained in:
parent
07cd7197e1
commit
aca39eff18
@ -58,6 +58,14 @@ impl InputFormat {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
/// Renturns an [InputFormat] based on the extension of a source path.
|
||||
pub fn from_source_path(source_path: &SourcePath) -> Option<InputFormat> {
|
||||
if let SourcePath::Path(p) = source_path {
|
||||
Self::from_path(p)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// File and terms cache.
|
||||
@ -456,50 +464,10 @@ impl Cache {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a source and populate the corresponding entry in the cache, or do nothing if the
|
||||
/// entry has already been parsed. This function is error tolerant: parts of the source which
|
||||
/// result in parse errors are parsed as [`crate::term::Term::ParseError`] and the
|
||||
/// corresponding error messages are collected and returned.
|
||||
///
|
||||
/// The `Err` part of the result corresponds to non-recoverable errors.
|
||||
fn parse_lax(&mut self, file_id: FileId) -> Result<CacheOp<ParseErrors>, ParseError> {
|
||||
if let Some(TermEntry { parse_errs, .. }) = self.terms.get(&file_id) {
|
||||
Ok(CacheOp::Cached(parse_errs.clone()))
|
||||
} else {
|
||||
let (term, parse_errs) = self.parse_nocache(file_id)?;
|
||||
self.terms.insert(
|
||||
file_id,
|
||||
TermEntry {
|
||||
term,
|
||||
state: EntryState::Parsed,
|
||||
parse_errs: parse_errs.clone(),
|
||||
},
|
||||
);
|
||||
|
||||
Ok(CacheOp::Done(parse_errs))
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a source and populate the corresponding entry in the cache, or do
|
||||
/// nothing if the entry has already been parsed. This function is error
|
||||
/// tolerant if `self.error_tolerant` is `true`.
|
||||
pub fn parse(&mut self, file_id: FileId) -> Result<CacheOp<ParseErrors>, ParseErrors> {
|
||||
let result = self.parse_lax(file_id);
|
||||
|
||||
match self.error_tolerance {
|
||||
ErrorTolerance::Tolerant => result.map_err(|err| err.into()),
|
||||
ErrorTolerance::Strict => match result? {
|
||||
CacheOp::Done(e) | CacheOp::Cached(e) if !e.no_errors() => Err(e),
|
||||
CacheOp::Done(_) => Ok(CacheOp::Done(ParseErrors::none())),
|
||||
CacheOp::Cached(_) => Ok(CacheOp::Cached(ParseErrors::none())),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a source and populate the corresponding entry in the cache, or do
|
||||
/// nothing if the entry has already been parsed. Support multiple formats.
|
||||
/// This function is always error tolerant, independently from `self.error_tolerant`.
|
||||
fn parse_multi_lax(
|
||||
fn parse_lax(
|
||||
&mut self,
|
||||
file_id: FileId,
|
||||
format: InputFormat,
|
||||
@ -523,12 +491,12 @@ impl Cache {
|
||||
/// Parse a source and populate the corresponding entry in the cache, or do
|
||||
/// nothing if the entry has already been parsed. Support multiple formats.
|
||||
/// This function is error tolerant if `self.error_tolerant` is `true`.
|
||||
pub fn parse_multi(
|
||||
pub fn parse(
|
||||
&mut self,
|
||||
file_id: FileId,
|
||||
format: InputFormat,
|
||||
) -> Result<CacheOp<ParseErrors>, ParseErrors> {
|
||||
let result = self.parse_multi_lax(file_id, format);
|
||||
let result = self.parse_lax(file_id, format);
|
||||
|
||||
match self.error_tolerance {
|
||||
ErrorTolerance::Tolerant => result.map_err(|err| err.into()),
|
||||
@ -902,7 +870,12 @@ impl Cache {
|
||||
) -> Result<CacheOp<()>, Error> {
|
||||
let mut result = CacheOp::Cached(());
|
||||
|
||||
if let CacheOp::Done(_) = self.parse(file_id)? {
|
||||
let format = self
|
||||
.file_paths
|
||||
.get(&file_id)
|
||||
.and_then(InputFormat::from_source_path)
|
||||
.unwrap_or_default();
|
||||
if let CacheOp::Done(_) = self.parse(file_id, format)? {
|
||||
result = CacheOp::Done(());
|
||||
}
|
||||
|
||||
@ -1134,7 +1107,7 @@ impl Cache {
|
||||
.collect();
|
||||
|
||||
for (_, file_id) in file_ids.iter() {
|
||||
self.parse(*file_id)?;
|
||||
self.parse(*file_id, InputFormat::Nickel)?;
|
||||
}
|
||||
self.stdlib_ids.replace(file_ids);
|
||||
Ok(CacheOp::Done(()))
|
||||
@ -1371,7 +1344,7 @@ impl ImportResolver for Cache {
|
||||
self.rev_imports.entry(file_id).or_default().insert(parent);
|
||||
}
|
||||
|
||||
self.parse_multi(file_id, format)
|
||||
self.parse(file_id, format)
|
||||
.map_err(|err| ImportError::ParseErrors(err, *pos))?;
|
||||
|
||||
Ok((result, file_id))
|
||||
|
@ -371,7 +371,7 @@ impl<EC: EvalCache> Program<EC> {
|
||||
pub fn parse(&mut self) -> Result<RichTerm, Error> {
|
||||
self.vm
|
||||
.import_resolver_mut()
|
||||
.parse(self.main_id)
|
||||
.parse(self.main_id, InputFormat::Nickel)
|
||||
.map_err(Error::ParseErrors)?;
|
||||
Ok(self
|
||||
.vm
|
||||
@ -496,7 +496,9 @@ impl<EC: EvalCache> Program<EC> {
|
||||
|
||||
/// Load, parse, and typecheck the program and the standard library, if not already done.
|
||||
pub fn typecheck(&mut self) -> Result<(), Error> {
|
||||
self.vm.import_resolver_mut().parse(self.main_id)?;
|
||||
self.vm
|
||||
.import_resolver_mut()
|
||||
.parse(self.main_id, InputFormat::Nickel)?;
|
||||
self.vm.import_resolver_mut().load_stdlib()?;
|
||||
let initial_env = self.vm.import_resolver().mk_type_ctxt().expect(
|
||||
"program::typecheck(): \
|
||||
|
@ -6,7 +6,7 @@
|
||||
//! Dually, the frontend is the user-facing part, which may be a CLI, a web application, a
|
||||
//! jupyter-kernel (which is not exactly user-facing, but still manages input/output and
|
||||
//! formatting), etc.
|
||||
use crate::cache::{Cache, Envs, ErrorTolerance, SourcePath};
|
||||
use crate::cache::{Cache, Envs, ErrorTolerance, InputFormat, SourcePath};
|
||||
use crate::error::{
|
||||
report::{self, ColorOpt, ErrorFormat},
|
||||
Error, EvalError, IOError, IntoDiagnostics, ParseError, ParseErrors, ReplError,
|
||||
@ -232,7 +232,9 @@ impl<EC: EvalCache> Repl for ReplImpl<EC> {
|
||||
.import_resolver_mut()
|
||||
.add_file(OsString::from(path.as_ref()))
|
||||
.map_err(IOError::from)?;
|
||||
self.vm.import_resolver_mut().parse(file_id)?;
|
||||
self.vm
|
||||
.import_resolver_mut()
|
||||
.parse(file_id, InputFormat::Nickel)?;
|
||||
|
||||
let term = self.vm.import_resolver().get_owned(file_id).unwrap();
|
||||
let pos = term.pos;
|
||||
|
@ -8,7 +8,7 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use nickel_lang_core::{
|
||||
cache::SourcePath,
|
||||
cache::{InputFormat, SourcePath},
|
||||
parser::lexer::{self, NormalToken, SpannedToken, Token},
|
||||
position::RawSpan,
|
||||
term::{RichTerm, Term},
|
||||
@ -102,7 +102,7 @@ fn resolve_imports(rt: RichTerm, world: &mut World) -> RichTerm {
|
||||
} = import_resolution::tolerant::resolve_imports(rt, &mut world.cache);
|
||||
|
||||
for id in resolved_ids {
|
||||
if world.cache.parse(id).is_ok() {
|
||||
if world.cache.parse(id, InputFormat::Nickel).is_ok() {
|
||||
// If a new input got imported in an incomplete term, try to typecheck
|
||||
// (and build lookup tables etc.) for it, but don't issue diagnostics.
|
||||
let _ = world.typecheck(id);
|
||||
|
@ -8,7 +8,7 @@ use codespan::FileId;
|
||||
use lsp_server::{ErrorCode, ResponseError};
|
||||
use lsp_types::Url;
|
||||
use nickel_lang_core::{
|
||||
cache::{Cache, CacheError, ErrorTolerance, SourcePath},
|
||||
cache::{Cache, CacheError, ErrorTolerance, InputFormat, SourcePath},
|
||||
error::{ImportError, IntoDiagnostics},
|
||||
position::{RawPos, RawSpan},
|
||||
term::{record::FieldMetadata, RichTerm, Term, UnaryOp},
|
||||
@ -160,7 +160,7 @@ impl World {
|
||||
file_id: FileId,
|
||||
) -> Result<Vec<SerializableDiagnostic>, Vec<SerializableDiagnostic>> {
|
||||
self.cache
|
||||
.parse(file_id)
|
||||
.parse(file_id, InputFormat::Nickel)
|
||||
.map(|nonfatal| self.lsp_diagnostics(file_id, nonfatal.inner()))
|
||||
.map_err(|fatal| self.lsp_diagnostics(file_id, fatal))
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ macro_rules! ncl_bench_group {
|
||||
(name = $group_name:ident; config = $config:expr; $($b:tt),+ $(,)*) => {
|
||||
pub fn $group_name() {
|
||||
use nickel_lang_core::{
|
||||
cache::{Envs, Cache, ErrorTolerance, ImportResolver},
|
||||
cache::{Envs, Cache, ErrorTolerance, ImportResolver, InputFormat},
|
||||
eval::{VirtualMachine, cache::{CacheImpl, Cache as EvalCache}},
|
||||
transform::import_resolution::strict::resolve_imports,
|
||||
error::report::{report, ColorOpt, ErrorFormat},
|
||||
@ -194,7 +194,7 @@ macro_rules! ncl_bench_group {
|
||||
.unwrap()
|
||||
.transformed_term;
|
||||
if bench.eval_mode == $crate::bench::EvalMode::TypeCheck {
|
||||
cache.parse(id).unwrap();
|
||||
cache.parse(id, InputFormat::Nickel).unwrap();
|
||||
cache.resolve_imports(id).unwrap();
|
||||
}
|
||||
(cache, id, t)
|
||||
|
Loading…
Reference in New Issue
Block a user