Skip to content

Commit fd7238c

Browse files
committed
WIP: Rename firstPotentialTokenKind to firstPotentialTokenChoices
Add logic for `firstPotentialTokenChoices` of base nodes and unexpected nodes
1 parent ec9161f commit fd7238c

File tree

4 files changed

+69
-10
lines changed

4 files changed

+69
-10
lines changed

CodeGeneration/Sources/SyntaxSupport/Node.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public class Node {
129129
}
130130

131131
choices.append(contentsOf: getChildTokenChoice(child))
132-
132+
133133
if !child.isOptional {
134134
break
135135
}
@@ -146,6 +146,11 @@ public class Node {
146146
}.flatMap { $0 }
147147
}
148148

149+
if self.kind.isBase {
150+
return []
151+
}
152+
153+
assertionFailure("should not match this case")
149154
return []
150155
}
151156

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

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ let IncrementalParseUtilsFile = SourceFileSyntax(leadingTrivia: copyrightHeader)
2727
"""
2828
/// This property presents the first potential ``TokenSpec``s of all ``SyntaxKind``s
2929
@_spi(IncrementalParse)
30-
public var firstPotentialTokenKind: [TokenSpec]
30+
public var firstPotentialTokenChoices: [TokenSpec]
3131
"""
3232
) {
3333
try SwitchExprSyntax("switch self") {
@@ -93,12 +93,38 @@ let IncrementalParseUtilsFile = SourceFileSyntax(leadingTrivia: copyrightHeader)
9393
return []
9494
}
9595
96-
return self.kind.syntaxLayout[nextPotentialNodeIndex].flatMap { $0.firstPotentialTokenKind }
96+
return self.kind.syntaxLayout[nextPotentialNodeIndex].flatMap { $0.firstPotentialTokenChoices }
9797
9898
}
9999
return []
100100
}
101101
"""
102102
)
103+
104+
DeclSyntax(
105+
"""
106+
public var isSelfCompleted: Bool {
107+
if let children = self.layoutView?.children,
108+
let lastNonNilChildIdx = children.lastIndex(where: {
109+
$0 != nil
110+
}),
111+
lastNonNilChildIdx != children.endIndex
112+
{
113+
114+
let nextPotentialNodeIndex = children.index(after: lastNonNilChildIdx)
115+
116+
if self.kind.syntaxLayout[nextPotentialNodeIndex].allSatisfy({
117+
$0 == .unexpectedNodes
118+
}) {
119+
return nextPotentialNodeIndex == children.index(before: children.endIndex)
120+
} else {
121+
return children.index(after: nextPotentialNodeIndex) == children.index(before: children.endIndex)
122+
}
123+
}
124+
125+
return true
126+
}
127+
"""
128+
)
103129
}
104130
}

Sources/SwiftParser/Parser.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -652,15 +652,21 @@ extension Parser {
652652
func nodeCanBeReused(node: Syntax) -> Bool {
653653
var underlyingRaw = node.raw
654654

655+
if let codeBlockItem = node.as(CodeBlockItemSyntax.self) {
656+
underlyingRaw = codeBlockItem.item.raw
657+
}
658+
// Since `firstPotentialTokenChoices` of an unexpected node is empty too, we need to verify whether the node to be reused is completed, if so, we just break.
659+
// See comments below.
660+
if underlyingRaw.isSelfCompleted {
661+
return true
662+
}
663+
655664
var lookahead = self.lookahead()
656665
lookahead.lexemes.advance(by: node.byteSize, currentToken: &lookahead.currentToken)
657666

658667
let currentTokenSpec = PrepareForKeywordMatch(lookahead.currentToken)
659668

660-
if let codeBlockItem = node.as(CodeBlockItemSyntax.self) {
661-
underlyingRaw = codeBlockItem.item.raw
662-
}
663-
664-
return underlyingRaw.nextPotentialTokenChoices.allSatisfy { !($0 ~= currentTokenSpec) }
669+
// If `nextPotentialTokenChoices` is empty, we presume next potential child is a base node and reject this node to be reused. Since almost all tokens can be the introducer of a base node.
670+
return underlyingRaw.nextPotentialTokenChoices.allSatisfy { !($0 ~= currentTokenSpec) } && !underlyingRaw.nextPotentialTokenChoices.isEmpty
665671
}
666672
}

Sources/SwiftParser/generated/IncrementalParseUtils.swift

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
extension SyntaxKind {
1818
/// This property presents the first potential ``TokenSpec``s of all ``SyntaxKind``s
1919
@_spi(IncrementalParse)
20-
public var firstPotentialTokenKind: [TokenSpec] {
20+
public var firstPotentialTokenChoices: [TokenSpec] {
2121
switch self {
2222
case .accessorBlock:
2323
return [.leftBrace]
@@ -7682,10 +7682,32 @@ extension RawSyntax {
76827682
}
76837683

76847684
return self.kind.syntaxLayout[nextPotentialNodeIndex].flatMap {
7685-
$0.firstPotentialTokenKind
7685+
$0.firstPotentialTokenChoices
76867686
}
76877687

76887688
}
76897689
return []
76907690
}
7691+
7692+
public var isSelfCompleted: Bool {
7693+
if let children = self.layoutView?.children,
7694+
let lastNonNilChildIdx = children.lastIndex(where: {
7695+
$0 != nil
7696+
}),
7697+
lastNonNilChildIdx != children.endIndex
7698+
{
7699+
7700+
let nextPotentialNodeIndex = children.index(after: lastNonNilChildIdx)
7701+
7702+
if self.kind.syntaxLayout[nextPotentialNodeIndex].allSatisfy({
7703+
$0 == .unexpectedNodes
7704+
}) {
7705+
return nextPotentialNodeIndex == children.index(before: children.endIndex)
7706+
} else {
7707+
return children.index(after: nextPotentialNodeIndex) == children.index(before: children.endIndex)
7708+
}
7709+
}
7710+
7711+
return true
7712+
}
76917713
}

0 commit comments

Comments
 (0)