mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-14 22:14:53 +00:00
Use bitflags for ParseTreeFlags + ParserTestErrorBits
For consistency with simlar code.
This commit is contained in:
parent
cb368f70ee
commit
1dafb77cda
4 changed files with 56 additions and 91 deletions
|
@ -14,9 +14,7 @@ use crate::flog::FLOG;
|
||||||
use crate::parse_constants::{
|
use crate::parse_constants::{
|
||||||
token_type_user_presentable_description, ParseError, ParseErrorCode, ParseErrorList,
|
token_type_user_presentable_description, ParseError, ParseErrorCode, ParseErrorList,
|
||||||
ParseErrorListFfi, ParseKeyword, ParseTokenType, ParseTreeFlags, SourceRange,
|
ParseErrorListFfi, ParseKeyword, ParseTokenType, ParseTreeFlags, SourceRange,
|
||||||
StatementDecoration, INVALID_PIPELINE_CMD_ERR_MSG, PARSE_FLAG_ACCEPT_INCOMPLETE_TOKENS,
|
StatementDecoration, INVALID_PIPELINE_CMD_ERR_MSG, SOURCE_OFFSET_INVALID,
|
||||||
PARSE_FLAG_CONTINUE_AFTER_ERROR, PARSE_FLAG_INCLUDE_COMMENTS, PARSE_FLAG_LEAVE_UNTERMINATED,
|
|
||||||
PARSE_FLAG_SHOW_EXTRA_SEMIS, SOURCE_OFFSET_INVALID,
|
|
||||||
};
|
};
|
||||||
use crate::parse_tree::ParseToken;
|
use crate::parse_tree::ParseToken;
|
||||||
use crate::tokenizer::{
|
use crate::tokenizer::{
|
||||||
|
@ -2937,7 +2935,7 @@ impl<'s> Populator<'s> {
|
||||||
fn status(&mut self) -> ParserStatus {
|
fn status(&mut self) -> ParserStatus {
|
||||||
if self.unwinding {
|
if self.unwinding {
|
||||||
ParserStatus::unwinding
|
ParserStatus::unwinding
|
||||||
} else if self.flags & PARSE_FLAG_LEAVE_UNTERMINATED
|
} else if self.flags.contains(ParseTreeFlags::LEAVE_UNTERMINATED)
|
||||||
&& self.peek_type(0) == ParseTokenType::terminate
|
&& self.peek_type(0) == ParseTokenType::terminate
|
||||||
{
|
{
|
||||||
ParserStatus::unsourcing
|
ParserStatus::unsourcing
|
||||||
|
@ -2956,7 +2954,7 @@ impl<'s> Populator<'s> {
|
||||||
|
|
||||||
/// \return whether we permit an incomplete parse tree.
|
/// \return whether we permit an incomplete parse tree.
|
||||||
fn allow_incomplete(&self) -> bool {
|
fn allow_incomplete(&self) -> bool {
|
||||||
self.flags & PARSE_FLAG_LEAVE_UNTERMINATED
|
self.flags.contains(ParseTreeFlags::LEAVE_UNTERMINATED)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \return whether a list type \p type allows arbitrary newlines in it.
|
/// \return whether a list type \p type allows arbitrary newlines in it.
|
||||||
|
@ -3074,7 +3072,7 @@ impl<'s> Populator<'s> {
|
||||||
} else if chomp_semis && peek.typ == ParseTokenType::end && !peek.is_newline {
|
} else if chomp_semis && peek.typ == ParseTokenType::end && !peek.is_newline {
|
||||||
let tok = self.tokens.pop();
|
let tok = self.tokens.pop();
|
||||||
// Perhaps save this extra semi.
|
// Perhaps save this extra semi.
|
||||||
if self.flags & PARSE_FLAG_SHOW_EXTRA_SEMIS {
|
if self.flags.contains(ParseTreeFlags::SHOW_EXTRA_SEMIS) {
|
||||||
self.semis.push(tok.range());
|
self.semis.push(tok.range());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3086,7 +3084,7 @@ impl<'s> Populator<'s> {
|
||||||
/// \return whether a list type should recover from errors.s
|
/// \return whether a list type should recover from errors.s
|
||||||
/// That is, whether we should stop unwinding when we encounter this type.
|
/// That is, whether we should stop unwinding when we encounter this type.
|
||||||
fn list_type_stops_unwind(&self, typ: Type) -> bool {
|
fn list_type_stops_unwind(&self, typ: Type) -> bool {
|
||||||
typ == Type::job_list && self.flags & PARSE_FLAG_CONTINUE_AFTER_ERROR
|
typ == Type::job_list && self.flags.contains(ParseTreeFlags::CONTINUE_AFTER_ERROR)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \return a reference to a non-comment token at index \p idx.
|
/// \return a reference to a non-comment token at index \p idx.
|
||||||
|
@ -3678,7 +3676,7 @@ impl<'s> Populator<'s> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !token.allows_token(self.peek_token(0).typ) {
|
if !token.allows_token(self.peek_token(0).typ) {
|
||||||
if self.flags & PARSE_FLAG_LEAVE_UNTERMINATED
|
if self.flags.contains(ParseTreeFlags::LEAVE_UNTERMINATED)
|
||||||
&& [
|
&& [
|
||||||
TokenizerError::unterminated_quote,
|
TokenizerError::unterminated_quote,
|
||||||
TokenizerError::unterminated_subshell,
|
TokenizerError::unterminated_subshell,
|
||||||
|
@ -3714,7 +3712,7 @@ impl<'s> Populator<'s> {
|
||||||
if !keyword.allows_keyword(self.peek_token(0).keyword) {
|
if !keyword.allows_keyword(self.peek_token(0).keyword) {
|
||||||
*keyword.range_mut() = None;
|
*keyword.range_mut() = None;
|
||||||
|
|
||||||
if self.flags & PARSE_FLAG_LEAVE_UNTERMINATED
|
if self.flags.contains(ParseTreeFlags::LEAVE_UNTERMINATED)
|
||||||
&& [
|
&& [
|
||||||
TokenizerError::unterminated_quote,
|
TokenizerError::unterminated_quote,
|
||||||
TokenizerError::unterminated_subshell,
|
TokenizerError::unterminated_subshell,
|
||||||
|
@ -3842,13 +3840,13 @@ impl From<ParseTreeFlags> for TokFlags {
|
||||||
let mut tok_flags = TokFlags(0);
|
let mut tok_flags = TokFlags(0);
|
||||||
// Note we do not need to respect parse_flag_show_blank_lines, no clients are interested
|
// Note we do not need to respect parse_flag_show_blank_lines, no clients are interested
|
||||||
// in them.
|
// in them.
|
||||||
if flags & PARSE_FLAG_INCLUDE_COMMENTS {
|
if flags.contains(ParseTreeFlags::INCLUDE_COMMENTS) {
|
||||||
tok_flags |= TOK_SHOW_COMMENTS;
|
tok_flags |= TOK_SHOW_COMMENTS;
|
||||||
}
|
}
|
||||||
if flags & PARSE_FLAG_ACCEPT_INCOMPLETE_TOKENS {
|
if flags.contains(ParseTreeFlags::ACCEPT_INCOMPLETE_TOKENS) {
|
||||||
tok_flags |= TOK_ACCEPT_UNFINISHED;
|
tok_flags |= TOK_ACCEPT_UNFINISHED;
|
||||||
}
|
}
|
||||||
if flags & PARSE_FLAG_CONTINUE_AFTER_ERROR {
|
if flags.contains(ParseTreeFlags::CONTINUE_AFTER_ERROR) {
|
||||||
tok_flags |= TOK_CONTINUE_AFTER_ERROR
|
tok_flags |= TOK_CONTINUE_AFTER_ERROR
|
||||||
}
|
}
|
||||||
tok_flags
|
tok_flags
|
||||||
|
@ -3921,9 +3919,8 @@ fn keyword_for_token(tok: TokenType, token: &wstr) -> ParseKeyword {
|
||||||
|
|
||||||
use crate::ffi_tests::add_test;
|
use crate::ffi_tests::add_test;
|
||||||
add_test!("test_ast_parse", || {
|
add_test!("test_ast_parse", || {
|
||||||
use crate::parse_constants::PARSE_FLAG_NONE;
|
|
||||||
let src = L!("echo");
|
let src = L!("echo");
|
||||||
let ast = Ast::parse(src, PARSE_FLAG_NONE, None);
|
let ast = Ast::parse(src, ParseTreeFlags::empty(), None);
|
||||||
assert!(!ast.any_error);
|
assert!(!ast.any_error);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4422,7 +4419,7 @@ impl Ast {
|
||||||
fn ast_parse_ffi(src: &CxxWString, flags: u8, errors: *mut ParseErrorListFfi) -> Box<Ast> {
|
fn ast_parse_ffi(src: &CxxWString, flags: u8, errors: *mut ParseErrorListFfi) -> Box<Ast> {
|
||||||
Box::new(Ast::parse(
|
Box::new(Ast::parse(
|
||||||
src.as_wstr(),
|
src.as_wstr(),
|
||||||
ParseTreeFlags(flags),
|
ParseTreeFlags::from_bits(flags).unwrap(),
|
||||||
if errors.is_null() {
|
if errors.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -4438,7 +4435,7 @@ fn ast_parse_argument_list_ffi(
|
||||||
) -> Box<Ast> {
|
) -> Box<Ast> {
|
||||||
Box::new(Ast::parse_argument_list(
|
Box::new(Ast::parse_argument_list(
|
||||||
src.as_wstr(),
|
src.as_wstr(),
|
||||||
ParseTreeFlags(flags),
|
ParseTreeFlags::from_bits(flags).unwrap(),
|
||||||
if errors.is_null() {
|
if errors.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,9 +5,9 @@ use crate::tokenizer::variable_assignment_equals_pos;
|
||||||
use crate::wchar::{wstr, WString, L};
|
use crate::wchar::{wstr, WString, L};
|
||||||
use crate::wchar_ffi::{wcharz, AsWstr, WCharFromFFI, WCharToFFI};
|
use crate::wchar_ffi::{wcharz, AsWstr, WCharFromFFI, WCharToFFI};
|
||||||
use crate::wutil::{sprintf, wgettext_fmt};
|
use crate::wutil::{sprintf, wgettext_fmt};
|
||||||
|
use bitflags::bitflags;
|
||||||
use cxx::{type_id, ExternType};
|
use cxx::{type_id, ExternType};
|
||||||
use cxx::{CxxWString, UniquePtr};
|
use cxx::{CxxWString, UniquePtr};
|
||||||
use std::ops::{BitAnd, BitOr, BitOrAssign};
|
|
||||||
use widestring_suffix::widestrs;
|
use widestring_suffix::widestrs;
|
||||||
|
|
||||||
pub type SourceOffset = u32;
|
pub type SourceOffset = u32;
|
||||||
|
@ -15,58 +15,30 @@ pub type SourceOffset = u32;
|
||||||
pub const SOURCE_OFFSET_INVALID: usize = SourceOffset::MAX as _;
|
pub const SOURCE_OFFSET_INVALID: usize = SourceOffset::MAX as _;
|
||||||
pub const SOURCE_LOCATION_UNKNOWN: usize = usize::MAX;
|
pub const SOURCE_LOCATION_UNKNOWN: usize = usize::MAX;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
bitflags! {
|
||||||
pub struct ParseTreeFlags(pub u8);
|
pub struct ParseTreeFlags: u8 {
|
||||||
|
/// attempt to build a "parse tree" no matter what. this may result in a 'forest' of
|
||||||
pub const PARSE_FLAG_NONE: ParseTreeFlags = ParseTreeFlags(0);
|
/// disconnected trees. this is intended to be used by syntax highlighting.
|
||||||
/// attempt to build a "parse tree" no matter what. this may result in a 'forest' of
|
const CONTINUE_AFTER_ERROR = 1 << 0;
|
||||||
/// disconnected trees. this is intended to be used by syntax highlighting.
|
/// include comment tokens.
|
||||||
pub const PARSE_FLAG_CONTINUE_AFTER_ERROR: ParseTreeFlags = ParseTreeFlags(1 << 0);
|
const INCLUDE_COMMENTS = 1 << 1;
|
||||||
/// include comment tokens.
|
/// indicate that the tokenizer should accept incomplete tokens */
|
||||||
pub const PARSE_FLAG_INCLUDE_COMMENTS: ParseTreeFlags = ParseTreeFlags(1 << 1);
|
const ACCEPT_INCOMPLETE_TOKENS = 1 << 2;
|
||||||
/// indicate that the tokenizer should accept incomplete tokens */
|
/// indicate that the parser should not generate the terminate token, allowing an 'unfinished'
|
||||||
pub const PARSE_FLAG_ACCEPT_INCOMPLETE_TOKENS: ParseTreeFlags = ParseTreeFlags(1 << 2);
|
/// tree where some nodes may have no productions.
|
||||||
/// indicate that the parser should not generate the terminate token, allowing an 'unfinished'
|
const LEAVE_UNTERMINATED = 1 << 3;
|
||||||
/// tree where some nodes may have no productions.
|
/// indicate that the parser should generate job_list entries for blank lines.
|
||||||
pub const PARSE_FLAG_LEAVE_UNTERMINATED: ParseTreeFlags = ParseTreeFlags(1 << 3);
|
const SHOW_BLANK_LINES = 1 << 4;
|
||||||
/// indicate that the parser should generate job_list entries for blank lines.
|
/// indicate that extra semis should be generated.
|
||||||
pub const PARSE_FLAG_SHOW_BLANK_LINES: ParseTreeFlags = ParseTreeFlags(1 << 4);
|
const SHOW_EXTRA_SEMIS = 1 << 5;
|
||||||
/// indicate that extra semis should be generated.
|
|
||||||
pub const PARSE_FLAG_SHOW_EXTRA_SEMIS: ParseTreeFlags = ParseTreeFlags(1 << 5);
|
|
||||||
|
|
||||||
impl BitAnd for ParseTreeFlags {
|
|
||||||
type Output = bool;
|
|
||||||
fn bitand(self, rhs: Self) -> Self::Output {
|
|
||||||
(self.0 & rhs.0) != 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl BitOr for ParseTreeFlags {
|
|
||||||
type Output = ParseTreeFlags;
|
|
||||||
fn bitor(self, rhs: Self) -> Self::Output {
|
|
||||||
Self(self.0 | rhs.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl BitOrAssign for ParseTreeFlags {
|
|
||||||
fn bitor_assign(&mut self, rhs: Self) {
|
|
||||||
self.0 |= rhs.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Copy, Clone, Default)]
|
bitflags! {
|
||||||
pub struct ParserTestErrorBits(u8);
|
#[derive(Default)]
|
||||||
|
pub struct ParserTestErrorBits: u8 {
|
||||||
pub const PARSER_TEST_ERROR: ParserTestErrorBits = ParserTestErrorBits(1);
|
const ERROR = 1;
|
||||||
pub const PARSER_TEST_INCOMPLETE: ParserTestErrorBits = ParserTestErrorBits(2);
|
const INCOMPLETE = 2;
|
||||||
|
|
||||||
impl BitAnd for ParserTestErrorBits {
|
|
||||||
type Output = bool;
|
|
||||||
fn bitand(self, rhs: Self) -> Self::Output {
|
|
||||||
(self.0 & rhs.0) != 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl BitOrAssign for ParserTestErrorBits {
|
|
||||||
fn bitor_assign(&mut self, rhs: Self) {
|
|
||||||
self.0 |= rhs.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@ use std::rc::Rc;
|
||||||
use crate::ast::Ast;
|
use crate::ast::Ast;
|
||||||
use crate::parse_constants::{
|
use crate::parse_constants::{
|
||||||
token_type_user_presentable_description, ParseErrorCode, ParseErrorList, ParseErrorListFfi,
|
token_type_user_presentable_description, ParseErrorCode, ParseErrorList, ParseErrorListFfi,
|
||||||
ParseKeyword, ParseTokenType, ParseTreeFlags, SourceOffset, SourceRange,
|
ParseKeyword, ParseTokenType, ParseTreeFlags, SourceOffset, SourceRange, SOURCE_OFFSET_INVALID,
|
||||||
PARSE_FLAG_CONTINUE_AFTER_ERROR, SOURCE_OFFSET_INVALID,
|
|
||||||
};
|
};
|
||||||
use crate::tokenizer::TokenizerError;
|
use crate::tokenizer::TokenizerError;
|
||||||
use crate::wchar::{wstr, WString, L};
|
use crate::wchar::{wstr, WString, L};
|
||||||
|
@ -123,7 +122,7 @@ pub fn parse_source(
|
||||||
errors: Option<&mut ParseErrorList>,
|
errors: Option<&mut ParseErrorList>,
|
||||||
) -> ParsedSourceRef {
|
) -> ParsedSourceRef {
|
||||||
let ast = Ast::parse(&src, flags, errors);
|
let ast = Ast::parse(&src, flags, errors);
|
||||||
if ast.errored() && !(flags & PARSE_FLAG_CONTINUE_AFTER_ERROR) {
|
if ast.errored() && !flags.contains(ParseTreeFlags::CONTINUE_AFTER_ERROR) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(Rc::new(ParsedSource::new(src, ast)))
|
Some(Rc::new(ParsedSource::new(src, ast)))
|
||||||
|
@ -179,7 +178,7 @@ fn parse_source_ffi(
|
||||||
) -> Box<ParsedSourceRefFFI> {
|
) -> Box<ParsedSourceRefFFI> {
|
||||||
Box::new(ParsedSourceRefFFI(parse_source(
|
Box::new(ParsedSourceRefFFI(parse_source(
|
||||||
src.from_ffi(),
|
src.from_ffi(),
|
||||||
ParseTreeFlags(flags),
|
ParseTreeFlags::from_bits(flags).unwrap(),
|
||||||
if errors.is_null() {
|
if errors.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,14 +14,11 @@ use crate::future_feature_flags::{feature_test, FeatureFlag};
|
||||||
use crate::operation_context::OperationContext;
|
use crate::operation_context::OperationContext;
|
||||||
use crate::parse_constants::{
|
use crate::parse_constants::{
|
||||||
parse_error_offset_source_start, ParseError, ParseErrorCode, ParseErrorList, ParseKeyword,
|
parse_error_offset_source_start, ParseError, ParseErrorCode, ParseErrorList, ParseKeyword,
|
||||||
ParseTokenType, ParserTestErrorBits, PipelinePosition, StatementDecoration,
|
ParseTokenType, ParseTreeFlags, ParserTestErrorBits, PipelinePosition, StatementDecoration,
|
||||||
ERROR_BAD_VAR_CHAR1, ERROR_BRACKETED_VARIABLE1, ERROR_BRACKETED_VARIABLE_QUOTED1,
|
ERROR_BAD_VAR_CHAR1, ERROR_BRACKETED_VARIABLE1, ERROR_BRACKETED_VARIABLE_QUOTED1,
|
||||||
ERROR_NOT_ARGV_AT, ERROR_NOT_ARGV_COUNT, ERROR_NOT_ARGV_STAR, ERROR_NOT_PID, ERROR_NOT_STATUS,
|
ERROR_NOT_ARGV_AT, ERROR_NOT_ARGV_COUNT, ERROR_NOT_ARGV_STAR, ERROR_NOT_PID, ERROR_NOT_STATUS,
|
||||||
ERROR_NO_VAR_NAME, INVALID_BREAK_ERR_MSG, INVALID_CONTINUE_ERR_MSG,
|
ERROR_NO_VAR_NAME, INVALID_BREAK_ERR_MSG, INVALID_CONTINUE_ERR_MSG,
|
||||||
INVALID_PIPELINE_CMD_ERR_MSG, PARSER_TEST_ERROR, PARSER_TEST_INCOMPLETE,
|
INVALID_PIPELINE_CMD_ERR_MSG, UNKNOWN_BUILTIN_ERR_MSG,
|
||||||
PARSE_FLAG_ACCEPT_INCOMPLETE_TOKENS, PARSE_FLAG_CONTINUE_AFTER_ERROR,
|
|
||||||
PARSE_FLAG_INCLUDE_COMMENTS, PARSE_FLAG_LEAVE_UNTERMINATED, PARSE_FLAG_NONE,
|
|
||||||
UNKNOWN_BUILTIN_ERR_MSG,
|
|
||||||
};
|
};
|
||||||
use crate::tokenizer::{
|
use crate::tokenizer::{
|
||||||
comment_end, is_token_delimiter, quote_end, Tok, TokenType, Tokenizer, TOK_ACCEPT_UNFINISHED,
|
comment_end, is_token_delimiter, quote_end, Tok, TokenType, Tokenizer, TOK_ACCEPT_UNFINISHED,
|
||||||
|
@ -742,10 +739,10 @@ pub fn parse_util_compute_indents(src: &wstr) -> Vec<i32> {
|
||||||
// were a case item list.
|
// were a case item list.
|
||||||
let ast = Ast::parse(
|
let ast = Ast::parse(
|
||||||
src,
|
src,
|
||||||
PARSE_FLAG_CONTINUE_AFTER_ERROR
|
ParseTreeFlags::CONTINUE_AFTER_ERROR
|
||||||
| PARSE_FLAG_INCLUDE_COMMENTS
|
| ParseTreeFlags::INCLUDE_COMMENTS
|
||||||
| PARSE_FLAG_ACCEPT_INCOMPLETE_TOKENS
|
| ParseTreeFlags::ACCEPT_INCOMPLETE_TOKENS
|
||||||
| PARSE_FLAG_LEAVE_UNTERMINATED,
|
| ParseTreeFlags::LEAVE_UNTERMINATED,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
{
|
{
|
||||||
|
@ -965,7 +962,7 @@ impl<'a> NodeVisitor<'a> for IndentVisitor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a string, detect parse errors in it. If allow_incomplete is set, then if the string is
|
/// Given a string, detect parse errors in it. If allow_incomplete is set, then if the string is
|
||||||
/// incomplete (e.g. an unclosed quote), an error is not returned and the PARSER_TEST_INCOMPLETE bit
|
/// incomplete (e.g. an unclosed quote), an error is not returned and the ParserTestErrorBits::INCOMPLETE bit
|
||||||
/// is set in the return value. If allow_incomplete is not set, then incomplete strings result in an
|
/// is set in the return value. If allow_incomplete is not set, then incomplete strings result in an
|
||||||
/// error.
|
/// error.
|
||||||
pub fn parse_util_detect_errors(
|
pub fn parse_util_detect_errors(
|
||||||
|
@ -978,9 +975,9 @@ pub fn parse_util_detect_errors(
|
||||||
let mut has_unclosed_quote_or_subshell = false;
|
let mut has_unclosed_quote_or_subshell = false;
|
||||||
|
|
||||||
let parse_flags = if allow_incomplete {
|
let parse_flags = if allow_incomplete {
|
||||||
PARSE_FLAG_LEAVE_UNTERMINATED
|
ParseTreeFlags::LEAVE_UNTERMINATED
|
||||||
} else {
|
} else {
|
||||||
PARSE_FLAG_NONE
|
ParseTreeFlags::empty()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse the input string into an ast. Some errors are detected here.
|
// Parse the input string into an ast. Some errors are detected here.
|
||||||
|
@ -1009,14 +1006,14 @@ pub fn parse_util_detect_errors(
|
||||||
assert!(!has_unclosed_quote_or_subshell || allow_incomplete);
|
assert!(!has_unclosed_quote_or_subshell || allow_incomplete);
|
||||||
if has_unclosed_quote_or_subshell {
|
if has_unclosed_quote_or_subshell {
|
||||||
// We do not bother to validate the rest of the tree in this case.
|
// We do not bother to validate the rest of the tree in this case.
|
||||||
return Err(PARSER_TEST_INCOMPLETE);
|
return Err(ParserTestErrorBits::INCOMPLETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Early parse error, stop here.
|
// Early parse error, stop here.
|
||||||
if !parse_errors.is_empty() {
|
if !parse_errors.is_empty() {
|
||||||
if let Some(errors) = out_errors.as_mut() {
|
if let Some(errors) = out_errors.as_mut() {
|
||||||
errors.extend(parse_errors.into_iter());
|
errors.extend(parse_errors.into_iter());
|
||||||
return Err(PARSER_TEST_ERROR);
|
return Err(ParserTestErrorBits::ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1107,11 +1104,11 @@ pub fn parse_util_detect_errors_in_ast(
|
||||||
}
|
}
|
||||||
|
|
||||||
if errored {
|
if errored {
|
||||||
res |= PARSER_TEST_ERROR;
|
res |= ParserTestErrorBits::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if has_unclosed_block || has_unclosed_pipe || has_unclosed_conjunction {
|
if has_unclosed_block || has_unclosed_pipe || has_unclosed_conjunction {
|
||||||
res |= PARSER_TEST_INCOMPLETE;
|
res |= ParserTestErrorBits::INCOMPLETE;
|
||||||
}
|
}
|
||||||
if res == ParserTestErrorBits::default() {
|
if res == ParserTestErrorBits::default() {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1139,7 +1136,7 @@ pub fn parse_util_detect_errors_in_argument_list(
|
||||||
|
|
||||||
// Parse the string as a freestanding argument list.
|
// Parse the string as a freestanding argument list.
|
||||||
let mut errors = ParseErrorList::new();
|
let mut errors = ParseErrorList::new();
|
||||||
let ast = Ast::parse_argument_list(arg_list_src, PARSE_FLAG_NONE, Some(&mut errors));
|
let ast = Ast::parse_argument_list(arg_list_src, ParseTreeFlags::empty(), Some(&mut errors));
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
return get_error_text(&errors);
|
return get_error_text(&errors);
|
||||||
}
|
}
|
||||||
|
@ -1219,13 +1216,13 @@ pub fn parse_util_detect_errors_in_argument(
|
||||||
append_syntax_error!(
|
append_syntax_error!(
|
||||||
out_errors, source_start + begin, end - begin,
|
out_errors, source_start + begin, end - begin,
|
||||||
"Incomplete escape sequence '%ls'", arg_src);
|
"Incomplete escape sequence '%ls'", arg_src);
|
||||||
return PARSER_TEST_ERROR;
|
return ParserTestErrorBits::ERROR;
|
||||||
}
|
}
|
||||||
append_syntax_error!(
|
append_syntax_error!(
|
||||||
out_errors, source_start + begin, end - begin,
|
out_errors, source_start + begin, end - begin,
|
||||||
"Invalid token '%ls'", arg_src);
|
"Invalid token '%ls'", arg_src);
|
||||||
}
|
}
|
||||||
return PARSER_TEST_ERROR;
|
return ParserTestErrorBits::ERROR;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut err = ParserTestErrorBits::default();
|
let mut err = ParserTestErrorBits::default();
|
||||||
|
@ -1239,7 +1236,7 @@ pub fn parse_util_detect_errors_in_argument(
|
||||||
if ![VARIABLE_EXPAND, VARIABLE_EXPAND_SINGLE, '('].contains(&next_char)
|
if ![VARIABLE_EXPAND, VARIABLE_EXPAND_SINGLE, '('].contains(&next_char)
|
||||||
&& !valid_var_name_char(next_char)
|
&& !valid_var_name_char(next_char)
|
||||||
{
|
{
|
||||||
err = PARSER_TEST_ERROR;
|
err = ParserTestErrorBits::ERROR;
|
||||||
if let Some(ref mut out_errors) = out_errors {
|
if let Some(ref mut out_errors) = out_errors {
|
||||||
let mut first_dollar = idx;
|
let mut first_dollar = idx;
|
||||||
while first_dollar > 0
|
while first_dollar > 0
|
||||||
|
@ -1282,7 +1279,7 @@ pub fn parse_util_detect_errors_in_argument(
|
||||||
Some(&mut has_dollar),
|
Some(&mut has_dollar),
|
||||||
) {
|
) {
|
||||||
-1 => {
|
-1 => {
|
||||||
err |= PARSER_TEST_ERROR;
|
err |= ParserTestErrorBits::ERROR;
|
||||||
append_syntax_error!(out_errors, source_start, 1, "Mismatched parenthesis");
|
append_syntax_error!(out_errors, source_start, 1, "Mismatched parenthesis");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue