@@ -687,27 +687,74 @@ extension Parser.Lookahead {
687687 return true
688688 }
689689
690- mutating func skipTypeAttributeList ( ) {
690+ mutating func canParseTypeAttributeList ( ) -> Bool {
691691 var specifierProgress = LoopProgressCondition ( )
692692 while canHaveParameterSpecifier,
693693 self . at ( anyIn: SimpleTypeSpecifierSyntax . SpecifierOptions. self) != nil
694694 || self . at ( . keyword( . nonisolated) , . keyword( . dependsOn) ) ,
695695 self . hasProgressed ( & specifierProgress)
696696 {
697697 switch self . currentToken {
698- case . keyword( . nonisolated) , . keyword( . dependsOn) :
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+
699726 self . consumeAnyToken ( )
700727
701- // The argument is missing but it still could be a valid modifier,
702- // i.e. `nonisolated` in an inheritance clause.
703728 guard self . at ( TokenSpec ( . leftParen, allowAtStartOfLine: false ) ) else {
704729 continue
705730 }
706731
707- if self . withLookahead ( { $0. atAttributeOrSpecifierArgument ( ) } ) {
708- skipSingle ( )
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
709753 }
710754
755+ self . consumeAnyToken ( )
756+ self . skipSingle ( )
757+
711758 default :
712759 self . consumeAnyToken ( )
713760 }
@@ -718,10 +765,14 @@ extension Parser.Lookahead {
718765 self . consumeAnyToken ( )
719766 self . skipTypeAttribute ( )
720767 }
768+
769+ return true
721770 }
722771
723772 mutating func canParseTypeScalar( ) -> Bool {
724- self . skipTypeAttributeList ( )
773+ guard self . canParseTypeAttributeList ( ) else {
774+ return false
775+ }
725776
726777 guard self . canParseSimpleOrCompositionType ( ) else {
727778 return false
0 commit comments