Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed

- Fixed parsing of logical lines with sequential `<` and `>` comparisons.
- Fixed formatting of `interface` as a generic constraint.

### Added

- Added support for Delphi 13 `noreturn` directive.
- Added support for Delphi 13 `unmanaged` generic constraint.

## [0.7.0] - 2025-11-11

Expand Down
3 changes: 3 additions & 0 deletions core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

- Fixed parsing of logical lines with sequential `<` and `>` comparisons.
- Fixed formatting of `interface` as a generic constraint.

### Added

- Added support for Delphi 13 `noreturn` directive.
- Added `KeywordKind::is_generic_constraint`.
- Added support for Delphi 13 `unmanaged` generic constraint.

## 0.7.0 - 2025-11-11

Expand Down
10 changes: 8 additions & 2 deletions core/datatests/generators/optimising_line_formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2640,7 +2640,7 @@ mod routines {
procedure Apples<
AA, BB: record;
AAAAAAAAAA, BBBBBBBB:
IInterface;
interface;
AAAAAAAA,
BBBBBBBB,
CCCCCCC: record;
Expand All @@ -2651,12 +2651,18 @@ mod routines {
CC:
constructor,
record,
interface,
class;
CC:
AAAAAAAA,
BBBBBBBB,
CCCCCCCC,
DDDDDDDD;
CC:
constructor,
record,
class,
IInterface
interface
>();
",
generic_routines_and_params = "
Expand Down
4 changes: 3 additions & 1 deletion core/src/defaults/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ const fn make_byte_map<T: Copy>(map: &[(ByteSet<'_>, T)], default: T) -> [T; 256
// endregion: byte-set

// region: keywords
const KEYWORDS: [(&str, RawTokenType); 123] = [
const KEYWORDS: [(&str, RawTokenType); 124] = [
("absolute", TT::IdentifierOrKeyword(KK::Absolute)),
("abstract", TT::IdentifierOrKeyword(KK::Abstract)),
("align", TT::IdentifierOrKeyword(KK::Align)),
Expand Down Expand Up @@ -433,6 +433,7 @@ const KEYWORDS: [(&str, RawTokenType); 123] = [
("try", TT::Keyword(KK::Try)),
("type", TT::Keyword(KK::Type)),
("unit", TT::Keyword(KK::Unit)),
("unmanaged", TT::IdentifierOrKeyword(KK::Unmanaged)),
("unsafe", TT::IdentifierOrKeyword(KK::Unsafe)),
("until", TT::Keyword(KK::Until)),
("uses", TT::Keyword(KK::Uses)),
Expand Down Expand Up @@ -2136,6 +2137,7 @@ mod tests {
("try", TT::Keyword(KK::Try)),
("type", TT::Keyword(KK::Type)),
("unit", TT::Keyword(KK::Unit)),
("unmanaged", TT::IdentifierOrKeyword(KK::Unmanaged)),
("unsafe", TT::IdentifierOrKeyword(KK::Unsafe)),
("until", TT::Keyword(KK::Until)),
("uses", TT::Keyword(KK::Uses)),
Expand Down
38 changes: 37 additions & 1 deletion core/src/defaults/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1449,8 +1449,44 @@ impl<'a, 'b> InternalDelphiLogicalLineParser<'a, 'b> {
parser.parse_expression();
}
}
// Generics
Some(TT::Op(OK::LessThan(_))) => {
parser.skip_pair();
let paren_level = parser.paren_level;
let brack_level = parser.brack_level;
let generic_level = parser.generic_level;
let mut in_constraint = false;
parser.next_token();
while (parser.paren_level != paren_level
|| parser.brack_level != brack_level
|| parser.generic_level != generic_level)
&& parser.get_current_token_type().is_some()
{
match parser.get_current_token_type() {
Some(TT::Op(OK::Colon)) => {
/*
E.g., function <A: BB>();
In constraint ^
*/
in_constraint = true;
}
Some(TT::Op(OK::Semicolon)) => {
/*
E.g., function <A: BB; C: DD>();
Not in constraint ^
*/
in_constraint = false;
}
Some(TT::IdentifierOrKeyword(kk)) if kk.is_generic_constraint() => {
if in_constraint {
parser.consolidate_current_keyword();
} else {
parser.consolidate_current_ident();
}
}
_ => {}
}
parser.next_token();
}
}
Some(TT::Op(OK::Semicolon)) => {
parser.next_token();
Expand Down
7 changes: 7 additions & 0 deletions core/src/defaults/parser/token_consolidation_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,13 @@ casing_token_consolidation_test!(
strict,
identifier = { "type foo = class STRICT: STRICT; strict private STRICT: STRICT end;" },
);
casing_token_consolidation_test!(
generic_constraint,
unmanaged = {
"function UNMANAGED<UNMANAGED: unmanaged, unmanaged; UNMANAGED: unmanaged, unmanaged>(UNMANAGED: UNMANAGED; UNMANAGED: UNMANAGED);"
},
fake = { "function SEALED<UNMANAGED: SEALED; UNMANAGED: STRICT>(UNMANAGED: UNMANAGED);" },
);

/*
In cases like these, `helper` can be both an identifier and a keyword based on the conditional
Expand Down
12 changes: 12 additions & 0 deletions core/src/lang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ pub enum KeywordKind {
StdCall,
Stored,
Strict,
Unmanaged,
Unsafe,
VarArgs,
Virtual,
Expand Down Expand Up @@ -256,6 +257,17 @@ impl KeywordKind {
| KeywordKind::Type
)
}

pub fn is_generic_constraint(&self) -> bool {
matches!(
self,
KeywordKind::Record
| KeywordKind::Class
| KeywordKind::Constructor
| KeywordKind::Interface
| KeywordKind::Unmanaged
)
}
}

/// Used to distinguish the semantic meanings of `=`
Expand Down
6 changes: 2 additions & 4 deletions core/src/rules/generics_consolidator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ impl TokenConsolidator for DistinguishGenericTypeParamsConsolidator {
Some(TokenType::Op(OperatorKind::Comma)) => {
comma_found = true;
}
Some(TokenType::Keyword(kk)) if kk.is_generic_constraint() => {}
// all the other tokens you can include in a generic type parameter list
Some(
TokenType::Identifier
Expand All @@ -54,10 +55,7 @@ impl TokenConsolidator for DistinguishGenericTypeParamsConsolidator {
| TokenType::Comment(_)
| TokenType::ConditionalDirective(_)
| TokenType::Keyword(
KeywordKind::Class
| KeywordKind::Record
| KeywordKind::Constructor
| KeywordKind::String
KeywordKind::String
| KeywordKind::Array
| KeywordKind::Set
| KeywordKind::Of,
Expand Down
1 change: 1 addition & 0 deletions misc/keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ to
try
type
unit
unmanaged
unsafe
until
uses
Expand Down
Loading