diff --git a/src/parser/internal/definition/class.rs b/src/parser/internal/definition/class.rs index 3ccfee0..9f30cf7 100644 --- a/src/parser/internal/definition/class.rs +++ b/src/parser/internal/definition/class.rs @@ -59,14 +59,12 @@ pub fn class_definition(state: &mut State) -> ParseResult { None }; - let has_abstract = modifiers.has_abstract(); - let body = ClassDefinitionBody { left_brace: utils::skip_left_brace(state)?, members: { let mut members = Vec::new(); while state.iterator.current().kind != TokenKind::RightBrace { - members.push(class_definition_member(state, has_abstract, &name)?); + members.push(class_definition_member(state, &name)?); } members @@ -89,7 +87,6 @@ pub fn class_definition(state: &mut State) -> ParseResult { fn class_definition_member( state: &mut State, - has_abstract: bool, name: &Identifier, ) -> ParseResult { attribute::gather(state)?; @@ -113,26 +110,12 @@ fn class_definition_member( return match method { MethodDefinitionReference::Abstract(method) => { - if !has_abstract { - crate::parser_report!( - state, - cannot_declare_abstract_method_on_non_abstract_class(name, &method), - ); - } - Ok(ClassDefinitionMember::AbstractMethod(method)) } MethodDefinitionReference::Concrete(method) => { Ok(ClassDefinitionMember::ConcreteMethod(method)) } MethodDefinitionReference::AbstractConstructor(ctor) => { - if !has_abstract { - crate::parser_report!( - state, - cannot_declare_abstract_ctor_on_non_abstract_class(name, &ctor), - ); - } - Ok(ClassDefinitionMember::AbstractConstructor(ctor)) } MethodDefinitionReference::ConcreteConstructor(ctor) => { @@ -144,5 +127,5 @@ fn class_definition_member( // e.g: public static let modifiers = modifier::property_modifier_definition_group(state, modifiers)?; - property::property_definition(state, Some(name), modifiers).map(ClassDefinitionMember::Property) + property::property_definition(state, modifiers).map(ClassDefinitionMember::Property) } diff --git a/src/parser/internal/definition/modifier.rs b/src/parser/internal/definition/modifier.rs index ad26d7f..bc89cf5 100644 --- a/src/parser/internal/definition/modifier.rs +++ b/src/parser/internal/definition/modifier.rs @@ -51,13 +51,6 @@ pub fn class_modifier_definition_group( } } - if let (Some(abstract_modifier), Some(final_modifier)) = (&abstract_modifier, &final_modifier) { - crate::parser_report!( - state, - final_class_cannot_be_abstract(final_modifier, abstract_modifier) - ); - } - Ok(ClassModifierDefinitionGroup { modifiers }) } @@ -109,13 +102,6 @@ pub fn method_modifier_definition_group( } } - if let (Some(abstract_modifier), Some(final_modifier)) = (&abstract_modifier, &final_modifier) { - crate::parser_report!( - state, - final_class_member_cannot_be_abstract(final_modifier, abstract_modifier) - ); - } - Ok(MethodModifierDefinitionGroup { modifiers }) } diff --git a/src/parser/internal/definition/parameter.rs b/src/parser/internal/definition/parameter.rs index 855af27..a6b665c 100644 --- a/src/parser/internal/definition/parameter.rs +++ b/src/parser/internal/definition/parameter.rs @@ -38,13 +38,6 @@ pub fn function_like_parameter_list_definition( // 2. Then expect a variable. let variable = variable::parse(state)?; - if type_definition.is_bottom() { - crate::parser_report!( - state, - bottom_type_cannot_be_used_for_parameter(&type_definition, &variable) - ); - } - let current = state.iterator.current(); let default = if current.kind == TokenKind::Equals { state.iterator.next(); @@ -118,13 +111,6 @@ pub fn constructor_parameter_list_definition( (None, variable::parse(state)?) }; - if type_definition.is_bottom() { - crate::parser_report!( - state, - bottom_type_cannot_be_used_for_parameter(&type_definition, &variable) - ); - } - let current = state.iterator.current(); let default = if current.kind == TokenKind::Equals { state.iterator.next(); diff --git a/src/parser/internal/definition/property.rs b/src/parser/internal/definition/property.rs index c16173c..88c50f4 100644 --- a/src/parser/internal/definition/property.rs +++ b/src/parser/internal/definition/property.rs @@ -8,35 +8,19 @@ use crate::parser::state::State; use crate::tree::definition::modifier::PropertyModifierDefinitionGroup; use crate::tree::definition::property::PropertyDefinition; use crate::tree::definition::property::PropertyEntryDefinition; -use crate::tree::identifier::Identifier; pub fn property_definition( state: &mut State, - class_name: Option<&Identifier>, modifiers: PropertyModifierDefinitionGroup, ) -> ParseResult { let type_definition = r#type::type_definition(state)?; let variable = variable::parse(state)?; - if type_definition.is_bottom() { - crate::parser_report!( - state, - bottom_type_cannot_be_used_for_property(class_name, &type_definition, &variable) - ); - } - - if let (Some(readonly), Some(r#static)) = (modifiers.get_readonly(), modifiers.get_static()) { - crate::parser_report!( - state, - readonly_property_cannot_be_static(class_name, &variable, readonly, r#static) - ); - } - let attributes = state.get_attributes(); let current = state.iterator.current(); let entry = if current.kind == TokenKind::Equals { - let entry = PropertyEntryDefinition::Initialized { + PropertyEntryDefinition::Initialized { variable, equals: utils::skip(state, TokenKind::Equals)?, value: { @@ -55,16 +39,7 @@ pub fn property_definition( expression }, - }; - - if let Some(modifier) = modifiers.get_readonly() { - crate::parser_report!( - state, - readonly_property_cannot_have_default_value(class_name, &entry, modifier,) - ); } - - entry } else { PropertyEntryDefinition::Uninitialized { variable } }; diff --git a/src/parser/internal/definition/type.rs b/src/parser/internal/definition/type.rs index c08340d..3bbc52a 100644 --- a/src/parser/internal/definition/type.rs +++ b/src/parser/internal/definition/type.rs @@ -27,10 +27,10 @@ pub fn type_alias_definition(state: &mut State) -> ParseResult ParseResult { - atomic(state, false) + atomic(state) } -fn atomic(state: &mut State, within_ndf: bool) -> ParseResult { +fn atomic(state: &mut State) -> ParseResult { let current = state.iterator.current(); if current.kind == TokenKind::Question { return nullable(state); @@ -44,13 +44,13 @@ fn atomic(state: &mut State, within_ndf: bool) -> ParseResult { let current = state.iterator.current(); if current.kind == TokenKind::Pipe { - return union(state, type_definition, within_ndf); + return union(state, type_definition); } if current.kind == TokenKind::Ampersand && !matches!(state.iterator.lookahead(1).kind, TokenKind::Ampersand) { - return intersection(state, type_definition, within_ndf); + return intersection(state, type_definition); } Ok(type_definition) @@ -69,7 +69,7 @@ fn parenthesized(state: &mut State) -> ParseResult { }); } - let initial_type_definition = atomic(state, true)?; + let initial_type_definition = atomic(state)?; let current = state.iterator.current(); match current.kind { TokenKind::Comma | TokenKind::RightParen => { @@ -248,16 +248,12 @@ fn nullable(state: &mut State) -> ParseResult { state.iterator.next(); - let ty = single(state)?; + let type_definition = single(state)?; - if ty.is_standalone() { - crate::parser_report!( - state, - standalone_type_cannot_be_nullable(&ty, current.position) - ); - } - - Ok(TypeDefinition::Nullable(current.position, Box::new(ty))) + Ok(TypeDefinition::Nullable( + current.position, + Box::new(type_definition), + )) } fn tuple( @@ -284,17 +280,6 @@ fn tuple( }); } - if initial_type_definition.is_bottom() { - crate::parser_report!( - state, - bottom_type_cannot_be_used_in_tuple( - &initial_type_definition, - left_parenthesis, - right_parenthesis - ) - ); - } - return Ok(TypeDefinition::Tuple { left_parenthesis, type_definitions: CommaSeparated { @@ -327,19 +312,6 @@ fn tuple( let right_parenthesis = utils::skip_right_parenthesis(state)?; - for type_definition in type_definitions.inner.iter_mut() { - if type_definition.is_bottom() { - crate::parser_report!( - state, - bottom_type_cannot_be_used_in_tuple( - type_definition, - left_parenthesis, - right_parenthesis - ) - ); - } - } - Ok(TypeDefinition::Tuple { left_parenthesis, type_definitions, @@ -347,19 +319,8 @@ fn tuple( }) } -fn union( - state: &mut State, - type_definition: TypeDefinition, - within_dnf: bool, -) -> ParseResult { - let mut last_pipe = utils::skip(state, TokenKind::Pipe)?; - - if type_definition.is_standalone() { - crate::parser_report!( - state, - standalone_type_cannot_be_used_in_union(&type_definition, last_pipe) - ); - } +fn union(state: &mut State, type_definition: TypeDefinition) -> ParseResult { + utils::skip(state, TokenKind::Pipe)?; let mut type_definitions = vec![type_definition]; @@ -368,43 +329,25 @@ fn union( let type_definition = if current.kind == TokenKind::LeftParen { let left_parenthesis = current.position; state.iterator.next(); - let other = atomic(state, true)?; + let other = atomic(state)?; if let TypeDefinition::Intersection(_) = other { - let type_definition = TypeDefinition::Parenthesized { + TypeDefinition::Parenthesized { left_parenthesis, type_definition: Box::new(other), right_parenthesis: utils::skip_right_parenthesis(state)?, - }; - - if within_dnf { - // don't allow nesting. - crate::parser_report!( - state, - disjunctive_normal_form_types_cannot_be_nested(&type_definition) - ); } - - type_definition } else { tuple(state, left_parenthesis, other)? } } else { - let type_definition = single(state)?; - if type_definition.is_standalone() { - crate::parser_report!( - state, - standalone_type_cannot_be_used_in_union(&type_definition, last_pipe) - ); - } - - type_definition + single(state)? }; type_definitions.push(type_definition); if state.iterator.current().kind == TokenKind::Pipe { - last_pipe = utils::skip(state, TokenKind::Pipe)?; + utils::skip(state, TokenKind::Pipe)?; } else { break; } @@ -413,33 +356,8 @@ fn union( Ok(TypeDefinition::Union(type_definitions)) } -fn intersection( - state: &mut State, - type_definition: TypeDefinition, - within_dnf: bool, -) -> ParseResult { - let mut last_ampersand = utils::skip(state, TokenKind::Ampersand)?; - - if type_definition.is_standalone() { - crate::parser_report!( - state, - standalone_type_cannot_be_used_in_intersection(&type_definition, last_ampersand) - ); - } - - if type_definition.is_scalar() { - crate::parser_report!( - state, - scalar_type_cannot_be_used_in_intersection(&type_definition, last_ampersand) - ); - } - - if type_definition.is_literal() { - crate::parser_report!( - state, - literal_type_cannot_be_used_in_intersection(&type_definition, last_ampersand) - ); - } +fn intersection(state: &mut State, type_definition: TypeDefinition) -> ParseResult { + utils::skip(state, TokenKind::Ampersand)?; let mut type_definitions = vec![type_definition]; @@ -448,54 +366,19 @@ fn intersection( let type_definition = if current.kind == TokenKind::LeftParen { let left_parenthesis = current.position; state.iterator.next(); - let other = atomic(state, true)?; + let other = atomic(state)?; if let TypeDefinition::Union(_) = other { - let type_definition = TypeDefinition::Parenthesized { + TypeDefinition::Parenthesized { left_parenthesis, type_definition: Box::new(other), right_parenthesis: utils::skip_right_parenthesis(state)?, - }; - - if within_dnf { - // don't allow nesting. - crate::parser_report!( - state, - disjunctive_normal_form_types_cannot_be_nested(&type_definition) - ); } - - type_definition } else { tuple(state, left_parenthesis, other)? } } else { - let type_definition = single(state)?; - if type_definition.is_standalone() { - crate::parser_report!( - state, - standalone_type_cannot_be_used_in_intersection( - &type_definition, - last_ampersand, - ) - ); - } - - if type_definition.is_scalar() { - crate::parser_report!( - state, - scalar_type_cannot_be_used_in_intersection(&type_definition, last_ampersand) - ); - } - - if type_definition.is_literal() { - crate::parser_report!( - state, - literal_type_cannot_be_used_in_intersection(&type_definition, last_ampersand) - ); - } - - type_definition + single(state)? }; type_definitions.push(type_definition); @@ -503,7 +386,7 @@ fn intersection( if state.iterator.current().kind == TokenKind::Ampersand && !matches!(state.iterator.lookahead(1).kind, TokenKind::Ampersand) { - last_ampersand = utils::skip(state, TokenKind::Ampersand)?; + utils::skip(state, TokenKind::Ampersand)?; } else { break; } diff --git a/src/parser/internal/expression/class.rs b/src/parser/internal/expression/class.rs index 4792af0..8f371a5 100644 --- a/src/parser/internal/expression/class.rs +++ b/src/parser/internal/expression/class.rs @@ -120,6 +120,5 @@ fn anonymous_class_expression_member( // e.g: public static let modifiers = modifier::property_modifier_definition_group(state, modifiers)?; - property::property_definition(state, None, modifiers) - .map(AnonymousClassExpressionMember::Property) + property::property_definition(state, modifiers).map(AnonymousClassExpressionMember::Property) } diff --git a/src/parser/issue.rs b/src/parser/issue.rs index d609892..bc51b74 100644 --- a/src/parser/issue.rs +++ b/src/parser/issue.rs @@ -6,18 +6,12 @@ use ara_reporting::issue::Issue; use crate::lexer::token::Token; use crate::lexer::token::TokenKind; use crate::parser::state::State as ParserState; -use crate::tree::definition::function::AbstractConstructorDefinition; -use crate::tree::definition::function::AbstractMethodDefinition; use crate::tree::definition::function::ConcreteConstructorDefinition; use crate::tree::definition::function::ConcreteMethodDefinition; use crate::tree::definition::function::ConstructorParameterDefinition; -use crate::tree::definition::modifier::PropertyModifierDefinition; -use crate::tree::definition::property::PropertyEntryDefinition; -use crate::tree::definition::r#type::TypeDefinition; use crate::tree::expression::Expression; use crate::tree::identifier::Identifier; use crate::tree::statement::r#try::TryStatement; -use crate::tree::variable::Variable; use crate::tree::Node; #[derive(Debug, Copy, Clone)] @@ -161,147 +155,7 @@ pub enum ParserIssueCode { /// - Remove one of the modifiers DuplicateModifier = 9, - /// Bottom type cannot be used for parameter ( code = 10 ) - /// - /// Example: - /// - /// ```ara - /// function foo(never $bar): void {} - /// ``` - /// - /// Possible solution(s): - /// - /// - Use a different type - BottomTypeCannotBeUsedForParameter = 10, - - /// Bottom type cannot be used for property ( code = 11 ) - /// - /// Example: - /// - /// ```ara - /// class Foo { - /// public never $bar; - /// } - /// ``` - /// - /// Possible solution(s): - /// - /// - Use a different type - BottomTypeCannotBeUsedForProperty = 11, - - /// Standalone type cannot be used in union ( code = 12 ) - /// - /// Example: - /// - /// ```ara - /// function foo(int|void $bar): void {} - /// ``` - /// - /// Possible solution(s): - /// - /// - Use a different type - StandaloneTypeCannotBeUsedInUnion = 12, - - /// Standalone type cannot be used in intersection ( code = 13 ) - /// - /// Example: - /// - /// ```ara - /// function foo(int&void $bar): void {} - /// ``` - /// - /// Possible solution(s): - /// - /// - Use a different type - StandaloneTypeCannotBeUsedInIntersection = 13, - - /// Standalone type cannot be nullable ( code = 14 ) - /// - /// Example: - /// - /// ```ara - /// function foo(?mixed $bar): void {} - /// ``` - /// - /// Possible solution(s): - /// - /// - Use a different type - /// - Remove the `?` - StandaloneTypeCannotBeNullable = 14, - - /// Scalar type cannot be used in intersection ( code = 15 ) - /// - /// Example: - /// - /// ```ara - /// function foo(int&string $bar): void {} - /// ``` - /// - /// Possible solution(s): - /// - /// - Use a different type - /// - Change the intersection to a union - ScalarTypeCannotBeUsedInIntersection = 15, - - /// Readonly property cannot be static ( code = 17 ) - /// - /// Example: - /// - /// ```ara - /// class Foo { - /// public readonly static int $bar; - /// } - /// ``` - /// - /// Possible solution(s): - /// - /// - Remove the `static` modifier - /// - Remove the `readonly` modifier - ReadonlyPropertyCannotBeStatic = 17, - - /// Readonly property cannot have a default value ( code = 18 ) - /// - /// Example: - /// - /// ```ara - /// class Foo { - /// public readonly int $bar = 1; - /// } - /// ``` - /// - /// Possible solution(s): - /// - /// - Remove the default value - /// - Remove the `readonly` modifier - ReadonlyPropertyCannotHaveDefaultValue = 18, - - /// Bottom type cannot be used in tuple type parameter ( code = 19 ) - /// - /// Example: - /// - /// ```ara - /// type Foo = (void, string); - /// ``` - /// - /// Possible solution(s): - /// - /// - Use a different type - BottomTypeCannotBeUsedInTuple = 19, - - /// Disjunctive normal form types cannot be nested ( code = 20 ) - /// - /// Example: - /// - /// ```ara - /// type Foo = (A&(B|C))|(D&E); - /// ``` - /// - /// Possible solution(s): - /// - /// - Refactor the type to not be nested, e.g. `(A&B)|(A&C)|(D&E)` - DisjunctiveNormalFormTypesCannotBeNested = 20, - - /// Reserved keyword cannot be used for type name ( code = 21 ) + /// Reserved keyword cannot be used for type name ( code = 10 ) /// /// Example: /// @@ -312,9 +166,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Use a different name - ReservedKeywordCannotBeUsedForTypeName = 21, + ReservedKeywordCannotBeUsedForTypeName = 10, - /// Reserved keyword cannot be used for constant name ( code = 22 ) + /// Reserved keyword cannot be used for constant name ( code = 11 ) /// /// Example: /// @@ -325,9 +179,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Use a different name - ReservedKeywordCannotBeUsedForConstantName = 22, + ReservedKeywordCannotBeUsedForConstantName = 11, - /// Type cannot be used in current context ( code = 23 ) + /// Type cannot be used in current context ( code = 12 ) /// /// Example: /// @@ -338,9 +192,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Use a different type - TypeCannotBeUsedInCurrentContext = 23, + TypeCannotBeUsedInCurrentContext = 12, - /// Missing item expression after attribute(s) ( code = 24 ) + /// Missing item expression after attribute(s) ( code = 13 ) /// /// Example: /// @@ -354,39 +208,9 @@ pub enum ParserIssueCode { /// /// - Add an item expression after the attribute(s) /// - Remove the attribute(s) - MissingItemExpressionAfterAttributes = 24, - - /// Final class cannot be abstract ( code = 25 ) - /// - /// Example: - /// - /// ```ara - /// final abstract class Foo {} - /// ``` - /// - /// Possible solution(s): - /// - /// - Remove the `abstract` modifier - /// - Remove the `final` modifier - FinalClassCannotBeAbstract = 25, - - /// Final class member cannot be abstract ( code = 26 ) - /// - /// Example: - /// - /// ```ara - /// class Foo { - /// final abstract public function bar(): void {} - /// } - /// ``` - /// - /// Possible solution(s): - /// - /// - Remove the `abstract` modifier - /// - Remove the `final` modifier - FinalClassMemberCannotBeAbstract = 26, + MissingItemExpressionAfterAttributes = 13, - /// Private constant cannot be final ( code = 27 ) + /// Private constant cannot be final ( code = 14 ) /// /// Example: /// @@ -400,9 +224,9 @@ pub enum ParserIssueCode { /// /// - Remove the `final` modifier /// - Remove the `private` modifier - PrivateConstantCannotBeFinal = 27, + PrivateConstantCannotBeFinal = 14, - /// Modifier cannot be used on classes ( code = 28 ) + /// Modifier cannot be used on classes ( code = 15 ) /// /// Example: /// @@ -413,9 +237,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Remove the modifier - ModifierCannotBeUsedOnClass = 28, + ModifierCannotBeUsedOnClass = 15, - /// Modifier cannot be used on class methods ( code = 29 ) + /// Modifier cannot be used on class methods ( code = 16 ) /// /// Example: /// @@ -428,9 +252,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Remove the modifier - ModifierCannotBeUsedOnClassMethod = 29, + ModifierCannotBeUsedOnClassMethod = 16, - /// Modifier cannot be used on interface methods ( code = 30 ) + /// Modifier cannot be used on interface methods ( code = 17 ) /// /// Example: /// @@ -443,9 +267,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Remove the modifier - ModifierCannotBeUsedOnInterfaceMethod = 30, + ModifierCannotBeUsedOnInterfaceMethod = 17, - /// Modifier cannot be used on enum methods ( code = 31 ) + /// Modifier cannot be used on enum methods ( code = 18 ) /// /// Example: /// @@ -458,9 +282,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Remove the modifier - ModifierCannotBeUsedOnEnumMethod = 31, + ModifierCannotBeUsedOnEnumMethod = 18, - /// Modifier cannot be used on properties ( code = 32 ) + /// Modifier cannot be used on properties ( code = 19 ) /// /// Example: /// @@ -474,9 +298,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Remove the modifier - ModifierCannotBeUsedOnProperty = 32, + ModifierCannotBeUsedOnProperty = 19, - /// Modifier cannot be used on promoted properties ( code = 33 ) + /// Modifier cannot be used on promoted properties ( code = 20 ) /// /// Example: /// @@ -491,9 +315,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Remove the modifier - ModifierCannotBeUsedOnPromotedProperty = 33, + ModifierCannotBeUsedOnPromotedProperty = 20, - /// Modifier cannot be used on constants ( code = 34 ) + /// Modifier cannot be used on constants ( code = 21 ) /// /// Example: /// @@ -506,9 +330,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Remove the modifier - ModifierCannotBeUsedOnConstant = 34, + ModifierCannotBeUsedOnConstant = 21, - /// Modifier cannot be used on interface constants ( code = 35 ) + /// Modifier cannot be used on interface constants ( code = 22 ) /// /// Example: /// @@ -521,9 +345,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Remove the modifier - ModifierCannotBeUsedOnInterfaceConstant = 35, + ModifierCannotBeUsedOnInterfaceConstant = 22, - /// Match expression cannot have multiple default arms ( code = 36 ) + /// Match expression cannot have multiple default arms ( code = 23 ) /// /// Example: /// @@ -540,9 +364,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Remove one of the default arms - MatchExpressionCannotHaveMultipleDefaultArms = 36, + MatchExpressionCannotHaveMultipleDefaultArms = 23, - /// Promoted property cannot be variadic ( code = 37 ) + /// Promoted property cannot be variadic ( code = 24 ) /// /// Example: /// @@ -558,9 +382,9 @@ pub enum ParserIssueCode { /// /// - Remove the variadic declaration ( `...` ) /// - Demote the property - PromotedPropertyCannotBeVariadic = 37, + PromotedPropertyCannotBeVariadic = 24, - /// Enum backing type must be either `int` or `string` ( code = 38 ) + /// Enum backing type must be either `int` or `string` ( code = 25 ) /// /// Example: /// @@ -573,9 +397,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Change the backing type to `int` or `string` - InvalidEnumBackingType = 38, + InvalidEnumBackingType = 25, - /// Catch block must have a catch or finally block ( code = 39 ) + /// Catch block must have a catch or finally block ( code = 26 ) /// /// Example: /// @@ -591,25 +415,9 @@ pub enum ParserIssueCode { /// /// - Add a catch or finally block /// - Remove the try block - TryStatementMustHaveCatchOrFinally = 39, + TryStatementMustHaveCatchOrFinally = 26, - /// Abstract method cannot be declared on a non-abstract class ( code = 40 ) - /// - /// Example: - /// - /// ```ara - /// class Foo { - /// abstract function bar(): void; - /// } - /// ``` - /// - /// Possible solution(s): - /// - /// - Remove the `abstract` modifier - /// - Make the class abstract - CannotDeclareAbstractMethodOnNonAbstractClass = 40, - - /// Unexpected empty statement ( code = 41 ) + /// Unexpected empty statement ( code = 27 ) /// /// Example: /// @@ -622,7 +430,7 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Remove the empty statement ( `;` ) - UnexpectedEmptyStatement = 41, + UnexpectedEmptyStatement = 27, /// Unexpected token /// @@ -632,9 +440,9 @@ pub enum ParserIssueCode { /// function foo() -> void { /// } /// ``` - UnexpectedToken = 42, + UnexpectedToken = 28, - /// Invalid constant expression ( code = 43 ) + /// Invalid constant expression ( code = 29 ) /// /// Example: /// @@ -645,9 +453,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Use a valid constant expression - InvalidConstantExpression = 43, + InvalidConstantExpression = 29, - /// Invalid constant initialization expression ( code = 44 ) + /// Invalid constant initialization expression ( code = 30 ) /// /// Example: /// @@ -662,9 +470,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Use a valid constant initialization expression - InvalidConstantInitializationExpression = 44, + InvalidConstantInitializationExpression = 30, - /// Invalid constant initialization expression ( code = 45 ) + /// Invalid constant initialization expression ( code = 31 ) /// /// Example: /// @@ -675,9 +483,9 @@ pub enum ParserIssueCode { /// Possible solution(s): /// /// - Remove the class instantiation expression(s) - InvalidInitializationInConstantExpression = 45, + InvalidInitializationInConstantExpression = 31, - /// Invalid empty type template ( code = 46 ) + /// Invalid empty type template ( code = 32 ) /// /// Example: /// @@ -689,21 +497,7 @@ pub enum ParserIssueCode { /// /// - Remove the empty type template /// - Add a type template - ExpectedAtLeastOneTypeInTemplateGroup = 46, - - /// Literal type cannot be used in intersection ( code = 47 ) - /// - /// Example: - /// - /// ```ara - /// function foo(Foo&null $bar): void {} - /// ``` - /// - /// Possible solution(s): - /// - /// - Use a different type (instead of `null`) - /// - Change the intersection to a union - LiteralTypeCannotBeUsedInIntersection = 47, + ExpectedAtLeastOneTypeInTemplateGroup = 32, } pub(crate) fn unreachable_code>(state: &ParserState, message: M) -> Issue { @@ -899,329 +693,6 @@ pub(crate) fn duplicate_modifier( .with_annotation(Annotation::primary(origin, first, first + modifier.len())) } -pub(crate) fn bottom_type_cannot_be_used_for_parameter( - state: &ParserState, - type_definition: &TypeDefinition, - parameter: &Variable, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::BottomTypeCannotBeUsedForParameter, - format!( - "bottom type `{}` cannot be used for parameter `{}`", - &type_definition, ¶meter, - ), - ) - .with_source( - origin, - type_definition.initial_position(), - type_definition.final_position(), - ) - .with_annotation(Annotation::secondary( - origin, - parameter.initial_position(), - parameter.final_position(), - )) - .with_note("bottom types are types that have no values, such as `never` and `void`.") -} - -pub(crate) fn bottom_type_cannot_be_used_for_property( - state: &ParserState, - class_name: Option<&Identifier>, - type_definition: &TypeDefinition, - property: &Variable, -) -> Issue { - let origin = state.source.name(); - - let mut issue = Issue::error( - ParserIssueCode::BottomTypeCannotBeUsedForProperty, - format!( - "bottom type `{}` cannot be used for property `{}::{}`", - &type_definition, - class_name - .map(|c| state.named(c)) - .unwrap_or_else(|| "anonymous@class".to_string()), - &property, - ), - ) - .with_source( - origin, - type_definition.initial_position(), - type_definition.final_position(), - ) - .with_annotation(Annotation::secondary( - origin, - property.initial_position(), - property.final_position(), - )) - .with_note("bottom types are types that have no values, such as `never` and `void`."); - - if let Some(class_name) = class_name { - issue = issue.with_annotation(Annotation::secondary( - origin, - class_name.initial_position(), - class_name.final_position(), - )); - } - - issue -} - -pub(crate) fn standalone_type_cannot_be_used_in_union( - state: &ParserState, - type_definition: &TypeDefinition, - pipe: usize, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::StandaloneTypeCannotBeUsedInUnion, - format!( - "standalone type `{}` cannot be used in a union", - &type_definition, - ), - ).with_source( - origin, - type_definition.initial_position(), - type_definition.final_position(), - ) - .with_annotation(Annotation::secondary(origin, pipe, pipe + 1)) - .with_note("a standalone type is either `mixed`, `void`, `never`, `resource`, `nonnull` or a nullable type.") -} - -pub(crate) fn standalone_type_cannot_be_used_in_intersection( - state: &ParserState, - type_definition: &TypeDefinition, - ampersand: usize, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::StandaloneTypeCannotBeUsedInIntersection, - format!( - "standalone type `{}` cannot be used in an intersection", - &type_definition, - ), - ).with_source( - origin, - type_definition.initial_position(), - type_definition.final_position(), - ) - .with_annotation(Annotation::secondary( - origin, - ampersand, - ampersand + 1, - )) - .with_note("a standalone type is either `mixed`, `void`, `never`, `resource`, `nonnull` or a nullable type.") -} - -pub(crate) fn standalone_type_cannot_be_nullable( - state: &ParserState, - type_definition: &TypeDefinition, - question_mark: usize, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::StandaloneTypeCannotBeNullable, - format!("standalone type `{}` cannot be nullable", &type_definition,), - ).with_source( - origin, - type_definition.initial_position(), - type_definition.final_position(), - ) - .with_annotation(Annotation::secondary( - origin, - question_mark, - question_mark + 1, - )) - .with_note("a standalone type is either `mixed`, `void`, `never`, `resource`, `nonnull` or a nullable type.") -} - -pub(crate) fn scalar_type_cannot_be_used_in_intersection( - state: &ParserState, - type_definition: &TypeDefinition, - ampersand: usize, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::ScalarTypeCannotBeUsedInIntersection, - format!( - "scalar type `{}` cannot be used in an intersection", - &type_definition, - ), - ) - .with_source( - origin, - type_definition.initial_position(), - type_definition.final_position(), - ) - .with_annotation(Annotation::secondary(origin, ampersand, ampersand + 1)) - .with_note("a scalar type is either `int`, `float`, `string`, or `bool`.") -} - -pub(crate) fn literal_type_cannot_be_used_in_intersection( - state: &ParserState, - type_definition: &TypeDefinition, - ampersand: usize, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::LiteralTypeCannotBeUsedInIntersection, - format!( - "literal type `{}` cannot be used in an intersection", - &type_definition, - ), - ).with_source( - origin, - type_definition.initial_position(), - type_definition.final_position(), - ) - .with_annotation(Annotation::secondary(origin, ampersand, ampersand + 1)) - .with_note("a literal type is either a literal integer, a literal float, a literal string, `false`, `true`, or `null`.") -} - -pub(crate) fn readonly_property_cannot_be_static( - state: &ParserState, - class_name: Option<&Identifier>, - property: &Variable, - readonly: &PropertyModifierDefinition, - r#static: &PropertyModifierDefinition, -) -> Issue { - let origin = state.source.name(); - - let mut issue = Issue::error( - ParserIssueCode::ReadonlyPropertyCannotBeStatic, - format!( - "readonly property `{}::{}` cannot be static", - class_name - .map(|c| state.named(c)) - .unwrap_or_else(|| "anonymous@class".to_string()), - &property, - ), - ) - .with_source( - origin, - r#static.initial_position(), - r#static.final_position(), - ) - .with_annotation(Annotation::primary( - origin, - readonly.initial_position(), - readonly.final_position(), - )) - .with_annotation(Annotation::secondary( - origin, - property.initial_position(), - property.final_position(), - )) - .with_note("a property cannot be both readonly and static."); - - if let Some(class_name) = class_name { - issue = issue.with_annotation(Annotation::secondary( - origin, - class_name.initial_position(), - class_name.final_position(), - )); - } - - issue -} - -pub(crate) fn readonly_property_cannot_have_default_value( - state: &ParserState, - class_name: Option<&Identifier>, - entry: &PropertyEntryDefinition, - readonly: &PropertyModifierDefinition, -) -> Issue { - let origin = state.source.name(); - - let mut issue = Issue::error( - ParserIssueCode::ReadonlyPropertyCannotHaveDefaultValue, - format!( - "readonly property `{}::{}` cannot have a default value", - class_name - .map(|c| state.named(c)) - .unwrap_or_else(|| "anonymous@class".to_string()), - &entry.variable(), - ), - ) - .with_source( - origin, - entry.initial_position(), - entry.final_position(), - ) - .with_annotation(Annotation::primary( - origin, - readonly.initial_position(), - readonly.final_position(), - )) - .with_note( - "a readonly property cannot have a default value because it cannot be changed after initialization.", - ); - - if let Some(class_name) = class_name { - issue = issue.with_annotation(Annotation::secondary( - origin, - class_name.initial_position(), - class_name.final_position(), - )); - } - - issue -} - -pub(crate) fn bottom_type_cannot_be_used_in_tuple( - state: &ParserState, - type_definition: &TypeDefinition, - left_parenthesis: usize, - right_parenthesis: usize, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::BottomTypeCannotBeUsedInTuple, - format!( - "bottom type `{}` cannot be used in a tuple type", - &type_definition, - ), - ) - .with_source( - origin, - type_definition.initial_position(), - type_definition.final_position(), - ) - .with_annotation(Annotation::secondary( - origin, - left_parenthesis, - right_parenthesis + 1, - )) - .with_note("bottom types are types that have no values, such as `never` and `void`.") -} - -pub(crate) fn disjunctive_normal_form_types_cannot_be_nested( - state: &ParserState, - type_definition: &TypeDefinition, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::DisjunctiveNormalFormTypesCannotBeNested, - "cannot nest disjunctive normal form types", - ) - .with_source( - origin, - type_definition.initial_position(), - type_definition.final_position(), - ) - .with_note( - "disjunctive normal form types are types that are separated by `|`, or `&` and are enclosed in `(` and `)`.", - ) -} - pub(crate) fn reserved_keyword_cannot_be_used_for_type_name( state: &ParserState, identifier: &Identifier, @@ -1303,56 +774,6 @@ pub(crate) fn missing_item_expression_after_attributes(state: &ParserState) -> I issue } -pub(crate) fn final_class_cannot_be_abstract( - state: &ParserState, - r#final: &dyn Node, - r#abstract: &dyn Node, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::FinalClassCannotBeAbstract, - "final class cannot be abstract", - ) - .with_source( - origin, - r#abstract.initial_position(), - r#abstract.final_position(), - ) - .with_annotation(Annotation::primary( - origin, - r#final.initial_position(), - r#final.final_position(), - )) - .with_note("a final class cannot be abstract because it cannot be extended by other classes.") -} - -pub(crate) fn final_class_member_cannot_be_abstract( - state: &ParserState, - r#final: &dyn Node, - r#abstract: &dyn Node, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::FinalClassMemberCannotBeAbstract, - "final class member cannot be abstract", - ) - .with_source( - origin, - r#abstract.initial_position(), - r#abstract.final_position(), - ) - .with_annotation(Annotation::primary( - origin, - r#final.initial_position(), - r#final.final_position(), - )) - .with_note( - "a final class member cannot be abstract because it cannot be overridden by other classes.", - ) -} - pub(crate) fn private_constant_cannot_be_final( state: &ParserState, r#private: &dyn Node, @@ -1601,53 +1022,6 @@ pub(crate) fn try_statement_must_have_catch_or_finally( ) } -pub(crate) fn cannot_declare_abstract_method_on_non_abstract_class( - state: &ParserState, - class_name: &Identifier, - method: &AbstractMethodDefinition, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::CannotDeclareAbstractMethodOnNonAbstractClass, - format!( - "cannot declare abstract method `{}::{}` on a non-abstract class", - state.named(class_name), - method.name - ), - ) - .with_source(origin, method.initial_position(), method.final_position()) - .with_annotation(Annotation::secondary( - origin, - class_name.initial_position(), - class_name.final_position(), - )) - .with_note("abstract methods can only be declared on abstract classes.") -} - -pub(crate) fn cannot_declare_abstract_ctor_on_non_abstract_class( - state: &ParserState, - class_name: &Identifier, - method: &AbstractConstructorDefinition, -) -> Issue { - let origin = state.source.name(); - - Issue::error( - ParserIssueCode::CannotDeclareAbstractMethodOnNonAbstractClass, - format!( - "cannot declare abstract constructor on non-abstract class `{}`", - state.named(class_name), - ), - ) - .with_source(origin, method.initial_position(), method.final_position()) - .with_annotation(Annotation::secondary( - origin, - class_name.initial_position(), - class_name.final_position(), - )) - .with_note("abstract methods can only be declared on abstract classes.") -} - pub(crate) fn unexpected_empty_statement(state: &ParserState, current: &Token) -> Issue { Issue::error( ParserIssueCode::UnexpectedEmptyStatement, diff --git a/tests/samples/0003/error.txt b/tests/samples/0003/error.txt index 455d89b..25b4516 100644 --- a/tests/samples/0003/error.txt +++ b/tests/samples/0003/error.txt @@ -1,4 +1,4 @@ -error[P0042]: unexpected token `[`, expected an expression +error[P0028]: unexpected token `[`, expected an expression --> 0003/code.ara:5:10 | 5 | $a = [ diff --git a/tests/samples/0023/error.txt b/tests/samples/0023/error.txt index 225484e..7df70dd 100644 --- a/tests/samples/0023/error.txt +++ b/tests/samples/0023/error.txt @@ -1,4 +1,4 @@ -error[P0042]: unexpected token `implements`, expected `(` +error[P0028]: unexpected token `implements`, expected `(` --> 0023/code.ara:3:22 | 3 | return new class implements Foo, Bar {}; diff --git a/tests/samples/0065/error.txt b/tests/samples/0065/error.txt index 65b47a2..73cbd92 100644 --- a/tests/samples/0065/error.txt +++ b/tests/samples/0065/error.txt @@ -1,4 +1,4 @@ -error[P0042]: unexpected token `[`, expected an expression +error[P0028]: unexpected token `[`, expected an expression --> 0065/code.ara:2:10 | 2 | $a = [1, 2, 3]; diff --git a/tests/samples/0067/error.txt b/tests/samples/0067/error.txt index 91aac36..dbfb214 100644 --- a/tests/samples/0067/error.txt +++ b/tests/samples/0067/error.txt @@ -1,4 +1,4 @@ -error[P0042]: unexpected token `[`, expected an expression +error[P0028]: unexpected token `[`, expected an expression --> 0067/code.ara:2:10 | 2 | $a = []; diff --git a/tests/samples/0068/error.txt b/tests/samples/0068/error.txt index b84b66a..8ef877e 100644 --- a/tests/samples/0068/error.txt +++ b/tests/samples/0068/error.txt @@ -1,4 +1,4 @@ -error[P0042]: unexpected token `[`, expected an expression +error[P0028]: unexpected token `[`, expected an expression --> 0068/code.ara:2:10 | 2 | $a = []; diff --git a/tests/samples/0083/error.txt b/tests/samples/0083/error.txt index 35fb687..b2be783 100644 --- a/tests/samples/0083/error.txt +++ b/tests/samples/0083/error.txt @@ -40,7 +40,7 @@ error[P0006]: enum `Bar` cannot have magic method 14 | | } | \-----^ -error[P0042]: unexpected token `?>`, expected a definition +error[P0028]: unexpected token `?>`, expected a definition --> 0083/code.ara:17:1 | 17 | ?> diff --git a/tests/samples/0086/error.txt b/tests/samples/0086/error.txt index 805e93d..c7e79a5 100644 --- a/tests/samples/0086/error.txt +++ b/tests/samples/0086/error.txt @@ -1,4 +1,4 @@ -error[P0045]: invalid initialization in constant expression +error[P0031]: invalid initialization in constant expression --> 0086/code.ara:1:13 | 1 | const FOO = new Foo(); @@ -6,7 +6,7 @@ error[P0045]: invalid initialization in constant expression | = constant expressions cannot contain `new` expressions. -error[P0043]: invalid constant expression +error[P0029]: invalid constant expression --> 0086/code.ara:3:13 | 3 | const BAR = function(): Bar { @@ -15,49 +15,49 @@ error[P0043]: invalid constant expression 5 | | }; | \-^ -error[P0043]: invalid constant expression +error[P0029]: invalid constant expression --> 0086/code.ara:7:13 | 7 | const BAZ = fn(): Baz => new Baz(); | ^^^^^^^^^^^^^^^^^^^^^^ -error[P0044]: invalid constant initialization expression +error[P0030]: invalid constant initialization expression --> 0086/code.ara:9:7 | 9 | #[Foo(new Bar($bar), new Baz($baz), new Qux(function(): void {}))] | ^^^^^^^^^^^^^ -error[P0044]: invalid constant initialization expression +error[P0030]: invalid constant initialization expression --> 0086/code.ara:9:22 | 9 | #[Foo(new Bar($bar), new Baz($baz), new Qux(function(): void {}))] | ^^^^^^^^^^^^^ -error[P0044]: invalid constant initialization expression +error[P0030]: invalid constant initialization expression --> 0086/code.ara:9:37 | 9 | #[Foo(new Bar($bar), new Baz($baz), new Qux(function(): void {}))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[P0044]: invalid constant initialization expression +error[P0030]: invalid constant initialization expression --> 0086/code.ara:11:14 | 11 | Bar $a = new Bar($bar), | ^^^^^^^^^^^^^ -error[P0044]: invalid constant initialization expression +error[P0030]: invalid constant initialization expression --> 0086/code.ara:12:14 | 12 | Baz $b = new Baz($baz), | ^^^^^^^^^^^^^ -error[P0044]: invalid constant initialization expression +error[P0030]: invalid constant initialization expression --> 0086/code.ara:13:14 | 13 | Qux $c = new Qux(function(): void {}) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[P0045]: invalid initialization in constant expression +error[P0031]: invalid initialization in constant expression --> 0086/code.ara:17:17 | 17 | const FOO = new Foo(); @@ -65,7 +65,7 @@ error[P0045]: invalid initialization in constant expression | = constant expressions cannot contain `new` expressions. -error[P0043]: invalid constant expression +error[P0029]: invalid constant expression --> 0086/code.ara:19:17 | 19 | const BAR = function(): Bar { @@ -74,13 +74,13 @@ error[P0043]: invalid constant expression 21 | | }; | \-----^ -error[P0043]: invalid constant expression +error[P0029]: invalid constant expression --> 0086/code.ara:23:17 | 23 | const BAZ = fn(): Baz => new Baz(); | ^^^^^^^^^^^^^^^^^^^^^^ -error[P0042]: unexpected identifier, expected `;` +error[P0028]: unexpected identifier, expected `;` --> 0086/code.ara:25:22 | 25 | private mixed $a FOO = new Foo(); diff --git a/tests/samples/0104/error.txt b/tests/samples/0104/error.txt index 385c54f..712fdfa 100644 --- a/tests/samples/0104/error.txt +++ b/tests/samples/0104/error.txt @@ -1,22 +1,22 @@ -error[P0044]: invalid constant initialization expression +error[P0030]: invalid constant initialization expression --> 0104/code.ara:2:7 | 2 | #[Baz(...BAZ)] | ^^^^^^ -error[P0044]: invalid constant initialization expression +error[P0030]: invalid constant initialization expression --> 0104/code.ara:4:16 | 4 | Bar $bar = new Bar(...BAZ), | ^^^^^^^^^^^^^^^ -error[P0044]: invalid constant initialization expression +error[P0030]: invalid constant initialization expression --> 0104/code.ara:7:7 | 7 | #[Bar(...BAZ)] | ^^^^^^ -error[P0044]: invalid constant initialization expression +error[P0030]: invalid constant initialization expression --> 0104/code.ara:9:16 | 9 | Bar $bar = new Bar(BAZ...), diff --git a/tests/samples/0105/code.ara b/tests/samples/0105/code.ara deleted file mode 100644 index 07e3707..0000000 --- a/tests/samples/0105/code.ara +++ /dev/null @@ -1,4 +0,0 @@ - -function foo(null&Bar $bar): mixed {} - -function foo(Bar&null $bar): mixed {} diff --git a/tests/samples/0105/error.txt b/tests/samples/0105/error.txt deleted file mode 100644 index dbbdb09..0000000 --- a/tests/samples/0105/error.txt +++ /dev/null @@ -1,19 +0,0 @@ -error[P0047]: literal type `null` cannot be used in an intersection - --> 0105/code.ara:2:14 - | -2 | function foo(null&Bar $bar): mixed {} - | ^^^^- - | - = a literal type is either a literal integer, a literal float, a literal string, `false`, `true`, or `null`. - -error[P0047]: literal type `null` cannot be used in an intersection - --> 0105/code.ara:4:18 - | -4 | function foo(Bar&null $bar): mixed {} - | -^^^^ - | - = a literal type is either a literal integer, a literal float, a literal string, `false`, `true`, or `null`. - -error: failed to parse "0105/code.ara" due to the above issue(s) - = summary: 2 error(s) -