mirror of
https://github.com/nushell/nushell
synced 2024-12-28 05:53:09 +00:00
Add canonicalization to source & use paths (#421)
Also added file path print to FileNotFound error
This commit is contained in:
parent
405a4e58c7
commit
ee45755ea9
3 changed files with 102 additions and 81 deletions
|
@ -187,7 +187,7 @@ pub enum ParseError {
|
||||||
#[diagnostic(code(nu::parser::export_not_found), url(docsrs))]
|
#[diagnostic(code(nu::parser::export_not_found), url(docsrs))]
|
||||||
ExportNotFound(#[label = "could not find imports"] Span),
|
ExportNotFound(#[label = "could not find imports"] Span),
|
||||||
|
|
||||||
#[error("File not found")]
|
#[error("File not found: {0}")]
|
||||||
#[diagnostic(code(nu::parser::file_not_found), url(docsrs))]
|
#[diagnostic(code(nu::parser::file_not_found), url(docsrs))]
|
||||||
FileNotFound(String),
|
FileNotFound(String),
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use nu_path::canonicalize;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{
|
ast::{
|
||||||
Block, Call, Expr, Expression, ImportPattern, ImportPatternHead, ImportPatternMember,
|
Block, Call, Expr, Expression, ImportPattern, ImportPatternHead, ImportPatternMember,
|
||||||
|
@ -7,7 +8,6 @@ use nu_protocol::{
|
||||||
span, Exportable, Overlay, Span, SyntaxShape, Type, CONFIG_VARIABLE_ID,
|
span, Exportable, Overlay, Span, SyntaxShape, Type, CONFIG_VARIABLE_ID,
|
||||||
};
|
};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
lex, lite_parse,
|
lex, lite_parse,
|
||||||
|
@ -679,44 +679,48 @@ pub fn parse_use(
|
||||||
// TODO: Do not close over when loading module from file
|
// TODO: Do not close over when loading module from file
|
||||||
// It could be a file
|
// It could be a file
|
||||||
if let Ok(module_filename) = String::from_utf8(import_pattern.head.name) {
|
if let Ok(module_filename) = String::from_utf8(import_pattern.head.name) {
|
||||||
let module_path = Path::new(&module_filename);
|
if let Ok(module_path) = canonicalize(&module_filename) {
|
||||||
let module_name = if let Some(stem) = module_path.file_stem() {
|
let module_name = if let Some(stem) = module_path.file_stem() {
|
||||||
stem.to_string_lossy().to_string()
|
stem.to_string_lossy().to_string()
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_statement(spans),
|
||||||
Some(ParseError::ModuleNotFound(spans[1])),
|
Some(ParseError::ModuleNotFound(spans[1])),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(contents) = std::fs::read(module_path) {
|
if let Ok(contents) = std::fs::read(module_path) {
|
||||||
let span_start = working_set.next_span_start();
|
let span_start = working_set.next_span_start();
|
||||||
working_set.add_file(module_filename, &contents);
|
working_set.add_file(module_filename, &contents);
|
||||||
let span_end = working_set.next_span_start();
|
let span_end = working_set.next_span_start();
|
||||||
|
|
||||||
let (block, overlay, err) =
|
let (block, overlay, err) =
|
||||||
parse_module_block(working_set, Span::new(span_start, span_end));
|
parse_module_block(working_set, Span::new(span_start, span_end));
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let _ = working_set.add_block(block);
|
let _ = working_set.add_block(block);
|
||||||
let _ = working_set.add_overlay(&module_name, overlay.clone());
|
let _ = working_set.add_overlay(&module_name, overlay.clone());
|
||||||
|
|
||||||
(
|
(
|
||||||
ImportPattern {
|
ImportPattern {
|
||||||
head: ImportPatternHead {
|
head: ImportPatternHead {
|
||||||
name: module_name.into(),
|
name: module_name.into(),
|
||||||
span: spans[1],
|
span: spans[1],
|
||||||
|
},
|
||||||
|
members: import_pattern.members,
|
||||||
|
hidden: HashSet::new(),
|
||||||
},
|
},
|
||||||
members: import_pattern.members,
|
overlay,
|
||||||
hidden: HashSet::new(),
|
)
|
||||||
},
|
} else {
|
||||||
overlay,
|
return (
|
||||||
)
|
garbage_statement(spans),
|
||||||
|
Some(ParseError::ModuleNotFound(spans[1])),
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
error = error.or(Some(ParseError::FileNotFound(module_filename)));
|
||||||
garbage_statement(spans),
|
(ImportPattern::new(), Overlay::new())
|
||||||
Some(ParseError::ModuleNotFound(spans[1])),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
|
@ -990,6 +994,7 @@ pub fn parse_source(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Statement, Option<ParseError>) {
|
||||||
|
let mut error = None;
|
||||||
let name = working_set.get_span_contents(spans[0]);
|
let name = working_set.get_span_contents(spans[0]);
|
||||||
|
|
||||||
if name == b"source" {
|
if name == b"source" {
|
||||||
|
@ -998,63 +1003,63 @@ pub fn parse_source(
|
||||||
// Some of the others (`parse_let`) use it, some of them (`parse_hide`) don't.
|
// Some of the others (`parse_let`) use it, some of them (`parse_hide`) don't.
|
||||||
let (call, call_span, err) =
|
let (call, call_span, err) =
|
||||||
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
|
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
// Command and one file name
|
// Command and one file name
|
||||||
if spans.len() >= 2 {
|
if spans.len() >= 2 {
|
||||||
let name_expr = working_set.get_span_contents(spans[1]);
|
let name_expr = working_set.get_span_contents(spans[1]);
|
||||||
if let Ok(filename) = String::from_utf8(name_expr.to_vec()) {
|
if let Ok(filename) = String::from_utf8(name_expr.to_vec()) {
|
||||||
let source_file = Path::new(&filename);
|
if let Ok(path) = canonicalize(&filename) {
|
||||||
|
if let Ok(contents) = std::fs::read(&path) {
|
||||||
|
// This will load the defs from the file into the
|
||||||
|
// working set, if it was a successful parse.
|
||||||
|
let (block, err) = parse(
|
||||||
|
working_set,
|
||||||
|
path.file_name().and_then(|x| x.to_str()),
|
||||||
|
&contents,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
let path = source_file;
|
if err.is_some() {
|
||||||
let contents = std::fs::read(path);
|
// Unsuccessful parse of file
|
||||||
|
return (
|
||||||
|
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
||||||
|
expr: Expr::Call(call),
|
||||||
|
span: span(&spans[1..]),
|
||||||
|
ty: Type::Unknown,
|
||||||
|
custom_completion: None,
|
||||||
|
}])),
|
||||||
|
// Return the file parse error
|
||||||
|
err,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Save the block into the working set
|
||||||
|
let block_id = working_set.add_block(block);
|
||||||
|
|
||||||
if let Ok(contents) = contents {
|
let mut call_with_block = call;
|
||||||
// This will load the defs from the file into the
|
|
||||||
// working set, if it was a successful parse.
|
|
||||||
let (block, err) = parse(
|
|
||||||
working_set,
|
|
||||||
path.file_name().and_then(|x| x.to_str()),
|
|
||||||
&contents,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
if err.is_some() {
|
// Adding this expression to the positional creates a syntax highlighting error
|
||||||
// Unsuccessful parse of file
|
// after writing `source example.nu`
|
||||||
return (
|
call_with_block.positional.push(Expression {
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
expr: Expr::Int(block_id as i64),
|
||||||
expr: Expr::Call(call),
|
span: spans[1],
|
||||||
span: span(&spans[1..]),
|
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
});
|
||||||
// Return the file parse error
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Save the block into the working set
|
|
||||||
let block_id = working_set.add_block(block);
|
|
||||||
|
|
||||||
let mut call_with_block = call;
|
return (
|
||||||
|
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
||||||
// Adding this expression to the positional creates a syntax highlighting error
|
expr: Expr::Call(call_with_block),
|
||||||
// after writing `source example.nu`
|
span: call_span,
|
||||||
call_with_block.positional.push(Expression {
|
ty: Type::Unknown,
|
||||||
expr: Expr::Int(block_id as i64),
|
custom_completion: None,
|
||||||
span: spans[1],
|
}])),
|
||||||
ty: Type::Unknown,
|
None,
|
||||||
custom_completion: None,
|
);
|
||||||
});
|
}
|
||||||
|
|
||||||
return (
|
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
|
||||||
expr: Expr::Call(call_with_block),
|
|
||||||
span: call_span,
|
|
||||||
ty: Type::Unknown,
|
|
||||||
custom_completion: None,
|
|
||||||
}])),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
error = error.or(Some(ParseError::FileNotFound(filename)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
|
@ -1070,7 +1075,7 @@ pub fn parse_source(
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}])),
|
||||||
err,
|
error,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1090,7 +1095,6 @@ pub fn parse_register(
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Statement, Option<ParseError>) {
|
||||||
use std::{path::PathBuf, str::FromStr};
|
use std::{path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
use nu_path::canonicalize;
|
|
||||||
use nu_plugin::plugin::{get_signature, PluginDeclaration};
|
use nu_plugin::plugin::{get_signature, PluginDeclaration};
|
||||||
use nu_protocol::Signature;
|
use nu_protocol::Signature;
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,17 @@ pub struct ImportPattern {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportPattern {
|
impl ImportPattern {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
ImportPattern {
|
||||||
|
head: ImportPatternHead {
|
||||||
|
name: vec![],
|
||||||
|
span: Span::unknown(),
|
||||||
|
},
|
||||||
|
members: vec![],
|
||||||
|
hidden: HashSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn span(&self) -> Span {
|
pub fn span(&self) -> Span {
|
||||||
let mut spans = vec![self.head.span];
|
let mut spans = vec![self.head.span];
|
||||||
|
|
||||||
|
@ -50,3 +61,9 @@ impl ImportPattern {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for ImportPattern {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue