Skip to content

Commit f3bfdae

Browse files
committed
[SwiftParser] Avoid consuming invalid dependsOn and nonisolated modifiers while skipping
Otherwise in situations like `nonisolated()` `canParseType` would return `true` because `()` is valid type.
1 parent 2b13304 commit f3bfdae

File tree

1 file changed

+58
-7
lines changed

1 file changed

+58
-7
lines changed

Sources/SwiftParser/Types.swift

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -687,27 +687,74 @@ extension Parser.Lookahead {
687687
return true
688688
}
689689

690-
mutating func skipTypeAttributeList() {
690+
mutating func skipTypeAttributeList() -> 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+
guard
700+
self.withLookahead({
701+
// Consume 'nonisolated'
702+
$0.consumeAnyToken()
703+
704+
// The argument is missing but it still could be a valid modifier,
705+
// i.e. `nonisolated` in an inheritance clause.
706+
guard $0.at(TokenSpec(.leftParen, allowAtStartOfLine: false)) else {
707+
return true
708+
}
709+
710+
// Consume '('
711+
$0.consumeAnyToken()
712+
713+
// nonisolated accepts a single modifier at the moment: 'nonsending'
714+
// we need to check for that explicitly to avoid misinterpreting this
715+
// keyword to be a modifier when it isn't i.e. `[nonisolated(42)]`
716+
guard $0.consume(if: TokenSpec(.nonsending, allowAtStartOfLine: false)) != nil else {
717+
return false
718+
}
719+
720+
return $0.consume(if: TokenSpec(.rightParen, allowAtStartOfLine: false)) != nil
721+
})
722+
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+
guard
736+
self.withLookahead({
737+
// Consume 'dependsOn'
738+
$0.consumeAnyToken()
739+
740+
if $0.currentToken.isAtStartOfLine {
741+
return false
742+
}
743+
744+
// `dependsOn` requires an argument list.
745+
guard $0.atAttributeOrSpecifierArgument() else {
746+
return false
747+
}
748+
749+
return true
750+
})
751+
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.skipTypeAttributeList() else {
774+
return false
775+
}
725776

726777
guard self.canParseSimpleOrCompositionType() else {
727778
return false

0 commit comments

Comments
 (0)