Skip to content

Commit 343c511

Browse files
committed
Add diagnostic for wrong specialize label
1 parent 49b3bbd commit 343c511

File tree

8 files changed

+1109
-117
lines changed

8 files changed

+1109
-117
lines changed

CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,15 @@ public let ATTRIBUTE_NODES: [Node] = [
657657
children: [
658658
Child(
659659
name: "Label",
660-
kind: .node(kind: .token),
660+
kind: .token(choices: [
661+
.keyword(text: "target"),
662+
.keyword(text: "availability"),
663+
.keyword(text: "exported"),
664+
.keyword(text: "kind"),
665+
.keyword(text: "spi"),
666+
.keyword(text: "spiModule"),
667+
.keyword(text: "available"),
668+
]),
661669
nameForDiagnostics: "label",
662670
documentation: "The label of the argument"
663671
),

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftparser/ParserTokenSpecSetFile.swift

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ let parserTokenSpecSetFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
2222
for child in layoutNode.children {
2323
if case let .token(choices, _, _) = child.kind, choices.count > 1 {
2424
try! ExtensionDeclSyntax("extension \(raw: layoutNode.kind.syntaxType)") {
25-
try EnumDeclSyntax("enum \(raw: child.name)Options: TokenSpecSet") {
25+
try EnumDeclSyntax(
26+
"""
27+
@_spi(Diagnostics)
28+
public enum \(raw: child.name)Options: TokenSpecSet
29+
"""
30+
) {
2631
for choice in choices {
2732
switch choice {
2833
case .keyword(let keywordText):
@@ -70,6 +75,30 @@ let parserTokenSpecSetFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
7075
}
7176
}
7277
}
78+
79+
try VariableDeclSyntax(
80+
"""
81+
@_spi(Diagnostics)
82+
public var tokenSyntax: TokenSyntax
83+
"""
84+
) {
85+
try SwitchExprSyntax("switch self") {
86+
for choice in choices {
87+
switch choice {
88+
case .keyword(let keywordText):
89+
let keyword = KEYWORDS.first(where: { $0.name == keywordText })!
90+
SwitchCaseSyntax(
91+
"case .\(raw: keyword.escapedName): return .keyword(.\(raw: keyword.escapedName))"
92+
)
93+
case .token(let tokenText):
94+
let token = SYNTAX_TOKEN_MAP[tokenText]!
95+
SwitchCaseSyntax(
96+
"case .\(raw: token.swiftKind): return .\(raw: token.swiftKind)()"
97+
)
98+
}
99+
}
100+
}
101+
}
73102
}
74103
}
75104
}

Sources/SwiftParser/Attributes.swift

Lines changed: 21 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -610,48 +610,14 @@ extension Parser {
610610
}
611611

612612
extension Parser {
613-
enum SpecializeParameter: TokenSpecSet {
614-
case target
615-
case availability
616-
case exported
617-
case kind
618-
case spi
619-
case spiModule
620-
case available
621-
622-
init?(lexeme: Lexer.Lexeme) {
623-
switch PrepareForKeywordMatch(lexeme) {
624-
case TokenSpec(.target): self = .target
625-
case TokenSpec(.availability): self = .availability
626-
case TokenSpec(.exported): self = .exported
627-
case TokenSpec(.kind): self = .kind
628-
case TokenSpec(.spi): self = .spi
629-
case TokenSpec(.spiModule): self = .spiModule
630-
case TokenSpec(.available): self = .available
631-
default: return nil
632-
}
633-
}
634-
635-
var spec: TokenSpec {
636-
switch self {
637-
case .target: return .keyword(.target)
638-
case .availability: return .keyword(.availability)
639-
case .exported: return .keyword(.exported)
640-
case .kind: return .keyword(.kind)
641-
case .spi: return .keyword(.spi)
642-
case .spiModule: return .keyword(.spiModule)
643-
case .available: return .keyword(.available)
644-
}
645-
}
646-
}
647613
mutating func parseSpecializeAttributeSpecList() -> RawSpecializeAttributeSpecListSyntax {
648614
var elements = [RawSpecializeAttributeSpecListSyntax.Element]()
649615
// Parse optional "exported" and "kind" labeled parameters.
650616
var loopProgress = LoopProgressCondition()
651617
while !self.at(.eof, .rightParen, .keyword(.where)) && loopProgress.evaluate(currentToken) {
652-
switch self.at(anyIn: SpecializeParameter.self) {
618+
switch self.canRecoverTo(anyIn: LabeledSpecializeEntrySyntax.LabelOptions.self) {
653619
case (.target, let handle)?:
654-
let ident = self.eat(handle)
620+
let (unexpectedBeforeLabel, label) = self.eat(handle)
655621
let (unexpectedBeforeColon, colon) = self.expect(.colon)
656622
let (targetFunction, args) = self.parseDeclNameRef([.zeroArgCompoundNames, .keywordsUsingSpecialNames, .operators])
657623
let declName = RawDeclNameSyntax(
@@ -663,7 +629,8 @@ extension Parser {
663629
elements.append(
664630
.targetFunctionEntry(
665631
RawTargetFunctionEntrySyntax(
666-
label: ident,
632+
unexpectedBeforeLabel,
633+
label: label,
667634
unexpectedBeforeColon,
668635
colon: colon,
669636
declname: declName,
@@ -673,14 +640,15 @@ extension Parser {
673640
)
674641
)
675642
case (.availability, let handle)?:
676-
let ident = self.eat(handle)
643+
let (unexpectedBeforeLabel, label) = self.eat(handle)
677644
let (unexpectedBeforeColon, colon) = self.expect(.colon)
678645
let availability = self.parseAvailabilitySpecList()
679646
let (unexpectedBeforeSemi, semi) = self.expect(.semicolon)
680647
elements.append(
681648
.availabilityEntry(
682649
RawAvailabilityEntrySyntax(
683-
label: ident,
650+
unexpectedBeforeLabel,
651+
label: label,
684652
unexpectedBeforeColon,
685653
colon: colon,
686654
availabilityArguments: availability,
@@ -691,7 +659,7 @@ extension Parser {
691659
)
692660
)
693661
case (.available, let handle)?:
694-
let ident = self.eat(handle)
662+
let (unexpectedBeforeLabel, label) = self.eat(handle)
695663
let (unexpectedBeforeColon, colon) = self.expect(.colon)
696664
// FIXME: I have no idea what this is supposed to be, but the Syntax
697665
// tree only allows us to insert a token so we'll take anything.
@@ -700,7 +668,8 @@ extension Parser {
700668
elements.append(
701669
.labeledSpecializeEntry(
702670
RawLabeledSpecializeEntrySyntax(
703-
label: ident,
671+
unexpectedBeforeLabel,
672+
label: label,
704673
unexpectedBeforeColon,
705674
colon: colon,
706675
value: available,
@@ -710,14 +679,15 @@ extension Parser {
710679
)
711680
)
712681
case (.exported, let handle)?:
713-
let ident = self.eat(handle)
682+
let (unexpectedBeforeLabel, label) = self.eat(handle)
714683
let (unexpectedBeforeColon, colon) = self.expect(.colon)
715684
let (unexpectedBeforeValue, value) = self.expect(.keyword(.true), .keyword(.false), default: .keyword(.false))
716685
let comma = self.consume(if: .comma)
717686
elements.append(
718687
.labeledSpecializeEntry(
719688
RawLabeledSpecializeEntrySyntax(
720-
label: ident,
689+
unexpectedBeforeLabel,
690+
label: label,
721691
unexpectedBeforeColon,
722692
colon: colon,
723693
unexpectedBeforeValue,
@@ -728,14 +698,15 @@ extension Parser {
728698
)
729699
)
730700
case (.kind, let handle)?:
731-
let ident = self.eat(handle)
701+
let (unexpectedBeforeLabel, label) = self.eat(handle)
732702
let (unexpectedBeforeColon, colon) = self.expect(.colon)
733703
let valueLabel = self.parseAnyIdentifier()
734704
let comma = self.consume(if: .comma)
735705
elements.append(
736706
.labeledSpecializeEntry(
737707
RawLabeledSpecializeEntrySyntax(
738-
label: ident,
708+
unexpectedBeforeLabel,
709+
label: label,
739710
unexpectedBeforeColon,
740711
colon: colon,
741712
value: valueLabel,
@@ -746,14 +717,15 @@ extension Parser {
746717
)
747718
case (.spiModule, let handle)?,
748719
(.spi, let handle)?:
749-
let ident = self.eat(handle)
720+
let (unexpectedBeforeLabel, label) = self.eat(handle)
750721
let (unexpectedBeforeColon, colon) = self.expect(.colon)
751722
let valueLabel = self.consumeAnyToken()
752723
let comma = self.consume(if: .comma)
753724
elements.append(
754725
.labeledSpecializeEntry(
755726
RawLabeledSpecializeEntrySyntax(
756-
label: ident,
727+
unexpectedBeforeLabel,
728+
label: label,
757729
unexpectedBeforeColon,
758730
colon: colon,
759731
value: valueLabel,
@@ -770,7 +742,8 @@ extension Parser {
770742
elements.append(
771743
.labeledSpecializeEntry(
772744
RawLabeledSpecializeEntrySyntax(
773-
label: ident,
745+
RawUnexpectedNodesSyntax([ident], arena: self.arena),
746+
label: RawTokenSyntax(missing: .identifier, arena: self.arena),
774747
unexpectedBeforeColon,
775748
colon: colon,
776749
value: valueLabel,

0 commit comments

Comments
 (0)