From 93c336010f74a36452836a88a5ad5139663eabc0 Mon Sep 17 00:00:00 2001 From: Mine Starks <16928427+minestarks@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:36:34 +0000 Subject: [PATCH] bit more cleanup and more test cases --- compiler/qsc_parse/src/expr/tests.rs | 60 ++------- compiler/qsc_parse/src/item.rs | 40 +----- compiler/qsc_parse/src/item/tests.rs | 115 ---------------- compiler/qsc_parse/src/prim/tests.rs | 25 ++-- compiler/qsc_parse/src/ty.rs | 29 +--- compiler/qsc_parse/src/ty/tests.rs | 23 ---- language_service/src/completion/tests.rs | 164 +++++++++++++++++++++++ 7 files changed, 193 insertions(+), 263 deletions(-) diff --git a/compiler/qsc_parse/src/expr/tests.rs b/compiler/qsc_parse/src/expr/tests.rs index 431970bdb4..4a64bf8ae6 100644 --- a/compiler/qsc_parse/src/expr/tests.rs +++ b/compiler/qsc_parse/src/expr/tests.rs @@ -348,19 +348,19 @@ fn lit_int_hexadecimal_dot() { expr, "0x123.45", &expect![[r#" - Error( - Rule( - "identifier", - Int( - Decimal, - ), - Span { - lo: 6, - hi: 8, - }, + Error( + Rule( + "identifier", + Int( + Decimal, ), - ) - "#]], + Span { + lo: 6, + hi: 8, + }, + ), + ) + "#]], ); } @@ -1763,42 +1763,6 @@ fn struct_copy_cons_empty() { ); } -#[test] -fn struct_recovery() { - check( - expr, - "new Foo. ;", - &expect![[r#" - Expr _id_ [0-9]: Struct (Err IncompletePath [4-9]: - Ident _id_ [4-7] "Foo"): - - [ - Error( - Rule( - "identifier", - Semi, - Span { - lo: 9, - hi: 10, - }, - ), - ), - Error( - Token( - Open( - Brace, - ), - Semi, - Span { - lo: 9, - hi: 10, - }, - ), - ), - ]"#]], - ); -} - #[test] fn call_op_one() { check( diff --git a/compiler/qsc_parse/src/item.rs b/compiler/qsc_parse/src/item.rs index 5875666cea..2dfb7a5351 100644 --- a/compiler/qsc_parse/src/item.rs +++ b/compiler/qsc_parse/src/item.rs @@ -26,7 +26,7 @@ use crate::{ barrier, path, recovering, recovering_path, recovering_semi, recovering_token, shorten, }, stmt::check_semis, - ty::{array_or_arrow, strict_ty}, + ty::array_or_arrow, ErrorKind, }; use qsc_ast::ast::{ @@ -198,7 +198,7 @@ pub fn parse_implicit_namespace(source_name: &str, s: &mut ParserContext) -> Res /// Invalid or disallowed characters are cleaned up in a best effort manner. fn source_name_to_namespace_name(raw: &str, span: Span) -> Result> { let path = std::path::Path::new(raw); - let mut parts = Vec::new(); + let mut namespace = Vec::new(); for component in path.components() { match component { std::path::Component::Normal(name) => { @@ -216,7 +216,7 @@ fn source_name_to_namespace_name(raw: &str, span: Span) -> Result> let mut ident = validate_namespace_name(span, name)?; ident.span = span; - parts.push(*ident); + namespace.push(*ident); } _ => { return Err(Error::new(ErrorKind::InvalidFileName( @@ -227,7 +227,7 @@ fn source_name_to_namespace_name(raw: &str, span: Span) -> Result> } } - Ok(parts.into()) + Ok(namespace.into()) } fn clean_namespace_name(name: &str) -> String { @@ -360,35 +360,7 @@ fn parse_newtype(s: &mut ParserContext) -> Result> { let name = ident(s)?; token(s, TokenKind::Eq)?; let lo = s.peek().span.lo; - let mut def = match parse_ty_def(s) { - Ok(def) => def, - Err(error) if s.peek().span.lo > lo => return Err(error), - Err(error) => { - s.push_error(error); - - // Grab the whitespace from the end of the last token until - // the beginning of the next token - let last_hi = s.span(0).hi; - let span = Span { - lo: last_hi, - hi: s.peek().span.lo, - }; - - Box::new(TyDef { - id: NodeId::default(), - span, - kind: Box::new(TyDefKind::Field( - None, - Box::new(Ty { - id: NodeId::default(), - span, - kind: Box::new(TyKind::Err), - }), - )), - }) - } - }; - + let mut def = parse_ty_def(s)?; if let Some(ty) = try_tydef_as_ty(def.as_ref()) { let ty = array_or_arrow(s, ty, lo)?; def = Box::new(TyDef { @@ -456,7 +428,7 @@ fn parse_ty_def(s: &mut ParserContext) -> Result> { token(s, TokenKind::Close(Delim::Paren))?; final_sep.reify(defs, TyDefKind::Paren, TyDefKind::Tuple) } else { - let field_ty = strict_ty(s)?; + let field_ty = ty(s)?; if token(s, TokenKind::Colon).is_ok() { let name = ty_as_ident(field_ty)?; let field_ty = ty(s)?; diff --git a/compiler/qsc_parse/src/item/tests.rs b/compiler/qsc_parse/src/item/tests.rs index 7a59cdd04a..3e60684deb 100644 --- a/compiler/qsc_parse/src/item/tests.rs +++ b/compiler/qsc_parse/src/item/tests.rs @@ -569,56 +569,6 @@ fn ty_def_named_duplicate_comma() { ); } -#[test] -fn ty_def_missing_type_with_semi() { - check( - parse, - "newtype Foo = ;", - &expect![[r#" - Item _id_ [0-15]: - New Type (Ident _id_ [8-11] "Foo"): TyDef _id_ [13-14]: Field: - Type _id_ [13-14]: Err - - [ - Error( - Rule( - "type", - Semi, - Span { - lo: 14, - hi: 15, - }, - ), - ), - ]"#]], - ); -} - -#[test] -fn ty_def_missing_type_no_semi() { - check( - parse, - "newtype Foo = ", - &expect![[r#" - Item _id_ [0-13]: - New Type (Ident _id_ [8-11] "Foo"): TyDef _id_ [13-14]: Field: - Type _id_ [13-14]: Err - - [ - Error( - Rule( - "type", - Eof, - Span { - lo: 14, - hi: 14, - }, - ), - ), - ]"#]], - ); -} - #[test] fn function_decl() { check( @@ -995,71 +945,6 @@ fn function_missing_output_ty() { ); } -#[test] -fn function_missing_output_ty_after_colon() { - check( - parse, - "function Foo() : { body intrinsic; }", - &expect![[r#" - Item _id_ [0-36]: - Callable _id_ [0-36] (Function): - name: Ident _id_ [9-12] "Foo" - input: Pat _id_ [12-14]: Unit - output: Type _id_ [16-17]: Err - body: Specializations: - SpecDecl _id_ [19-34] (Body): Gen: Intrinsic - - [ - Error( - Rule( - "type", - Open( - Brace, - ), - Span { - lo: 17, - hi: 18, - }, - ), - ), - ]"#]], - ); -} - -#[test] -fn function_missing_input_ty_after_colon() { - check( - parse, - "function Foo(x : ) : Unit { body intrinsic; }", - &expect![[r#" - Item _id_ [0-46]: - Callable _id_ [0-46] (Function): - name: Ident _id_ [9-12] "Foo" - input: Pat _id_ [12-19]: Paren: - Pat _id_ [13-16]: Bind: - Ident _id_ [13-14] "x" - Type _id_ [16-18]: Err - output: Type _id_ [22-26]: Path: Path _id_ [22-26] (Ident _id_ [22-26] "Unit") - body: Specializations: - SpecDecl _id_ [29-44] (Body): Gen: Intrinsic - - [ - Error( - Rule( - "type", - Close( - Paren, - ), - Span { - lo: 18, - hi: 19, - }, - ), - ), - ]"#]], - ); -} - #[test] fn internal_ty() { check( diff --git a/compiler/qsc_parse/src/prim/tests.rs b/compiler/qsc_parse/src/prim/tests.rs index daea66020f..efef4e139a 100644 --- a/compiler/qsc_parse/src/prim/tests.rs +++ b/compiler/qsc_parse/src/prim/tests.rs @@ -260,22 +260,17 @@ fn pat_missing_ty() { pat, "foo :", &expect![[r#" - Pat _id_ [0-5]: Bind: - Ident _id_ [0-3] "foo" - Type _id_ [5-5]: Err - - [ - Error( - Rule( - "type", - Eof, - Span { - lo: 5, - hi: 5, - }, - ), + Error( + Rule( + "type", + Eof, + Span { + lo: 5, + hi: 5, + }, ), - ]"#]], + ) + "#]], ); } diff --git a/compiler/qsc_parse/src/ty.rs b/compiler/qsc_parse/src/ty.rs index f36e989d6c..e5c82c7d3e 100644 --- a/compiler/qsc_parse/src/ty.rs +++ b/compiler/qsc_parse/src/ty.rs @@ -20,36 +20,9 @@ use crate::{ use qsc_ast::ast::{ CallableKind, Functor, FunctorExpr, FunctorExprKind, Ident, NodeId, SetOp, Ty, TyKind, }; -use qsc_data_structures::span::Span; pub(super) fn ty(s: &mut ParserContext) -> Result { s.expect(WordKinds::PathTy); - if let Some(ty) = opt(s, strict_ty)? { - Ok(ty) - } else { - s.push_error(Error::new(ErrorKind::Rule( - "type", - s.peek().kind, - s.peek().span, - ))); - - // Grab the whitespace from the end of the last token until - // the beginning of the next token - let last_hi = s.span(0).hi; - let span = Span { - lo: last_hi, - hi: s.peek().span.lo, - }; - - Ok(Ty { - id: NodeId::default(), - span, - kind: Box::new(TyKind::Err), - }) - } -} - -pub(super) fn strict_ty(s: &mut ParserContext) -> Result { let lo = s.peek().span.lo; let lhs = base(s)?; array_or_arrow(s, lhs, lo) @@ -122,7 +95,7 @@ fn base(s: &mut ParserContext) -> Result { } else if let Some(path) = opt(s, |s| recovering_path(s, WordKinds::PathTy))? { Ok(TyKind::Path(path)) } else if token(s, TokenKind::Open(Delim::Paren)).is_ok() { - let (tys, final_sep) = seq(s, strict_ty)?; + let (tys, final_sep) = seq(s, ty)?; token(s, TokenKind::Close(Delim::Paren))?; Ok(final_sep.reify(tys, |t| TyKind::Paren(Box::new(t)), TyKind::Tuple)) } else { diff --git a/compiler/qsc_parse/src/ty/tests.rs b/compiler/qsc_parse/src/ty/tests.rs index 296ec873c5..8d38def154 100644 --- a/compiler/qsc_parse/src/ty/tests.rs +++ b/compiler/qsc_parse/src/ty/tests.rs @@ -397,29 +397,6 @@ fn ty_incomplete() { ); } -#[test] -fn ty_missing() { - check( - ty, - " ", - &expect![[r#" - Type _id_ [0-2]: Err - - [ - Error( - Rule( - "type", - Eof, - Span { - lo: 2, - hi: 2, - }, - ), - ), - ]"#]], - ); -} - #[test] fn ty_incomplete_in_tuple() { check( diff --git a/language_service/src/completion/tests.rs b/language_service/src/completion/tests.rs index cea2a6e574..7a27f82b09 100644 --- a/language_service/src/completion/tests.rs +++ b/language_service/src/completion/tests.rs @@ -2539,6 +2539,36 @@ fn type_position_namespace() { ); } +#[test] +fn udt_base_type_part() { + check( + r#" + namespace Test { + newtype Foo = FakeStdLib.↘ + }"#, + &["Udt", "Qubit", "FakeWithParam"], + &expect![[r#" + [ + Some( + CompletionItem { + label: "Udt", + kind: Interface, + sort_text: Some( + "0300Udt", + ), + detail: Some( + "struct Udt { x : Int, y : Int }", + ), + additional_text_edits: None, + }, + ), + None, + None, + ] + "#]], + ); +} + #[test] fn struct_init() { check( @@ -3146,3 +3176,137 @@ fn open_does_not_match_pkg_alias() { "#]], ); } + +#[test] +fn input_type_missing() { + check( + "namespace Test { function Foo(x : FakeStdLib.↘ ) : Unit { body intrinsic; } }", + &["Udt", "Library"], + &expect![[r#" + [ + Some( + CompletionItem { + label: "Udt", + kind: Interface, + sort_text: Some( + "0300Udt", + ), + detail: Some( + "struct Udt { x : Int, y : Int }", + ), + additional_text_edits: None, + }, + ), + Some( + CompletionItem { + label: "Library", + kind: Module, + sort_text: Some( + "0600Library", + ), + detail: None, + additional_text_edits: None, + }, + ), + ] + "#]], + ); +} + +#[test] +fn notebook_top_level_path_part() { + check_notebook( + &[( + "cell1", + (" + FakeStdLib.↘ + "), + )], + &["Udt", "Library", "FakeStdLib", "FakeWithParam"], + &expect![[r#" + [ + Some( + CompletionItem { + label: "Udt", + kind: Interface, + sort_text: Some( + "0300Udt", + ), + detail: Some( + "struct Udt { x : Int, y : Int }", + ), + additional_text_edits: None, + }, + ), + Some( + CompletionItem { + label: "Library", + kind: Module, + sort_text: Some( + "0600Library", + ), + detail: None, + additional_text_edits: None, + }, + ), + None, + Some( + CompletionItem { + label: "FakeWithParam", + kind: Function, + sort_text: Some( + "0300FakeWithParam", + ), + detail: Some( + "operation FakeWithParam(x : Int) : Unit", + ), + additional_text_edits: None, + }, + ), + ] + "#]], + ); +} + +#[test] +fn notebook_top_level_path_part_in_type() { + check_notebook( + &[( + "cell1", + (" + let x : FakeStdLib.↘ + "), + )], + &["Udt", "Library", "FakeStdLib", "FakeWithParam"], + &expect![[r#" + [ + Some( + CompletionItem { + label: "Udt", + kind: Interface, + sort_text: Some( + "0300Udt", + ), + detail: Some( + "struct Udt { x : Int, y : Int }", + ), + additional_text_edits: None, + }, + ), + Some( + CompletionItem { + label: "Library", + kind: Module, + sort_text: Some( + "0600Library", + ), + detail: None, + additional_text_edits: None, + }, + ), + None, + None, + ] + "#]], + ); +}