Skip to content

Commit d9f839c

Browse files
ahoppenRintaro Ishizaki
and
Rintaro Ishizaki
committed
Address review comments to #1650
This addresses the review comments I made on #1650. Co-Authored-By: Rintaro Ishizaki <rintaro@apple.com>
1 parent 967e487 commit d9f839c

13 files changed

+378
-240
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,30 @@ extension DeclarationModifier {
3030

3131
extension TokenConsumer {
3232
mutating func atStartOfFreestandingMacroExpansion() -> Bool {
33+
// Check if "'#' <identifier>" where the identifier is on the sameline.
3334
if !self.at(.pound) {
3435
return false
3536
}
36-
if self.peek().rawTokenKind != .identifier && !self.peek().isLexerClassifiedKeyword {
37+
if self.peek().isAtStartOfLine {
3738
return false
3839
}
39-
if self.currentToken.trailingTriviaByteLength != 0 || self.peek().leadingTriviaByteLength != 0 {
40+
switch self.peek().rawTokenKind {
41+
case .identifier:
42+
return true
43+
case .keyword:
44+
// allow keywords right after '#' so we can diagnose it when parsing.
45+
return (self.currentToken.trailingTriviaByteLength == 0 && self.peek().leadingTriviaByteLength == 0)
46+
default:
4047
return false
4148
}
42-
return true
4349
}
4450

4551
mutating func atStartOfDeclaration(
4652
isAtTopLevel: Bool = false,
4753
allowInitDecl: Bool = true,
4854
allowRecovery: Bool = false
4955
) -> Bool {
50-
if self.at(anyIn: PoundDeclarationStart.self) != nil {
56+
if self.at(.poundIfKeyword) {
5157
return true
5258
}
5359

@@ -188,13 +194,9 @@ extension Parser {
188194
/// If `inMemberDeclList` is `true`, we know that the next item must be a
189195
/// declaration and thus start with a keyword. This allows futher recovery.
190196
mutating func parseDeclaration(inMemberDeclList: Bool = false) -> RawDeclSyntax {
191-
switch self.at(anyIn: PoundDeclarationStart.self) {
192-
case (.poundIfKeyword, _)?:
193-
if self.withLookahead({ $0.consumeIfConfigOfAttributes() }) {
194-
// If we are at a `#if` of attributes, the `#if` directive should be
195-
// parsed when we're parsing the attributes.
196-
break
197-
}
197+
// If we are at a `#if` of attributes, the `#if` directive should be
198+
// parsed when we're parsing the attributes.
199+
if self.at(.poundIfKeyword) && !self.withLookahead({ $0.consumeIfConfigOfAttributes() }) {
198200
let directive = self.parsePoundIfDirective { (parser, _) in
199201
let parsedDecl = parser.parseDeclaration()
200202
let semicolon = parser.consume(if: .semicolon)
@@ -220,8 +222,6 @@ extension Parser {
220222
return .decls(RawMemberDeclListSyntax(elements: elements, arena: parser.arena))
221223
}
222224
return RawDeclSyntax(directive)
223-
case nil:
224-
break
225225
}
226226

227227
let attrs = DeclAttributes(
@@ -2022,25 +2022,24 @@ extension Parser {
20222022
_ handle: RecoveryConsumptionHandle
20232023
) -> RawMacroExpansionDeclSyntax {
20242024

2025-
let (unexpectedBeforePound, poundKeyword) = self.eat(handle)
2026-
// Don't allow space between '#' and the macro name.
2027-
if poundKeyword.trailingTriviaByteLength != 0 || self.currentToken.leadingTriviaByteLength != 0 {
2028-
return RawMacroExpansionDeclSyntax(
2029-
attributes: attrs.attributes,
2030-
modifiers: attrs.modifiers,
2031-
unexpectedBeforePound,
2032-
poundToken: poundKeyword,
2033-
macro: self.missingToken(.identifier),
2034-
genericArguments: nil,
2035-
leftParen: nil,
2036-
argumentList: .init(elements: [], arena: self.arena),
2037-
rightParen: nil,
2038-
trailingClosure: nil,
2039-
additionalTrailingClosures: nil,
2040-
arena: self.arena
2041-
)
2025+
var (unexpectedBeforePound, pound) = self.eat(handle)
2026+
if pound.trailingTriviaByteLength != 0 {
2027+
// `#` and the macro name must not be separated by a newline.
2028+
unexpectedBeforePound = RawUnexpectedNodesSyntax(combining: unexpectedBeforePound, pound, arena: self.arena)
2029+
pound = RawTokenSyntax(missing: .pound, text: "#", leadingTriviaPieces: pound.leadingTriviaPieces, arena: self.arena)
2030+
}
2031+
var unexpectedBeforeMacro: RawUnexpectedNodesSyntax?
2032+
var macro: RawTokenSyntax
2033+
if !self.currentToken.isAtStartOfLine {
2034+
(unexpectedBeforeMacro, macro) = self.expectIdentifier(keywordRecovery: true)
2035+
if macro.leadingTriviaByteLength != 0 {
2036+
unexpectedBeforeMacro = RawUnexpectedNodesSyntax(combining: unexpectedBeforeMacro, macro, arena: self.arena)
2037+
pound = self.missingToken(.identifier, text: macro.tokenText)
2038+
}
2039+
} else {
2040+
unexpectedBeforeMacro = nil
2041+
macro = self.missingToken(.identifier)
20422042
}
2043-
let (unexpectedBeforeMacro, macro) = self.expectIdentifier(keywordRecovery: true)
20442043

20452044
// Parse the optional generic argument list.
20462045
let generics: RawGenericArgumentClauseSyntax?
@@ -2081,7 +2080,7 @@ extension Parser {
20812080
attributes: attrs.attributes,
20822081
modifiers: attrs.modifiers,
20832082
unexpectedBeforePound,
2084-
poundToken: poundKeyword,
2083+
poundToken: pound,
20852084
unexpectedBeforeMacro,
20862085
macro: macro,
20872086
genericArguments: generics,

Sources/SwiftParser/Expressions.swift

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,21 +1409,25 @@ extension Parser {
14091409
pattern: PatternContext,
14101410
flavor: ExprFlavor
14111411
) -> RawMacroExpansionExprSyntax {
1412-
if !atStartOfFreestandingMacroExpansion() {
1413-
return RawMacroExpansionExprSyntax(
1414-
poundToken: self.consumeAnyToken(),
1415-
macro: self.missingToken(.identifier),
1416-
genericArguments: nil,
1417-
leftParen: nil,
1418-
argumentList: .init(elements: [], arena: self.arena),
1419-
rightParen: nil,
1420-
trailingClosure: nil,
1421-
additionalTrailingClosures: nil,
1422-
arena: self.arena
1423-
)
1412+
var (unexpectedBeforePound, pound) = self.expect(.pound)
1413+
if pound.trailingTriviaByteLength != 0 {
1414+
// If there are whitespaces after '#' diagnose.
1415+
unexpectedBeforePound = RawUnexpectedNodesSyntax(combining: unexpectedBeforePound, pound, arena: self.arena)
1416+
pound = self.missingToken(.pound)
1417+
}
1418+
var unexpectedBeforeMacro: RawUnexpectedNodesSyntax?
1419+
var macro: RawTokenSyntax
1420+
if !self.currentToken.isAtStartOfLine {
1421+
(unexpectedBeforeMacro, macro) = self.expectIdentifier(keywordRecovery: true)
1422+
if macro.leadingTriviaByteLength != 0 {
1423+
// If there're whitespaces after '#' diagnose.
1424+
unexpectedBeforeMacro = RawUnexpectedNodesSyntax(combining: unexpectedBeforeMacro, macro, arena: self.arena)
1425+
pound = self.missingToken(.identifier, text: macro.tokenText)
1426+
}
1427+
} else {
1428+
unexpectedBeforeMacro = nil
1429+
macro = self.missingToken(.identifier)
14241430
}
1425-
let poundKeyword = self.consumeAnyToken()
1426-
let (unexpectedBeforeMacro, macro) = self.expectIdentifier(keywordRecovery: true)
14271431

14281432
// Parse the optional generic argument list.
14291433
let generics: RawGenericArgumentClauseSyntax?
@@ -1458,7 +1462,8 @@ extension Parser {
14581462
}
14591463

14601464
return RawMacroExpansionExprSyntax(
1461-
poundToken: poundKeyword,
1465+
unexpectedBeforePound,
1466+
poundToken: pound,
14621467
unexpectedBeforeMacro,
14631468
macro: macro,
14641469
genericArguments: generics,

Sources/SwiftParser/TokenSpecSet.swift

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -397,23 +397,6 @@ enum OperatorLike: TokenSpecSet {
397397
}
398398
}
399399

400-
enum PoundDeclarationStart: TokenSpecSet {
401-
case poundIfKeyword
402-
403-
init?(lexeme: Lexer.Lexeme) {
404-
switch lexeme.rawTokenKind {
405-
case .poundIfKeyword: self = .poundIfKeyword
406-
default: return nil
407-
}
408-
}
409-
410-
var spec: TokenSpec {
411-
switch self {
412-
case .poundIfKeyword: return .poundIfKeyword
413-
}
414-
}
415-
}
416-
417400
enum SwitchCaseStart: TokenSpecSet {
418401
case caseKeyword
419402
case defaultKeyword

Sources/SwiftParserDiagnostics/DiagnosticExtensions.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ extension FixIt.MultiNodeChange {
5959
/// removed node will be transferred to the trailing trivia of the previous token.
6060
static func makeMissing(_ tokens: [TokenSyntax], transferTrivia: Bool = true) -> Self {
6161
precondition(!tokens.isEmpty)
62-
precondition(tokens.allSatisfy({ $0.presence == .present }))
62+
precondition(tokens.allSatisfy({ $0.isPresent }))
6363
var changes = tokens.map {
6464
FixIt.Change.replace(
6565
oldNode: Syntax($0),
@@ -111,7 +111,7 @@ extension FixIt.MultiNodeChange {
111111
class MissingNodesBasicFormatter: BasicFormat {
112112
override func isMutable(_ token: TokenSyntax) -> Bool {
113113
// Assume that all missing nodes will be made present by the Fix-It.
114-
return token.presence == .missing
114+
return token.isMissing
115115
}
116116
}
117117

@@ -153,7 +153,7 @@ extension FixIt.MultiNodeChange {
153153
}
154154

155155
if let previousToken = node.previousToken(viewMode: .fixedUp),
156-
previousToken.presence == .present,
156+
previousToken.isPresent,
157157
let firstToken = node.firstToken(viewMode: .all),
158158
previousToken.trailingTrivia.allSatisfy({ $0.isWhitespace }),
159159
!BasicFormat().requiresWhitespace(between: previousToken, and: firstToken),

Sources/SwiftParserDiagnostics/MissingNodesError.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ fileprivate enum NodesDescriptionPart {
7171
for missingNode in nodes {
7272
if let token = missingNode.as(TokenSyntax.self) {
7373
let newPart: NodesDescriptionPart
74-
if token.presence == .present {
74+
if token.isPresent {
7575
newPart = .tokensWithDefaultText([token])
7676
} else {
7777
let (rawKind, text) = token.tokenKind.decomposeToRaw()
@@ -356,7 +356,7 @@ extension ParseDiagnosticsGenerator {
356356
let siblings = parentWithTokens.children(viewMode: .all)
357357
let siblingsAfter = siblings[siblings.index(after: index)...]
358358
for sibling in siblingsAfter {
359-
if sibling.as(TokenSyntax.self)?.presence == .missing {
359+
if sibling.as(TokenSyntax.self)?.isMissing ?? false {
360360
// Handle missing sibling tokens
361361
missingNodes += [sibling]
362362
} else if sibling.raw.kind.isMissing {

Sources/SwiftParserDiagnostics/MissingTokenError.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ extension ParseDiagnosticsGenerator {
105105

106106
if let identifier = missingToken.nextToken(viewMode: .all),
107107
identifier.tokenView.rawKind == .identifier,
108-
identifier.presence == .missing
108+
identifier.isMissing
109109
{
110110
// The extraneous whitespace caused a missing identifier, output a
111111
// diagnostic inserting it instead of a diagnostic to fix the trivia
@@ -123,7 +123,7 @@ extension ParseDiagnosticsGenerator {
123123
)
124124
} else {
125125
let fixIt = FixIt(message: .removeExtraneousWhitespace, changes: changes)
126-
addDiagnostic(invalidToken, .invalidWhitespaceAfterPeriod, fixIts: [fixIt], handledNodes: [invalidTokenContainer.id])
126+
addDiagnostic(invalidToken, ExtraneousWhitespace(tokenWithWhitespace: invalidToken), fixIts: [fixIt], handledNodes: [invalidTokenContainer.id])
127127
}
128128
return true
129129
}

0 commit comments

Comments
 (0)