Skip to content

Commit adbc285

Browse files
committed
Forbid newline after ::
This restricts the code styles developers can use, but makes it less likely to eat syntax that was meant to belong to a different statement after an incomplete line.
1 parent 2f40d65 commit adbc285

File tree

5 files changed

+189
-72
lines changed

5 files changed

+189
-72
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,8 @@ extension Parser {
451451
// Special case: scoped import with module selector-style syntax. This always has exactly two path components
452452
// separated by '::'.
453453
if hasImportKind,
454-
let (moduleNameOrUnexpected, colonColon, unexpectedAfterColonColon) = self.consumeModuleSelectorTokensIfPresent()
454+
let (moduleNameOrUnexpected, colonColon, unexpectedAfterColonColon, skipQualifiedName) =
455+
self.consumeModuleSelectorTokensIfPresent()
455456
{
456457
// Is the token in module name position really a module name?
457458
let unexpectedBeforeModuleName: RawUnexpectedNodesSyntax?, moduleName: RawTokenSyntax
@@ -463,7 +464,7 @@ extension Parser {
463464
moduleName = self.missingToken(.identifier)
464465
}
465466

466-
let declName = self.parseAnyIdentifier()
467+
let declName = skipQualifiedName ? self.missingToken(.identifier) : self.parseAnyIdentifier()
467468

468469
elements = [
469470
RawImportPathComponentSyntax(
@@ -2236,13 +2237,17 @@ extension Parser {
22362237
}
22372238

22382239
let moduleSelector: RawModuleSelectorSyntax?
2240+
if !self.atStartOfLine {
2241+
(moduleSelector, _) = self.parseModuleSelectorIfPresent()
2242+
} else {
2243+
moduleSelector = nil
2244+
}
2245+
22392246
let unexpectedBeforeMacro: RawUnexpectedNodesSyntax?
22402247
let macro: RawTokenSyntax
22412248
if !self.atStartOfLine {
2242-
moduleSelector = self.parseModuleSelectorIfPresent()
22432249
(unexpectedBeforeMacro, macro) = self.expectIdentifier(allowKeywordsAsIdentifier: true)
22442250
} else {
2245-
moduleSelector = nil
22462251
unexpectedBeforeMacro = nil
22472252
macro = self.missingToken(.identifier)
22482253
}

Sources/SwiftParser/Expressions.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1398,7 +1398,14 @@ extension Parser {
13981398
)
13991399
pound = pound.tokenView.withTokenDiagnostic(tokenDiagnostic: diagnostic, arena: self.arena)
14001400
}
1401-
let moduleSelector = parseModuleSelectorIfPresent()
1401+
1402+
let moduleSelector: RawModuleSelectorSyntax?
1403+
if !self.atStartOfLine {
1404+
(moduleSelector, _) = self.parseModuleSelectorIfPresent()
1405+
} else {
1406+
moduleSelector = nil
1407+
}
1408+
14021409
let unexpectedBeforeMacroName: RawUnexpectedNodesSyntax?
14031410
let macroName: RawTokenSyntax
14041411
if !self.atStartOfLine {

Sources/SwiftParser/Names.swift

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,9 @@ extension TokenConsumer {
8383
/// - `colonColonToken`: The `::` indicating this module selector. Always `.colonColon`, always present.
8484
/// - `extra`: Tokens for additional trailing module selectors. There is no situation in which two module selectors
8585
/// can be validly chained.
86+
/// - `skipQualifiedName`: True if the next token should be interpreted as a different statement.
8687
mutating func consumeModuleSelectorTokensIfPresent() -> (
87-
moduleNameOrUnexpected: Token, colonColonToken: Token, extra: [Token]
88+
moduleNameOrUnexpected: Token, colonColonToken: Token, extra: [Token], skipQualifiedName: Bool
8889
)? {
8990
guard self.isAtModuleSelector() else {
9091
return nil
@@ -111,15 +112,21 @@ extension TokenConsumer {
111112
}
112113
extra.append(self.eat(.colonColon))
113114
}
114-
return (moduleName, colonColonToken, extra)
115+
116+
let afterContainsAnyNewline = self.atStartOfLine
117+
118+
return (moduleName, colonColonToken, extra, afterContainsAnyNewline)
115119
}
116120
}
117121

118122
extension Parser {
119123
/// Parses one or more module selectors, if present.
120-
mutating func parseModuleSelectorIfPresent() -> RawModuleSelectorSyntax? {
121-
guard let (moduleNameOrUnexpected, colonColon, extra) = consumeModuleSelectorTokensIfPresent() else {
122-
return nil
124+
mutating func parseModuleSelectorIfPresent() -> (moduleSelector: RawModuleSelectorSyntax?, skipQualifiedName: Bool) {
125+
guard
126+
let (moduleNameOrUnexpected, colonColon, extra, skipQualifiedName) =
127+
consumeModuleSelectorTokensIfPresent()
128+
else {
129+
return (nil, false)
123130
}
124131

125132
let leadingUnexpected: [RawSyntax]
@@ -136,12 +143,15 @@ extension Parser {
136143

137144
trailingUnexpected = extra.map { RawSyntax($0) }
138145

139-
return RawModuleSelectorSyntax(
140-
RawUnexpectedNodesSyntax(leadingUnexpected, arena: arena),
141-
moduleName: moduleName,
142-
colonColon: colonColon,
143-
RawUnexpectedNodesSyntax(trailingUnexpected, arena: arena),
144-
arena: arena
146+
return (
147+
moduleSelector: RawModuleSelectorSyntax(
148+
RawUnexpectedNodesSyntax(leadingUnexpected, arena: arena),
149+
moduleName: moduleName,
150+
colonColon: colonColon,
151+
RawUnexpectedNodesSyntax(trailingUnexpected, arena: arena),
152+
arena: arena
153+
),
154+
skipQualifiedName: skipQualifiedName
145155
)
146156
}
147157
}
@@ -169,29 +179,8 @@ extension Parser {
169179
}
170180

171181
mutating func parseDeclReferenceExpr(_ flags: DeclNameOptions = []) -> RawDeclReferenceExprSyntax {
172-
// Consume a module selector if present.
173-
let moduleSelector = self.parseModuleSelectorIfPresent()
174-
175-
// If a module selector is found, we parse the name after it according to SE-0071 rules.
176-
let allowKeywords = flags.contains(.keywords) || moduleSelector != nil
177-
178-
// Consume the base name.
179-
let base: RawTokenSyntax
180-
if let identOrSelf = self.consume(if: .identifier, .keyword(.self), .keyword(.Self))
181-
?? self.consume(if: .keyword(.`init`))
182-
{
183-
base = identOrSelf
184-
} else if flags.contains(.operators), let (_, _) = self.at(anyIn: Operator.self) {
185-
base = self.consumeAnyToken(remapping: .binaryOperator)
186-
} else if flags.contains(.keywordsUsingSpecialNames),
187-
let special = self.consume(if: .keyword(.`deinit`), .keyword(.`subscript`))
188-
{
189-
base = special
190-
} else if allowKeywords && self.currentToken.isLexerClassifiedKeyword {
191-
base = self.consumeAnyToken(remapping: .identifier)
192-
} else {
193-
base = missingToken(.identifier)
194-
}
182+
// Consume the module selector, if present, and base name.
183+
let (moduleSelector, base) = self.parseDeclReferenceBase(flags)
195184

196185
// Parse an argument list, if the flags allow it and it's present.
197186
let args = self.parseArgLabelList(flags)
@@ -203,6 +192,35 @@ extension Parser {
203192
)
204193
}
205194

195+
private mutating func parseDeclReferenceBase(
196+
_ flags: DeclNameOptions
197+
) -> (moduleSelector: RawModuleSelectorSyntax?, base: RawTokenSyntax) {
198+
// Consume a module selector if present.
199+
let (moduleSelector, skipQualifiedName) = self.parseModuleSelectorIfPresent()
200+
201+
// Consume the base name.
202+
if !skipQualifiedName {
203+
if let identOrInit = self.consume(if: .identifier, .keyword(.`init`)) {
204+
return (moduleSelector, identOrInit)
205+
}
206+
if moduleSelector == nil, let selfOrSelf = self.consume(if: .keyword(.`self`), .keyword(.`Self`)) {
207+
return (moduleSelector, selfOrSelf)
208+
}
209+
if flags.contains(.operators), let (_, _) = self.at(anyIn: Operator.self) {
210+
return (moduleSelector, self.consumeAnyToken(remapping: .binaryOperator))
211+
}
212+
if flags.contains(.keywordsUsingSpecialNames),
213+
let special = self.consume(if: .keyword(.`deinit`), .keyword(.`subscript`))
214+
{
215+
return (moduleSelector, special)
216+
}
217+
if (flags.contains(.keywords) || moduleSelector != nil) && self.currentToken.isLexerClassifiedKeyword {
218+
return (moduleSelector, self.consumeAnyToken(remapping: .identifier))
219+
}
220+
}
221+
return (moduleSelector, missingToken(.identifier))
222+
}
223+
206224
mutating func parseArgLabelList(_ flags: DeclNameOptions) -> RawDeclNameArgumentsSyntax? {
207225
guard flags.contains(.compoundNames) else {
208226
return nil
@@ -319,8 +337,8 @@ extension Parser {
319337
var keepGoing = self.consume(if: .period)
320338
var loopProgress = LoopProgressCondition()
321339
while keepGoing != nil && self.hasProgressed(&loopProgress) {
322-
let memberModuleSelector = self.parseModuleSelectorIfPresent()
323-
let name = self.parseMemberTypeName()
340+
let (memberModuleSelector, skipQualifiedName) = self.parseModuleSelectorIfPresent()
341+
let name = self.parseMemberTypeName(moduleSelector: memberModuleSelector, skipName: skipQualifiedName)
324342
let generics: RawGenericArgumentClauseSyntax?
325343
if self.at(prefix: "<") {
326344
generics = self.parseGenericArguments()
@@ -338,7 +356,7 @@ extension Parser {
338356
)
339357
)
340358

341-
guard hasAnotherMember() else {
359+
guard !skipQualifiedName && hasAnotherMember() else {
342360
break
343361
}
344362

Sources/SwiftParser/Types.swift

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,8 @@ extension Parser {
293293
)
294294
)
295295
} else {
296-
let memberModuleSelector = self.parseModuleSelectorIfPresent()
297-
let name: RawTokenSyntax = self.parseMemberTypeName()
296+
let (memberModuleSelector, skipQualifiedName) = self.parseModuleSelectorIfPresent()
297+
let name = self.parseMemberTypeName(moduleSelector: memberModuleSelector, skipName: skipQualifiedName)
298298
let generics: RawGenericArgumentClauseSyntax?
299299
if self.at(prefix: "<") {
300300
generics = self.parseGenericArguments()
@@ -312,6 +312,9 @@ extension Parser {
312312
arena: self.arena
313313
)
314314
)
315+
if skipQualifiedName {
316+
break
317+
}
315318
}
316319
continue
317320
}
@@ -336,16 +339,39 @@ extension Parser {
336339
return base
337340
}
338341

342+
/// Parse a type name that has been qualiified by a module selector. This very aggressively interprets keywords as
343+
/// identifiers.
344+
///
345+
/// - Parameter skipQualifiedName: If `true`, the next token should not be parsed because it includes forbidden whitespace.
346+
mutating func parseTypeNameAfterModuleSelector(skipQualifiedName: Bool) -> RawTokenSyntax {
347+
if !skipQualifiedName {
348+
if let identifier = self.consume(if: .identifier) {
349+
return identifier
350+
} else if self.currentToken.isLexerClassifiedKeyword {
351+
return self.consumeAnyToken(remapping: .identifier)
352+
}
353+
}
354+
return missingToken(.identifier)
355+
}
356+
339357
/// Parse the name of a member type, which may be a keyword that's
340358
/// interpreted as an identifier (per SE-0071).
341-
mutating func parseMemberTypeName() -> RawTokenSyntax {
342-
if let handle = self.at(anyIn: MemberTypeSyntax.NameOptions.self)?.handle {
343-
return self.eat(handle)
344-
} else if self.currentToken.isLexerClassifiedKeyword {
345-
return self.consumeAnyToken(remapping: .identifier)
346-
} else {
347-
return missingToken(.identifier)
359+
///
360+
/// - Parameter moduleSelector: The module selector that will be attached to this name, if any.
361+
/// - Parameter skipName: If `true`, the next token should not be parsed because it includes forbidden whitespace.
362+
mutating func parseMemberTypeName(moduleSelector: RawModuleSelectorSyntax?, skipName: Bool) -> RawTokenSyntax {
363+
if moduleSelector != nil {
364+
return self.parseTypeNameAfterModuleSelector(skipQualifiedName: skipName)
365+
}
366+
367+
if !skipName {
368+
if let handle = self.at(anyIn: MemberTypeSyntax.NameOptions.self)?.handle {
369+
return self.eat(handle)
370+
} else if self.currentToken.isLexerClassifiedKeyword {
371+
return self.consumeAnyToken(remapping: .identifier)
372+
}
348373
}
374+
return missingToken(.identifier)
349375
}
350376

351377
/// Parse an optional type.
@@ -374,7 +400,7 @@ extension Parser {
374400

375401
/// Parse a type identifier.
376402
mutating func parseTypeIdentifier() -> RawIdentifierTypeSyntax {
377-
let moduleSelector = self.parseModuleSelectorIfPresent()
403+
let (moduleSelector, skipQualifiedName) = self.parseModuleSelectorIfPresent()
378404

379405
if moduleSelector == nil && self.at(.keyword(.Any)) {
380406
return self.parseAnyType()
@@ -384,10 +410,10 @@ extension Parser {
384410
if moduleSelector == nil {
385411
(unexpectedBeforeName, name) = self.expect(anyIn: IdentifierTypeSyntax.NameOptions.self, default: .identifier)
386412
} else {
387-
// A name after a module selector gets parsed like a member
388413
unexpectedBeforeName = nil
389-
name = self.parseMemberTypeName()
414+
name = self.parseTypeNameAfterModuleSelector(skipQualifiedName: skipQualifiedName)
390415
}
416+
391417
let generics: RawGenericArgumentClauseSyntax?
392418
if self.at(prefix: "<") {
393419
generics = self.parseGenericArguments()

0 commit comments

Comments
 (0)