diff --git a/src/parser/ast.rs b/src/parser/ast.rs index f52d8ca9..7fa0307b 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -65,6 +65,10 @@ impl Type { _ => false, } } + + pub fn is_bottom(&self) -> bool { + matches!(self, Type::Never | Type::Void) + } } impl Display for Type { diff --git a/src/parser/error.rs b/src/parser/error.rs index 00e9edb5..a201f392 100644 --- a/src/parser/error.rs +++ b/src/parser/error.rs @@ -32,6 +32,7 @@ pub enum ParseError { ReadonlyPropertyHasDefaultValue(String, String, Span), MixingBracedAndUnBracedNamespaceDeclarations(Span), NestedNamespaceDeclarations(Span), + ForbiddenTypeUsedInProperty(String, String, Type, Span), } impl Display for ParseError { @@ -71,11 +72,12 @@ impl Display for ParseError { Self::ConstructorInEnum(name, span) => write!(f, "Parse Error: Enum '{}' cannot have a constructor on line {} column {}", name, span.0, span.1), Self::MissingCaseValueForBackedEnum(case, name, span) => write!(f, "Parse Error: Case `{}` of backed enum `{}` must have a value on line {} column {}", case, name, span.0, span.1), Self::CaseValueForUnitEnum(case, name, span) => write!(f, "Parse Error: Case `{}` of unit enum `{}` must not have a value on line {} column {}", case, name, span.0, span.1), - Self::UnpredictableState(span) => write!(f, "Parse Error: Reached an unpredictable state on line {} column {}", span.0, span.1), Self::StaticPropertyUsingReadonlyModifier(class, prop, span) => write!(f, "Parse Error: Static property {}:${} cannot be readonly on line {} column {}", class, prop, span.0, span.1), Self::ReadonlyPropertyHasDefaultValue(class, prop, span) => write!(f, "Parse Error: Readonly property {}:${} cannot have a default value on line {} column {}", class, prop, span.0, span.1), Self::MixingBracedAndUnBracedNamespaceDeclarations(span) => write!(f, "Parse Error: Cannot mix braced namespace declarations with unbraced namespace declarations on line {} column {}", span.0, span.1), Self::NestedNamespaceDeclarations(span) => write!(f, "Parse Error: Namespace declarations cannot be mixed on line {} column {}", span.0, span.1), + Self::UnpredictableState(span) => write!(f, "Parse Error: Reached an unpredictable state on line {} column {}", span.0, span.1), + Self::ForbiddenTypeUsedInProperty(class, prop, ty, span) => write!(f, "Parse Error: Property {}::${} cannot have type `{}` on line {} column {}", class, prop, ty, span.0, span.1), } } } diff --git a/src/parser/internal/classish_statement.rs b/src/parser/internal/classish_statement.rs index cd5985a2..c8e8ac48 100644 --- a/src/parser/internal/classish_statement.rs +++ b/src/parser/internal/classish_statement.rs @@ -146,30 +146,47 @@ impl Parser { value = Some(self.expression(state, Precedence::Lowest)?); } - self.semi(state)?; + let class_name: String = expected_scope!([ + Scope::Class(name, _) => state.named(&name), + Scope::Trait(name) => state.named(&name), + Scope::AnonymousClass => state.named(&"class@anonymous".into()), + ], state); if flags.contains(&PropertyFlag::Readonly) { if flags.contains(&PropertyFlag::Static) { - let class_name: String = expected_scope!([ - Scope::Class(name, _) => state.named(&name), - Scope::Trait(name) => state.named(&name), - Scope::AnonymousClass => state.named(&"class@anonymous".into()), - ], state); - return Err(ParseError::StaticPropertyUsingReadonlyModifier(class_name, var.to_string(), state.current.span)); } if value.is_some() { - let class_name: String = expected_scope!([ - Scope::Class(name, _) => state.named(&name), - Scope::Trait(name) => state.named(&name), - Scope::AnonymousClass => state.named(&"class@anonymous".into()), - ], state); return Err(ParseError::ReadonlyPropertyHasDefaultValue(class_name, var.to_string(), state.current.span)); } } + match &ty { + Some(ty) => { + if ty.includes_callable() || ty.is_bottom() { + return Err(ParseError::ForbiddenTypeUsedInProperty( + class_name, + var.to_string(), + ty.clone(), + state.current.span, + )); + } + } + None => { + if flags.contains(&PropertyFlag::Readonly) { + return Err(ParseError::MissingTypeForReadonlyProperty( + class_name, + var.to_string(), + state.current.span, + )); + } + } + } + + self.semi(state)?; + Ok(Statement::Property { var, value, diff --git a/src/parser/internal/params.rs b/src/parser/internal/params.rs index ec59c1b4..56ee1279 100644 --- a/src/parser/internal/params.rs +++ b/src/parser/internal/params.rs @@ -53,37 +53,13 @@ impl Parser { }; while !state.is_eof() && state.current.kind != TokenKind::RightParen { - let mut param_type = None; - let flags: Vec = self .promoted_property_flags(state)? .iter() .map(|f| f.into()) .collect(); - if !flags.is_empty() { - match construct { - 0 => { - return Err(ParseError::PromotedPropertyOutsideConstructor( - state.current.span, - )); - } - 1 => { - return Err(ParseError::PromotedPropertyOnAbstractConstructor( - state.current.span, - )); - } - _ => {} - } - } - - if !matches!( - state.current.kind, - TokenKind::Variable(_) | TokenKind::Ellipsis | TokenKind::Ampersand - ) { - // Try to parse the type. - param_type = Some(self.get_type(state)?); - } + let ty = self.get_optional_type(state)?; let mut variadic = false; let mut by_ref = false; @@ -107,12 +83,42 @@ impl Parser { TokenKind::Variable(v) => v ], state, "a varaible"); - if flags.contains(&PropertyFlag::Readonly) && param_type.is_none() { - return Err(ParseError::MissingTypeForReadonlyProperty( - class_name, - var.to_string(), - state.current.span, - )); + if !flags.is_empty() { + match construct { + 0 => { + return Err(ParseError::PromotedPropertyOutsideConstructor( + state.current.span, + )); + } + 1 => { + return Err(ParseError::PromotedPropertyOnAbstractConstructor( + state.current.span, + )); + } + _ => {} + } + + match &ty { + Some(ty) => { + if ty.includes_callable() || ty.is_bottom() { + return Err(ParseError::ForbiddenTypeUsedInProperty( + class_name, + var.to_string(), + ty.clone(), + state.current.span, + )); + } + } + None => { + if flags.contains(&PropertyFlag::Readonly) { + return Err(ParseError::MissingTypeForReadonlyProperty( + class_name, + var.to_string(), + state.current.span, + )); + } + } + } } let mut default = None; @@ -123,13 +129,15 @@ impl Parser { params.push(Param { name: Expression::Variable { name: var }, - r#type: param_type, + r#type: ty, variadic, default, flags, by_ref, }); + // TODO: bug! this allows `function foo(string $a ...$b &$c) {}` + // TODO: if `,` is found, look for next param, otherwise break out of the loop. self.optional_comma(state)?; } diff --git a/src/parser/internal/types.rs b/src/parser/internal/types.rs index d4071e02..8af34bf3 100644 --- a/src/parser/internal/types.rs +++ b/src/parser/internal/types.rs @@ -118,16 +118,14 @@ impl Parser { &self, state: &mut State, ) -> ParseResult> { - let ty = self.maybe_optional_nullable(state, &|state| { - self.maybe_optional_static(state, &|state| self.get_optional_simple_type(state)) - }); + if state.current.kind == TokenKind::Question { + return Ok(Some(self.get_type(state)?)); + } + + let ty = self.maybe_optional_static(state, &|state| self.get_optional_simple_type(state)); match ty { Some(ty) => { - if ty.nullable() { - return Ok(Some(ty)); - } - if state.current.kind == TokenKind::Pipe { state.next(); @@ -271,8 +269,15 @@ impl Parser { ) -> ParseResult { if state.current.kind == TokenKind::Question { state.next(); + let inner = otherwise(state)?; + if inner.standalone() { + return Err(ParseError::StandaloneTypeUsedInCombination( + inner, + state.current.span, + )); + } - Ok(Type::Nullable(Box::new(otherwise(state)?))) + Ok(Type::Nullable(Box::new(inner))) } else { otherwise(state) } @@ -310,20 +315,6 @@ impl Parser { otherwise(state) } - fn maybe_optional_nullable( - &self, - state: &mut State, - otherwise: &(dyn Fn(&mut State) -> Option), - ) -> Option { - if state.current.kind == TokenKind::Question { - state.next(); - - Some(Type::Nullable(Box::new(otherwise(state)?))) - } else { - otherwise(state) - } - } - fn maybe_optional_static( &self, state: &mut State, diff --git a/tests/0086/ast.txt b/tests/0086/ast.txt deleted file mode 100644 index 6ddd97b2..00000000 --- a/tests/0086/ast.txt +++ /dev/null @@ -1,21 +0,0 @@ -[ - Class { - name: Identifier { - name: "Foo", - }, - extends: None, - implements: [], - body: [ - Property { - var: "bar", - value: None, - type: None, - flags: [ - Public, - Readonly, - ], - }, - ], - flags: [], - }, -] diff --git a/tests/0086/parser-error.txt b/tests/0086/parser-error.txt new file mode 100644 index 00000000..43df73db --- /dev/null +++ b/tests/0086/parser-error.txt @@ -0,0 +1 @@ +MissingTypeForReadonlyProperty("Foo", "bar", (1, 39)) -> Parse Error: Readonly property Foo::$bar must have type on line 1 column 39 diff --git a/tests/0113/parser-error.txt b/tests/0113/parser-error.txt index da1607de..63d82ac1 100644 --- a/tests/0113/parser-error.txt +++ b/tests/0113/parser-error.txt @@ -1 +1 @@ -PromotedPropertyOutsideConstructor((5, 16)) -> Parse Error: Cannot declare promoted property outside a constructor on line 5 column 16 +PromotedPropertyOutsideConstructor((5, 25)) -> Parse Error: Cannot declare promoted property outside a constructor on line 5 column 25 diff --git a/tests/0114/parser-error.txt b/tests/0114/parser-error.txt index 9eec84bf..5dbd2f76 100644 --- a/tests/0114/parser-error.txt +++ b/tests/0114/parser-error.txt @@ -1 +1 @@ -PromotedPropertyOnAbstractConstructor((5, 16)) -> Parse Error: Cannot declare promoted property in an abstract constructor on line 5 column 16 +PromotedPropertyOnAbstractConstructor((5, 25)) -> Parse Error: Cannot declare promoted property in an abstract constructor on line 5 column 25 diff --git a/tests/0115/parser-error.txt b/tests/0115/parser-error.txt index 9eec84bf..5dbd2f76 100644 --- a/tests/0115/parser-error.txt +++ b/tests/0115/parser-error.txt @@ -1 +1 @@ -PromotedPropertyOnAbstractConstructor((5, 16)) -> Parse Error: Cannot declare promoted property in an abstract constructor on line 5 column 16 +PromotedPropertyOnAbstractConstructor((5, 25)) -> Parse Error: Cannot declare promoted property in an abstract constructor on line 5 column 25 diff --git a/tests/0116/parser-error.txt b/tests/0116/parser-error.txt index 9eec84bf..5dbd2f76 100644 --- a/tests/0116/parser-error.txt +++ b/tests/0116/parser-error.txt @@ -1 +1 @@ -PromotedPropertyOnAbstractConstructor((5, 16)) -> Parse Error: Cannot declare promoted property in an abstract constructor on line 5 column 16 +PromotedPropertyOnAbstractConstructor((5, 25)) -> Parse Error: Cannot declare promoted property in an abstract constructor on line 5 column 25 diff --git a/tests/0154/parser-error.txt b/tests/0154/parser-error.txt index e5ed2581..8e362edd 100644 --- a/tests/0154/parser-error.txt +++ b/tests/0154/parser-error.txt @@ -1 +1 @@ -StaticPropertyUsingReadonlyModifier("Foo\\Bar\\Baz", "foo", (7, 1)) -> Parse Error: Static property Foo\Bar\Baz:$foo cannot be readonly on line 7 column 1 +StaticPropertyUsingReadonlyModifier("Foo\\Bar\\Baz", "foo", (6, 40)) -> Parse Error: Static property Foo\Bar\Baz:$foo cannot be readonly on line 6 column 40 diff --git a/tests/0156/parser-error.txt b/tests/0156/parser-error.txt index 349560f4..b84d9493 100644 --- a/tests/0156/parser-error.txt +++ b/tests/0156/parser-error.txt @@ -1 +1 @@ -ReadonlyPropertyHasDefaultValue("Foo\\Bar\\Baz", "foo", (7, 1)) -> Parse Error: Readonly property Foo\Bar\Baz:$foo cannot have a default value on line 7 column 1 +ReadonlyPropertyHasDefaultValue("Foo\\Bar\\Baz", "foo", (6, 41)) -> Parse Error: Readonly property Foo\Bar\Baz:$foo cannot have a default value on line 6 column 41 diff --git a/tests/0165/0166/code.php b/tests/0165/0166/code.php new file mode 100644 index 00000000..01f0d3c2 --- /dev/null +++ b/tests/0165/0166/code.php @@ -0,0 +1,7 @@ + Parse Error: Property Foo::$s cannot have type `void` on line 5 column 23 diff --git a/tests/0165/0166/tokens.txt b/tests/0165/0166/tokens.txt new file mode 100644 index 00000000..d57a33d5 --- /dev/null +++ b/tests/0165/0166/tokens.txt @@ -0,0 +1,124 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Function, + span: ( + 4, + 12, + ), + }, + Token { + kind: Identifier( + "__construct", + ), + span: ( + 4, + 21, + ), + }, + Token { + kind: LeftParen, + span: ( + 4, + 32, + ), + }, + Token { + kind: Public, + span: ( + 5, + 9, + ), + }, + Token { + kind: Identifier( + "void", + ), + span: ( + 5, + 16, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 5, + 21, + ), + }, + Token { + kind: Comma, + span: ( + 5, + 23, + ), + }, + Token { + kind: RightParen, + span: ( + 6, + 5, + ), + }, + Token { + kind: LeftBrace, + span: ( + 6, + 7, + ), + }, + Token { + kind: RightBrace, + span: ( + 6, + 8, + ), + }, + Token { + kind: RightBrace, + span: ( + 7, + 1, + ), + }, +] diff --git a/tests/0165/0167/code.php b/tests/0165/0167/code.php new file mode 100644 index 00000000..b9d53459 --- /dev/null +++ b/tests/0165/0167/code.php @@ -0,0 +1,7 @@ + Parse Error: Property Foo::$s cannot have type `never` on line 5 column 24 diff --git a/tests/0165/0167/tokens.txt b/tests/0165/0167/tokens.txt new file mode 100644 index 00000000..af824054 --- /dev/null +++ b/tests/0165/0167/tokens.txt @@ -0,0 +1,124 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Function, + span: ( + 4, + 12, + ), + }, + Token { + kind: Identifier( + "__construct", + ), + span: ( + 4, + 21, + ), + }, + Token { + kind: LeftParen, + span: ( + 4, + 32, + ), + }, + Token { + kind: Public, + span: ( + 5, + 9, + ), + }, + Token { + kind: Identifier( + "never", + ), + span: ( + 5, + 16, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 5, + 22, + ), + }, + Token { + kind: Comma, + span: ( + 5, + 24, + ), + }, + Token { + kind: RightParen, + span: ( + 6, + 5, + ), + }, + Token { + kind: LeftBrace, + span: ( + 6, + 7, + ), + }, + Token { + kind: RightBrace, + span: ( + 6, + 8, + ), + }, + Token { + kind: RightBrace, + span: ( + 7, + 1, + ), + }, +] diff --git a/tests/0165/0168/code.php b/tests/0165/0168/code.php new file mode 100644 index 00000000..e926c5ea --- /dev/null +++ b/tests/0165/0168/code.php @@ -0,0 +1,7 @@ + Parse Error: Property Foo::$s cannot have type `string|int|callable` on line 5 column 38 diff --git a/tests/0165/0168/tokens.txt b/tests/0165/0168/tokens.txt new file mode 100644 index 00000000..889cabed --- /dev/null +++ b/tests/0165/0168/tokens.txt @@ -0,0 +1,156 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Function, + span: ( + 4, + 12, + ), + }, + Token { + kind: Identifier( + "__construct", + ), + span: ( + 4, + 21, + ), + }, + Token { + kind: LeftParen, + span: ( + 4, + 32, + ), + }, + Token { + kind: Public, + span: ( + 5, + 9, + ), + }, + Token { + kind: Identifier( + "string", + ), + span: ( + 5, + 16, + ), + }, + Token { + kind: Pipe, + span: ( + 5, + 22, + ), + }, + Token { + kind: Identifier( + "int", + ), + span: ( + 5, + 23, + ), + }, + Token { + kind: Pipe, + span: ( + 5, + 26, + ), + }, + Token { + kind: Identifier( + "callable", + ), + span: ( + 5, + 27, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 5, + 36, + ), + }, + Token { + kind: Comma, + span: ( + 5, + 38, + ), + }, + Token { + kind: RightParen, + span: ( + 6, + 5, + ), + }, + Token { + kind: LeftBrace, + span: ( + 6, + 7, + ), + }, + Token { + kind: RightBrace, + span: ( + 6, + 8, + ), + }, + Token { + kind: RightBrace, + span: ( + 7, + 1, + ), + }, +] diff --git a/tests/0165/code.php b/tests/0165/code.php new file mode 100644 index 00000000..d6804c16 --- /dev/null +++ b/tests/0165/code.php @@ -0,0 +1,7 @@ + Parse Error: Property Foo::$s cannot have type `callable` on line 5 column 27 diff --git a/tests/0165/tokens.txt b/tests/0165/tokens.txt new file mode 100644 index 00000000..aea37dd8 --- /dev/null +++ b/tests/0165/tokens.txt @@ -0,0 +1,124 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Function, + span: ( + 4, + 12, + ), + }, + Token { + kind: Identifier( + "__construct", + ), + span: ( + 4, + 21, + ), + }, + Token { + kind: LeftParen, + span: ( + 4, + 32, + ), + }, + Token { + kind: Public, + span: ( + 5, + 9, + ), + }, + Token { + kind: Identifier( + "callable", + ), + span: ( + 5, + 16, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 5, + 25, + ), + }, + Token { + kind: Comma, + span: ( + 5, + 27, + ), + }, + Token { + kind: RightParen, + span: ( + 6, + 5, + ), + }, + Token { + kind: LeftBrace, + span: ( + 6, + 7, + ), + }, + Token { + kind: RightBrace, + span: ( + 6, + 8, + ), + }, + Token { + kind: RightBrace, + span: ( + 7, + 1, + ), + }, +] diff --git a/tests/0166/code.php b/tests/0166/code.php new file mode 100644 index 00000000..01f0d3c2 --- /dev/null +++ b/tests/0166/code.php @@ -0,0 +1,7 @@ + Parse Error: Property Foo::$s cannot have type `void` on line 5 column 23 diff --git a/tests/0166/tokens.txt b/tests/0166/tokens.txt new file mode 100644 index 00000000..d57a33d5 --- /dev/null +++ b/tests/0166/tokens.txt @@ -0,0 +1,124 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Function, + span: ( + 4, + 12, + ), + }, + Token { + kind: Identifier( + "__construct", + ), + span: ( + 4, + 21, + ), + }, + Token { + kind: LeftParen, + span: ( + 4, + 32, + ), + }, + Token { + kind: Public, + span: ( + 5, + 9, + ), + }, + Token { + kind: Identifier( + "void", + ), + span: ( + 5, + 16, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 5, + 21, + ), + }, + Token { + kind: Comma, + span: ( + 5, + 23, + ), + }, + Token { + kind: RightParen, + span: ( + 6, + 5, + ), + }, + Token { + kind: LeftBrace, + span: ( + 6, + 7, + ), + }, + Token { + kind: RightBrace, + span: ( + 6, + 8, + ), + }, + Token { + kind: RightBrace, + span: ( + 7, + 1, + ), + }, +] diff --git a/tests/0167/code.php b/tests/0167/code.php new file mode 100644 index 00000000..b9d53459 --- /dev/null +++ b/tests/0167/code.php @@ -0,0 +1,7 @@ + Parse Error: Property Foo::$s cannot have type `never` on line 5 column 24 diff --git a/tests/0167/tokens.txt b/tests/0167/tokens.txt new file mode 100644 index 00000000..af824054 --- /dev/null +++ b/tests/0167/tokens.txt @@ -0,0 +1,124 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Function, + span: ( + 4, + 12, + ), + }, + Token { + kind: Identifier( + "__construct", + ), + span: ( + 4, + 21, + ), + }, + Token { + kind: LeftParen, + span: ( + 4, + 32, + ), + }, + Token { + kind: Public, + span: ( + 5, + 9, + ), + }, + Token { + kind: Identifier( + "never", + ), + span: ( + 5, + 16, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 5, + 22, + ), + }, + Token { + kind: Comma, + span: ( + 5, + 24, + ), + }, + Token { + kind: RightParen, + span: ( + 6, + 5, + ), + }, + Token { + kind: LeftBrace, + span: ( + 6, + 7, + ), + }, + Token { + kind: RightBrace, + span: ( + 6, + 8, + ), + }, + Token { + kind: RightBrace, + span: ( + 7, + 1, + ), + }, +] diff --git a/tests/0168/code.php b/tests/0168/code.php new file mode 100644 index 00000000..e926c5ea --- /dev/null +++ b/tests/0168/code.php @@ -0,0 +1,7 @@ + Parse Error: Property Foo::$s cannot have type `string|int|callable` on line 5 column 38 diff --git a/tests/0168/tokens.txt b/tests/0168/tokens.txt new file mode 100644 index 00000000..889cabed --- /dev/null +++ b/tests/0168/tokens.txt @@ -0,0 +1,156 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Function, + span: ( + 4, + 12, + ), + }, + Token { + kind: Identifier( + "__construct", + ), + span: ( + 4, + 21, + ), + }, + Token { + kind: LeftParen, + span: ( + 4, + 32, + ), + }, + Token { + kind: Public, + span: ( + 5, + 9, + ), + }, + Token { + kind: Identifier( + "string", + ), + span: ( + 5, + 16, + ), + }, + Token { + kind: Pipe, + span: ( + 5, + 22, + ), + }, + Token { + kind: Identifier( + "int", + ), + span: ( + 5, + 23, + ), + }, + Token { + kind: Pipe, + span: ( + 5, + 26, + ), + }, + Token { + kind: Identifier( + "callable", + ), + span: ( + 5, + 27, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 5, + 36, + ), + }, + Token { + kind: Comma, + span: ( + 5, + 38, + ), + }, + Token { + kind: RightParen, + span: ( + 6, + 5, + ), + }, + Token { + kind: LeftBrace, + span: ( + 6, + 7, + ), + }, + Token { + kind: RightBrace, + span: ( + 6, + 8, + ), + }, + Token { + kind: RightBrace, + span: ( + 7, + 1, + ), + }, +] diff --git a/tests/0169/code.php b/tests/0169/code.php new file mode 100644 index 00000000..074db080 --- /dev/null +++ b/tests/0169/code.php @@ -0,0 +1,5 @@ + Parse Error: Property Foo::$s cannot have type `callable` on line 4 column 23 diff --git a/tests/0169/tokens.txt b/tests/0169/tokens.txt new file mode 100644 index 00000000..3e08aeb0 --- /dev/null +++ b/tests/0169/tokens.txt @@ -0,0 +1,73 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Identifier( + "callable", + ), + span: ( + 4, + 12, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 4, + 21, + ), + }, + Token { + kind: SemiColon, + span: ( + 4, + 23, + ), + }, + Token { + kind: RightBrace, + span: ( + 5, + 1, + ), + }, +] diff --git a/tests/0170/code.php b/tests/0170/code.php new file mode 100644 index 00000000..dec93cbe --- /dev/null +++ b/tests/0170/code.php @@ -0,0 +1,5 @@ + Parse Error: Property Foo::$s cannot have type `void` on line 4 column 19 diff --git a/tests/0170/tokens.txt b/tests/0170/tokens.txt new file mode 100644 index 00000000..9ed70d2c --- /dev/null +++ b/tests/0170/tokens.txt @@ -0,0 +1,73 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Identifier( + "void", + ), + span: ( + 4, + 12, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 4, + 17, + ), + }, + Token { + kind: SemiColon, + span: ( + 4, + 19, + ), + }, + Token { + kind: RightBrace, + span: ( + 5, + 1, + ), + }, +] diff --git a/tests/0171/code.php b/tests/0171/code.php new file mode 100644 index 00000000..110d7d43 --- /dev/null +++ b/tests/0171/code.php @@ -0,0 +1,5 @@ + Parse Error: Property Foo::$s cannot have type `string|int|callable` on line 4 column 34 diff --git a/tests/0171/tokens.txt b/tests/0171/tokens.txt new file mode 100644 index 00000000..f696c802 --- /dev/null +++ b/tests/0171/tokens.txt @@ -0,0 +1,105 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Identifier( + "string", + ), + span: ( + 4, + 12, + ), + }, + Token { + kind: Pipe, + span: ( + 4, + 18, + ), + }, + Token { + kind: Identifier( + "int", + ), + span: ( + 4, + 19, + ), + }, + Token { + kind: Pipe, + span: ( + 4, + 22, + ), + }, + Token { + kind: Identifier( + "callable", + ), + span: ( + 4, + 23, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 4, + 32, + ), + }, + Token { + kind: SemiColon, + span: ( + 4, + 34, + ), + }, + Token { + kind: RightBrace, + span: ( + 5, + 1, + ), + }, +] diff --git a/tests/0172/code.php b/tests/0172/code.php new file mode 100644 index 00000000..9ff2c7bb --- /dev/null +++ b/tests/0172/code.php @@ -0,0 +1,5 @@ + Parse Error: Property Foo::$s cannot have type `never` on line 4 column 20 diff --git a/tests/0172/tokens.txt b/tests/0172/tokens.txt new file mode 100644 index 00000000..ffc0ad49 --- /dev/null +++ b/tests/0172/tokens.txt @@ -0,0 +1,73 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Identifier( + "never", + ), + span: ( + 4, + 12, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 4, + 18, + ), + }, + Token { + kind: SemiColon, + span: ( + 4, + 20, + ), + }, + Token { + kind: RightBrace, + span: ( + 5, + 1, + ), + }, +] diff --git a/tests/0173/code.php b/tests/0173/code.php new file mode 100644 index 00000000..0d1b4833 --- /dev/null +++ b/tests/0173/code.php @@ -0,0 +1,5 @@ + Parse error: 'never' can only be used as a standalone type on line 4 column 19 diff --git a/tests/0173/tokens.txt b/tests/0173/tokens.txt new file mode 100644 index 00000000..73767ce0 --- /dev/null +++ b/tests/0173/tokens.txt @@ -0,0 +1,80 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "Foo", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 11, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Question, + span: ( + 4, + 12, + ), + }, + Token { + kind: Identifier( + "never", + ), + span: ( + 4, + 13, + ), + }, + Token { + kind: Variable( + "s", + ), + span: ( + 4, + 19, + ), + }, + Token { + kind: SemiColon, + span: ( + 4, + 21, + ), + }, + Token { + kind: RightBrace, + span: ( + 5, + 1, + ), + }, +]