Skip to content

Commit

Permalink
More fixes
Browse files Browse the repository at this point in the history
- More errors (still non-final)
- Change variant name of `default` TS function for `.d.ts` file
- Refactor some lexer APIs (add `parse_comment_literal`)
- Get parser tests passing
- Remove EMPTY from `bracketed_items_from_reader`
  • Loading branch information
kaleidawave committed Oct 15, 2024
1 parent d133428 commit 724fcc2
Show file tree
Hide file tree
Showing 27 changed files with 335 additions and 439 deletions.
5 changes: 4 additions & 1 deletion checker/src/synthesis/declarations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,10 @@ pub(crate) fn synthesise_declaration<T: crate::ReadFromFS>(
);
}
}
parser::declarations::ExportDeclaration::DefaultFunction { position, .. } => {
parser::declarations::ExportDeclaration::TSDefaultFunctionDeclaration {
position,
..
} => {
checking_data.diagnostics_container.add_error(
TypeCheckError::FunctionWithoutBodyNotAllowedHere {
position: position.with_source(environment.get_source()),
Expand Down
2 changes: 1 addition & 1 deletion checker/src/synthesis/hoisting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ pub(crate) fn hoist_statements<T: crate::ReadFromFS>(
);
}
Declaration::Export(Decorated {
on: ExportDeclaration::DefaultFunction { position, .. },
on: ExportDeclaration::TSDefaultFunctionDeclaration { position, .. },
..
}) => {
// TODO under definition file
Expand Down
9 changes: 4 additions & 5 deletions parser/src/comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,16 @@ impl<T: ASTNode> ASTNode for WithComment<T> {
fn from_reader(reader: &mut crate::new::Lexer) -> ParseResult<Self> {
let start = reader.get_start();
if reader.is_operator_advance("/*") {
let comment = reader.parse_until("*/").expect("TODO");
dbg!(&comment);
let comment = reader.parse_comment_literal(true)?.to_owned();
let item = T::from_reader(reader)?;
let position = start.union(item.get_position());
Ok(Self::PrefixComment(comment.to_owned(), item, position))
Ok(Self::PrefixComment(comment, item, position))
} else {
let item = T::from_reader(reader)?;
if reader.is_operator_advance("/*") {
let comment = reader.parse_until("*/").expect("TODO");
let comment = reader.parse_comment_literal(true)?.to_owned();
let position = start.union(reader.get_end());
Ok(Self::PostfixComment(item, comment.to_owned(), position))
Ok(Self::PostfixComment(item, comment, position))
} else {
Ok(Self::None(item))
}
Expand Down
9 changes: 6 additions & 3 deletions parser/src/declarations/classes/class_member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl ASTNode for ClassMember {
todo!("comment; return Ok(Self::Comment(comment, is_multiline, span));");
}

// TODO temp fixes
// TODO temp fixes. Should be recorded
let _ = reader.is_keyword_advance("declare");
let _ = reader.is_keyword_advance("public");
let _ = reader.is_keyword_advance("private");
Expand Down Expand Up @@ -130,8 +130,11 @@ impl ASTNode for ClassMember {
Ok(ClassMember::Method(is_static, function))
} else {
if !header.is_no_modifiers() {
todo!()
// return crate::throw_unexpected_token(reader, &[TSXToken::OpenParentheses]);
// TODO ""
return Err(crate::ParseError::new(
crate::ParseErrors::ExpectedOperator { expected: "(", found: "" },
reader.next_item_span(),
));
}
let is_optional = reader.is_operator_advance("?:");
let type_annotation = if is_optional || reader.is_operator_advance(":") {
Expand Down
6 changes: 3 additions & 3 deletions parser/src/declarations/classes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ impl<U: ExpressionOrStatementPosition + Debug + PartialEq + Clone + 'static> AST
break;
}
let value = Decorated::<ClassMember>::from_reader(reader)?;
if let ClassMember::Property { .. } | ClassMember::Indexer { .. } = &value.on {
reader.expect_semi_colon()?;
}
members.push(value);

// TODO comments probably don't need this
reader.expect_semi_colon()?;
}

let end = reader.expect('}')?;
Expand Down
50 changes: 15 additions & 35 deletions parser/src/declarations/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,12 @@ use visitable_derive::Visitable;
#[derive(Debug, PartialEq, Clone, Visitable, get_field_by_type::GetFieldByType)]
#[get_field_by_type_target(Span)]
pub enum ExportDeclaration {
Item {
exported: Exportable,
position: Span,
},
// `export default ...`
Default {
expression: Box<Expression>,
position: Span,
},
DefaultFunction {
/// `export *Exportable*`
Item { exported: Exportable, position: Span },
/// `export default ...`
Default { expression: Box<Expression>, position: Span },
/// In TypeScript you can `export default name` in type definition modules
TSDefaultFunctionDeclaration {
/// Technically not allowed in TypeScript
is_async: bool,
identifier: Option<VariableIdentifier>,
Expand Down Expand Up @@ -75,6 +71,8 @@ impl ASTNode for ExportDeclaration {
if reader.get_options().type_definition_module
&& crate::lexer::utilities::is_function_header(reader.get_current())
{
// Always have == .d.ts file here
// Unfortuantly have to do quite a bit of parsing here
let is_async = reader.is_operator_advance("async");
let _ = reader.expect_keyword("function");

Expand All @@ -93,8 +91,7 @@ impl ASTNode for ExportDeclaration {
};

let position = start.union(reader.get_end());

Ok(ExportDeclaration::DefaultFunction {
Ok(ExportDeclaration::TSDefaultFunctionDeclaration {
position,
is_async,
identifier,
Expand Down Expand Up @@ -223,28 +220,11 @@ impl ASTNode for ExportDeclaration {
return Ok(Self::Item { exported: Exportable::Namespace(namespace), position });
}

todo!("{:?}", reader.get_current().get(..20))
// }
// Token(TSXToken::Keyword(kw), _) if kw.is_in_function_header() => {
// let function_declaration = StatementFunction::from_reader(reader)?;
// let position = start.union(function_declaration.get_position());
// Ok(Self::Variable {
// exported: Exportable::Function(function_declaration),
// position,
// })
// }
// _ => throw_unexpected_token(
// reader,
// &[
// TSXToken::Keyword(TSXKeyword::Class),
// TSXToken::Keyword(TSXKeyword::Function),
// TSXToken::Keyword(TSXKeyword::Const),
// TSXToken::Keyword(TSXKeyword::Let),
// TSXToken::Keyword(TSXKeyword::Interface),
// TSXToken::Keyword(TSXKeyword::Type),
// TSXToken::OpenBrace,
// ],
// ),
// TODO vary list on certain parameters
Err(crate::lexer::utilities::expected_one_of_keywords(
reader,
&["let", "const", "function", "class", "enum", "type", "interface", "{"],
))
}
}

Expand Down Expand Up @@ -317,7 +297,7 @@ impl ASTNode for ExportDeclaration {
buf.push_str("export default ");
expression.to_string_from_buffer(buf, options, local);
}
ExportDeclaration::DefaultFunction {
ExportDeclaration::TSDefaultFunctionDeclaration {
is_async,
identifier,
parameters,
Expand Down
3 changes: 1 addition & 2 deletions parser/src/declarations/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,7 @@ pub(crate) fn import_specifier_and_parts_from_reader(
} else if reader.starts_with_string_delimeter() || reader.is_keyword("from") {
ImportedItems::Parts(None)
} else {
todo!("error for: {:?}", reader.get_current().get(..20).unwrap_or(reader.get_current()))
// return throw_unexpected_token(reader, &[TSXToken::Multiply, TSXToken::OpenBrace]);
return Err(crate::lexer::utilities::expected_one_of_keywords(reader, &["*", "["]));
};

Ok(PartsResult {
Expand Down
116 changes: 36 additions & 80 deletions parser/src/declarations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@ pub enum Declaration {

impl Declaration {
// TODO strict mode can affect result
// TODO reuse
// Warning expects skip to have been called
pub(crate) fn is_declaration_start(reader: &crate::new::Lexer) -> bool {
let declaration_keyword = reader.is_one_of_keywords(&[
let mut declaration_keyword = reader.is_one_of_keywords(&[
"let",
"const",
"function",
"class",
"enum",
"interface",
Expand All @@ -78,76 +79,30 @@ impl Declaration {
"declare",
"import",
"export",
// Extra
"from",
]);

if let Some(name @ ("from" | "import" | "export" | "namespace" | "type")) =
if let Some("from") = declaration_keyword {
reader.get_options().reversed_imports
} else if let Some(name @ ("import" | "export" | "namespace" | "type")) =
declaration_keyword
{
if let (false, "from") = (reader.get_options().reversed_imports, name) {
return false;
}

let after_declaration_keyword = reader.get_current()[name.len()..].trim_start();

// TODO more (is operator like?)
let is_declaration_keyword_expression = after_declaration_keyword.starts_with('(')
|| after_declaration_keyword.starts_with('.')
|| after_declaration_keyword.starts_with('[')
|| after_declaration_keyword.starts_with('(')
|| after_declaration_keyword.starts_with('=');

!is_declaration_keyword_expression
} else if declaration_keyword.is_some() {
true
} else {
declaration_keyword.is_some()
crate::lexer::utilities::is_function_header(reader.get_current())
}

// #[cfg(feature = "extras")]
// return result
// || matches!(token, TSXToken::Keyword(kw) if options.custom_function_headers && kw.is_special_function_header())
// || (matches!(token, TSXToken::Keyword(TSXKeyword::Namespace) if cfg!(feature = "full-typescript")))
// || {
// let TSXToken::Keyword(token) = *token else { return false };
// let Some(Token(after, _)) = reader.peek_n(1) else { return false };

// #[allow(clippy::match_same_arms)]
// match (token, after) {
// // For dynamic import
// (
// TSXKeyword::Import,
// TSXToken::OpenBrace
// | TSXToken::Keyword(..)
// | TSXToken::Identifier(..)
// | TSXToken::StringLiteral(..)
// | TSXToken::Multiply,
// ) => true,
// (TSXKeyword::Declare | TSXKeyword::Interface, _) => options.type_annotations,
// (TSXKeyword::Async, TSXToken::Keyword(TSXKeyword::Function)) => true,
// (TSXKeyword::Async, TSXToken::Keyword(kw)) => {
// options.custom_function_headers && kw.is_special_function_header()
// }
// // Extra
// (TSXKeyword::From, TSXToken::StringLiteral(..)) => true,
// (..) => false,
// }
// };

// #[cfg(not(feature = "extras"))]
// return result || {
// let TSXToken::Keyword(token) = *token else { return false };

// // For dynamic import
// matches!(token, TSXKeyword::Import)
// && matches!(
// reader.peek_n(1),
// Some(Token(
// TSXToken::OpenBrace
// | TSXToken::Keyword(..) | TSXToken::Identifier(..)
// | TSXToken::StringLiteral(..)
// | TSXToken::Multiply,
// _
// ))
// )
// };
// }
}
}

Expand Down Expand Up @@ -230,8 +185,7 @@ impl crate::ASTNode for Declaration {
&["let", "const", "var", "class", "type", "async", "function", "namespace"],
))
}
} else if reader.is_keyword("function") || reader.is_keyword("async") {
// TODO more above ^^^
} else if crate::lexer::utilities::is_function_header(reader.get_current()) {
let function = StatementFunction::from_reader(reader)?;
Ok(Declaration::Function(Decorated::new(decorators, function)))
} else {
Expand All @@ -253,7 +207,7 @@ impl crate::ASTNode for Declaration {
// Ok(Declaration::Function(Decorated::new(decorators, function)))
// }

// TODO vary list on certain paramters
// TODO vary list on certain parameters
Err(crate::lexer::utilities::expected_one_of_keywords(
reader,
&[
Expand Down Expand Up @@ -355,8 +309,14 @@ impl<U: ImportOrExport> crate::ASTNode for ImportExportPart<U> {
let name = crate::VariableIdentifier::Standard(name, position);
Ok(Self { just_type, name, alias: None, position, _marker: Default::default() })
} else {
todo!()
// crate::throw_unexpected_token(reader, &[TSXToken::Keyword(TSXKeyword::As)])
Err(ParseError::new(
ParseErrors::ExpectedKeyword {
expected: "as",
// TODO
found: reader.get_current(),
},
reader.next_item_span(),
))
}
} else {
let name = crate::VariableIdentifier::from_reader(reader)?;
Expand Down Expand Up @@ -438,7 +398,7 @@ impl<U: ImportOrExport> self_rust_tokenize::SelfRustTokenize for ImportExportPar
&self,
_token_stream: &mut self_rust_tokenize::proc_macro2::TokenStream,
) {
todo!()
todo!("import export part to token stream")
}
}

Expand All @@ -464,7 +424,7 @@ impl ImportExportName {
reader.skip();
let start = reader.get_start();
if reader.starts_with_string_delimeter() {
let (content, quoted) = reader.parse_string_literal().expect("TODO");
let (content, quoted) = reader.parse_string_literal()?;
let position = start.with_length(content.len() + 2);
Ok((ImportExportName::Quoted(content.to_owned(), quoted), position))
} else {
Expand Down Expand Up @@ -523,25 +483,21 @@ impl ImportLocation {
// ));
// }
// }
// else if options.interpolation_points
// && matches!(&token.0, TSXToken::Identifier(i) if i == crate::marker::MARKER)
// {
// Ok((Self::Marker(state.new_partial_point_marker(token.1)), source_map::End(token.1 .0)))
// todo!()
// Err(ParseError::new(
// ParseErrors::ExpectedStringLiteral { found: token.0 },
// token.1.with_length(0),
// ))

reader.skip();

if reader.starts_with_string_delimeter() {
let start = reader.get_start();
let (content, quoted) = reader.parse_string_literal().expect("TODO");
Ok((ImportLocation::Quoted(content.to_owned(), quoted)))
} else {
todo!("{:?}", reader.get_current().get(..20))
// else if options.interpolation_points
// && matches!(&token.0, TSXToken::Identifier(i) if i == crate::marker::MARKER)
// {
// Ok((Self::Marker(state.new_partial_point_marker(token.1)), source_map::End(token.1 .0)))
// todo!()
// Err(ParseError::new(
// ParseErrors::ExpectedStringLiteral { found: token.0 },
// token.1.with_length(0),
// ))
}
let start = reader.get_start();
let (content, quoted) = reader.parse_string_literal()?;
Ok((ImportLocation::Quoted(content.to_owned(), quoted)))
}

pub(crate) fn to_string_from_buffer<T: source_map::ToString>(&self, buf: &mut T) {
Expand Down
Loading

0 comments on commit 724fcc2

Please sign in to comment.