Skip to content

Commit 97513d6

Browse files
committed
wip Parse module selectors in most valid locations
This commit ports over tests from the compiler’s (future) `test/NameLookup/module_selector.swift` file and makes sure the correct uses parse as expected. It also tests that ill-formed module selectors (ones with a missing or non-identifier module name) are diagnosed correctly. This commit doesn’t fully handle recovery from module selectors inserted at invalid locations; the test cases that require recovery are XFAILed. TODO: • Add assertions about syntax tree nodes for valid parses
1 parent 580734b commit 97513d6

File tree

7 files changed

+2026
-34
lines changed

7 files changed

+2026
-34
lines changed

Sources/SwiftParser/Attributes.swift

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,11 @@ extension Parser {
227227
)
228228
}
229229

230-
switch peek(isAtAnyIn: DeclarationAttributeWithSpecialSyntax.self) {
230+
// An attribute qualified by a module selector is *always* a custom attribute, even if it has the same name (or
231+
// module name) as a builtin attribute.
232+
let builtinAttr = self.unlessPeekModuleSelector { $0.peek(isAtAnyIn: DeclarationAttributeWithSpecialSyntax.self) }
233+
234+
switch builtinAttr {
231235
case .abi:
232236
return parseAttribute(argumentMode: .required) { parser in
233237
return (nil, .abiArguments(parser.parseABIAttributeArguments()))
@@ -680,7 +684,11 @@ extension Parser {
680684
case (.target, let handle)?:
681685
let label = self.eat(handle)
682686
let (unexpectedBeforeColon, colon) = self.expect(.colon)
683-
let declName = self.parseDeclReferenceExpr([.zeroArgCompoundNames, .keywordsUsingSpecialNames, .operators])
687+
let moduleSelector = self.parseModuleSelector()
688+
let declName = self.parseDeclReferenceExpr(
689+
moduleSelector: moduleSelector,
690+
[.zeroArgCompoundNames, .keywordsUsingSpecialNames, .operators]
691+
)
684692
let comma = self.consume(if: .comma)
685693
elements.append(
686694
.specializeTargetFunctionArgument(
@@ -783,14 +791,17 @@ extension Parser {
783791
mutating func parseImplementsAttributeArguments() -> RawImplementsAttributeArgumentsSyntax {
784792
let type = self.parseType()
785793
let (unexpectedBeforeComma, comma) = self.expect(.comma)
786-
let declName = self.parseDeclReferenceExpr([
787-
.zeroArgCompoundNames,
788-
.operators,
789-
])
794+
795+
// You can't put a module selector on the member name--it's meaningless because the member has to come from the
796+
// same module as the protocol.
797+
let moduleSelector = self.parseModuleSelector()
798+
let declName = self.parseDeclReferenceExpr(moduleSelector: nil, [.zeroArgCompoundNames, .operators])
799+
790800
return RawImplementsAttributeArgumentsSyntax(
791801
type: type,
792802
unexpectedBeforeComma,
793803
comma: comma,
804+
unexpected(moduleSelector),
794805
declName: declName,
795806
arena: self.arena
796807
)
@@ -930,6 +941,7 @@ extension Parser {
930941
mutating func parseDynamicReplacementAttributeArguments() -> RawDynamicReplacementAttributeArgumentsSyntax {
931942
let (unexpectedBeforeLabel, label) = self.expect(.keyword(.for))
932943
let (unexpectedBeforeColon, colon) = self.expect(.colon)
944+
933945
let declName: RawDeclReferenceExprSyntax
934946
if label.isMissing && colon.isMissing && self.atStartOfLine {
935947
declName = RawDeclReferenceExprSyntax(
@@ -939,9 +951,11 @@ extension Parser {
939951
arena: self.arena
940952
)
941953
} else {
942-
declName = self.parseDeclReferenceExpr([
943-
.zeroArgCompoundNames, .keywordsUsingSpecialNames, .operators,
944-
])
954+
let moduleSelector = self.parseModuleSelector()
955+
declName = self.parseDeclReferenceExpr(
956+
moduleSelector: moduleSelector,
957+
[.zeroArgCompoundNames, .keywordsUsingSpecialNames, .operators]
958+
)
945959
}
946960
return RawDynamicReplacementAttributeArgumentsSyntax(
947961
unexpectedBeforeLabel,
@@ -1006,7 +1020,7 @@ extension Parser {
10061020
unexpectedBeforeValue = unexpected
10071021
value = .token(token)
10081022
case "metadata":
1009-
unexpectedBeforeValue = nil
1023+
unexpectedBeforeValue = unexpected(self.parseModuleSelector())
10101024
if let identifier = self.consume(if: .identifier) {
10111025
value = .token(identifier)
10121026
} else {

Sources/SwiftParser/Expressions.swift

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818

1919
extension TokenConsumer {
2020
mutating func atStartOfExpression() -> Bool {
21+
if self.isAtModuleSelector() {
22+
var lookahead = self.lookahead()
23+
_ = lookahead.consumeModuleSelectorTokens()
24+
return lookahead.atStartOfExpression()
25+
}
26+
2127
switch self.at(anyIn: ExpressionStart.self) {
2228
case (.awaitTryMove, let handle)?:
2329
var lookahead = self.lookahead()
@@ -572,6 +578,11 @@ extension Parser {
572578
flavor: ExprFlavor,
573579
pattern: PatternContext = .none
574580
) -> RawExprSyntax {
581+
if let moduleSelector = self.parseModuleSelector() {
582+
let qualifiedExpr = self.parseUnaryExpression(flavor: flavor, pattern: pattern)
583+
return attach(moduleSelector, to: qualifiedExpr)
584+
}
585+
575586
// Try parse a single value statement as an expression (e.g do/if/switch).
576587
// Note we do this here in parseUnaryExpression as we don't allow postfix
577588
// syntax to be attached to such expressions to avoid ambiguities such as postfix
@@ -660,19 +671,22 @@ extension Parser {
660671
return (unexpectedPeriod, period, declName, nil)
661672
}
662673

674+
let moduleSelector = parseModuleSelector()
675+
663676
// Parse the name portion.
664677
let declName: RawDeclReferenceExprSyntax
665678
if let indexOrSelf = self.consume(if: .integerLiteral, .keyword(.self)) {
666679
// Handle "x.42" - a tuple index.
667680
declName = RawDeclReferenceExprSyntax(
681+
unexpected(moduleSelector),
668682
moduleSelector: nil,
669683
baseName: indexOrSelf,
670684
argumentNames: nil,
671685
arena: self.arena
672686
)
673687
} else {
674688
// Handle an arbitrary declaration name.
675-
declName = self.parseDeclReferenceExpr([.keywords, .compoundNames])
689+
declName = self.parseDeclReferenceExpr(moduleSelector: moduleSelector, [.keywords, .compoundNames])
676690
}
677691

678692
// Parse the generic arguments, if any.
@@ -1248,11 +1262,11 @@ extension Parser {
12481262
// is the start of an enum or expr pattern.
12491263
if pattern.admitsBinding && self.lookahead().isInBindingPatternPosition() {
12501264
let identifier = self.eat(handle)
1251-
let pattern = RawIdentifierPatternSyntax(
1265+
let patternNode = RawIdentifierPatternSyntax(
12521266
identifier: identifier,
12531267
arena: self.arena
12541268
)
1255-
return RawExprSyntax(RawPatternExprSyntax(pattern: pattern, arena: self.arena))
1269+
return RawExprSyntax(RawPatternExprSyntax(pattern: patternNode, arena: self.arena))
12561270
}
12571271

12581272
return self.parseIdentifierExpression(flavor: flavor)
@@ -1316,7 +1330,10 @@ extension Parser {
13161330
)
13171331
}
13181332

1319-
let declName = self.parseDeclReferenceExpr([.keywords, .compoundNames])
1333+
// If there's a module selector after the period, parse and use it.
1334+
let moduleSelector = self.parseModuleSelector()
1335+
let declName = self.parseDeclReferenceExpr(moduleSelector: moduleSelector, [.keywords, .compoundNames])
1336+
13201337
return RawExprSyntax(
13211338
RawMemberAccessExprSyntax(
13221339
base: nil,
@@ -1354,7 +1371,8 @@ extension Parser {
13541371
case .attributeArguments: options.insert(.keywordsUsingSpecialNames)
13551372
}
13561373

1357-
let declName = self.parseDeclReferenceExpr(options)
1374+
// If something up the call stack has parsed a module selector, it will be attached using `attach(_:to:)`.
1375+
let declName = self.parseDeclReferenceExpr(moduleSelector: nil, options)
13581376
guard self.withLookahead({ $0.canParseAsGenericArgumentList() }) else {
13591377
return RawExprSyntax(declName)
13601378
}
@@ -1385,6 +1403,7 @@ extension Parser {
13851403
)
13861404
pound = pound.tokenView.withTokenDiagnostic(tokenDiagnostic: diagnostic, arena: self.arena)
13871405
}
1406+
let moduleSelector = parseModuleSelector()
13881407
let unexpectedBeforeMacroName: RawUnexpectedNodesSyntax?
13891408
let macroName: RawTokenSyntax
13901409
if !self.atStartOfLine {
@@ -1432,7 +1451,7 @@ extension Parser {
14321451
return RawMacroExpansionExprSyntax(
14331452
unexpectedBeforePound,
14341453
pound: pound,
1435-
moduleSelector: nil,
1454+
moduleSelector: moduleSelector,
14361455
unexpectedBeforeMacroName,
14371456
macroName: macroName,
14381457
genericArgumentClause: generics,
@@ -1746,6 +1765,7 @@ extension Parser {
17461765
extension Parser {
17471766
mutating func parseAnonymousClosureArgument() -> RawDeclReferenceExprSyntax {
17481767
let (unexpectedBeforeBaseName, baseName) = self.expect(.dollarIdentifier)
1768+
// If something up the call stack has parsed a module selector, it will be attached using `attach(_:to:)`.
17491769
return RawDeclReferenceExprSyntax(
17501770
moduleSelector: nil,
17511771
unexpectedBeforeBaseName,
@@ -1969,6 +1989,14 @@ extension Parser {
19691989
}
19701990
}
19711991

1992+
extension TokenConsumer {
1993+
mutating func atBinaryOperatorArgument() -> Bool {
1994+
var lookahead = self.lookahead()
1995+
_ = lookahead.consumeModuleSelectorTokens()
1996+
return lookahead.at(.binaryOperator) && lookahead.peek(isAt: .comma, .rightParen, .rightSquare)
1997+
}
1998+
}
1999+
19722000
extension Parser {
19732001
/// Parse the elements of an argument list.
19742002
///
@@ -2020,8 +2048,9 @@ extension Parser {
20202048
// this case lexes as a binary operator because it neither leads nor
20212049
// follows a proper subexpression.
20222050
let expr: RawExprSyntax
2023-
if self.at(.binaryOperator) && self.peek(isAt: .comma, .rightParen, .rightSquare) {
2024-
expr = RawExprSyntax(self.parseDeclReferenceExpr(.operators))
2051+
if self.atBinaryOperatorArgument() {
2052+
let moduleSelector = self.parseModuleSelector()
2053+
expr = RawExprSyntax(self.parseDeclReferenceExpr(moduleSelector: moduleSelector, .operators))
20252054
} else {
20262055
expr = self.parseExpression(flavor: flavor, pattern: pattern)
20272056
}
@@ -2400,9 +2429,9 @@ extension Parser {
24002429

24012430
unknownAttr = RawAttributeSyntax(
24022431
atSign: at,
2403-
unexpectedBeforeIdent,
24042432
attributeName: RawIdentifierTypeSyntax(
24052433
moduleSelector: nil,
2434+
unexpectedBeforeIdent,
24062435
name: ident,
24072436
genericArgumentClause: nil,
24082437
arena: self.arena

0 commit comments

Comments
 (0)