@@ -687,26 +687,92 @@ extension Parser.Lookahead {
687
687
return true
688
688
}
689
689
690
- mutating func skipTypeAttributeList ( ) {
690
+ mutating func canParseTypeAttributeList ( ) -> Bool {
691
691
var specifierProgress = LoopProgressCondition ( )
692
- // TODO: Can we model isolated/_const so that they're specified in both canParse* and parse*?
693
692
while canHaveParameterSpecifier,
694
- self . at ( anyIn: SimpleTypeSpecifierSyntax . SpecifierOptions. self) != nil || self . at ( . keyword ( . isolated ) )
695
- || self . at ( . keyword( . _const ) ) ,
693
+ self . at ( anyIn: SimpleTypeSpecifierSyntax . SpecifierOptions. self) != nil
694
+ || self . at ( . keyword( . nonisolated ) , . keyword ( . dependsOn ) ) ,
696
695
self . hasProgressed ( & specifierProgress)
697
696
{
698
- self . consumeAnyToken ( )
697
+ switch self . currentToken {
698
+ case . keyword( . nonisolated) :
699
+ let canParseNonisolated = self . withLookahead ( {
700
+ // Consume 'nonisolated'
701
+ $0. consumeAnyToken ( )
702
+
703
+ // The argument is missing but it still could be a valid modifier,
704
+ // i.e. `nonisolated` in an inheritance clause.
705
+ guard $0. at ( TokenSpec ( . leftParen, allowAtStartOfLine: false ) ) else {
706
+ return true
707
+ }
708
+
709
+ // Consume '('
710
+ $0. consumeAnyToken ( )
711
+
712
+ // nonisolated accepts a single modifier at the moment: 'nonsending'
713
+ // we need to check for that explicitly to avoid misinterpreting this
714
+ // keyword to be a modifier when it isn't i.e. `[nonisolated(42)]`
715
+ guard $0. consume ( if: TokenSpec ( . nonsending, allowAtStartOfLine: false ) ) != nil else {
716
+ return false
717
+ }
718
+
719
+ return $0. consume ( if: TokenSpec ( . rightParen, allowAtStartOfLine: false ) ) != nil
720
+ } )
721
+
722
+ guard canParseNonisolated else {
723
+ return false
724
+ }
725
+
726
+ self . consumeAnyToken ( )
727
+
728
+ guard self . at ( TokenSpec ( . leftParen, allowAtStartOfLine: false ) ) else {
729
+ continue
730
+ }
731
+
732
+ self . skipSingle ( )
733
+
734
+ case . keyword( . dependsOn) :
735
+ let canParseDependsOn = self . withLookahead ( {
736
+ // Consume 'dependsOn'
737
+ $0. consumeAnyToken ( )
738
+
739
+ if $0. currentToken. isAtStartOfLine {
740
+ return false
741
+ }
742
+
743
+ // `dependsOn` requires an argument list.
744
+ guard $0. atAttributeOrSpecifierArgument ( ) else {
745
+ return false
746
+ }
747
+
748
+ return true
749
+ } )
750
+
751
+ guard canParseDependsOn else {
752
+ return false
753
+ }
754
+
755
+ self . consumeAnyToken ( )
756
+ self . skipSingle ( )
757
+
758
+ default :
759
+ self . consumeAnyToken ( )
760
+ }
699
761
}
700
762
701
763
var attributeProgress = LoopProgressCondition ( )
702
764
while self . at ( . atSign) , self . hasProgressed ( & attributeProgress) {
703
765
self . consumeAnyToken ( )
704
766
self . skipTypeAttribute ( )
705
767
}
768
+
769
+ return true
706
770
}
707
771
708
772
mutating func canParseTypeScalar( ) -> Bool {
709
- self . skipTypeAttributeList ( )
773
+ guard self . canParseTypeAttributeList ( ) else {
774
+ return false
775
+ }
710
776
711
777
guard self . canParseSimpleOrCompositionType ( ) else {
712
778
return false
@@ -1056,6 +1122,88 @@ extension Parser {
1056
1122
return . lifetimeTypeSpecifier( lifetimeSpecifier)
1057
1123
}
1058
1124
1125
+ private mutating func parseNonisolatedTypeSpecifier( ) -> RawTypeSpecifierListSyntax . Element {
1126
+ let ( unexpectedBeforeNonisolatedKeyword, nonisolatedKeyword) = self . expect ( . keyword( . nonisolated) )
1127
+
1128
+ // If the next token is not '(' this could mean two things:
1129
+ // - What follows is a type and we should allow it because
1130
+ // using `nonsisolated` without an argument is allowed in
1131
+ // an inheritance clause.
1132
+ // - The '(nonsending)' was omitted.
1133
+ if !self . at ( . leftParen) {
1134
+ // `nonisolated P<...>` is allowed in an inheritance clause.
1135
+ if withLookahead ( { $0. canParseTypeIdentifier ( ) } ) {
1136
+ let nonisolatedSpecifier = RawNonisolatedTypeSpecifierSyntax (
1137
+ unexpectedBeforeNonisolatedKeyword,
1138
+ nonisolatedKeyword: nonisolatedKeyword,
1139
+ argument: nil ,
1140
+ arena: self . arena
1141
+ )
1142
+ return . nonisolatedTypeSpecifier( nonisolatedSpecifier)
1143
+ }
1144
+
1145
+ // Otherwise require '(nonsending)'
1146
+ let argument = RawNonisolatedSpecifierArgumentSyntax (
1147
+ leftParen: missingToken ( . leftParen) ,
1148
+ nonsendingKeyword: missingToken ( . keyword( . nonsending) ) ,
1149
+ rightParen: missingToken ( . rightParen) ,
1150
+ arena: self . arena
1151
+ )
1152
+
1153
+ let nonisolatedSpecifier = RawNonisolatedTypeSpecifierSyntax (
1154
+ unexpectedBeforeNonisolatedKeyword,
1155
+ nonisolatedKeyword: nonisolatedKeyword,
1156
+ argument: argument,
1157
+ arena: self . arena
1158
+ )
1159
+
1160
+ return . nonisolatedTypeSpecifier( nonisolatedSpecifier)
1161
+ }
1162
+
1163
+ // Avoid being to greedy about `(` since this modifier should be associated with
1164
+ // function types, it's possible that the argument is omitted and what follows
1165
+ // is a function type i.e. `nonisolated () async -> Void`.
1166
+ if self . at ( . leftParen) && !withLookahead( { $0. atAttributeOrSpecifierArgument ( ) } ) {
1167
+ let argument = RawNonisolatedSpecifierArgumentSyntax (
1168
+ leftParen: missingToken ( . leftParen) ,
1169
+ nonsendingKeyword: missingToken ( . keyword( . nonsending) ) ,
1170
+ rightParen: missingToken ( . rightParen) ,
1171
+ arena: self . arena
1172
+ )
1173
+
1174
+ let nonisolatedSpecifier = RawNonisolatedTypeSpecifierSyntax (
1175
+ unexpectedBeforeNonisolatedKeyword,
1176
+ nonisolatedKeyword: nonisolatedKeyword,
1177
+ argument: argument,
1178
+ arena: self . arena
1179
+ )
1180
+
1181
+ return . nonisolatedTypeSpecifier( nonisolatedSpecifier)
1182
+ }
1183
+
1184
+ let ( unexpectedBeforeLeftParen, leftParen) = self . expect ( . leftParen)
1185
+ let ( unexpectedBeforeModifier, modifier) = self . expect ( . keyword( . nonsending) )
1186
+ let ( unexpectedBeforeRightParen, rightParen) = self . expect ( . rightParen)
1187
+
1188
+ let argument = RawNonisolatedSpecifierArgumentSyntax (
1189
+ unexpectedBeforeLeftParen,
1190
+ leftParen: leftParen,
1191
+ unexpectedBeforeModifier,
1192
+ nonsendingKeyword: modifier,
1193
+ unexpectedBeforeRightParen,
1194
+ rightParen: rightParen,
1195
+ arena: self . arena
1196
+ )
1197
+
1198
+ let nonisolatedSpecifier = RawNonisolatedTypeSpecifierSyntax (
1199
+ unexpectedBeforeNonisolatedKeyword,
1200
+ nonisolatedKeyword: nonisolatedKeyword,
1201
+ argument: argument,
1202
+ arena: self . arena
1203
+ )
1204
+ return . nonisolatedTypeSpecifier( nonisolatedSpecifier)
1205
+ }
1206
+
1059
1207
private mutating func parseSimpleTypeSpecifier(
1060
1208
specifierHandle: TokenConsumptionHandle
1061
1209
) -> RawTypeSpecifierListSyntax . Element {
@@ -1079,6 +1227,13 @@ extension Parser {
1079
1227
} else {
1080
1228
break SPECIFIER_PARSING
1081
1229
}
1230
+ } else if self . at ( . keyword( . nonisolated) ) {
1231
+ // If '(' is located on the new line 'nonisolated' cannot be parsed
1232
+ // as a specifier.
1233
+ if self . peek ( isAt: . leftParen) && self . peek ( ) . isAtStartOfLine {
1234
+ break SPECIFIER_PARSING
1235
+ }
1236
+ specifiers. append ( parseNonisolatedTypeSpecifier ( ) )
1082
1237
} else {
1083
1238
break SPECIFIER_PARSING
1084
1239
}
0 commit comments