Skip to content

Commit

Permalink
chore: report intersection with literal types (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
KennedyTedesco committed Jan 6, 2023
1 parent 8d926e0 commit de08a1c
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/parser/internal/definition/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,13 @@ fn intersection(
);
}

if type_definition.is_literal() {
crate::parser_report!(
state,
literal_type_cannot_be_used_in_intersection(&type_definition, last_ampersand)
);
}

let mut type_definitions = vec![type_definition];

loop {
Expand Down Expand Up @@ -481,6 +488,13 @@ fn intersection(
);
}

if type_definition.is_literal() {
crate::parser_report!(
state,
literal_type_cannot_be_used_in_intersection(&type_definition, last_ampersand)
);
}

type_definition
};

Expand Down
36 changes: 36 additions & 0 deletions src/parser/issue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,20 @@ 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,
}

pub(crate) fn php_opening_tag_not_supported(state: &ParserState, token: &Token) -> Issue {
Expand Down Expand Up @@ -1036,6 +1050,28 @@ pub(crate) fn scalar_type_cannot_be_used_in_intersection(
.with_help("try using a different type for the intersection.")
}

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,
),
origin,
type_definition.initial_position(),
type_definition.final_position(),
)
.with_annotation(Annotation::new(origin, ampersand, ampersand + 1))
.with_note("a literal type is either a literal integer, a literal float, a literal string, `false`, `true`, or `null`.")
.with_help("try using a different type for the intersection.")
}

pub(crate) fn readonly_property_cannot_be_static(
state: &ParserState,
class_name: Option<&Identifier>,
Expand Down
4 changes: 4 additions & 0 deletions tests/samples/0105/code.ara
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

function foo(null&Bar $bar): mixed {}

function foo(Bar&null $bar): mixed {}
20 changes: 20 additions & 0 deletions tests/samples/0105/error.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[P0047]: literal type `null` cannot be used in an intersection
--> 0105/code.ara:2:14
|
2 | function foo(null&Bar $bar): mixed {}
| ^^^^-
| |
| literal type `null` cannot be used in an intersection
|
= note: a literal type is either a literal integer, a literal float, a literal string, `false`, `true`, or `null`.
= help: try using a different type for the intersection.

error[P0047]: literal type `null` cannot be used in an intersection
--> 0105/code.ara:4:18
|
4 | function foo(Bar&null $bar): mixed {}
| -^^^^ literal type `null` cannot be used in an intersection
|
= note: a literal type is either a literal integer, a literal float, a literal string, `false`, `true`, or `null`.
= help: try using a different type for the intersection.

0 comments on commit de08a1c

Please sign in to comment.