From 339cf7a233438e50f23e4107ed83197b717bf79f Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Thu, 22 May 2025 20:13:37 -0700 Subject: [PATCH 01/15] [NFC] Thread experimental features through lexer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This capability is currently unused, but it’ll matter soon. --- Sources/SwiftParser/Lexer/Cursor.swift | 19 ++++++++++++++----- .../SwiftParser/Lexer/LexemeSequence.swift | 17 +++++++++++++---- Sources/SwiftParser/Parser.swift | 6 +++++- ...StringLiteralRepresentedLiteralValue.swift | 2 +- Sources/SwiftParser/TriviaParser.swift | 4 +++- Tests/SwiftParserTest/Assertions.swift | 8 +++++++- Tests/SwiftParserTest/LexerTests.swift | 6 +++--- 7 files changed, 46 insertions(+), 16 deletions(-) diff --git a/Sources/SwiftParser/Lexer/Cursor.swift b/Sources/SwiftParser/Lexer/Cursor.swift index 855f0995dcf..0386f4c3eba 100644 --- a/Sources/SwiftParser/Lexer/Cursor.swift +++ b/Sources/SwiftParser/Lexer/Cursor.swift @@ -255,6 +255,8 @@ extension Lexer { } var position: Position + var experimentalFeatures: Parser.ExperimentalFeatures + /// If we have already lexed a token, the kind of the previously lexed token var previousTokenKind: RawTokenKind? @@ -267,8 +269,9 @@ extension Lexer { private var stateStack: StateStack = StateStack() - init(input: UnsafeBufferPointer, previous: UInt8) { + init(input: UnsafeBufferPointer, previous: UInt8, experimentalFeatures: Parser.ExperimentalFeatures) { self.position = Position(input: input, previous: previous) + self.experimentalFeatures = experimentalFeatures } /// Returns `true` if this cursor is sufficiently different to `other` in a way that indicates that the lexer has @@ -2472,7 +2475,7 @@ extension Lexer.Cursor { return false } - guard let end = Self.findConflictEnd(start, markerKind: kind) else { + guard let end = Self.findConflictEnd(start, markerKind: kind, experimentalFeatures: experimentalFeatures) else { // No end of conflict marker found. return false } @@ -2488,13 +2491,18 @@ extension Lexer.Cursor { } /// Find the end of a version control conflict marker. - static func findConflictEnd(_ curPtr: Lexer.Cursor, markerKind: ConflictMarker) -> Lexer.Cursor? { + static func findConflictEnd( + _ curPtr: Lexer.Cursor, + markerKind: ConflictMarker, + experimentalFeatures: Parser.ExperimentalFeatures + ) -> Lexer.Cursor? { // Get a reference to the rest of the buffer minus the length of the start // of the conflict marker. let advanced = curPtr.input.baseAddress?.advanced(by: markerKind.introducer.count) var restOfBuffer = Lexer.Cursor( input: .init(start: advanced, count: curPtr.input.count - markerKind.introducer.count), - previous: curPtr.input[markerKind.introducer.count - 1] + previous: curPtr.input[markerKind.introducer.count - 1], + experimentalFeatures: experimentalFeatures ) let terminator = markerKind.terminator let terminatorStart = terminator.first! @@ -2515,7 +2523,8 @@ extension Lexer.Cursor { let advanced = restOfBuffer.input.baseAddress?.advanced(by: terminator.count) return Lexer.Cursor( input: .init(start: advanced, count: restOfBuffer.input.count - terminator.count), - previous: restOfBuffer.input[terminator.count - 1] + previous: restOfBuffer.input[terminator.count - 1], + experimentalFeatures: experimentalFeatures ) } return nil diff --git a/Sources/SwiftParser/Lexer/LexemeSequence.swift b/Sources/SwiftParser/Lexer/LexemeSequence.swift index e64d976f12d..1f9950aae18 100644 --- a/Sources/SwiftParser/Lexer/LexemeSequence.swift +++ b/Sources/SwiftParser/Lexer/LexemeSequence.swift @@ -152,12 +152,21 @@ extension Lexer { public static func tokenize( _ input: UnsafeBufferPointer, from startIndex: Int = 0, - lookaheadTracker: UnsafeMutablePointer + lookaheadTracker: UnsafeMutablePointer, + experimentalFeatures: Parser.ExperimentalFeatures ) -> LexemeSequence { precondition(input.isEmpty || startIndex < input.endIndex) let startChar = startIndex == input.startIndex ? UInt8(ascii: "\0") : input[startIndex - 1] - let start = Cursor(input: input, previous: UInt8(ascii: "\0")) - let cursor = Cursor(input: UnsafeBufferPointer(rebasing: input[startIndex...]), previous: startChar) - return LexemeSequence(sourceBufferStart: start, cursor: cursor, lookaheadTracker: lookaheadTracker) + let start = Cursor(input: input, previous: UInt8(ascii: "\0"), experimentalFeatures: experimentalFeatures) + let cursor = Cursor( + input: UnsafeBufferPointer(rebasing: input[startIndex...]), + previous: startChar, + experimentalFeatures: experimentalFeatures + ) + return LexemeSequence( + sourceBufferStart: start, + cursor: cursor, + lookaheadTracker: lookaheadTracker + ) } } diff --git a/Sources/SwiftParser/Parser.swift b/Sources/SwiftParser/Parser.swift index dfe5ec65779..36e79b0da5a 100644 --- a/Sources/SwiftParser/Parser.swift +++ b/Sources/SwiftParser/Parser.swift @@ -240,7 +240,11 @@ public struct Parser { self.experimentalFeatures = experimentalFeatures self.lookaheadTrackerOwner = LookaheadTrackerOwner() - self.lexemes = Lexer.tokenize(input, lookaheadTracker: lookaheadTrackerOwner.lookaheadTracker) + self.lexemes = Lexer.tokenize( + input, + lookaheadTracker: lookaheadTrackerOwner.lookaheadTracker, + experimentalFeatures: experimentalFeatures + ) self.currentToken = self.lexemes.advance() if let parseTransition { self.parseLookup = IncrementalParseLookup(transition: parseTransition) diff --git a/Sources/SwiftParser/StringLiteralRepresentedLiteralValue.swift b/Sources/SwiftParser/StringLiteralRepresentedLiteralValue.swift index ad7c9d6e944..d4d30e62b50 100644 --- a/Sources/SwiftParser/StringLiteralRepresentedLiteralValue.swift +++ b/Sources/SwiftParser/StringLiteralRepresentedLiteralValue.swift @@ -90,7 +90,7 @@ extension StringSegmentSyntax { } rawText.withBuffer { buffer in - var cursor = Lexer.Cursor(input: buffer, previous: 0) + var cursor = Lexer.Cursor(input: buffer, previous: 0, experimentalFeatures: []) // Put the cursor in the string literal lexing state. This is just // defensive as it's currently not used by `lexCharacterInStringLiteral`. diff --git a/Sources/SwiftParser/TriviaParser.swift b/Sources/SwiftParser/TriviaParser.swift index e6fe482c8d8..4ef4d3fe9f5 100644 --- a/Sources/SwiftParser/TriviaParser.swift +++ b/Sources/SwiftParser/TriviaParser.swift @@ -25,7 +25,9 @@ public struct TriviaParser { var pieces: [RawTriviaPiece] = [] var cursor = Lexer.Cursor( input: UnsafeBufferPointer(start: source.baseAddress, count: source.count), - previous: 0 + previous: 0, + // There are currently no experimental features that affect trivia parsing. + experimentalFeatures: [] ) while true { diff --git a/Tests/SwiftParserTest/Assertions.swift b/Tests/SwiftParserTest/Assertions.swift index cb537012a3c..da6f7008056 100644 --- a/Tests/SwiftParserTest/Assertions.swift +++ b/Tests/SwiftParserTest/Assertions.swift @@ -190,6 +190,7 @@ private func assertTokens( func assertLexemes( _ markedSource: String, lexemes expectedLexemes: [LexemeSpec], + experimentalFeatures: Parser.ExperimentalFeatures = [], file: StaticString = #filePath, line: UInt = #line ) { @@ -206,7 +207,12 @@ func assertLexemes( lookaheadTracker.initialize(to: LookaheadTracker()) source.withUTF8 { buf in var lexemes = [Lexer.Lexeme]() - for token in Lexer.tokenize(buf, from: 0, lookaheadTracker: lookaheadTracker) { + for token in Lexer.tokenize( + buf, + from: 0, + lookaheadTracker: lookaheadTracker, + experimentalFeatures: experimentalFeatures + ) { lexemes.append(token) if token.rawTokenKind == .endOfFile { diff --git a/Tests/SwiftParserTest/LexerTests.swift b/Tests/SwiftParserTest/LexerTests.swift index 876958ea385..c12424537f7 100644 --- a/Tests/SwiftParserTest/LexerTests.swift +++ b/Tests/SwiftParserTest/LexerTests.swift @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// -@_spi(RawSyntax) @_spi(Testing) import SwiftParser -@_spi(RawSyntax) import SwiftSyntax +@_spi(RawSyntax) @_spi(Testing) @_spi(ExperimentalLanguageFeatures) import SwiftParser +@_spi(RawSyntax) @_spi(ExperimentalLanguageFeatures) import SwiftSyntax import XCTest private func lex(_ sourceBytes: [UInt8], body: ([Lexer.Lexeme]) throws -> Void) rethrows { @@ -22,7 +22,7 @@ private func lex(_ sourceBytes: [UInt8], body: ([Lexer.Lexeme]) throws -> Void) lookaheadTracker.initialize(to: LookaheadTracker()) try sourceBytes.withUnsafeBufferPointer { (buf) in var lexemes = [Lexer.Lexeme]() - for token in Lexer.tokenize(buf, from: 0, lookaheadTracker: lookaheadTracker) { + for token in Lexer.tokenize(buf, from: 0, lookaheadTracker: lookaheadTracker, experimentalFeatures: []) { lexemes.append(token) if token.rawTokenKind == .endOfFile { From e745408bfcc0bd4c0b529f84fad45d7bd0c3e94d Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Tue, 5 Aug 2025 15:52:19 -0700 Subject: [PATCH 02/15] Add experimental colonColon token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And make sure it doesn’t break Objective-C selector lexing. --- .../SyntaxSupport/ExperimentalFeatures.swift | 5 ++ .../Sources/SyntaxSupport/TokenSpec.swift | 3 + .../SwiftIDEUtils/SyntaxClassification.swift | 2 + Sources/SwiftParser/Attributes.swift | 7 +- Sources/SwiftParser/Lexer/Cursor.swift | 10 ++- .../SwiftParser/Lexer/RegexLiteralLexer.swift | 6 +- Sources/SwiftParser/Parser.swift | 19 +++++ Sources/SwiftParser/Statements.swift | 3 + Sources/SwiftParser/TokenPrecedence.swift | 2 +- .../generated/ExperimentalFeatures.swift | 5 ++ .../generated/TokenSpecStaticMembers.swift | 4 + .../generated/TokenNameForDiagnostics.swift | 2 + Sources/SwiftSyntax/generated/TokenKind.swift | 19 +++++ Sources/SwiftSyntax/generated/Tokens.swift | 13 ++++ Tests/SwiftParserTest/AttributeTests.swift | 14 +++- Tests/SwiftParserTest/LexerTests.swift | 75 +++++++++++++++++++ 16 files changed, 182 insertions(+), 7 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift index 2823bf6f3d0..f14f1de8e9d 100644 --- a/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift +++ b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift @@ -22,6 +22,7 @@ public enum ExperimentalFeature: String, CaseIterable { case keypathWithMethodMembers case oldOwnershipOperatorSpellings case defaultIsolationPerFile + case moduleSelector /// The name of the feature as it is written in the compiler's `Features.def` file. public var featureName: String { @@ -44,6 +45,8 @@ public enum ExperimentalFeature: String, CaseIterable { return "OldOwnershipOperatorSpellings" case .defaultIsolationPerFile: return "DefaultIsolationPerFile" + case .moduleSelector: + return "ModuleSelector" } } @@ -68,6 +71,8 @@ public enum ExperimentalFeature: String, CaseIterable { return "`_move` and `_borrow` as ownership operators" case .defaultIsolationPerFile: return "set default actor isolation for a file" + case .moduleSelector: + return "Module selector syntax (`ModName::identifier`)" } } diff --git a/CodeGeneration/Sources/SyntaxSupport/TokenSpec.swift b/CodeGeneration/Sources/SyntaxSupport/TokenSpec.swift index 2abbc28adc8..b276a715251 100644 --- a/CodeGeneration/Sources/SyntaxSupport/TokenSpec.swift +++ b/CodeGeneration/Sources/SyntaxSupport/TokenSpec.swift @@ -126,6 +126,7 @@ public enum Token: CaseIterable { case backtick case binaryOperator case colon + case colonColon case comma case dollarIdentifier case ellipsis @@ -185,6 +186,8 @@ public enum Token: CaseIterable { return .other(name: "binaryOperator", nameForDiagnostics: "binary operator") case .colon: return .punctuator(name: "colon", text: ":") + case .colonColon: + return .punctuator(name: "colonColon", text: "::") case .comma: return .punctuator(name: "comma", text: ",") case .dollarIdentifier: diff --git a/Sources/SwiftIDEUtils/SyntaxClassification.swift b/Sources/SwiftIDEUtils/SyntaxClassification.swift index 1979483c777..92a35d91723 100644 --- a/Sources/SwiftIDEUtils/SyntaxClassification.swift +++ b/Sources/SwiftIDEUtils/SyntaxClassification.swift @@ -114,6 +114,8 @@ extension RawTokenKind { return .operator case .colon: return .none + case .colonColon: + return .operator case .comma: return .none case .dollarIdentifier: diff --git a/Sources/SwiftParser/Attributes.swift b/Sources/SwiftParser/Attributes.swift index 39e7d5a0241..e3a4274ae71 100644 --- a/Sources/SwiftParser/Attributes.swift +++ b/Sources/SwiftParser/Attributes.swift @@ -629,8 +629,8 @@ extension Parser { var elements = [RawObjCSelectorPieceSyntax]() var loopProgress = LoopProgressCondition() while self.hasProgressed(&loopProgress) { - // Empty selector piece. - if let colon = self.consume(if: .colon) { + // Empty selector piece, splitting `::` into two colons. + if let colon = self.consume(ifPrefix: ":", as: .colon) { elements.append( RawObjCSelectorPieceSyntax( name: nil, @@ -654,7 +654,8 @@ extension Parser { break } - let (unexpectedBeforeColon, colon) = self.expect(.colon) + // Match ending colon, spliting `::` into two colons. + let (unexpectedBeforeColon, colon) = self.expect(prefix: ":", as: .colon) elements.append( RawObjCSelectorPieceSyntax( name: name, diff --git a/Sources/SwiftParser/Lexer/Cursor.swift b/Sources/SwiftParser/Lexer/Cursor.swift index 0386f4c3eba..cf06623cb3b 100644 --- a/Sources/SwiftParser/Lexer/Cursor.swift +++ b/Sources/SwiftParser/Lexer/Cursor.swift @@ -943,9 +943,17 @@ extension Lexer.Cursor { case ",": _ = self.advance(); return Lexer.Result(.comma) case ";": _ = self.advance(); return Lexer.Result(.semicolon) - case ":": _ = self.advance(); return Lexer.Result(.colon) case "\\": _ = self.advance(); return Lexer.Result(.backslash) + case ":": + _ = self.advance() + guard self.experimentalFeatures.contains(.moduleSelector) && self.peek() == ":" else { + return Lexer.Result(.colon) + } + + _ = self.advance() + return Lexer.Result(.colonColon) + case "#": // Try lex shebang. if self.isAtStartOfFile, self.peek(at: 1) == "!" { diff --git a/Sources/SwiftParser/Lexer/RegexLiteralLexer.swift b/Sources/SwiftParser/Lexer/RegexLiteralLexer.swift index 9048ae84444..477c2773e68 100644 --- a/Sources/SwiftParser/Lexer/RegexLiteralLexer.swift +++ b/Sources/SwiftParser/Lexer/RegexLiteralLexer.swift @@ -643,6 +643,10 @@ extension Lexer.Cursor { case .identifier, .dollarIdentifier, .wildcard: return false + // Module selectors are allowed before an operator, but not a regex. + case .colonColon: + return false + // Literals are themselves expressions and therefore don't sequence expressions. case .floatLiteral, .integerLiteral: return false @@ -737,7 +741,7 @@ extension Lexer.Cursor { // an unapplied operator is legal, and we should prefer to lex as that // instead. switch previousTokenKind { - case .leftParen, .leftSquare, .comma, .colon: + case .leftParen, .leftSquare, .comma, .colon, .colonColon: break default: mustBeRegex = true diff --git a/Sources/SwiftParser/Parser.swift b/Sources/SwiftParser/Parser.swift index 36e79b0da5a..d60b37d7533 100644 --- a/Sources/SwiftParser/Parser.swift +++ b/Sources/SwiftParser/Parser.swift @@ -645,6 +645,25 @@ extension Parser { ) } + /// Attempts to consume a token starting with the given `prefix` and forming it into `tokenKind`. + /// If it cannot be found, the parser tries + /// 1. To eat unexpected tokens that have lower ``TokenPrecedence`` than + /// specified by `TokenSpec(tokenKind)` and see if the token occurs after that unexpected. + /// 2. If the token couldn't be found after skipping unexpected, it synthesizes + /// a missing token of the requested kind. + @inline(__always) + mutating func expect( + prefix: SyntaxText, + as tokenKind: RawTokenKind + ) -> (unexpected: RawUnexpectedNodesSyntax?, token: RawTokenSyntax) { + let spec = TokenSpec(tokenKind) + return expectImpl( + consume: { $0.consume(ifPrefix: prefix, as: tokenKind) }, + canRecoverTo: { $0.canRecoverTo(spec) }, + makeMissing: { $0.missingToken(spec) } + ) + } + /// If the current token starts with the given prefix, consume the prefis as the given token kind. /// /// Otherwise, synthesize a missing token of the given kind. diff --git a/Sources/SwiftParser/Statements.swift b/Sources/SwiftParser/Statements.swift index b6834a69af5..619794f19e7 100644 --- a/Sources/SwiftParser/Statements.swift +++ b/Sources/SwiftParser/Statements.swift @@ -969,6 +969,9 @@ extension TokenConsumer { return false case .semicolon, .endOfFile, .poundElse, .poundElseif, .poundEndif: return false + case .colonColon: + // E.g. :: + return false case .leftAngle, .rightAngle: // Lexer never produce these token kinds. diff --git a/Sources/SwiftParser/TokenPrecedence.swift b/Sources/SwiftParser/TokenPrecedence.swift index 6fe15a0388a..c0edb214bff 100644 --- a/Sources/SwiftParser/TokenPrecedence.swift +++ b/Sources/SwiftParser/TokenPrecedence.swift @@ -128,7 +128,7 @@ enum TokenPrecedence: Comparable { // Pound literals .poundAvailable, .poundSourceLocation, .poundUnavailable, // Identifiers - .dollarIdentifier, .identifier, + .dollarIdentifier, .identifier, .colonColon, // '_' can occur in types to replace a type identifier .wildcard, // String segment, string interpolation anchor, pound, shebang and regex pattern don't really fit anywhere else diff --git a/Sources/SwiftParser/generated/ExperimentalFeatures.swift b/Sources/SwiftParser/generated/ExperimentalFeatures.swift index 35aac037436..1c12c14a148 100644 --- a/Sources/SwiftParser/generated/ExperimentalFeatures.swift +++ b/Sources/SwiftParser/generated/ExperimentalFeatures.swift @@ -52,6 +52,9 @@ extension Parser.ExperimentalFeatures { /// Whether to enable the parsing of set default actor isolation for a file. public static let defaultIsolationPerFile = Self (rawValue: 1 << 8) + /// Whether to enable the parsing of Module selector syntax (`ModName::identifier`). + public static let moduleSelector = Self (rawValue: 1 << 9) + /// Creates a new value representing the experimental feature with the /// given name, or returns nil if the name is not recognized. public init?(name: String) { @@ -74,6 +77,8 @@ extension Parser.ExperimentalFeatures { self = .oldOwnershipOperatorSpellings case "DefaultIsolationPerFile": self = .defaultIsolationPerFile + case "ModuleSelector": + self = .moduleSelector default: return nil } diff --git a/Sources/SwiftParser/generated/TokenSpecStaticMembers.swift b/Sources/SwiftParser/generated/TokenSpecStaticMembers.swift index 853e2fbb690..13b547bb2ca 100644 --- a/Sources/SwiftParser/generated/TokenSpecStaticMembers.swift +++ b/Sources/SwiftParser/generated/TokenSpecStaticMembers.swift @@ -44,6 +44,10 @@ extension TokenSpec { return TokenSpec(.colon) } + static var colonColon: TokenSpec { + return TokenSpec(.colonColon) + } + static var comma: TokenSpec { return TokenSpec(.comma) } diff --git a/Sources/SwiftParserDiagnostics/generated/TokenNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/TokenNameForDiagnostics.swift index 4d1a90253da..2f7cfd67902 100644 --- a/Sources/SwiftParserDiagnostics/generated/TokenNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/TokenNameForDiagnostics.swift @@ -34,6 +34,8 @@ extension TokenKind { return "binary operator" case .colon: return ":" + case .colonColon: + return "::" case .comma: return "," case .dollarIdentifier: diff --git a/Sources/SwiftSyntax/generated/TokenKind.swift b/Sources/SwiftSyntax/generated/TokenKind.swift index 10589e1b4e4..ab41c2cd4c7 100644 --- a/Sources/SwiftSyntax/generated/TokenKind.swift +++ b/Sources/SwiftSyntax/generated/TokenKind.swift @@ -21,6 +21,7 @@ public enum TokenKind: Hashable, Sendable { case backtick case binaryOperator(String) case colon + case colonColon case comma case dollarIdentifier(String) case ellipsis @@ -82,6 +83,8 @@ public enum TokenKind: Hashable, Sendable { return text case .colon: return ":" + case .colonColon: + return "::" case .comma: return "," case .dollarIdentifier(let text): @@ -187,6 +190,8 @@ public enum TokenKind: Hashable, Sendable { return "`" case .colon: return ":" + case .colonColon: + return "::" case .comma: return "," case .ellipsis: @@ -275,6 +280,8 @@ public enum TokenKind: Hashable, Sendable { return false case .colon: return true + case .colonColon: + return true case .comma: return true case .dollarIdentifier: @@ -382,6 +389,8 @@ extension TokenKind: Equatable { return lhsText == rhsText case (.colon, .colon): return true + case (.colonColon, .colonColon): + return true case (.comma, .comma): return true case (.dollarIdentifier(let lhsText), .dollarIdentifier(let rhsText)): @@ -489,6 +498,7 @@ public enum RawTokenKind: UInt8, Equatable, Hashable { case backtick case binaryOperator case colon + case colonColon case comma case dollarIdentifier case ellipsis @@ -547,6 +557,8 @@ public enum RawTokenKind: UInt8, Equatable, Hashable { return "`" case .colon: return ":" + case .colonColon: + return "::" case .comma: return "," case .ellipsis: @@ -633,6 +645,8 @@ public enum RawTokenKind: UInt8, Equatable, Hashable { return false case .colon: return true + case .colonColon: + return true case .comma: return true case .dollarIdentifier: @@ -747,6 +761,9 @@ extension TokenKind { case .colon: precondition(text.isEmpty || rawKind.defaultText.map(String.init) == text) return .colon + case .colonColon: + precondition(text.isEmpty || rawKind.defaultText.map(String.init) == text) + return .colonColon case .comma: precondition(text.isEmpty || rawKind.defaultText.map(String.init) == text) return .comma @@ -889,6 +906,8 @@ extension TokenKind { return (.binaryOperator, str) case .colon: return (.colon, nil) + case .colonColon: + return (.colonColon, nil) case .comma: return (.comma, nil) case .dollarIdentifier(let str): diff --git a/Sources/SwiftSyntax/generated/Tokens.swift b/Sources/SwiftSyntax/generated/Tokens.swift index 421aa3ed3d9..30ec618c5a4 100644 --- a/Sources/SwiftSyntax/generated/Tokens.swift +++ b/Sources/SwiftSyntax/generated/Tokens.swift @@ -93,6 +93,19 @@ extension TokenSyntax { ) } + public static func colonColonToken( + leadingTrivia: Trivia = [], + trailingTrivia: Trivia = [], + presence: SourcePresence = .present + ) -> TokenSyntax { + return TokenSyntax( + .colonColon, + leadingTrivia: leadingTrivia, + trailingTrivia: trailingTrivia, + presence: presence + ) + } + public static func commaToken( leadingTrivia: Trivia = [], trailingTrivia: Trivia = [], diff --git a/Tests/SwiftParserTest/AttributeTests.swift b/Tests/SwiftParserTest/AttributeTests.swift index bdb1c728d0f..9109559cee8 100644 --- a/Tests/SwiftParserTest/AttributeTests.swift +++ b/Tests/SwiftParserTest/AttributeTests.swift @@ -188,11 +188,23 @@ final class AttributeTests: ParserTestCase { @objc(zeroArg) class A { } - @objc(:::::) + @objc(:::x::) func f(_: Int, _: Int, _: Int, _: Int, _: Int) { } """ ) + // Same as above, but with module selectors, which introduce a token for adjacent colons. + assertParse( + """ + @objc(zeroArg) + class A { } + + @objc(:::x::) + func f(_: Int, _: Int, _: Int, _: Int, _: Int) { } + """, + experimentalFeatures: [.moduleSelector] + ) + assertParse( """ @objc(_:) diff --git a/Tests/SwiftParserTest/LexerTests.swift b/Tests/SwiftParserTest/LexerTests.swift index c12424537f7..7d9cc753ece 100644 --- a/Tests/SwiftParserTest/LexerTests.swift +++ b/Tests/SwiftParserTest/LexerTests.swift @@ -579,6 +579,17 @@ class LexerTests: ParserTestCase { LexemeSpec(.binaryOperator, text: "^", trailing: "/*/", diagnostic: "unterminated '/*' comment") ] ) + assertLexemes( + "(Foo::/)", + lexemes: [ + LexemeSpec(.leftParen, text: "("), + LexemeSpec(.identifier, text: "Foo"), + LexemeSpec(.colonColon, text: "::"), + LexemeSpec(.binaryOperator, text: "/"), + LexemeSpec(.rightParen, text: ")"), + ], + experimentalFeatures: [.moduleSelector] + ) } func testUnexpectedLexing() { @@ -834,6 +845,70 @@ class LexerTests: ParserTestCase { ) } + func testTwoColons() { + assertLexemes( + "Foo::bar", + lexemes: [ + LexemeSpec(.identifier, text: "Foo"), + LexemeSpec(.colonColon, text: "::"), + LexemeSpec(.identifier, text: "bar"), + ], + experimentalFeatures: [.moduleSelector] + ) + + assertLexemes( + "Foo ::bar", + lexemes: [ + LexemeSpec(.identifier, text: "Foo", trailing: " "), + LexemeSpec(.colonColon, text: "::"), + LexemeSpec(.identifier, text: "bar"), + ], + experimentalFeatures: [.moduleSelector] + ) + + assertLexemes( + "Foo:: bar", + lexemes: [ + LexemeSpec(.identifier, text: "Foo"), + LexemeSpec(.colonColon, text: "::", trailing: " "), + LexemeSpec(.identifier, text: "bar"), + ], + experimentalFeatures: [.moduleSelector] + ) + + assertLexemes( + "Foo :: bar", + lexemes: [ + LexemeSpec(.identifier, text: "Foo", trailing: " "), + LexemeSpec(.colonColon, text: "::", trailing: " "), + LexemeSpec(.identifier, text: "bar"), + ], + experimentalFeatures: [.moduleSelector] + ) + + assertLexemes( + "Foo: :bar", + lexemes: [ + LexemeSpec(.identifier, text: "Foo"), + LexemeSpec(.colon, text: ":", trailing: " "), + LexemeSpec(.colon, text: ":"), + LexemeSpec(.identifier, text: "bar"), + ], + experimentalFeatures: [.moduleSelector] + ) + + // Only produce the new token when the experimental feature is enabled. + assertLexemes( + "Foo::bar", + lexemes: [ + LexemeSpec(.identifier, text: "Foo"), + LexemeSpec(.colon, text: ":"), + LexemeSpec(.colon, text: ":"), + LexemeSpec(.identifier, text: "bar"), + ] + ) + } + func testEditorPlaceholders() { assertLexemes( "!1️⃣<#b1#> && !2️⃣<#b2#>", From d404abc66f04d6930b087a9032f012eb8283bd7d Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Thu, 29 May 2025 15:22:40 -0700 Subject: [PATCH 03/15] [NFC] Refactor parsing of suppressed types --- Sources/SwiftParser/Types.swift | 41 +++++++++++++++++---------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index df054e3a53b..73e8795c1fb 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -194,6 +194,26 @@ extension Parser { mutating func parseSimpleType( allowMemberTypes: Bool = true, forAttributeName: Bool = false + ) -> RawTypeSyntax { + let tilde = self.consumeIfContextualPunctuator("~", remapping: .prefixOperator) + + let baseType = self.parseUnsuppressedSimpleType( + allowMemberTypes: allowMemberTypes, + forAttributeName: forAttributeName + ) + + guard let tilde else { + return baseType + } + + return RawTypeSyntax( + RawSuppressedTypeSyntax(withoutTilde: tilde, type: baseType, arena: self.arena) + ) + } + + mutating func parseUnsuppressedSimpleType( + allowMemberTypes: Bool = true, + forAttributeName: Bool = false ) -> RawTypeSyntax { enum TypeBaseStart: TokenSpecSet { case `Self` @@ -227,23 +247,6 @@ extension Parser { } } - // Eat any '~' preceding the type. - let maybeTilde = self.consumeIfContextualPunctuator("~", remapping: .prefixOperator) - - // Wrap as a suppressed type if needed. - func wrapInTilde(_ node: RawTypeSyntax) -> RawTypeSyntax { - if let tilde = maybeTilde { - return RawTypeSyntax( - RawSuppressedTypeSyntax( - withoutTilde: tilde, - type: node, - arena: self.arena - ) - ) - } - return node - } - var base: RawTypeSyntax switch self.at(anyIn: TypeBaseStart.self)?.spec { case .Self, .Any, .identifier: @@ -255,7 +258,7 @@ extension Parser { case .wildcard: base = RawTypeSyntax(self.parsePlaceholderType()) case nil: - return wrapInTilde(RawTypeSyntax(RawMissingTypeSyntax(arena: self.arena))) + return RawTypeSyntax(RawMissingTypeSyntax(arena: self.arena)) } var loopProgress = LoopProgressCondition() @@ -332,8 +335,6 @@ extension Parser { break } - base = wrapInTilde(base) - return base } From 2d27936a80cab2357ddf1b436ec2bb18dd2cc272 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Thu, 29 May 2025 14:31:04 -0700 Subject: [PATCH 04/15] [NFC] Allow wildcards in contextual-keyword PBDs --- Sources/SwiftParser/Patterns.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftParser/Patterns.swift b/Sources/SwiftParser/Patterns.swift index b58d68e51b0..37e5c390ecf 100644 --- a/Sources/SwiftParser/Patterns.swift +++ b/Sources/SwiftParser/Patterns.swift @@ -272,7 +272,10 @@ extension Parser.Lookahead { // than likely need to be made contextual as well before finalizing their // grammar. case ._borrowing, .borrowing: - return peek(isAt: TokenSpec(.identifier, allowAtStartOfLine: false)) + return peek( + isAt: TokenSpec(.identifier, allowAtStartOfLine: false), + TokenSpec(.wildcard, allowAtStartOfLine: false) + ) default: // Other keywords can be parsed unconditionally. return true From 26d50e8aafc82537d9b34a32faed998f8c15f597 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Fri, 30 May 2025 20:12:33 -0700 Subject: [PATCH 05/15] [NFC] Correct @_implements diagnostic typo --- CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift | 2 +- .../generated/SyntaxKindNameForDiagnostics.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift index d960ec5db26..cc561d27a49 100644 --- a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift @@ -581,7 +581,7 @@ public let ATTRIBUTE_NODES: [Node] = [ Node( kind: .implementsAttributeArguments, base: .syntax, - nameForDiagnostics: "@_implements arguemnts", + nameForDiagnostics: "@_implements arguments", documentation: "The arguments for the `@_implements` attribute of the form `Type, methodName(arg1Label:arg2Label:)`", children: [ diff --git a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift index 52e2023df3e..9ff481ccbb0 100644 --- a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift @@ -221,7 +221,7 @@ extension SyntaxKind { case .ifExpr: return "'if' statement" case .implementsAttributeArguments: - return "@_implements arguemnts" + return "@_implements arguments" case .implicitlyUnwrappedOptionalType: return "implicitly unwrapped optional type" case .importDecl: From 9b197f1a95f531db4554ab5b2704f562f4749bfc Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Tue, 5 Aug 2025 15:56:47 -0700 Subject: [PATCH 06/15] [NFC] Generate code for experimental nodes better MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initializers for nodes with experimental node children need to be marked `@_spi`. This PR: • Adds that attribute. • Generates an alternative which *doesn’t* use SPI as part of the compatibility layer. • As a side effect, adds a `Child.Refactoring.introduced` case that can be used to generate compatibility `unexpected` properties. No functional change in this commit, but it will affect the code generation in the next one. --- .../Sources/SyntaxSupport/Child.swift | 45 +++- .../SyntaxSupport/CompatibilityLayer.swift | 210 ++++++++++++++---- .../Sources/SyntaxSupport/InitSignature.swift | 19 +- .../InitSignature+Extensions.swift | 33 ++- .../RenamedChildrenCompatibilityFile.swift | 67 ++++-- ...amedChildrenBuilderCompatibilityFile.swift | 44 ++-- 6 files changed, 309 insertions(+), 109 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/Child.swift b/CodeGeneration/Sources/SyntaxSupport/Child.swift index e7cd360a28b..6c9badb33eb 100644 --- a/CodeGeneration/Sources/SyntaxSupport/Child.swift +++ b/CodeGeneration/Sources/SyntaxSupport/Child.swift @@ -140,6 +140,19 @@ public class Child: NodeChoiceConvertible { } } + /// Should this child be hidden? + /// + /// A hidden child is one that is not accessible in any way at a specific point in the history, but still needs to be + /// (default) initialized. As always, its `newestChildPath` indicates the current way to access it. + /// + /// Hidden children are used for `Refactoring.introduced` and for the implicit changeset that creates + /// non-experimental APIs that ignore experimental children. + public let isHidden: Bool + + /// True if this child was created by a `childHistory` change set. Such children + /// are part of the compatibility layer and are therefore deprecated. + public var isHistorical: Bool + /// A name of this child as an identifier. public var identifier: TokenSyntax { return .identifier(lowercaseFirstWord(name: name)) @@ -161,8 +174,8 @@ public class Child: NodeChoiceConvertible { return "\(raw: newestName.withFirstCharacterUppercased)Options" } - /// If this child is deprecated, describes the sequence of accesses necessary - /// to reach the equivalent value using non-deprecated children; if the child + /// If this child is part of a compatibility layer, describes the sequence of accesses necessary + /// to reach the equivalent value using non-compatibility-layer children; if the child /// is not deprecated, this array is empty. /// /// Think of the elements of this array like components in a key path: @@ -199,12 +212,6 @@ public class Child: NodeChoiceConvertible { /// of the child. That information is not directly available anywhere. public let newestChildPath: [Child] - /// True if this child was created by a `Child.Refactoring`. Such children - /// are part of the compatibility layer and are therefore deprecated. - public var isHistorical: Bool { - !newestChildPath.isEmpty - } - /// Replaces the nodes in `newerChildPath` with their own `newerChildPath`s, /// if any, to form a child path enitrely of non-historical nodes. static private func makeNewestChildPath(from newerChildPath: [Child]) -> [Child] { @@ -214,7 +221,7 @@ public class Child: NodeChoiceConvertible { var workStack = Array(newerChildPath.reversed()) while let elem = workStack.popLast() { - if elem.isHistorical { + if !elem.newestChildPath.isEmpty { // There's an even newer version. Start working on that. workStack.append(contentsOf: elem.newestChildPath.reversed()) } else { @@ -308,7 +315,8 @@ public class Child: NodeChoiceConvertible { documentation: String? = nil, isOptional: Bool = false, providesDefaultInitialization: Bool = true, - newerChildPath: [Child] = [] + newerChildPath: [Child] = [], + isHistorical: Bool = false ) { precondition(name.first?.isLowercase ?? true, "The first letter of a child’s name should be lowercase") self.name = name @@ -320,11 +328,18 @@ public class Child: NodeChoiceConvertible { self.documentationAbstract = String(documentation?.split(whereSeparator: \.isNewline).first ?? "") self.isOptional = isOptional self.providesDefaultInitialization = providesDefaultInitialization + self.isHidden = false + self.isHistorical = isHistorical } /// Create a node that is a copy of the last node in `newerChildPath`, but /// with modifications. - init(renamingTo replacementName: String? = nil, newerChildPath: [Child]) { + init( + renamingTo replacementName: String? = nil, + makingHistorical: Bool = false, + makingHidden: Bool = false, + newerChildPath: [Child] + ) { let other = newerChildPath.last! self.name = replacementName ?? other.name @@ -336,6 +351,8 @@ public class Child: NodeChoiceConvertible { self.documentationAbstract = other.documentationAbstract self.isOptional = other.isOptional self.providesDefaultInitialization = other.providesDefaultInitialization + self.isHidden = makingHidden || other.isHidden + self.isHistorical = makingHistorical || other.isHistorical } /// Create a child for the unexpected nodes between two children (either or @@ -361,7 +378,8 @@ public class Child: NodeChoiceConvertible { documentation: nil, isOptional: true, providesDefaultInitialization: true, - newerChildPath: newerChildPath + newerChildPath: newerChildPath, + isHistorical: (earlier?.isHistorical ?? false) || (later?.isHistorical ?? false) ) } } @@ -417,5 +435,8 @@ extension Child { /// point in the past, so deprecated aliases that flatten the other node's /// children into this node should be provided. case extracted + + /// A new child was added (and it's important to preserve the names around it). + case introduced } } diff --git a/CodeGeneration/Sources/SyntaxSupport/CompatibilityLayer.swift b/CodeGeneration/Sources/SyntaxSupport/CompatibilityLayer.swift index f95f3143669..fa1e2d26afa 100644 --- a/CodeGeneration/Sources/SyntaxSupport/CompatibilityLayer.swift +++ b/CodeGeneration/Sources/SyntaxSupport/CompatibilityLayer.swift @@ -18,8 +18,9 @@ public struct CompatibilityLayer { /// Deprecated members that the compatibility layer needs for each trait. public var deprecatedMembersByTrait: [String: DeprecatedMemberInfo] = [:] - /// Cache for `replacementChildren(for:by:)`. Ensures that we don't create two different replacement children even - /// if we refactor the same child twice, so we can reliably equate and hash `Child` objects by object identity. + /// Cache for `replacementChildren(for:by:historical:)`. Ensures that we don't create two different replacement + /// children even if we refactor the same child twice, so we can reliably equate and hash `Child` objects by + /// object identity. private var cachedReplacementChildren: [Child: [Child]] = [:] /// Returns the deprecated members that the compatibility layer needs for `node`. @@ -46,13 +47,23 @@ public struct CompatibilityLayer { /// Returns the child or children that would have existed in place of this /// child before this refactoring was applied. - private mutating func replacementChildren(for newerChild: Child, by refactoring: Child.Refactoring) -> [Child] { + /// + /// - Parameters: + /// - newerChild: The child which is being replaced. + /// - refactoring: The refactoring which created that child and must be + /// reversed. + fileprivate mutating func replacementChildren( + for newerChild: Child, + by refactoring: Child.Refactoring, + historical: Bool + ) -> [Child] { func make() -> [Child] { switch refactoring { case .renamed(from: let deprecatedName): return [ Child( renamingTo: deprecatedName, + makingHistorical: historical, newerChildPath: [newerChild] ) ] @@ -72,8 +83,20 @@ public struct CompatibilityLayer { } return newerGrandchildren.map { newerGrandchild in - Child(newerChildPath: [newerChild, newerGrandchild]) + Child( + makingHistorical: historical, + newerChildPath: [newerChild, newerGrandchild] + ) } + + case .introduced: + return [ + Child( + makingHistorical: historical, + makingHidden: true, + newerChildPath: [newerChild] + ) + ] } } @@ -100,6 +123,7 @@ public struct CompatibilityLayer { deprecatedMembersByNode[node.syntaxNodeKind] = result } + /// Compute and cache compatibility layer information for the given children. private mutating func computeMembers(for trait: Trait) { guard deprecatedMembersByTrait[trait.traitName] == nil else { return @@ -115,58 +139,160 @@ public struct CompatibilityLayer { deprecatedMembersByTrait[trait.traitName] = result } - /// Compute and cache compatibility layer information for the given children. + /// Compute compatibility layer information for the given children. private mutating func computeMembersFor( typeName: String, initialChildren: [Child], history: Child.History, areRequirements: Bool ) -> DeprecatedMemberInfo { - // The results that will ultimately be saved into the DeprecatedMemberInfo. + var builder = DeprecatedMemberInfo.Builder( + typeName: typeName, + children: initialChildren, + areRequirements: areRequirements + ) + + // If any of the children are experimental, apply an initial change set that hides them, ensuring that we generate + // APIs which aren't experimental. + let experimentalChildren = initialChildren.filter { $0.isExperimental && !$0.isUnexpectedNodes } + if !experimentalChildren.isEmpty { + let syntheticChangeSet = experimentalChildren.map { ($0.name, Child.Refactoring.introduced) } + builder.applyChangeSet(syntheticChangeSet, for: &self, historical: false) + } + + // Apply changes in the history + for changeSet in history { + builder.applyChangeSet(changeSet, for: &self, historical: true) + } + + return builder.make() + } +} + +/// Describes the deprecated members of a given type that the compatibility layer ought to provide. +public struct DeprecatedMemberInfo { + /// Properties that are needed in the compatibility layer, in the order they ought to appear in the generated file. + public var vars: [Child] = [] + + /// Initializer signatures that are needed in the compatibility layer, in the order they ought to appear in the generated file. + public var inits: [InitSignature] = [] + + /// Is there anything whatsoever that we ought to generate? + public var isEmpty: Bool { + return vars.isEmpty && inits.isEmpty + } + + fileprivate struct Builder { + /// Properties that are needed in the compatibility layer, in the order they ought to appear in the generated file. + /// This becomes a property of the `DeprecatedMemberInfo`. var vars: [Child] = [] - var initSignatures: [InitSignature] = [] - // Temporary working state for the loop. - var children = initialChildren - var knownVars = Set(children) + /// Initializer signatures that are needed in the compatibility layer, in the order they ought to appear in the generated file. + /// This becomes a property of the `DeprecatedMemberInfo`. + var inits: [InitSignature] = [] - func firstIndexOfChild(named targetName: String) -> Int { - guard let i = children.firstIndex(where: { $0.name == targetName }) else { - fatalError( - "couldn't find '\(targetName)' in current children of \(typeName): \(String(reflecting: children.map(\.name)))" - ) - } - return i + /// Name of the type we're generating a compatibility layer for. + private let typeName: String + + /// Are we building a compatibility layer for requirements of a trait? Traits don't have unexpected children or + /// initializers. + private let areRequirements: Bool + + /// The current set of children after applying all of the change sets ever passed to `applyChangeSet(_:for:historical:)`. + /// This is working state. + private var children: [Child] + + /// The set of all children that have ever been added to `vars`, plus the ones that were originally present. + /// Used to ensure duplicates aren't added to `vars`. This is working state. + private var knownVars: Set + + /// Creates a builder with no deprecated members, but ready to start adding change sets. + init(typeName: String, children: [Child], areRequirements: Bool) { + self.typeName = typeName + self.areRequirements = areRequirements + + self.children = children + self.knownVars = Set(children) } - for changeSet in history { + /// Creates a `DeprecatedMemberInfo` from all the change sets that have been passed to + /// `applyChangeSet(_:for:historical:)`. + func make() -> DeprecatedMemberInfo { + return DeprecatedMemberInfo(vars: vars, inits: inits) + } + + func lastVisibleChild(before i: Int, isUnexpectedNodes: Bool) -> Child? { + let allEarlier = children.prefix(through: max(i - 1, children.startIndex)) + return allEarlier.last { !$0.isHidden && $0.isUnexpectedNodes == isUnexpectedNodes } + } + + func firstVisibleChild(after i: Int, isUnexpectedNodes: Bool) -> Child? { + let allLater = children.suffix(from: min(i + 1, children.endIndex)) + return allLater.first { !$0.isHidden && $0.isUnexpectedNodes == isUnexpectedNodes } + } + + /// Generate the new `vars` and `inits` that are required to maintain compatibility with `changeSet`. + /// + /// - Parameters: + /// - changeSet: The changes to apply. This type is basically a generic form of `Child.ChangeSet`. + /// - compatibilityLayer: The compatibility layer that these children will ultimately belong to. + /// - historical: Should the children created by this change set be marked historical (and thus be deprecated)? + mutating func applyChangeSet( + _ changeSet: some RandomAccessCollection<(key: String, value: Child.Refactoring)>, + for compatibilityLayer: inout CompatibilityLayer, + historical: Bool + ) { var unexpectedChildrenWithNewNames: Set = [] // First pass: Apply the changes explicitly specified in the change set. for (currentName, refactoring) in changeSet { let i = firstIndexOfChild(named: currentName) + let oldChild = children[i] - let replacementChildren = replacementChildren(for: children[i], by: refactoring) + let replacementChildren = compatibilityLayer.replacementChildren( + for: children[i], + by: refactoring, + historical: historical + ) children.replaceSubrange(i...i, with: replacementChildren) if !areRequirements { + func isDifferent(_ newChild: Child) -> Bool { + oldChild.isHidden != newChild.isHidden || oldChild.name != newChild.name + } + // Mark adjacent unexpected node children whose names have changed too. - if currentName != replacementChildren.first?.name { - unexpectedChildrenWithNewNames.insert(children[i - 1]) + if let firstNewChild = replacementChildren.first, isDifferent(firstNewChild), + let adjacentUnexpectedChild = lastVisibleChild(before: i, isUnexpectedNodes: true) + { + unexpectedChildrenWithNewNames.insert(adjacentUnexpectedChild) } - if currentName != replacementChildren.last?.name { - unexpectedChildrenWithNewNames.insert(children[i + replacementChildren.count]) + if let lastNewChild = replacementChildren.last, isDifferent(lastNewChild), + let adjacentUnexpectedChild = firstVisibleChild( + after: i + replacementChildren.count - 1, + isUnexpectedNodes: true + ) + { + unexpectedChildrenWithNewNames.insert(adjacentUnexpectedChild) } } } // Second pass: Update unexpected node children adjacent to those changes whose names have probably changed. - for unexpectedChild in unexpectedChildrenWithNewNames { + for unexpectedChild in unexpectedChildrenWithNewNames where !unexpectedChild.isHidden { precondition(unexpectedChild.isUnexpectedNodes) let i = firstIndexOfChild(named: unexpectedChild.name) - let earlier = children[checked: i - 1] - let later = children[checked: i + 1] + guard i == 0 || !children[i - 1].isHidden else { + // Special case: `unexpectedChild` follows a hidden child and should be hidden too. + children[i] = Child(makingHistorical: historical, makingHidden: true, newerChildPath: [unexpectedChild]) + continue + } + + // Find nearest expected, non-hidden nodes around `unexpectedChild` + let earlier = lastVisibleChild(before: i, isUnexpectedNodes: false) + let later = firstVisibleChild(after: i, isUnexpectedNodes: false) + precondition(!(earlier?.isUnexpectedNodes ?? false) && !(later?.isUnexpectedNodes ?? false)) let newChild = Child(forUnexpectedBetween: earlier, and: later, newerChildPath: [unexpectedChild]) @@ -176,33 +302,23 @@ public struct CompatibilityLayer { children[i] = newChild } - // Third pass: Append newly-created children to vars. We do this now so that changes from the first two passes are properly interleaved, preserving source order. - vars += children.filter { knownVars.insert($0).inserted } + // Third pass: Append newly-created children to vars. We do this now so that changes from the first two passes + // are properly interleaved, preserving source order. + self.vars += children.filter { !$0.isHidden && knownVars.insert($0).inserted } // We don't create compatibility layers for protocol requirement inits. if !areRequirements { - initSignatures.append(InitSignature(children: children)) + self.inits.append(InitSignature(children: children)) } } - return DeprecatedMemberInfo(vars: vars, inits: initSignatures) - } -} - -/// Describes the deprecated members of a given type that the compatibility layer ought to provide. -public struct DeprecatedMemberInfo { - /// Properties that are needed in the compatibility layer, in the order they ought to appear in the generated file. - public var vars: [Child] = [] - - /// Initializer signatures that are needed in the compatibility layer, in the order they ought to appear in the generated file. - public var inits: [InitSignature] = [] -} - -extension Array { - /// Returns `nil` if `i` is out of bounds, or the indicated element otherwise. - fileprivate subscript(checked i: Index) -> Element? { - get { - return indices.contains(i) ? self[i] : nil + private func firstIndexOfChild(named targetName: String) -> Int { + guard let i = children.firstIndex(where: { $0.name == targetName }) else { + fatalError( + "couldn't find '\(targetName)' in current children of \(typeName): \(String(reflecting: children.map(\.name)))" + ) + } + return i } } } diff --git a/CodeGeneration/Sources/SyntaxSupport/InitSignature.swift b/CodeGeneration/Sources/SyntaxSupport/InitSignature.swift index e93ac4ed12a..799f62b1535 100644 --- a/CodeGeneration/Sources/SyntaxSupport/InitSignature.swift +++ b/CodeGeneration/Sources/SyntaxSupport/InitSignature.swift @@ -12,9 +12,26 @@ /// Represents an initializer that should be generated. public struct InitSignature { - /// The list of children which shoudl be given parameters and initialized by the initializer. + /// The list of children which should be initialized by the initializer. + /// Includes hidden children. public var children: [Child] + /// The list of children which should be given parameters. Excludes hidden + /// children. + public var visibleChildren: LazyFilterSequence<[Child]> { + return children.lazy.filter { !$0.isHidden } + } + + /// Does this initializer cover any experimental features? + public var isExperimental: Bool { + return visibleChildren.contains { $0.isExperimental && !$0.isUnexpectedNodes } + } + + /// Does this initializer cover any historical children (vs. just omitting experimental features)? + public var isHistorical: Bool { + return visibleChildren.contains { $0.isHistorical && !$0.isUnexpectedNodes } + } + /// Create an initializer with an arbitrary array of children. public init(children: [Child]) { self.children = children diff --git a/CodeGeneration/Sources/generate-swift-syntax/InitSignature+Extensions.swift b/CodeGeneration/Sources/generate-swift-syntax/InitSignature+Extensions.swift index 57a28de5a82..9c7e8a46096 100644 --- a/CodeGeneration/Sources/generate-swift-syntax/InitSignature+Extensions.swift +++ b/CodeGeneration/Sources/generate-swift-syntax/InitSignature+Extensions.swift @@ -17,7 +17,7 @@ import Utils extension InitSignature { var compoundName: String { - let renamedArguments = children.map { child in + let renamedArguments = visibleChildren.map { child in if child.isUnexpectedNodes { return "_:" } else { @@ -28,8 +28,16 @@ extension InitSignature { return "init(leadingTrivia:\(renamedArguments)trailingTrivia:)" } + func generateInitializerAttributes() -> AttributeListSyntax { + return AttributeListSyntax { + if self.isExperimental { + AttributeSyntax("@_spi(ExperimentalLanguageFeatures)").with(\.trailingTrivia, .space) + } + } + } + func generateInitializerDeclHeader() -> SyntaxNodeString { - if children.isEmpty { + if visibleChildren.isEmpty { return "public init()" } @@ -66,7 +74,7 @@ extension InitSignature { let params = FunctionParameterListSyntax { FunctionParameterSyntax("leadingTrivia: Trivia? = nil") - for child in children { + for child in visibleChildren { createFunctionParameterSyntax(for: child) } @@ -74,8 +82,10 @@ extension InitSignature { .with(\.leadingTrivia, .newline) } + let attributes = generateInitializerAttributes() + return """ - public init( + \(attributes)public init( \(params) ) """ @@ -93,7 +103,7 @@ extension InitSignature { - Parameters: - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. \ If the node is empty, there is no token to attach the trivia to and the parameter is ignored. - \(children.compactMap(generateParamDocComment).joined(separator: "\n")) + \(visibleChildren.compactMap(generateParamDocComment).joined(separator: "\n")) - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. \ If the node is empty, there is no token to attach the trivia to and the parameter is ignored. """.removingEmptyLines @@ -114,7 +124,7 @@ extension InitSignature { var builderParameters: [FunctionParameterSyntax] = [] var delegatedInitArgs: [LabeledExprSyntax] = [] - for child in children { + for child in visibleChildren { /// The expression that is used to call the default initializer defined above. let produceExpr: ExprSyntax let childName = child.identifier @@ -174,10 +184,12 @@ extension InitSignature { FunctionParameterSyntax("trailingTrivia: Trivia? = nil") } + let attributes = generateInitializerAttributes() + return try InitializerDeclSyntax( """ /// A convenience initializer that allows initializing syntax collections using result builders - public init\(params) rethrows + \(attributes)public init\(params) rethrows """ ) { FunctionCallExprSyntax(callee: ExprSyntax("try self.init")) { @@ -209,6 +221,7 @@ extension InitSignature { func makeArgumentsToInitializeNewestChildren() -> [LabeledExprSyntax] { var root: [InitParameterMapping] = [] + // This should also map hidden children. for child in children { InitParameterMapping.addChild(child, to: &root) } @@ -351,7 +364,11 @@ extension InitParameterMapping { let argValue = switch argument { case .decl(let olderChild): - ExprSyntax(DeclReferenceExprSyntax(baseName: olderChild.baseCallName)) + if olderChild.isHidden { + olderChild.defaultValue! + } else { + ExprSyntax(DeclReferenceExprSyntax(baseName: olderChild.baseCallName)) + } case .nestedInit(let initArgs): ExprSyntax( diff --git a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/RenamedChildrenCompatibilityFile.swift b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/RenamedChildrenCompatibilityFile.swift index 77f4548117b..8053ab29c99 100644 --- a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/RenamedChildrenCompatibilityFile.swift +++ b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/RenamedChildrenCompatibilityFile.swift @@ -16,36 +16,40 @@ import SyntaxSupport import Utils let renamedChildrenCompatibilityFile = try! SourceFileSyntax(leadingTrivia: copyrightHeader) { - for layoutNode in SYNTAX_NODES.compactMap(\.layoutNode).filter({ !$0.childHistory.isEmpty }) { + for layoutNode in SYNTAX_NODES.compactMap(\.layoutNode) { var deprecatedMembers = SYNTAX_COMPATIBILITY_LAYER.deprecatedMembers(for: layoutNode) - try ExtensionDeclSyntax("extension \(layoutNode.type.syntaxBaseName)") { - for child in deprecatedMembers.vars { - makeCompatibilityVar(for: child) - if let addMethod = makeCompatibilityAddMethod(for: child) { - addMethod + if !deprecatedMembers.isEmpty { + try ExtensionDeclSyntax("extension \(layoutNode.type.syntaxBaseName)") { + for child in deprecatedMembers.vars { + makeCompatibilityVar(for: child) + if let addMethod = makeCompatibilityAddMethod(for: child) { + addMethod + } } - } - let renamedName = InitSignature(layoutNode).compoundName - for signature in deprecatedMembers.inits { - makeCompatibilityInit(for: signature, renamedName: renamedName) + let renamedName = InitSignature(layoutNode).compoundName + for signature in deprecatedMembers.inits { + makeCompatibilityInit(for: signature, renamedName: renamedName) + } } } } - for trait in TRAITS.filter({ !$0.childHistory.isEmpty }) { + for trait in TRAITS { var deprecatedMembers = SYNTAX_COMPATIBILITY_LAYER.deprecatedMembers(for: trait) - try ExtensionDeclSyntax("extension \(trait.protocolName)") { - for child in deprecatedMembers.vars { - makeCompatibilityVar(for: child) - if let addMethod = makeCompatibilityAddMethod(for: child) { - addMethod + if !deprecatedMembers.isEmpty { + try ExtensionDeclSyntax("extension \(trait.protocolName)") { + for child in deprecatedMembers.vars { + makeCompatibilityVar(for: child) + if let addMethod = makeCompatibilityAddMethod(for: child) { + addMethod + } } - } - // Not currently generating compatibility inits for traits. + // Not currently generating compatibility inits for traits. + } } } } @@ -63,10 +67,16 @@ func makeCompatibilityVar(for child: Child) -> DeclSyntax { ExprSyntax(MemberAccessExprSyntax(base: base, name: child.baseCallName)) } + let attributes = AttributeListSyntax { + if child.isHistorical { + AttributeSyntax("@available(*, deprecated, renamed: \(literal: childPathString))") + .with(\.trailingTrivia, .newlines(1)) + } + } + return DeclSyntax( """ - @available(*, deprecated, renamed: \(literal: childPathString)) - public var \(child.identifier): \(type) { + \(attributes)public var \(child.identifier): \(type) { get { return \(childAccess) } @@ -105,11 +115,20 @@ func makeCompatibilityAddMethod(for child: Child) -> DeclSyntax? { } func makeCompatibilityInit(for signature: InitSignature, renamedName: String) -> InitializerDeclSyntax { - try! InitializerDeclSyntax( + let prefix: SyntaxNodeString + if signature.isHistorical { + prefix = """ + @available(*, deprecated, renamed: \(literal: renamedName)) + @_disfavoredOverload + + """ + } else { + prefix = "" + } + + return try! InitializerDeclSyntax( """ - @available(*, deprecated, renamed: \(literal: renamedName)) - @_disfavoredOverload - \(signature.generateInitializerDeclHeader()) + \(prefix)\(signature.generateInitializerDeclHeader()) """ ) { FunctionCallExprSyntax(callee: ExprSyntax("self.init")) { diff --git a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntaxbuilder/RenamedChildrenBuilderCompatibilityFile.swift b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntaxbuilder/RenamedChildrenBuilderCompatibilityFile.swift index 3f08259a46c..4d95acfa33a 100644 --- a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntaxbuilder/RenamedChildrenBuilderCompatibilityFile.swift +++ b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntaxbuilder/RenamedChildrenBuilderCompatibilityFile.swift @@ -18,25 +18,35 @@ import Utils let renamedChildrenBuilderCompatibilityFile = try! SourceFileSyntax(leadingTrivia: copyrightHeader) { importSwiftSyntax(accessLevel: .public) - for layoutNode in SYNTAX_NODES.compactMap(\.layoutNode).filter({ !$0.childHistory.isEmpty }) { + for layoutNode in SYNTAX_NODES.compactMap(\.layoutNode) { let deprecatedMembers = SYNTAX_COMPATIBILITY_LAYER.deprecatedMembers(for: layoutNode) - - for signature in deprecatedMembers.inits { - if let convenienceInit = try signature.createConvenienceBuilderInitializer() { - let deprecatedNames = layoutNode.children - .filter { !$0.isUnexpectedNodes && !signature.children.contains($0) } - .compactMap { $0.identifier.description } - .joined(separator: ", ") - - DeclSyntax( - """ - extension \(layoutNode.type.syntaxBaseName) { - @available(*, deprecated, message: "Use an initializer with \(raw: deprecatedNames) argument(s).") - @_disfavoredOverload - \(convenienceInit) + if !deprecatedMembers.isEmpty { + for signature in deprecatedMembers.inits { + if let convenienceInit = try signature.createConvenienceBuilderInitializer() { + if signature.isHistorical { + let deprecatedNames = layoutNode.children + .filter { !$0.isUnexpectedNodes && !signature.children.contains($0) } + .compactMap { $0.identifier.description } + .joined(separator: ", ") + DeclSyntax( + """ + extension \(layoutNode.type.syntaxBaseName) { + @available(*, deprecated, message: "Use an initializer with \(raw: deprecatedNames) argument(s).") + @_disfavoredOverload + \(convenienceInit) + } + """ + ) + } else { + DeclSyntax( + """ + extension \(layoutNode.type.syntaxBaseName) { + \(convenienceInit) + } + """ + ) } - """ - ) + } } } } From 658b0883c1c09582348c5050742d3651693f7330 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Thu, 29 May 2025 18:55:07 -0700 Subject: [PATCH 07/15] [NFC] Add module selector syntax nodes/children MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes the syntax tree to represent module selectors: • A `ModuleSelectorSyntax` node represents a module selector abstractly. • The following nodes now have an optional `moduleSelector` child: • `DeclReferenceExprSyntax` • `IdentifierTypeSyntax` • `MacroExpansionExprSyntax` • `MemberTypeSyntax` • BasicFormat knows the preferred format for module selectors. Other components, particularly the parser, were also updated to continue building, though without any changes in behavior. Parser implementation will come in a future commit. --- .../Sources/SyntaxSupport/CommonNodes.swift | 19 + .../Sources/SyntaxSupport/DeclNodes.swift | 6 + .../Sources/SyntaxSupport/ExprNodes.swift | 12 + .../SyntaxSupport/SyntaxNodeKind.swift | 1 + .../Sources/SyntaxSupport/Traits.swift | 6 + .../Sources/SyntaxSupport/TypeNodes.swift | 14 + Sources/SwiftBasicFormat/BasicFormat.swift | 2 + Sources/SwiftParser/Attributes.swift | 41 +- Sources/SwiftParser/Declarations.swift | 2 + Sources/SwiftParser/Expressions.swift | 12 +- Sources/SwiftParser/Names.swift | 7 +- Sources/SwiftParser/Parameters.swift | 1 + Sources/SwiftParser/Types.swift | 12 +- .../ParseDiagnosticsGenerator.swift | 90 ++-- .../generated/ChildNameForDiagnostics.swift | 8 + .../SyntaxKindNameForDiagnostics.swift | 2 + .../SwiftSyntaxCompatibility.swift | 27 ++ .../generated/ChildNameForKeyPath.swift | 50 ++- .../RenamedChildrenCompatibility.swift | 253 ++++++++++- .../generated/SyntaxAnyVisitor.swift | 10 + .../generated/SyntaxBaseNodes.swift | 1 + .../SwiftSyntax/generated/SyntaxEnum.swift | 4 + .../SwiftSyntax/generated/SyntaxKind.swift | 4 + .../generated/SyntaxRewriter.swift | 17 + .../SwiftSyntax/generated/SyntaxTraits.swift | 6 + .../SwiftSyntax/generated/SyntaxVisitor.swift | 26 ++ .../generated/raw/RawSyntaxNodesD.swift | 36 +- .../generated/raw/RawSyntaxNodesGHI.swift | 36 +- .../generated/raw/RawSyntaxNodesJKLMN.swift | 259 +++++++---- .../generated/raw/RawSyntaxValidation.swift | 74 ++-- .../generated/syntaxNodes/SyntaxNodesD.swift | 58 ++- .../syntaxNodes/SyntaxNodesGHI.swift | 58 ++- .../syntaxNodes/SyntaxNodesJKLMN.swift | 401 ++++++++++++++---- .../generated/BuildableNodes.swift | 20 +- .../RenamedChildrenBuilderCompatibility.swift | 106 ++++- .../BasicFormatTests.swift | 15 +- 36 files changed, 1370 insertions(+), 326 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/CommonNodes.swift b/CodeGeneration/Sources/SyntaxSupport/CommonNodes.swift index 7247e17a909..5e1b4f0a0b9 100644 --- a/CodeGeneration/Sources/SyntaxSupport/CommonNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/CommonNodes.swift @@ -330,6 +330,25 @@ public let COMMON_NODES: [Node] = [ ] ), + Node( + kind: .moduleSelector, + base: .syntax, + experimentalFeature: .moduleSelector, + nameForDiagnostics: "module selector", + children: [ + Child( + name: "moduleName", + kind: .token(choices: [.token(.identifier)]), + nameForDiagnostics: "module name" + ), + Child( + name: "colonColon", + kind: .token(choices: [.token(.colonColon)]), + nameForDiagnostics: "'::' operator" + ), + ] + ), + Node( kind: .pattern, base: .syntax, diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index 25ecbf84785..b87a2a1ac07 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -1554,6 +1554,12 @@ public let DECL_NODES: [Node] = [ kind: .token(choices: [.token(.pound)]), documentation: "The `#` sign." ), + Child( + name: "moduleSelector", + kind: .node(kind: .moduleSelector), + experimentalFeature: .moduleSelector, + isOptional: true + ), Child( name: "macroName", kind: .token(choices: [.token(.identifier)]) diff --git a/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift b/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift index bfe92058354..47f3d57817d 100644 --- a/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift @@ -1002,6 +1002,12 @@ public let EXPR_NODES: [Node] = [ base: .expr, nameForDiagnostics: nil, children: [ + Child( + name: "moduleSelector", + kind: .node(kind: .moduleSelector), + experimentalFeature: .moduleSelector, + isOptional: true + ), Child( name: "baseName", kind: .token(choices: [ @@ -1358,6 +1364,12 @@ public let EXPR_NODES: [Node] = [ kind: .token(choices: [.token(.pound)]), documentation: "The `#` sign." ), + Child( + name: "moduleSelector", + kind: .node(kind: .moduleSelector), + experimentalFeature: .moduleSelector, + isOptional: true + ), Child( name: "macroName", kind: .token(choices: [.token(.identifier)]) diff --git a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift index 011058348cd..85e93c701f1 100644 --- a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift +++ b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift @@ -206,6 +206,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon case missingPattern case missingStmt case missingType + case moduleSelector case multipleTrailingClosureElement case multipleTrailingClosureElementList case namedOpaqueReturnType diff --git a/CodeGeneration/Sources/SyntaxSupport/Traits.swift b/CodeGeneration/Sources/SyntaxSupport/Traits.swift index c9eb2828931..765a58c21a9 100644 --- a/CodeGeneration/Sources/SyntaxSupport/Traits.swift +++ b/CodeGeneration/Sources/SyntaxSupport/Traits.swift @@ -92,6 +92,12 @@ public let TRAITS: [Trait] = [ traitName: "FreestandingMacroExpansion", children: [ Child(name: "pound", kind: .token(choices: [.token(.pound)])), + Child( + name: "moduleSelector", + kind: .node(kind: .moduleSelector), + experimentalFeature: .moduleSelector, + isOptional: true + ), Child(name: "macroName", kind: .token(choices: [.token(.identifier)])), Child(name: "genericArgumentClause", kind: .node(kind: .genericArgumentClause), isOptional: true), Child(name: "leftParen", kind: .token(choices: [.token(.leftParen)]), isOptional: true), diff --git a/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift index 72b22f8db4a..0b3dc02c1d5 100644 --- a/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift @@ -365,6 +365,13 @@ public let TYPE_NODES: [Node] = [ name: "period", kind: .token(choices: [.token(.period)]) ), + Child( + name: "moduleSelector", + kind: .node(kind: .moduleSelector), + experimentalFeature: .moduleSelector, + nameForDiagnostics: "module selector", + isOptional: true + ), Child( name: "name", kind: .token(choices: [.token(.identifier), .keyword(.self)]), @@ -511,6 +518,13 @@ public let TYPE_NODES: [Node] = [ base: .type, nameForDiagnostics: "type", children: [ + Child( + name: "moduleSelector", + kind: .node(kind: .moduleSelector), + experimentalFeature: .moduleSelector, + nameForDiagnostics: "module selector", + isOptional: true + ), Child( name: "name", kind: .token(choices: [ diff --git a/Sources/SwiftBasicFormat/BasicFormat.swift b/Sources/SwiftBasicFormat/BasicFormat.swift index 1cf8b170bcb..77f84cfc7a8 100644 --- a/Sources/SwiftBasicFormat/BasicFormat.swift +++ b/Sources/SwiftBasicFormat/BasicFormat.swift @@ -308,10 +308,12 @@ open class BasicFormat: SyntaxRewriter { case (.atSign, _), (.backslash, _), (.backtick, _), + (.colonColon, .identifier), (.dollarIdentifier, .period), // a.b (.endOfFile, _), (.exclamationMark, .period), // myOptionalBar!.foo() (.regexPoundDelimiter, .regexSlash), // opening extended regex delimiter should never be separate by a space + (.identifier, .colonColon), (.identifier, .leftAngle), // MyType (.identifier, .leftSquare), // myArray[1] (.identifier, .period), // a.b diff --git a/Sources/SwiftParser/Attributes.swift b/Sources/SwiftParser/Attributes.swift index e3a4274ae71..bac0de0ba08 100644 --- a/Sources/SwiftParser/Attributes.swift +++ b/Sources/SwiftParser/Attributes.swift @@ -325,7 +325,12 @@ extension Parser { unexpectedBeforeAtSign, atSign: atSign, unexpectedBeforeAttributeName, - attributeName: RawIdentifierTypeSyntax(name: attributeName, genericArgumentClause: nil, arena: self.arena), + attributeName: RawIdentifierTypeSyntax( + moduleSelector: nil, + name: attributeName, + genericArgumentClause: nil, + arena: self.arena + ), leftParen: nil, arguments: nil, rightParen: nil, @@ -349,7 +354,9 @@ extension Parser { extension RawLabeledExprSyntax { fileprivate init( - _ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax? = nil, + _ unexpectedBeforeModuleSelector: RawUnexpectedNodesSyntax? = nil, + moduleSelector: RawModuleSelectorSyntax?, + _ unexpectedBetweenModuleSelectorAndIdentifier: RawUnexpectedNodesSyntax? = nil, identifier: RawTokenSyntax, _ unexpectedBetweenIdentifierAndTrailingComma: RawUnexpectedNodesSyntax? = nil, trailingComma: RawTokenSyntax? = nil, @@ -359,7 +366,9 @@ extension RawLabeledExprSyntax { label: nil, colon: nil, expression: RawDeclReferenceExprSyntax( - unexpectedBeforeIdentifier, + unexpectedBeforeModuleSelector, + moduleSelector: moduleSelector, + unexpectedBetweenModuleSelectorAndIdentifier, baseName: identifier, argumentNames: nil, arena: arena @@ -381,6 +390,7 @@ extension Parser { let roleTrailingComma = self.consume(if: .comma) let roleElement = RawLabeledExprSyntax( + moduleSelector: nil, unexpectedBeforeRole, identifier: role, trailingComma: roleTrailingComma, @@ -410,7 +420,12 @@ extension Parser { unexpectedBeforeAtSign, atSign: atSign, unexpectedBeforeDifferentiable, - attributeName: RawIdentifierTypeSyntax(name: differentiable, genericArgumentClause: nil, arena: self.arena), + attributeName: RawIdentifierTypeSyntax( + moduleSelector: nil, + name: differentiable, + genericArgumentClause: nil, + arena: self.arena + ), unexpectedBeforeLeftParen, leftParen: leftParen, arguments: .differentiableArguments(argument), @@ -551,8 +566,13 @@ extension Parser { return RawAttributeSyntax( unexpectedBeforeAtSign, atSign: atSign, - unexpectedBeforeDerivative, - attributeName: RawIdentifierTypeSyntax(name: derivative, genericArgumentClause: nil, arena: self.arena), + attributeName: RawIdentifierTypeSyntax( + moduleSelector: nil, + unexpectedBeforeDerivative, + name: derivative, + genericArgumentClause: nil, + arena: self.arena + ), unexpectedBeforeLeftParen, leftParen: leftParen, arguments: .derivativeRegistrationArguments(argument), @@ -574,7 +594,12 @@ extension Parser { unexpectedBeforeAtSign, atSign: atSign, unexpectedBeforeTranspose, - attributeName: RawIdentifierTypeSyntax(name: transpose, genericArgumentClause: nil, arena: self.arena), + attributeName: RawIdentifierTypeSyntax( + moduleSelector: nil, + name: transpose, + genericArgumentClause: nil, + arena: self.arena + ), unexpectedBeforeLeftParen, leftParen: leftParen, arguments: .derivativeRegistrationArguments(argument), @@ -809,6 +834,7 @@ extension Parser { let (unexpectedBeforeIsolationKind, isolationKind) = self.expectIdentifier(allowKeywordsAsIdentifier: true) let isolationKindElement = RawLabeledExprSyntax( + moduleSelector: nil, unexpectedBeforeIsolationKind, identifier: isolationKind, arena: self.arena @@ -939,6 +965,7 @@ extension Parser { let declName: RawDeclReferenceExprSyntax if label.isMissing && colon.isMissing && self.atStartOfLine { declName = RawDeclReferenceExprSyntax( + moduleSelector: nil, baseName: RawTokenSyntax(missing: .identifier, arena: self.arena), argumentNames: nil, arena: self.arena diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 3f7cd4b39e2..a00a76abddb 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -610,6 +610,7 @@ extension Parser { unexpectedBeforeInherited = RawUnexpectedNodesSyntax([classKeyword], arena: self.arena) inherited = RawTypeSyntax( RawIdentifierTypeSyntax( + moduleSelector: nil, name: missingToken(.identifier, text: "AnyObject"), genericArgumentClause: nil, arena: self.arena @@ -2246,6 +2247,7 @@ extension Parser { modifiers: attrs.modifiers, unexpectedBeforePound, pound: pound, + moduleSelector: nil, unexpectedBeforeMacro, macroName: macro, genericArgumentClause: generics, diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index eafa624b1e4..53fa3281edd 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -652,6 +652,7 @@ extension Parser { if skipMemberName { let missingIdentifier = missingToken(.identifier) let declName = RawDeclReferenceExprSyntax( + moduleSelector: nil, baseName: missingIdentifier, argumentNames: nil, arena: self.arena @@ -664,6 +665,7 @@ extension Parser { if let indexOrSelf = self.consume(if: .integerLiteral, .keyword(.self)) { // Handle "x.42" - a tuple index. declName = RawDeclReferenceExprSyntax( + moduleSelector: nil, baseName: indexOrSelf, argumentNames: nil, arena: self.arena @@ -1276,6 +1278,7 @@ extension Parser { let poundAvailable = self.parsePoundAvailableConditionElement() return RawExprSyntax( RawDeclReferenceExprSyntax( + moduleSelector: nil, RawUnexpectedNodesSyntax([poundAvailable], arena: self.arena), baseName: missingToken(.identifier), argumentNames: nil, @@ -1429,6 +1432,7 @@ extension Parser { return RawMacroExpansionExprSyntax( unexpectedBeforePound, pound: pound, + moduleSelector: nil, unexpectedBeforeMacroName, macroName: macroName, genericArgumentClause: generics, @@ -1743,6 +1747,7 @@ extension Parser { mutating func parseAnonymousClosureArgument() -> RawDeclReferenceExprSyntax { let (unexpectedBeforeBaseName, baseName) = self.expect(.dollarIdentifier) return RawDeclReferenceExprSyntax( + moduleSelector: nil, unexpectedBeforeBaseName, baseName: baseName, argumentNames: nil, @@ -2396,7 +2401,12 @@ extension Parser { unknownAttr = RawAttributeSyntax( atSign: at, unexpectedBeforeIdent, - attributeName: RawIdentifierTypeSyntax(name: ident, genericArgumentClause: nil, arena: self.arena), + attributeName: RawIdentifierTypeSyntax( + moduleSelector: nil, + name: ident, + genericArgumentClause: nil, + arena: self.arena + ), leftParen: nil, arguments: nil, rightParen: nil, diff --git a/Sources/SwiftParser/Names.swift b/Sources/SwiftParser/Names.swift index 3a9efe5878f..9ed8d5ac680 100644 --- a/Sources/SwiftParser/Names.swift +++ b/Sources/SwiftParser/Names.swift @@ -11,9 +11,9 @@ //===----------------------------------------------------------------------===// #if compiler(>=6) -@_spi(RawSyntax) internal import SwiftSyntax +@_spi(ExperimentalLanguageFeatures) @_spi(RawSyntax) internal import SwiftSyntax #else -@_spi(RawSyntax) import SwiftSyntax +@_spi(ExperimentalLanguageFeatures) @_spi(RawSyntax) import SwiftSyntax #endif extension Parser { @@ -89,6 +89,7 @@ extension Parser { // Parse an argument list, if the flags allow it and it's present. let args = self.parseArgLabelList(flags) return RawDeclReferenceExprSyntax( + moduleSelector: nil, baseName: base, argumentNames: args, arena: self.arena @@ -201,6 +202,7 @@ extension Parser { var result = RawTypeSyntax( RawIdentifierTypeSyntax( + moduleSelector: nil, unexpectedBeforeName, name: name, genericArgumentClause: generics, @@ -238,6 +240,7 @@ extension Parser { RawMemberTypeSyntax( baseType: result, period: keepGoing!, + moduleSelector: nil, unexpectedBeforeName, name: name, genericArgumentClause: generics, diff --git a/Sources/SwiftParser/Parameters.swift b/Sources/SwiftParser/Parameters.swift index 1a40901237b..e6ec75d36bb 100644 --- a/Sources/SwiftParser/Parameters.swift +++ b/Sources/SwiftParser/Parameters.swift @@ -131,6 +131,7 @@ extension Parser { // Synthesize the secondName parameter as a type node. type = RawTypeSyntax( RawIdentifierTypeSyntax( + moduleSelector: nil, name: secondName, genericArgumentClause: nil, arena: self.arena diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 73e8795c1fb..23f770347ff 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -272,6 +272,7 @@ extension Parser { baseType: base, unexpectedPeriod, period: period, + moduleSelector: nil, name: missingIdentifier, genericArgumentClause: nil, arena: self.arena @@ -309,6 +310,7 @@ extension Parser { baseType: base, unexpectedPeriod, period: period, + moduleSelector: nil, name: name, genericArgumentClause: generics, arena: self.arena @@ -378,6 +380,7 @@ extension Parser { return RawTypeSyntax( RawIdentifierTypeSyntax( + moduleSelector: nil, unexpectedBeforeName, name: name, genericArgumentClause: generics, @@ -390,6 +393,7 @@ extension Parser { mutating func parseAnyType() -> RawIdentifierTypeSyntax { let (unexpectedBeforeName, name) = self.expect(.keyword(.Any)) return RawIdentifierTypeSyntax( + moduleSelector: nil, unexpectedBeforeName, name: name, genericArgumentClause: nil, @@ -401,6 +405,7 @@ extension Parser { mutating func parsePlaceholderType() -> RawIdentifierTypeSyntax { let (unexpectedBeforeName, name) = self.expect(.wildcard) return RawIdentifierTypeSyntax( + moduleSelector: nil, unexpectedBeforeName, name: name, genericArgumentClause: nil, @@ -536,7 +541,12 @@ extension Parser { secondName: nil, RawUnexpectedNodesSyntax(combining: misplacedSpecifiers, unexpectedBeforeColon, arena: self.arena), colon: nil, - type: RawIdentifierTypeSyntax(name: first, genericArgumentClause: nil, arena: self.arena), + type: RawIdentifierTypeSyntax( + moduleSelector: nil, + name: first, + genericArgumentClause: nil, + arena: self.arena + ), ellipsis: nil, trailingComma: self.missingToken(.comma), arena: self.arena diff --git a/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift index 87f919e1829..83098cec92b 100644 --- a/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift +++ b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift @@ -1100,53 +1100,65 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor { if shouldSkip(node) { return .skipChildren } - if node.baseName.isMissing, let unexpected = node.unexpectedBeforeBaseName { - if unexpected.first?.as(TokenSyntax.self)?.tokenKind == .pound { - addDiagnostic( - unexpected, - UnknownDirectiveError(unexpected: unexpected), - handledNodes: [unexpected.id, node.baseName.id] - ) - } else if let availability = unexpected.first?.as(AvailabilityConditionSyntax.self) { - if let prefixOperatorExpr = node.parent?.as(PrefixOperatorExprSyntax.self), - prefixOperatorExpr.operator.text == "!", - let conditionElement = prefixOperatorExpr.parent?.as(ConditionElementSyntax.self) - { - // Diagnose !#available(...) and !#unavailable(...) - let negatedAvailabilityKeyword = availability.availabilityKeyword.negatedAvailabilityKeyword - let negatedConditionElement = ConditionElementSyntax( - condition: .availability(availability.with(\.availabilityKeyword, negatedAvailabilityKeyword)), - trailingComma: conditionElement.trailingComma - ) + if node.baseName.isMissing { + func considerUnexpectedBeforeBaseName(_ unexpected: UnexpectedNodesSyntax) { + if unexpected.first?.as(TokenSyntax.self)?.tokenKind == .pound { addDiagnostic( unexpected, - NegatedAvailabilityCondition( - availabilityCondition: availability, - negatedAvailabilityKeyword: negatedAvailabilityKeyword - ), - fixIts: [ - FixIt( - message: ReplaceTokensFixIt( - replaceTokens: [prefixOperatorExpr.operator, availability.availabilityKeyword], - replacements: [negatedAvailabilityKeyword] - ), - changes: [ - .replace(oldNode: Syntax(conditionElement), newNode: Syntax(negatedConditionElement)) - ] - ) - ], - handledNodes: [unexpected.id, node.baseName.id] - ) - } else { - addDiagnostic( - unexpected, - AvailabilityConditionInExpression(availabilityCondition: availability), + UnknownDirectiveError(unexpected: unexpected), handledNodes: [unexpected.id, node.baseName.id] ) + } else if let availability = unexpected.first?.as(AvailabilityConditionSyntax.self) { + if let prefixOperatorExpr = node.parent?.as(PrefixOperatorExprSyntax.self), + prefixOperatorExpr.operator.text == "!", + let conditionElement = prefixOperatorExpr.parent?.as(ConditionElementSyntax.self) + { + // Diagnose !#available(...) and !#unavailable(...) + + let negatedAvailabilityKeyword = availability.availabilityKeyword.negatedAvailabilityKeyword + let negatedConditionElement = ConditionElementSyntax( + condition: .availability(availability.with(\.availabilityKeyword, negatedAvailabilityKeyword)), + trailingComma: conditionElement.trailingComma + ) + addDiagnostic( + unexpected, + NegatedAvailabilityCondition( + availabilityCondition: availability, + negatedAvailabilityKeyword: negatedAvailabilityKeyword + ), + fixIts: [ + FixIt( + message: ReplaceTokensFixIt( + replaceTokens: [prefixOperatorExpr.operator, availability.availabilityKeyword], + replacements: [negatedAvailabilityKeyword] + ), + changes: [ + .replace(oldNode: Syntax(conditionElement), newNode: Syntax(negatedConditionElement)) + ] + ) + ], + handledNodes: [unexpected.id, node.baseName.id] + ) + } else { + addDiagnostic( + unexpected, + AvailabilityConditionInExpression(availabilityCondition: availability), + handledNodes: [unexpected.id, node.baseName.id] + ) + } } } + + // We care more about the first token in the unexpected node before the base name, so favor the module selector's + // unexpected nodes. + if node.moduleSelector == nil, let unexpected = node.unexpectedBeforeModuleSelector { + considerUnexpectedBeforeBaseName(unexpected) + } else if let unexpected = node.unexpectedBetweenModuleSelectorAndBaseName { + considerUnexpectedBeforeBaseName(unexpected) + } } + return .visitChildren } diff --git a/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift index 4a00dbace1f..f047dc2cc51 100644 --- a/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift @@ -179,6 +179,8 @@ private func childNameForDiagnostics(_ keyPath: AnyKeyPath) -> String? { return "condition" case \GuardStmtSyntax.body: return "body" + case \IdentifierTypeSyntax.moduleSelector: + return "module selector" case \IfConfigClauseSyntax.condition: return "condition" case \IfExprSyntax.body: @@ -255,10 +257,16 @@ private func childNameForDiagnostics(_ keyPath: AnyKeyPath) -> String? { return "name" case \MemberTypeSyntax.baseType: return "base type" + case \MemberTypeSyntax.moduleSelector: + return "module selector" case \MemberTypeSyntax.name: return "name" case \MetatypeTypeSyntax.baseType: return "base type" + case \ModuleSelectorSyntax.moduleName: + return "module name" + case \ModuleSelectorSyntax.colonColon: + return "'::' operator" case \MultipleTrailingClosureElementSyntax.label: return "label" case \ObjCSelectorPieceSyntax.name: diff --git a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift index 9ff481ccbb0..7fe6aeb6c0e 100644 --- a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift @@ -290,6 +290,8 @@ extension SyntaxKind { return "statement" case .missingType: return "type" + case .moduleSelector: + return "module selector" case .multipleTrailingClosureElement: return "trailing closure" case .namedOpaqueReturnType: diff --git a/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift b/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift index a7333a7838d..3adfb33fbd0 100644 --- a/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift +++ b/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift @@ -405,6 +405,21 @@ extension GenericArgumentSyntax { } } +extension FreestandingMacroExpansionSyntax { + // SPI protocol requirements require a default implementation, but this should never be used because there should be + // no conforming types outside of SwiftSyntax. + @_spi(ExperimentalLanguageFeatures) + @available(*, deprecated, message: "concrete type should implement its own moduleSelector property") + public var moduleSelector: ModuleSelectorSyntax? { + get { + return nil + } + set { + fatalError("\(Self.self) should implement its own moduleSelector property") + } + } +} + extension FunctionCallExprSyntax { @_disfavoredOverload @available( @@ -705,6 +720,18 @@ extension KeyPathPropertyComponentSyntax { } } +extension MemberTypeSyntax { + @available(*, deprecated, renamed: "unexpectedBetweenModuleSelectorAndName") + public var unexpectedBeforeName: UnexpectedNodesSyntax? { + get { + return unexpectedBetweenModuleSelectorAndName + } + set(value) { + unexpectedBetweenModuleSelectorAndName = value + } + } +} + extension NamedDeclSyntax { @available(*, deprecated, renamed: "name") public var identifier: TokenSyntax { diff --git a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift index 0bcd20aee62..7f199475e8b 100644 --- a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift +++ b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift @@ -824,8 +824,12 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "rightParen" case \DeclNameArgumentsSyntax.unexpectedAfterRightParen: return "unexpectedAfterRightParen" - case \DeclReferenceExprSyntax.unexpectedBeforeBaseName: - return "unexpectedBeforeBaseName" + case \DeclReferenceExprSyntax.unexpectedBeforeModuleSelector: + return "unexpectedBeforeModuleSelector" + case \DeclReferenceExprSyntax.moduleSelector: + return "moduleSelector" + case \DeclReferenceExprSyntax.unexpectedBetweenModuleSelectorAndBaseName: + return "unexpectedBetweenModuleSelectorAndBaseName" case \DeclReferenceExprSyntax.baseName: return "baseName" case \DeclReferenceExprSyntax.unexpectedBetweenBaseNameAndArgumentNames: @@ -1652,8 +1656,12 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "identifier" case \IdentifierPatternSyntax.unexpectedAfterIdentifier: return "unexpectedAfterIdentifier" - case \IdentifierTypeSyntax.unexpectedBeforeName: - return "unexpectedBeforeName" + case \IdentifierTypeSyntax.unexpectedBeforeModuleSelector: + return "unexpectedBeforeModuleSelector" + case \IdentifierTypeSyntax.moduleSelector: + return "moduleSelector" + case \IdentifierTypeSyntax.unexpectedBetweenModuleSelectorAndName: + return "unexpectedBetweenModuleSelectorAndName" case \IdentifierTypeSyntax.name: return "name" case \IdentifierTypeSyntax.unexpectedBetweenNameAndGenericArgumentClause: @@ -2138,8 +2146,12 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "unexpectedBetweenModifiersAndPound" case \MacroExpansionDeclSyntax.pound: return "pound" - case \MacroExpansionDeclSyntax.unexpectedBetweenPoundAndMacroName: - return "unexpectedBetweenPoundAndMacroName" + case \MacroExpansionDeclSyntax.unexpectedBetweenPoundAndModuleSelector: + return "unexpectedBetweenPoundAndModuleSelector" + case \MacroExpansionDeclSyntax.moduleSelector: + return "moduleSelector" + case \MacroExpansionDeclSyntax.unexpectedBetweenModuleSelectorAndMacroName: + return "unexpectedBetweenModuleSelectorAndMacroName" case \MacroExpansionDeclSyntax.macroName: return "macroName" case \MacroExpansionDeclSyntax.unexpectedBetweenMacroNameAndGenericArgumentClause: @@ -2172,8 +2184,12 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "unexpectedBeforePound" case \MacroExpansionExprSyntax.pound: return "pound" - case \MacroExpansionExprSyntax.unexpectedBetweenPoundAndMacroName: - return "unexpectedBetweenPoundAndMacroName" + case \MacroExpansionExprSyntax.unexpectedBetweenPoundAndModuleSelector: + return "unexpectedBetweenPoundAndModuleSelector" + case \MacroExpansionExprSyntax.moduleSelector: + return "moduleSelector" + case \MacroExpansionExprSyntax.unexpectedBetweenModuleSelectorAndMacroName: + return "unexpectedBetweenModuleSelectorAndMacroName" case \MacroExpansionExprSyntax.macroName: return "macroName" case \MacroExpansionExprSyntax.unexpectedBetweenMacroNameAndGenericArgumentClause: @@ -2276,8 +2292,12 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "unexpectedBetweenBaseTypeAndPeriod" case \MemberTypeSyntax.period: return "period" - case \MemberTypeSyntax.unexpectedBetweenPeriodAndName: - return "unexpectedBetweenPeriodAndName" + case \MemberTypeSyntax.unexpectedBetweenPeriodAndModuleSelector: + return "unexpectedBetweenPeriodAndModuleSelector" + case \MemberTypeSyntax.moduleSelector: + return "moduleSelector" + case \MemberTypeSyntax.unexpectedBetweenModuleSelectorAndName: + return "unexpectedBetweenModuleSelectorAndName" case \MemberTypeSyntax.name: return "name" case \MemberTypeSyntax.unexpectedBetweenNameAndGenericArgumentClause: @@ -2344,6 +2364,16 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "placeholder" case \MissingTypeSyntax.unexpectedAfterPlaceholder: return "unexpectedAfterPlaceholder" + case \ModuleSelectorSyntax.unexpectedBeforeModuleName: + return "unexpectedBeforeModuleName" + case \ModuleSelectorSyntax.moduleName: + return "moduleName" + case \ModuleSelectorSyntax.unexpectedBetweenModuleNameAndColonColon: + return "unexpectedBetweenModuleNameAndColonColon" + case \ModuleSelectorSyntax.colonColon: + return "colonColon" + case \ModuleSelectorSyntax.unexpectedAfterColonColon: + return "unexpectedAfterColonColon" case \MultipleTrailingClosureElementSyntax.unexpectedBeforeLabel: return "unexpectedBeforeLabel" case \MultipleTrailingClosureElementSyntax.label: diff --git a/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift b/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift index 88518daf105..1d82e4cbad3 100644 --- a/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift +++ b/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift @@ -1473,13 +1473,22 @@ extension ConsumeExprSyntax { } extension DeclReferenceExprSyntax { - @available(*, deprecated, renamed: "unexpectedBeforeBaseName") + public var unexpectedBeforeBaseName: UnexpectedNodesSyntax? { + get { + return unexpectedBeforeModuleSelector + } + set { + unexpectedBeforeModuleSelector = newValue + } + } + + @available(*, deprecated, renamed: "unexpectedBeforeModuleSelector") public var unexpectedBeforeIdentifier: UnexpectedNodesSyntax? { get { - return unexpectedBeforeBaseName + return unexpectedBeforeModuleSelector } set { - unexpectedBeforeBaseName = newValue + unexpectedBeforeModuleSelector = newValue } } @@ -1523,7 +1532,29 @@ extension DeclReferenceExprSyntax { } } - @available(*, deprecated, renamed: "init(leadingTrivia:_:baseName:_:argumentNames:_:trailingTrivia:)") + public init( + leadingTrivia: Trivia? = nil, + _ unexpectedBeforeBaseName: UnexpectedNodesSyntax? = nil, + baseName: TokenSyntax, + _ unexpectedBetweenBaseNameAndArgumentNames: UnexpectedNodesSyntax? = nil, + argumentNames: DeclNameArgumentsSyntax? = nil, + _ unexpectedAfterArgumentNames: UnexpectedNodesSyntax? = nil, + trailingTrivia: Trivia? = nil + ) { + self.init( + leadingTrivia: leadingTrivia, + unexpectedBeforeBaseName, + moduleSelector: nil, + nil, + baseName: baseName, + unexpectedBetweenBaseNameAndArgumentNames, + argumentNames: argumentNames, + unexpectedAfterArgumentNames, + trailingTrivia: trailingTrivia + ) + } + + @available(*, deprecated, renamed: "init(leadingTrivia:_:moduleSelector:_:baseName:_:argumentNames:_:trailingTrivia:)") @_disfavoredOverload public init( leadingTrivia: Trivia? = nil, @@ -1537,6 +1568,8 @@ extension DeclReferenceExprSyntax { self.init( leadingTrivia: leadingTrivia, unexpectedBeforeIdentifier, + moduleSelector: nil, + nil, baseName: identifier, unexpectedBetweenIdentifierAndDeclNameArguments, argumentNames: declNameArguments, @@ -3792,6 +3825,39 @@ extension GenericWhereClauseSyntax { } } +extension IdentifierTypeSyntax { + public var unexpectedBeforeName: UnexpectedNodesSyntax? { + get { + return unexpectedBeforeModuleSelector + } + set { + unexpectedBeforeModuleSelector = newValue + } + } + + public init( + leadingTrivia: Trivia? = nil, + _ unexpectedBeforeName: UnexpectedNodesSyntax? = nil, + name: TokenSyntax, + _ unexpectedBetweenNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, + genericArgumentClause: GenericArgumentClauseSyntax? = nil, + _ unexpectedAfterGenericArgumentClause: UnexpectedNodesSyntax? = nil, + trailingTrivia: Trivia? = nil + ) { + self.init( + leadingTrivia: leadingTrivia, + unexpectedBeforeName, + moduleSelector: nil, + nil, + name: name, + unexpectedBetweenNameAndGenericArgumentClause, + genericArgumentClause: genericArgumentClause, + unexpectedAfterGenericArgumentClause, + trailingTrivia: trailingTrivia + ) + } +} + extension ImplementsAttributeArgumentsSyntax { @available(*, deprecated, renamed: "unexpectedBetweenCommaAndDeclName") public var unexpectedBetweenCommaAndDeclname: UnexpectedNodesSyntax? { @@ -4647,6 +4713,15 @@ extension MacroDeclSyntax { } extension MacroExpansionDeclSyntax { + public var unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? { + get { + return unexpectedBetweenPoundAndModuleSelector + } + set { + unexpectedBetweenPoundAndModuleSelector = newValue + } + } + @available(*, deprecated, renamed: "unexpectedBetweenModifiersAndPound") public var unexpectedBetweenModifiersAndPoundToken: UnexpectedNodesSyntax? { get { @@ -4667,13 +4742,13 @@ extension MacroExpansionDeclSyntax { } } - @available(*, deprecated, renamed: "unexpectedBetweenPoundAndMacroName") + @available(*, deprecated, renamed: "unexpectedBetweenPoundAndModuleSelector") public var unexpectedBetweenPoundTokenAndMacro: UnexpectedNodesSyntax? { get { - return unexpectedBetweenPoundAndMacroName + return unexpectedBetweenPoundAndModuleSelector } set { - unexpectedBetweenPoundAndMacroName = newValue + unexpectedBetweenPoundAndModuleSelector = newValue } } @@ -4747,7 +4822,61 @@ extension MacroExpansionDeclSyntax { } } - @available(*, deprecated, renamed: "init(leadingTrivia:_:attributes:_:modifiers:_:pound:_:macroName:_:genericArgumentClause:_:leftParen:_:arguments:_:rightParen:_:trailingClosure:_:additionalTrailingClosures:_:trailingTrivia:)") + public init( + leadingTrivia: Trivia? = nil, + _ unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, + attributes: AttributeListSyntax = [], + _ unexpectedBetweenAttributesAndModifiers: UnexpectedNodesSyntax? = nil, + modifiers: DeclModifierListSyntax = [], + _ unexpectedBetweenModifiersAndPound: UnexpectedNodesSyntax? = nil, + pound: TokenSyntax = .poundToken(), + _ unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? = nil, + macroName: TokenSyntax, + _ unexpectedBetweenMacroNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, + genericArgumentClause: GenericArgumentClauseSyntax? = nil, + _ unexpectedBetweenGenericArgumentClauseAndLeftParen: UnexpectedNodesSyntax? = nil, + leftParen: TokenSyntax? = nil, + _ unexpectedBetweenLeftParenAndArguments: UnexpectedNodesSyntax? = nil, + arguments: LabeledExprListSyntax, + _ unexpectedBetweenArgumentsAndRightParen: UnexpectedNodesSyntax? = nil, + rightParen: TokenSyntax? = nil, + _ unexpectedBetweenRightParenAndTrailingClosure: UnexpectedNodesSyntax? = nil, + trailingClosure: ClosureExprSyntax? = nil, + _ unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures: UnexpectedNodesSyntax? = nil, + additionalTrailingClosures: MultipleTrailingClosureElementListSyntax = [], + _ unexpectedAfterAdditionalTrailingClosures: UnexpectedNodesSyntax? = nil, + trailingTrivia: Trivia? = nil + ) { + self.init( + leadingTrivia: leadingTrivia, + unexpectedBeforeAttributes, + attributes: attributes, + unexpectedBetweenAttributesAndModifiers, + modifiers: modifiers, + unexpectedBetweenModifiersAndPound, + pound: pound, + unexpectedBetweenPoundAndMacroName, + moduleSelector: nil, + nil, + macroName: macroName, + unexpectedBetweenMacroNameAndGenericArgumentClause, + genericArgumentClause: genericArgumentClause, + unexpectedBetweenGenericArgumentClauseAndLeftParen, + leftParen: leftParen, + unexpectedBetweenLeftParenAndArguments, + arguments: arguments, + unexpectedBetweenArgumentsAndRightParen, + rightParen: rightParen, + unexpectedBetweenRightParenAndTrailingClosure, + trailingClosure: trailingClosure, + unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures, + additionalTrailingClosures: additionalTrailingClosures, + unexpectedAfterAdditionalTrailingClosures, + trailingTrivia: trailingTrivia + ) + } + + @available(*, deprecated, renamed: "init(leadingTrivia:_:attributes:_:modifiers:_:pound:_:moduleSelector:_:macroName:_:genericArgumentClause:_:leftParen:_:arguments:_:rightParen:_:trailingClosure:_:additionalTrailingClosures:_:trailingTrivia:)") @_disfavoredOverload public init( leadingTrivia: Trivia? = nil, @@ -4783,6 +4912,8 @@ extension MacroExpansionDeclSyntax { unexpectedBetweenModifiersAndPoundToken, pound: poundToken, unexpectedBetweenPoundTokenAndMacro, + moduleSelector: nil, + nil, macroName: macro, unexpectedBetweenMacroAndGenericArguments, genericArgumentClause: genericArguments, @@ -4803,6 +4934,15 @@ extension MacroExpansionDeclSyntax { } extension MacroExpansionExprSyntax { + public var unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? { + get { + return unexpectedBetweenPoundAndModuleSelector + } + set { + unexpectedBetweenPoundAndModuleSelector = newValue + } + } + @available(*, deprecated, renamed: "unexpectedBeforePound") public var unexpectedBeforePoundToken: UnexpectedNodesSyntax? { get { @@ -4823,13 +4963,13 @@ extension MacroExpansionExprSyntax { } } - @available(*, deprecated, renamed: "unexpectedBetweenPoundAndMacroName") + @available(*, deprecated, renamed: "unexpectedBetweenPoundAndModuleSelector") public var unexpectedBetweenPoundTokenAndMacro: UnexpectedNodesSyntax? { get { - return unexpectedBetweenPoundAndMacroName + return unexpectedBetweenPoundAndModuleSelector } set { - unexpectedBetweenPoundAndMacroName = newValue + unexpectedBetweenPoundAndModuleSelector = newValue } } @@ -4903,7 +5043,53 @@ extension MacroExpansionExprSyntax { } } - @available(*, deprecated, renamed: "init(leadingTrivia:_:pound:_:macroName:_:genericArgumentClause:_:leftParen:_:arguments:_:rightParen:_:trailingClosure:_:additionalTrailingClosures:_:trailingTrivia:)") + public init( + leadingTrivia: Trivia? = nil, + _ unexpectedBeforePound: UnexpectedNodesSyntax? = nil, + pound: TokenSyntax = .poundToken(), + _ unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? = nil, + macroName: TokenSyntax, + _ unexpectedBetweenMacroNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, + genericArgumentClause: GenericArgumentClauseSyntax? = nil, + _ unexpectedBetweenGenericArgumentClauseAndLeftParen: UnexpectedNodesSyntax? = nil, + leftParen: TokenSyntax? = nil, + _ unexpectedBetweenLeftParenAndArguments: UnexpectedNodesSyntax? = nil, + arguments: LabeledExprListSyntax, + _ unexpectedBetweenArgumentsAndRightParen: UnexpectedNodesSyntax? = nil, + rightParen: TokenSyntax? = nil, + _ unexpectedBetweenRightParenAndTrailingClosure: UnexpectedNodesSyntax? = nil, + trailingClosure: ClosureExprSyntax? = nil, + _ unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures: UnexpectedNodesSyntax? = nil, + additionalTrailingClosures: MultipleTrailingClosureElementListSyntax = [], + _ unexpectedAfterAdditionalTrailingClosures: UnexpectedNodesSyntax? = nil, + trailingTrivia: Trivia? = nil + ) { + self.init( + leadingTrivia: leadingTrivia, + unexpectedBeforePound, + pound: pound, + unexpectedBetweenPoundAndMacroName, + moduleSelector: nil, + nil, + macroName: macroName, + unexpectedBetweenMacroNameAndGenericArgumentClause, + genericArgumentClause: genericArgumentClause, + unexpectedBetweenGenericArgumentClauseAndLeftParen, + leftParen: leftParen, + unexpectedBetweenLeftParenAndArguments, + arguments: arguments, + unexpectedBetweenArgumentsAndRightParen, + rightParen: rightParen, + unexpectedBetweenRightParenAndTrailingClosure, + trailingClosure: trailingClosure, + unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures, + additionalTrailingClosures: additionalTrailingClosures, + unexpectedAfterAdditionalTrailingClosures, + trailingTrivia: trailingTrivia + ) + } + + @available(*, deprecated, renamed: "init(leadingTrivia:_:pound:_:moduleSelector:_:macroName:_:genericArgumentClause:_:leftParen:_:arguments:_:rightParen:_:trailingClosure:_:additionalTrailingClosures:_:trailingTrivia:)") @_disfavoredOverload public init( leadingTrivia: Trivia? = nil, @@ -4931,6 +5117,8 @@ extension MacroExpansionExprSyntax { unexpectedBeforePoundToken, pound: poundToken, unexpectedBetweenPoundTokenAndMacro, + moduleSelector: nil, + nil, macroName: macro, unexpectedBetweenMacroAndGenericArguments, genericArgumentClause: genericArguments, @@ -5008,6 +5196,47 @@ extension MemberAccessExprSyntax { } } +extension MemberTypeSyntax { + public var unexpectedBetweenPeriodAndName: UnexpectedNodesSyntax? { + get { + return unexpectedBetweenPeriodAndModuleSelector + } + set { + unexpectedBetweenPeriodAndModuleSelector = newValue + } + } + + public init( + leadingTrivia: Trivia? = nil, + _ unexpectedBeforeBaseType: UnexpectedNodesSyntax? = nil, + baseType: some TypeSyntaxProtocol, + _ unexpectedBetweenBaseTypeAndPeriod: UnexpectedNodesSyntax? = nil, + period: TokenSyntax = .periodToken(), + _ unexpectedBetweenPeriodAndName: UnexpectedNodesSyntax? = nil, + name: TokenSyntax, + _ unexpectedBetweenNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, + genericArgumentClause: GenericArgumentClauseSyntax? = nil, + _ unexpectedAfterGenericArgumentClause: UnexpectedNodesSyntax? = nil, + trailingTrivia: Trivia? = nil + ) { + self.init( + leadingTrivia: leadingTrivia, + unexpectedBeforeBaseType, + baseType: baseType, + unexpectedBetweenBaseTypeAndPeriod, + period: period, + unexpectedBetweenPeriodAndName, + moduleSelector: nil, + nil, + name: name, + unexpectedBetweenNameAndGenericArgumentClause, + genericArgumentClause: genericArgumentClause, + unexpectedAfterGenericArgumentClause, + trailingTrivia: trailingTrivia + ) + } +} + extension MetatypeTypeSyntax { @available(*, deprecated, renamed: "unexpectedBetweenPeriodAndMetatypeSpecifier") public var unexpectedBetweenPeriodAndTypeOrProtocol: UnexpectedNodesSyntax? { diff --git a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift index 5aed3234809..093287a440e 100644 --- a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift @@ -1549,6 +1549,16 @@ open class SyntaxAnyVisitor: SyntaxVisitor { visitAnyPost(node._syntaxNode) } + @_spi(ExperimentalLanguageFeatures) + override open func visit(_ node: ModuleSelectorSyntax) -> SyntaxVisitorContinueKind { + return visitAny(node._syntaxNode) + } + + @_spi(ExperimentalLanguageFeatures) + override open func visitPost(_ node: ModuleSelectorSyntax) { + visitAnyPost(node._syntaxNode) + } + override open func visit(_ node: MultipleTrailingClosureElementListSyntax) -> SyntaxVisitorContinueKind { return visitAny(node._syntaxNode) } diff --git a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift index eeeb0d80cdb..4aede428e8c 100644 --- a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift +++ b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift @@ -1697,6 +1697,7 @@ extension Syntax { .node(MissingStmtSyntax.self), .node(MissingSyntax.self), .node(MissingTypeSyntax.self), + .node(ModuleSelectorSyntax.self), .node(MultipleTrailingClosureElementListSyntax.self), .node(MultipleTrailingClosureElementSyntax.self), .node(NamedOpaqueReturnTypeSyntax.self), diff --git a/Sources/SwiftSyntax/generated/SyntaxEnum.swift b/Sources/SwiftSyntax/generated/SyntaxEnum.swift index 64bec970ecb..7dfaad0a54f 100644 --- a/Sources/SwiftSyntax/generated/SyntaxEnum.swift +++ b/Sources/SwiftSyntax/generated/SyntaxEnum.swift @@ -210,6 +210,8 @@ public enum SyntaxEnum: Sendable { case missingStmt(MissingStmtSyntax) case missing(MissingSyntax) case missingType(MissingTypeSyntax) + @_spi(ExperimentalLanguageFeatures) + case moduleSelector(ModuleSelectorSyntax) case multipleTrailingClosureElementList(MultipleTrailingClosureElementListSyntax) case multipleTrailingClosureElement(MultipleTrailingClosureElementSyntax) case namedOpaqueReturnType(NamedOpaqueReturnTypeSyntax) @@ -694,6 +696,8 @@ extension Syntax { return .missing(MissingSyntax(self)!) case .missingType: return .missingType(MissingTypeSyntax(self)!) + case .moduleSelector: + return .moduleSelector(ModuleSelectorSyntax(self)!) case .multipleTrailingClosureElementList: return .multipleTrailingClosureElementList(MultipleTrailingClosureElementListSyntax(self)!) case .multipleTrailingClosureElement: diff --git a/Sources/SwiftSyntax/generated/SyntaxKind.swift b/Sources/SwiftSyntax/generated/SyntaxKind.swift index afc025276e3..48111e23c7c 100644 --- a/Sources/SwiftSyntax/generated/SyntaxKind.swift +++ b/Sources/SwiftSyntax/generated/SyntaxKind.swift @@ -210,6 +210,8 @@ public enum SyntaxKind: Sendable { case missingStmt case missing case missingType + @_spi(ExperimentalLanguageFeatures) + case moduleSelector case multipleTrailingClosureElementList case multipleTrailingClosureElement case namedOpaqueReturnType @@ -819,6 +821,8 @@ public enum SyntaxKind: Sendable { return MissingSyntax.self case .missingType: return MissingTypeSyntax.self + case .moduleSelector: + return ModuleSelectorSyntax.self case .multipleTrailingClosureElementList: return MultipleTrailingClosureElementListSyntax.self case .multipleTrailingClosureElement: diff --git a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift index 02c3e44e826..598f0786e17 100644 --- a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift +++ b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift @@ -1397,6 +1397,14 @@ open class SyntaxRewriter { return TypeSyntax(MissingTypeSyntax(unsafeCasting: visitChildren(node._syntaxNode))) } + /// Visit a `ModuleSelectorSyntax`. + /// - Parameter node: the node that is being visited + /// - Returns: the rewritten node + @_spi(ExperimentalLanguageFeatures) + open func visit(_ node: ModuleSelectorSyntax) -> ModuleSelectorSyntax { + return ModuleSelectorSyntax(unsafeCasting: visitChildren(node._syntaxNode)) + } + /// Visit a ``MultipleTrailingClosureElementListSyntax``. /// - Parameter node: the node that is being visited /// - Returns: the rewritten node @@ -3101,6 +3109,11 @@ open class SyntaxRewriter { Syntax(visit(MissingTypeSyntax(unsafeCasting: node))) } + @inline(never) + private func visitModuleSelectorSyntaxImpl(_ node: Syntax) -> Syntax { + Syntax(visit(ModuleSelectorSyntax(unsafeCasting: node))) + } + @inline(never) private func visitMultipleTrailingClosureElementListSyntaxImpl(_ node: Syntax) -> Syntax { Syntax(visit(MultipleTrailingClosureElementListSyntax(unsafeCasting: node))) @@ -4027,6 +4040,8 @@ open class SyntaxRewriter { return self.visitMissingSyntaxImpl(_:) case .missingType: return self.visitMissingTypeSyntaxImpl(_:) + case .moduleSelector: + return self.visitModuleSelectorSyntaxImpl(_:) case .multipleTrailingClosureElementList: return self.visitMultipleTrailingClosureElementListSyntaxImpl(_:) case .multipleTrailingClosureElement: @@ -4617,6 +4632,8 @@ open class SyntaxRewriter { return visitMissingSyntaxImpl(node) case .missingType: return visitMissingTypeSyntaxImpl(node) + case .moduleSelector: + return visitModuleSelectorSyntaxImpl(node) case .multipleTrailingClosureElementList: return visitMultipleTrailingClosureElementListSyntaxImpl(node) case .multipleTrailingClosureElement: diff --git a/Sources/SwiftSyntax/generated/SyntaxTraits.swift b/Sources/SwiftSyntax/generated/SyntaxTraits.swift index 368b529b45b..f982fc26147 100644 --- a/Sources/SwiftSyntax/generated/SyntaxTraits.swift +++ b/Sources/SwiftSyntax/generated/SyntaxTraits.swift @@ -205,6 +205,12 @@ public protocol FreestandingMacroExpansionSyntax: SyntaxProtocol { set } + @_spi(ExperimentalLanguageFeatures) + var moduleSelector: ModuleSelectorSyntax? { + get + set + } + /// ### Tokens /// /// For syntax trees generated by the parser, this is guaranteed to be ``. diff --git a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift index c61819a16a1..b6800a6db74 100644 --- a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift @@ -2263,6 +2263,20 @@ open class SyntaxVisitor { open func visitPost(_ node: MissingTypeSyntax) { } + /// Visiting `ModuleSelectorSyntax` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: how should we continue visiting. + @_spi(ExperimentalLanguageFeatures) + open func visit(_ node: ModuleSelectorSyntax) -> SyntaxVisitorContinueKind { + return .visitChildren + } + + /// The function called after visiting `ModuleSelectorSyntax` and its descendants. + /// - node: the node we just finished visiting. + @_spi(ExperimentalLanguageFeatures) + open func visitPost(_ node: ModuleSelectorSyntax) { + } + /// Visiting ``MultipleTrailingClosureElementListSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: how should we continue visiting. @@ -5030,6 +5044,14 @@ open class SyntaxVisitor { visitPost(MissingTypeSyntax(unsafeCasting: node)) } + @inline(never) + private func visitModuleSelectorSyntaxImpl(_ node: Syntax) { + if visit(ModuleSelectorSyntax(unsafeCasting: node)) == .visitChildren { + visitChildren(node) + } + visitPost(ModuleSelectorSyntax(unsafeCasting: node)) + } + @inline(never) private func visitMultipleTrailingClosureElementListSyntaxImpl(_ node: Syntax) { if visit(MultipleTrailingClosureElementListSyntax(unsafeCasting: node)) == .visitChildren { @@ -6274,6 +6296,8 @@ open class SyntaxVisitor { return self.visitMissingSyntaxImpl(_:) case .missingType: return self.visitMissingTypeSyntaxImpl(_:) + case .moduleSelector: + return self.visitModuleSelectorSyntaxImpl(_:) case .multipleTrailingClosureElementList: return self.visitMultipleTrailingClosureElementListSyntaxImpl(_:) case .multipleTrailingClosureElement: @@ -6864,6 +6888,8 @@ open class SyntaxVisitor { self.visitMissingSyntaxImpl(node) case .missingType: self.visitMissingTypeSyntaxImpl(node) + case .moduleSelector: + self.visitModuleSelectorSyntaxImpl(node) case .multipleTrailingClosureElementList: self.visitMultipleTrailingClosureElementListSyntaxImpl(node) case .multipleTrailingClosureElement: diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesD.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesD.swift index 79480c99c6b..53e55832a34 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesD.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesD.swift @@ -450,7 +450,9 @@ public struct RawDeclReferenceExprSyntax: RawExprSyntaxNodeProtocol { } public init( - _ unexpectedBeforeBaseName: RawUnexpectedNodesSyntax? = nil, + _ unexpectedBeforeModuleSelector: RawUnexpectedNodesSyntax? = nil, + moduleSelector: RawModuleSelectorSyntax?, + _ unexpectedBetweenModuleSelectorAndBaseName: RawUnexpectedNodesSyntax? = nil, baseName: RawTokenSyntax, _ unexpectedBetweenBaseNameAndArgumentNames: RawUnexpectedNodesSyntax? = nil, argumentNames: RawDeclNameArgumentsSyntax?, @@ -458,35 +460,45 @@ public struct RawDeclReferenceExprSyntax: RawExprSyntaxNodeProtocol { arena: __shared RawSyntaxArena ) { let raw = RawSyntax.makeLayout( - kind: .declReferenceExpr, uninitializedCount: 5, arena: arena) { layout in + kind: .declReferenceExpr, uninitializedCount: 7, arena: arena) { layout in layout.initialize(repeating: nil) - layout[0] = unexpectedBeforeBaseName?.raw - layout[1] = baseName.raw - layout[2] = unexpectedBetweenBaseNameAndArgumentNames?.raw - layout[3] = argumentNames?.raw - layout[4] = unexpectedAfterArgumentNames?.raw + layout[0] = unexpectedBeforeModuleSelector?.raw + layout[1] = moduleSelector?.raw + layout[2] = unexpectedBetweenModuleSelectorAndBaseName?.raw + layout[3] = baseName.raw + layout[4] = unexpectedBetweenBaseNameAndArgumentNames?.raw + layout[5] = argumentNames?.raw + layout[6] = unexpectedAfterArgumentNames?.raw } self.init(unchecked: raw) } - public var unexpectedBeforeBaseName: RawUnexpectedNodesSyntax? { + public var unexpectedBeforeModuleSelector: RawUnexpectedNodesSyntax? { layoutView.children[0].map(RawUnexpectedNodesSyntax.init(raw:)) } + public var moduleSelector: RawModuleSelectorSyntax? { + layoutView.children[1].map(RawModuleSelectorSyntax.init(raw:)) + } + + public var unexpectedBetweenModuleSelectorAndBaseName: RawUnexpectedNodesSyntax? { + layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) + } + public var baseName: RawTokenSyntax { - layoutView.children[1].map(RawTokenSyntax.init(raw:))! + layoutView.children[3].map(RawTokenSyntax.init(raw:))! } public var unexpectedBetweenBaseNameAndArgumentNames: RawUnexpectedNodesSyntax? { - layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) } public var argumentNames: RawDeclNameArgumentsSyntax? { - layoutView.children[3].map(RawDeclNameArgumentsSyntax.init(raw:)) + layoutView.children[5].map(RawDeclNameArgumentsSyntax.init(raw:)) } public var unexpectedAfterArgumentNames: RawUnexpectedNodesSyntax? { - layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[6].map(RawUnexpectedNodesSyntax.init(raw:)) } } diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift index d74ae1a0862..76ca3886071 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift @@ -988,7 +988,9 @@ public struct RawIdentifierTypeSyntax: RawTypeSyntaxNodeProtocol { } public init( - _ unexpectedBeforeName: RawUnexpectedNodesSyntax? = nil, + _ unexpectedBeforeModuleSelector: RawUnexpectedNodesSyntax? = nil, + moduleSelector: RawModuleSelectorSyntax?, + _ unexpectedBetweenModuleSelectorAndName: RawUnexpectedNodesSyntax? = nil, name: RawTokenSyntax, _ unexpectedBetweenNameAndGenericArgumentClause: RawUnexpectedNodesSyntax? = nil, genericArgumentClause: RawGenericArgumentClauseSyntax?, @@ -996,35 +998,45 @@ public struct RawIdentifierTypeSyntax: RawTypeSyntaxNodeProtocol { arena: __shared RawSyntaxArena ) { let raw = RawSyntax.makeLayout( - kind: .identifierType, uninitializedCount: 5, arena: arena) { layout in + kind: .identifierType, uninitializedCount: 7, arena: arena) { layout in layout.initialize(repeating: nil) - layout[0] = unexpectedBeforeName?.raw - layout[1] = name.raw - layout[2] = unexpectedBetweenNameAndGenericArgumentClause?.raw - layout[3] = genericArgumentClause?.raw - layout[4] = unexpectedAfterGenericArgumentClause?.raw + layout[0] = unexpectedBeforeModuleSelector?.raw + layout[1] = moduleSelector?.raw + layout[2] = unexpectedBetweenModuleSelectorAndName?.raw + layout[3] = name.raw + layout[4] = unexpectedBetweenNameAndGenericArgumentClause?.raw + layout[5] = genericArgumentClause?.raw + layout[6] = unexpectedAfterGenericArgumentClause?.raw } self.init(unchecked: raw) } - public var unexpectedBeforeName: RawUnexpectedNodesSyntax? { + public var unexpectedBeforeModuleSelector: RawUnexpectedNodesSyntax? { layoutView.children[0].map(RawUnexpectedNodesSyntax.init(raw:)) } + public var moduleSelector: RawModuleSelectorSyntax? { + layoutView.children[1].map(RawModuleSelectorSyntax.init(raw:)) + } + + public var unexpectedBetweenModuleSelectorAndName: RawUnexpectedNodesSyntax? { + layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) + } + public var name: RawTokenSyntax { - layoutView.children[1].map(RawTokenSyntax.init(raw:))! + layoutView.children[3].map(RawTokenSyntax.init(raw:))! } public var unexpectedBetweenNameAndGenericArgumentClause: RawUnexpectedNodesSyntax? { - layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) } public var genericArgumentClause: RawGenericArgumentClauseSyntax? { - layoutView.children[3].map(RawGenericArgumentClauseSyntax.init(raw:)) + layoutView.children[5].map(RawGenericArgumentClauseSyntax.init(raw:)) } public var unexpectedAfterGenericArgumentClause: RawUnexpectedNodesSyntax? { - layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[6].map(RawUnexpectedNodesSyntax.init(raw:)) } } diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesJKLMN.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesJKLMN.swift index 8e6766d2c4f..14aff2265cb 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesJKLMN.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesJKLMN.swift @@ -1429,7 +1429,9 @@ public struct RawMacroExpansionDeclSyntax: RawDeclSyntaxNodeProtocol { modifiers: RawDeclModifierListSyntax, _ unexpectedBetweenModifiersAndPound: RawUnexpectedNodesSyntax? = nil, pound: RawTokenSyntax, - _ unexpectedBetweenPoundAndMacroName: RawUnexpectedNodesSyntax? = nil, + _ unexpectedBetweenPoundAndModuleSelector: RawUnexpectedNodesSyntax? = nil, + moduleSelector: RawModuleSelectorSyntax?, + _ unexpectedBetweenModuleSelectorAndMacroName: RawUnexpectedNodesSyntax? = nil, macroName: RawTokenSyntax, _ unexpectedBetweenMacroNameAndGenericArgumentClause: RawUnexpectedNodesSyntax? = nil, genericArgumentClause: RawGenericArgumentClauseSyntax?, @@ -1447,7 +1449,7 @@ public struct RawMacroExpansionDeclSyntax: RawDeclSyntaxNodeProtocol { arena: __shared RawSyntaxArena ) { let raw = RawSyntax.makeLayout( - kind: .macroExpansionDecl, uninitializedCount: 21, arena: arena) { layout in + kind: .macroExpansionDecl, uninitializedCount: 23, arena: arena) { layout in layout.initialize(repeating: nil) layout[0] = unexpectedBeforeAttributes?.raw layout[1] = attributes.raw @@ -1455,21 +1457,23 @@ public struct RawMacroExpansionDeclSyntax: RawDeclSyntaxNodeProtocol { layout[3] = modifiers.raw layout[4] = unexpectedBetweenModifiersAndPound?.raw layout[5] = pound.raw - layout[6] = unexpectedBetweenPoundAndMacroName?.raw - layout[7] = macroName.raw - layout[8] = unexpectedBetweenMacroNameAndGenericArgumentClause?.raw - layout[9] = genericArgumentClause?.raw - layout[10] = unexpectedBetweenGenericArgumentClauseAndLeftParen?.raw - layout[11] = leftParen?.raw - layout[12] = unexpectedBetweenLeftParenAndArguments?.raw - layout[13] = arguments.raw - layout[14] = unexpectedBetweenArgumentsAndRightParen?.raw - layout[15] = rightParen?.raw - layout[16] = unexpectedBetweenRightParenAndTrailingClosure?.raw - layout[17] = trailingClosure?.raw - layout[18] = unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures?.raw - layout[19] = additionalTrailingClosures.raw - layout[20] = unexpectedAfterAdditionalTrailingClosures?.raw + layout[6] = unexpectedBetweenPoundAndModuleSelector?.raw + layout[7] = moduleSelector?.raw + layout[8] = unexpectedBetweenModuleSelectorAndMacroName?.raw + layout[9] = macroName.raw + layout[10] = unexpectedBetweenMacroNameAndGenericArgumentClause?.raw + layout[11] = genericArgumentClause?.raw + layout[12] = unexpectedBetweenGenericArgumentClauseAndLeftParen?.raw + layout[13] = leftParen?.raw + layout[14] = unexpectedBetweenLeftParenAndArguments?.raw + layout[15] = arguments.raw + layout[16] = unexpectedBetweenArgumentsAndRightParen?.raw + layout[17] = rightParen?.raw + layout[18] = unexpectedBetweenRightParenAndTrailingClosure?.raw + layout[19] = trailingClosure?.raw + layout[20] = unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures?.raw + layout[21] = additionalTrailingClosures.raw + layout[22] = unexpectedAfterAdditionalTrailingClosures?.raw } self.init(unchecked: raw) } @@ -1498,64 +1502,72 @@ public struct RawMacroExpansionDeclSyntax: RawDeclSyntaxNodeProtocol { layoutView.children[5].map(RawTokenSyntax.init(raw:))! } - public var unexpectedBetweenPoundAndMacroName: RawUnexpectedNodesSyntax? { + public var unexpectedBetweenPoundAndModuleSelector: RawUnexpectedNodesSyntax? { layoutView.children[6].map(RawUnexpectedNodesSyntax.init(raw:)) } + public var moduleSelector: RawModuleSelectorSyntax? { + layoutView.children[7].map(RawModuleSelectorSyntax.init(raw:)) + } + + public var unexpectedBetweenModuleSelectorAndMacroName: RawUnexpectedNodesSyntax? { + layoutView.children[8].map(RawUnexpectedNodesSyntax.init(raw:)) + } + public var macroName: RawTokenSyntax { - layoutView.children[7].map(RawTokenSyntax.init(raw:))! + layoutView.children[9].map(RawTokenSyntax.init(raw:))! } public var unexpectedBetweenMacroNameAndGenericArgumentClause: RawUnexpectedNodesSyntax? { - layoutView.children[8].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[10].map(RawUnexpectedNodesSyntax.init(raw:)) } public var genericArgumentClause: RawGenericArgumentClauseSyntax? { - layoutView.children[9].map(RawGenericArgumentClauseSyntax.init(raw:)) + layoutView.children[11].map(RawGenericArgumentClauseSyntax.init(raw:)) } public var unexpectedBetweenGenericArgumentClauseAndLeftParen: RawUnexpectedNodesSyntax? { - layoutView.children[10].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[12].map(RawUnexpectedNodesSyntax.init(raw:)) } public var leftParen: RawTokenSyntax? { - layoutView.children[11].map(RawTokenSyntax.init(raw:)) + layoutView.children[13].map(RawTokenSyntax.init(raw:)) } public var unexpectedBetweenLeftParenAndArguments: RawUnexpectedNodesSyntax? { - layoutView.children[12].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[14].map(RawUnexpectedNodesSyntax.init(raw:)) } public var arguments: RawLabeledExprListSyntax { - layoutView.children[13].map(RawLabeledExprListSyntax.init(raw:))! + layoutView.children[15].map(RawLabeledExprListSyntax.init(raw:))! } public var unexpectedBetweenArgumentsAndRightParen: RawUnexpectedNodesSyntax? { - layoutView.children[14].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[16].map(RawUnexpectedNodesSyntax.init(raw:)) } public var rightParen: RawTokenSyntax? { - layoutView.children[15].map(RawTokenSyntax.init(raw:)) + layoutView.children[17].map(RawTokenSyntax.init(raw:)) } public var unexpectedBetweenRightParenAndTrailingClosure: RawUnexpectedNodesSyntax? { - layoutView.children[16].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[18].map(RawUnexpectedNodesSyntax.init(raw:)) } public var trailingClosure: RawClosureExprSyntax? { - layoutView.children[17].map(RawClosureExprSyntax.init(raw:)) + layoutView.children[19].map(RawClosureExprSyntax.init(raw:)) } public var unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures: RawUnexpectedNodesSyntax? { - layoutView.children[18].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[20].map(RawUnexpectedNodesSyntax.init(raw:)) } public var additionalTrailingClosures: RawMultipleTrailingClosureElementListSyntax { - layoutView.children[19].map(RawMultipleTrailingClosureElementListSyntax.init(raw:))! + layoutView.children[21].map(RawMultipleTrailingClosureElementListSyntax.init(raw:))! } public var unexpectedAfterAdditionalTrailingClosures: RawUnexpectedNodesSyntax? { - layoutView.children[20].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[22].map(RawUnexpectedNodesSyntax.init(raw:)) } } @@ -1591,7 +1603,9 @@ public struct RawMacroExpansionExprSyntax: RawExprSyntaxNodeProtocol { public init( _ unexpectedBeforePound: RawUnexpectedNodesSyntax? = nil, pound: RawTokenSyntax, - _ unexpectedBetweenPoundAndMacroName: RawUnexpectedNodesSyntax? = nil, + _ unexpectedBetweenPoundAndModuleSelector: RawUnexpectedNodesSyntax? = nil, + moduleSelector: RawModuleSelectorSyntax?, + _ unexpectedBetweenModuleSelectorAndMacroName: RawUnexpectedNodesSyntax? = nil, macroName: RawTokenSyntax, _ unexpectedBetweenMacroNameAndGenericArgumentClause: RawUnexpectedNodesSyntax? = nil, genericArgumentClause: RawGenericArgumentClauseSyntax?, @@ -1609,25 +1623,27 @@ public struct RawMacroExpansionExprSyntax: RawExprSyntaxNodeProtocol { arena: __shared RawSyntaxArena ) { let raw = RawSyntax.makeLayout( - kind: .macroExpansionExpr, uninitializedCount: 17, arena: arena) { layout in + kind: .macroExpansionExpr, uninitializedCount: 19, arena: arena) { layout in layout.initialize(repeating: nil) layout[0] = unexpectedBeforePound?.raw layout[1] = pound.raw - layout[2] = unexpectedBetweenPoundAndMacroName?.raw - layout[3] = macroName.raw - layout[4] = unexpectedBetweenMacroNameAndGenericArgumentClause?.raw - layout[5] = genericArgumentClause?.raw - layout[6] = unexpectedBetweenGenericArgumentClauseAndLeftParen?.raw - layout[7] = leftParen?.raw - layout[8] = unexpectedBetweenLeftParenAndArguments?.raw - layout[9] = arguments.raw - layout[10] = unexpectedBetweenArgumentsAndRightParen?.raw - layout[11] = rightParen?.raw - layout[12] = unexpectedBetweenRightParenAndTrailingClosure?.raw - layout[13] = trailingClosure?.raw - layout[14] = unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures?.raw - layout[15] = additionalTrailingClosures.raw - layout[16] = unexpectedAfterAdditionalTrailingClosures?.raw + layout[2] = unexpectedBetweenPoundAndModuleSelector?.raw + layout[3] = moduleSelector?.raw + layout[4] = unexpectedBetweenModuleSelectorAndMacroName?.raw + layout[5] = macroName.raw + layout[6] = unexpectedBetweenMacroNameAndGenericArgumentClause?.raw + layout[7] = genericArgumentClause?.raw + layout[8] = unexpectedBetweenGenericArgumentClauseAndLeftParen?.raw + layout[9] = leftParen?.raw + layout[10] = unexpectedBetweenLeftParenAndArguments?.raw + layout[11] = arguments.raw + layout[12] = unexpectedBetweenArgumentsAndRightParen?.raw + layout[13] = rightParen?.raw + layout[14] = unexpectedBetweenRightParenAndTrailingClosure?.raw + layout[15] = trailingClosure?.raw + layout[16] = unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures?.raw + layout[17] = additionalTrailingClosures.raw + layout[18] = unexpectedAfterAdditionalTrailingClosures?.raw } self.init(unchecked: raw) } @@ -1640,64 +1656,72 @@ public struct RawMacroExpansionExprSyntax: RawExprSyntaxNodeProtocol { layoutView.children[1].map(RawTokenSyntax.init(raw:))! } - public var unexpectedBetweenPoundAndMacroName: RawUnexpectedNodesSyntax? { + public var unexpectedBetweenPoundAndModuleSelector: RawUnexpectedNodesSyntax? { layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) } + public var moduleSelector: RawModuleSelectorSyntax? { + layoutView.children[3].map(RawModuleSelectorSyntax.init(raw:)) + } + + public var unexpectedBetweenModuleSelectorAndMacroName: RawUnexpectedNodesSyntax? { + layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) + } + public var macroName: RawTokenSyntax { - layoutView.children[3].map(RawTokenSyntax.init(raw:))! + layoutView.children[5].map(RawTokenSyntax.init(raw:))! } public var unexpectedBetweenMacroNameAndGenericArgumentClause: RawUnexpectedNodesSyntax? { - layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[6].map(RawUnexpectedNodesSyntax.init(raw:)) } public var genericArgumentClause: RawGenericArgumentClauseSyntax? { - layoutView.children[5].map(RawGenericArgumentClauseSyntax.init(raw:)) + layoutView.children[7].map(RawGenericArgumentClauseSyntax.init(raw:)) } public var unexpectedBetweenGenericArgumentClauseAndLeftParen: RawUnexpectedNodesSyntax? { - layoutView.children[6].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[8].map(RawUnexpectedNodesSyntax.init(raw:)) } public var leftParen: RawTokenSyntax? { - layoutView.children[7].map(RawTokenSyntax.init(raw:)) + layoutView.children[9].map(RawTokenSyntax.init(raw:)) } public var unexpectedBetweenLeftParenAndArguments: RawUnexpectedNodesSyntax? { - layoutView.children[8].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[10].map(RawUnexpectedNodesSyntax.init(raw:)) } public var arguments: RawLabeledExprListSyntax { - layoutView.children[9].map(RawLabeledExprListSyntax.init(raw:))! + layoutView.children[11].map(RawLabeledExprListSyntax.init(raw:))! } public var unexpectedBetweenArgumentsAndRightParen: RawUnexpectedNodesSyntax? { - layoutView.children[10].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[12].map(RawUnexpectedNodesSyntax.init(raw:)) } public var rightParen: RawTokenSyntax? { - layoutView.children[11].map(RawTokenSyntax.init(raw:)) + layoutView.children[13].map(RawTokenSyntax.init(raw:)) } public var unexpectedBetweenRightParenAndTrailingClosure: RawUnexpectedNodesSyntax? { - layoutView.children[12].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[14].map(RawUnexpectedNodesSyntax.init(raw:)) } public var trailingClosure: RawClosureExprSyntax? { - layoutView.children[13].map(RawClosureExprSyntax.init(raw:)) + layoutView.children[15].map(RawClosureExprSyntax.init(raw:)) } public var unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures: RawUnexpectedNodesSyntax? { - layoutView.children[14].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[16].map(RawUnexpectedNodesSyntax.init(raw:)) } public var additionalTrailingClosures: RawMultipleTrailingClosureElementListSyntax { - layoutView.children[15].map(RawMultipleTrailingClosureElementListSyntax.init(raw:))! + layoutView.children[17].map(RawMultipleTrailingClosureElementListSyntax.init(raw:))! } public var unexpectedAfterAdditionalTrailingClosures: RawUnexpectedNodesSyntax? { - layoutView.children[16].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[18].map(RawUnexpectedNodesSyntax.init(raw:)) } } @@ -2184,7 +2208,9 @@ public struct RawMemberTypeSyntax: RawTypeSyntaxNodeProtocol { baseType: some RawTypeSyntaxNodeProtocol, _ unexpectedBetweenBaseTypeAndPeriod: RawUnexpectedNodesSyntax? = nil, period: RawTokenSyntax, - _ unexpectedBetweenPeriodAndName: RawUnexpectedNodesSyntax? = nil, + _ unexpectedBetweenPeriodAndModuleSelector: RawUnexpectedNodesSyntax? = nil, + moduleSelector: RawModuleSelectorSyntax?, + _ unexpectedBetweenModuleSelectorAndName: RawUnexpectedNodesSyntax? = nil, name: RawTokenSyntax, _ unexpectedBetweenNameAndGenericArgumentClause: RawUnexpectedNodesSyntax? = nil, genericArgumentClause: RawGenericArgumentClauseSyntax?, @@ -2192,17 +2218,19 @@ public struct RawMemberTypeSyntax: RawTypeSyntaxNodeProtocol { arena: __shared RawSyntaxArena ) { let raw = RawSyntax.makeLayout( - kind: .memberType, uninitializedCount: 9, arena: arena) { layout in + kind: .memberType, uninitializedCount: 11, arena: arena) { layout in layout.initialize(repeating: nil) layout[0] = unexpectedBeforeBaseType?.raw layout[1] = baseType.raw layout[2] = unexpectedBetweenBaseTypeAndPeriod?.raw layout[3] = period.raw - layout[4] = unexpectedBetweenPeriodAndName?.raw - layout[5] = name.raw - layout[6] = unexpectedBetweenNameAndGenericArgumentClause?.raw - layout[7] = genericArgumentClause?.raw - layout[8] = unexpectedAfterGenericArgumentClause?.raw + layout[4] = unexpectedBetweenPeriodAndModuleSelector?.raw + layout[5] = moduleSelector?.raw + layout[6] = unexpectedBetweenModuleSelectorAndName?.raw + layout[7] = name.raw + layout[8] = unexpectedBetweenNameAndGenericArgumentClause?.raw + layout[9] = genericArgumentClause?.raw + layout[10] = unexpectedAfterGenericArgumentClause?.raw } self.init(unchecked: raw) } @@ -2223,24 +2251,32 @@ public struct RawMemberTypeSyntax: RawTypeSyntaxNodeProtocol { layoutView.children[3].map(RawTokenSyntax.init(raw:))! } - public var unexpectedBetweenPeriodAndName: RawUnexpectedNodesSyntax? { + public var unexpectedBetweenPeriodAndModuleSelector: RawUnexpectedNodesSyntax? { layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) } + public var moduleSelector: RawModuleSelectorSyntax? { + layoutView.children[5].map(RawModuleSelectorSyntax.init(raw:)) + } + + public var unexpectedBetweenModuleSelectorAndName: RawUnexpectedNodesSyntax? { + layoutView.children[6].map(RawUnexpectedNodesSyntax.init(raw:)) + } + public var name: RawTokenSyntax { - layoutView.children[5].map(RawTokenSyntax.init(raw:))! + layoutView.children[7].map(RawTokenSyntax.init(raw:))! } public var unexpectedBetweenNameAndGenericArgumentClause: RawUnexpectedNodesSyntax? { - layoutView.children[6].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[8].map(RawUnexpectedNodesSyntax.init(raw:)) } public var genericArgumentClause: RawGenericArgumentClauseSyntax? { - layoutView.children[7].map(RawGenericArgumentClauseSyntax.init(raw:)) + layoutView.children[9].map(RawGenericArgumentClauseSyntax.init(raw:)) } public var unexpectedAfterGenericArgumentClause: RawUnexpectedNodesSyntax? { - layoutView.children[8].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[10].map(RawUnexpectedNodesSyntax.init(raw:)) } } @@ -2698,6 +2734,77 @@ public struct RawMissingTypeSyntax: RawTypeSyntaxNodeProtocol { } } +@_spi(ExperimentalLanguageFeatures) +@_spi(RawSyntax) +public struct RawModuleSelectorSyntax: RawSyntaxNodeProtocol { + @_spi(RawSyntax) + public var layoutView: RawSyntaxLayoutView { + return raw.layoutView! + } + + public static func isKindOf(_ raw: RawSyntax) -> Bool { + return raw.kind == .moduleSelector + } + + public var raw: RawSyntax + + init(raw: RawSyntax) { + precondition(Self.isKindOf(raw)) + self.raw = raw + } + + private init(unchecked raw: RawSyntax) { + self.raw = raw + } + + public init?(_ other: some RawSyntaxNodeProtocol) { + guard Self.isKindOf(other.raw) else { + return nil + } + self.init(unchecked: other.raw) + } + + public init( + _ unexpectedBeforeModuleName: RawUnexpectedNodesSyntax? = nil, + moduleName: RawTokenSyntax, + _ unexpectedBetweenModuleNameAndColonColon: RawUnexpectedNodesSyntax? = nil, + colonColon: RawTokenSyntax, + _ unexpectedAfterColonColon: RawUnexpectedNodesSyntax? = nil, + arena: __shared RawSyntaxArena + ) { + let raw = RawSyntax.makeLayout( + kind: .moduleSelector, uninitializedCount: 5, arena: arena) { layout in + layout.initialize(repeating: nil) + layout[0] = unexpectedBeforeModuleName?.raw + layout[1] = moduleName.raw + layout[2] = unexpectedBetweenModuleNameAndColonColon?.raw + layout[3] = colonColon.raw + layout[4] = unexpectedAfterColonColon?.raw + } + self.init(unchecked: raw) + } + + public var unexpectedBeforeModuleName: RawUnexpectedNodesSyntax? { + layoutView.children[0].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var moduleName: RawTokenSyntax { + layoutView.children[1].map(RawTokenSyntax.init(raw:))! + } + + public var unexpectedBetweenModuleNameAndColonColon: RawUnexpectedNodesSyntax? { + layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var colonColon: RawTokenSyntax { + layoutView.children[3].map(RawTokenSyntax.init(raw:))! + } + + public var unexpectedAfterColonColon: RawUnexpectedNodesSyntax? { + layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) + } +} + @_spi(RawSyntax) public struct RawMultipleTrailingClosureElementListSyntax: RawSyntaxNodeProtocol { @_spi(RawSyntax) diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index 4def2848664..dec95731828 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -915,9 +915,11 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self)) } func validateDeclReferenceExprSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { - assert(layout.count == 5) + assert(layout.count == 7) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [ + assertNoError(kind, 1, verify(layout[1], as: RawModuleSelectorSyntax?.self)) + assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 3, verify(layout[3], as: RawTokenSyntax.self, tokenChoices: [ .tokenKind(.identifier), .keyword("self"), .keyword("Self"), @@ -928,9 +930,9 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { .tokenKind(.binaryOperator), .tokenKind(.integerLiteral) ])) - assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 3, verify(layout[3], as: RawDeclNameArgumentsSyntax?.self)) assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 5, verify(layout[5], as: RawDeclNameArgumentsSyntax?.self)) + assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self)) } func validateDeferStmtSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { assert(layout.count == 5) @@ -1565,17 +1567,19 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) } func validateIdentifierTypeSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { - assert(layout.count == 5) + assert(layout.count == 7) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [ + assertNoError(kind, 1, verify(layout[1], as: RawModuleSelectorSyntax?.self)) + assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 3, verify(layout[3], as: RawTokenSyntax.self, tokenChoices: [ .tokenKind(.identifier), .keyword("Self"), .keyword("Any"), .tokenKind(.wildcard) ])) - assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 3, verify(layout[3], as: RawGenericArgumentClauseSyntax?.self)) assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 5, verify(layout[5], as: RawGenericArgumentClauseSyntax?.self)) + assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self)) } func validateIfConfigClauseListSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { for (index, element) in layout.enumerated() { @@ -1965,7 +1969,7 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 16, verify(layout[16], as: RawUnexpectedNodesSyntax?.self)) } func validateMacroExpansionDeclSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { - assert(layout.count == 21) + assert(layout.count == 23) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 1, verify(layout[1], as: RawAttributeListSyntax.self)) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) @@ -1973,40 +1977,44 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 5, verify(layout[5], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.pound)])) assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 7, verify(layout[7], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier)])) + assertNoError(kind, 7, verify(layout[7], as: RawModuleSelectorSyntax?.self)) assertNoError(kind, 8, verify(layout[8], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 9, verify(layout[9], as: RawGenericArgumentClauseSyntax?.self)) + assertNoError(kind, 9, verify(layout[9], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier)])) assertNoError(kind, 10, verify(layout[10], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 11, verify(layout[11], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.leftParen)])) + assertNoError(kind, 11, verify(layout[11], as: RawGenericArgumentClauseSyntax?.self)) assertNoError(kind, 12, verify(layout[12], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 13, verify(layout[13], as: RawLabeledExprListSyntax.self)) + assertNoError(kind, 13, verify(layout[13], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.leftParen)])) assertNoError(kind, 14, verify(layout[14], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 15, verify(layout[15], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.rightParen)])) + assertNoError(kind, 15, verify(layout[15], as: RawLabeledExprListSyntax.self)) assertNoError(kind, 16, verify(layout[16], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 17, verify(layout[17], as: RawClosureExprSyntax?.self)) + assertNoError(kind, 17, verify(layout[17], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.rightParen)])) assertNoError(kind, 18, verify(layout[18], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 19, verify(layout[19], as: RawMultipleTrailingClosureElementListSyntax.self)) + assertNoError(kind, 19, verify(layout[19], as: RawClosureExprSyntax?.self)) assertNoError(kind, 20, verify(layout[20], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 21, verify(layout[21], as: RawMultipleTrailingClosureElementListSyntax.self)) + assertNoError(kind, 22, verify(layout[22], as: RawUnexpectedNodesSyntax?.self)) } func validateMacroExpansionExprSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { - assert(layout.count == 17) + assert(layout.count == 19) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.pound)])) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 3, verify(layout[3], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier)])) + assertNoError(kind, 3, verify(layout[3], as: RawModuleSelectorSyntax?.self)) assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 5, verify(layout[5], as: RawGenericArgumentClauseSyntax?.self)) + assertNoError(kind, 5, verify(layout[5], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier)])) assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 7, verify(layout[7], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.leftParen)])) + assertNoError(kind, 7, verify(layout[7], as: RawGenericArgumentClauseSyntax?.self)) assertNoError(kind, 8, verify(layout[8], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 9, verify(layout[9], as: RawLabeledExprListSyntax.self)) + assertNoError(kind, 9, verify(layout[9], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.leftParen)])) assertNoError(kind, 10, verify(layout[10], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 11, verify(layout[11], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.rightParen)])) + assertNoError(kind, 11, verify(layout[11], as: RawLabeledExprListSyntax.self)) assertNoError(kind, 12, verify(layout[12], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 13, verify(layout[13], as: RawClosureExprSyntax?.self)) + assertNoError(kind, 13, verify(layout[13], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.rightParen)])) assertNoError(kind, 14, verify(layout[14], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 15, verify(layout[15], as: RawMultipleTrailingClosureElementListSyntax.self)) + assertNoError(kind, 15, verify(layout[15], as: RawClosureExprSyntax?.self)) assertNoError(kind, 16, verify(layout[16], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 17, verify(layout[17], as: RawMultipleTrailingClosureElementListSyntax.self)) + assertNoError(kind, 18, verify(layout[18], as: RawUnexpectedNodesSyntax?.self)) } func validateMatchingPatternConditionSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { assert(layout.count == 9) @@ -2062,16 +2070,18 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self)) } func validateMemberTypeSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { - assert(layout.count == 9) + assert(layout.count == 11) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 1, verify(layout[1], as: RawTypeSyntax.self)) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 3, verify(layout[3], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.period)])) assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 5, verify(layout[5], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier), .keyword("self")])) + assertNoError(kind, 5, verify(layout[5], as: RawModuleSelectorSyntax?.self)) assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 7, verify(layout[7], as: RawGenericArgumentClauseSyntax?.self)) + assertNoError(kind, 7, verify(layout[7], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier), .keyword("self")])) assertNoError(kind, 8, verify(layout[8], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 9, verify(layout[9], as: RawGenericArgumentClauseSyntax?.self)) + assertNoError(kind, 10, verify(layout[10], as: RawUnexpectedNodesSyntax?.self)) } func validateMetatypeTypeSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { assert(layout.count == 7) @@ -2123,6 +2133,14 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier)])) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) } + func validateModuleSelectorSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { + assert(layout.count == 5) + assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier)])) + assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 3, verify(layout[3], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.colonColon)])) + assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) + } func validateMultipleTrailingClosureElementListSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { for (index, element) in layout.enumerated() { assertNoError(kind, index, verify(element, as: RawMultipleTrailingClosureElementSyntax.self)) @@ -3515,6 +3533,8 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { validateMissingSyntax(kind: kind, layout: layout) case .missingType: validateMissingTypeSyntax(kind: kind, layout: layout) + case .moduleSelector: + validateModuleSelectorSyntax(kind: kind, layout: layout) case .multipleTrailingClosureElementList: validateMultipleTrailingClosureElementListSyntax(kind: kind, layout: layout) case .multipleTrailingClosureElement: diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift index 4891b0cdf97..7348868196b 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift @@ -628,6 +628,7 @@ public struct DeclNameArgumentsSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynt /// ### Children /// +/// - `moduleSelector`: `ModuleSelectorSyntax`? /// - `baseName`: (`` | `self` | `Self` | `init` | `deinit` | `subscript` | `` | `` | ``) /// - `argumentNames`: ``DeclNameArgumentsSyntax``? /// @@ -656,9 +657,11 @@ public struct DeclReferenceExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Leaf /// - Parameters: /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. - public init( + @_spi(ExperimentalLanguageFeatures) public init( leadingTrivia: Trivia? = nil, - _ unexpectedBeforeBaseName: UnexpectedNodesSyntax? = nil, + _ unexpectedBeforeModuleSelector: UnexpectedNodesSyntax? = nil, + moduleSelector: ModuleSelectorSyntax? = nil, + _ unexpectedBetweenModuleSelectorAndBaseName: UnexpectedNodesSyntax? = nil, baseName: TokenSyntax, _ unexpectedBetweenBaseNameAndArgumentNames: UnexpectedNodesSyntax? = nil, argumentNames: DeclNameArgumentsSyntax? = nil, @@ -668,14 +671,18 @@ public struct DeclReferenceExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Leaf // Extend the lifetime of all parameters so their arenas don't get destroyed // before they can be added as children of the new arena. self = withExtendedLifetime((RawSyntaxArena(), ( - unexpectedBeforeBaseName, + unexpectedBeforeModuleSelector, + moduleSelector, + unexpectedBetweenModuleSelectorAndBaseName, baseName, unexpectedBetweenBaseNameAndArgumentNames, argumentNames, unexpectedAfterArgumentNames ))) { (arena, _) in let layout: [RawSyntax?] = [ - unexpectedBeforeBaseName?.raw, + unexpectedBeforeModuleSelector?.raw, + moduleSelector?.raw, + unexpectedBetweenModuleSelectorAndBaseName?.raw, baseName.raw, unexpectedBetweenBaseNameAndArgumentNames?.raw, argumentNames?.raw, @@ -692,7 +699,8 @@ public struct DeclReferenceExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Leaf } } - public var unexpectedBeforeBaseName: UnexpectedNodesSyntax? { + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBeforeModuleSelector: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 0)?.cast(UnexpectedNodesSyntax.self) } @@ -701,6 +709,26 @@ public struct DeclReferenceExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Leaf } } + @_spi(ExperimentalLanguageFeatures) + public var moduleSelector: ModuleSelectorSyntax? { + get { + return Syntax(self).child(at: 1)?.cast(ModuleSelectorSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 1, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(DeclReferenceExprSyntax.self) + } + } + + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBetweenModuleSelectorAndBaseName: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 2, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(DeclReferenceExprSyntax.self) + } + } + /// ### Tokens /// /// For syntax trees generated by the parser, this is guaranteed to be one of the following kinds: @@ -715,42 +743,44 @@ public struct DeclReferenceExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Leaf /// - `` public var baseName: TokenSyntax { get { - return Syntax(self).child(at: 1)!.cast(TokenSyntax.self) + return Syntax(self).child(at: 3)!.cast(TokenSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 1, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(DeclReferenceExprSyntax.self) + self = Syntax(self).replacingChild(at: 3, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(DeclReferenceExprSyntax.self) } } public var unexpectedBetweenBaseNameAndArgumentNames: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 2, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(DeclReferenceExprSyntax.self) + self = Syntax(self).replacingChild(at: 4, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(DeclReferenceExprSyntax.self) } } public var argumentNames: DeclNameArgumentsSyntax? { get { - return Syntax(self).child(at: 3)?.cast(DeclNameArgumentsSyntax.self) + return Syntax(self).child(at: 5)?.cast(DeclNameArgumentsSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 3, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(DeclReferenceExprSyntax.self) + self = Syntax(self).replacingChild(at: 5, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(DeclReferenceExprSyntax.self) } } public var unexpectedAfterArgumentNames: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 6)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 4, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(DeclReferenceExprSyntax.self) + self = Syntax(self).replacingChild(at: 6, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(DeclReferenceExprSyntax.self) } } public static let structure: SyntaxNodeStructure = .layout([ - \Self.unexpectedBeforeBaseName, + \Self.unexpectedBeforeModuleSelector, + \Self.moduleSelector, + \Self.unexpectedBetweenModuleSelectorAndBaseName, \Self.baseName, \Self.unexpectedBetweenBaseNameAndArgumentNames, \Self.argumentNames, diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift index 0adecf1e7aa..f2ff12fa517 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift @@ -1709,6 +1709,7 @@ public struct IdentifierPatternSyntax: PatternSyntaxProtocol, SyntaxHashable, _L /// ### Children /// +/// - `moduleSelector`: `ModuleSelectorSyntax`? /// - `name`: (`` | `Self` | `Any` | `_`) /// - `genericArgumentClause`: ``GenericArgumentClauseSyntax``? public struct IdentifierTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyntaxNodeProtocol { @@ -1729,9 +1730,11 @@ public struct IdentifierTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp /// - Parameters: /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. - public init( + @_spi(ExperimentalLanguageFeatures) public init( leadingTrivia: Trivia? = nil, - _ unexpectedBeforeName: UnexpectedNodesSyntax? = nil, + _ unexpectedBeforeModuleSelector: UnexpectedNodesSyntax? = nil, + moduleSelector: ModuleSelectorSyntax? = nil, + _ unexpectedBetweenModuleSelectorAndName: UnexpectedNodesSyntax? = nil, name: TokenSyntax, _ unexpectedBetweenNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, genericArgumentClause: GenericArgumentClauseSyntax? = nil, @@ -1741,14 +1744,18 @@ public struct IdentifierTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp // Extend the lifetime of all parameters so their arenas don't get destroyed // before they can be added as children of the new arena. self = withExtendedLifetime((RawSyntaxArena(), ( - unexpectedBeforeName, + unexpectedBeforeModuleSelector, + moduleSelector, + unexpectedBetweenModuleSelectorAndName, name, unexpectedBetweenNameAndGenericArgumentClause, genericArgumentClause, unexpectedAfterGenericArgumentClause ))) { (arena, _) in let layout: [RawSyntax?] = [ - unexpectedBeforeName?.raw, + unexpectedBeforeModuleSelector?.raw, + moduleSelector?.raw, + unexpectedBetweenModuleSelectorAndName?.raw, name.raw, unexpectedBetweenNameAndGenericArgumentClause?.raw, genericArgumentClause?.raw, @@ -1765,7 +1772,8 @@ public struct IdentifierTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp } } - public var unexpectedBeforeName: UnexpectedNodesSyntax? { + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBeforeModuleSelector: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 0)?.cast(UnexpectedNodesSyntax.self) } @@ -1774,6 +1782,26 @@ public struct IdentifierTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp } } + @_spi(ExperimentalLanguageFeatures) + public var moduleSelector: ModuleSelectorSyntax? { + get { + return Syntax(self).child(at: 1)?.cast(ModuleSelectorSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 1, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(IdentifierTypeSyntax.self) + } + } + + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBetweenModuleSelectorAndName: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 2, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(IdentifierTypeSyntax.self) + } + } + /// ### Tokens /// /// For syntax trees generated by the parser, this is guaranteed to be one of the following kinds: @@ -1783,42 +1811,44 @@ public struct IdentifierTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp /// - `_` public var name: TokenSyntax { get { - return Syntax(self).child(at: 1)!.cast(TokenSyntax.self) + return Syntax(self).child(at: 3)!.cast(TokenSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 1, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(IdentifierTypeSyntax.self) + self = Syntax(self).replacingChild(at: 3, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(IdentifierTypeSyntax.self) } } public var unexpectedBetweenNameAndGenericArgumentClause: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 2, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(IdentifierTypeSyntax.self) + self = Syntax(self).replacingChild(at: 4, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(IdentifierTypeSyntax.self) } } public var genericArgumentClause: GenericArgumentClauseSyntax? { get { - return Syntax(self).child(at: 3)?.cast(GenericArgumentClauseSyntax.self) + return Syntax(self).child(at: 5)?.cast(GenericArgumentClauseSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 3, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(IdentifierTypeSyntax.self) + self = Syntax(self).replacingChild(at: 5, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(IdentifierTypeSyntax.self) } } public var unexpectedAfterGenericArgumentClause: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 6)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 4, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(IdentifierTypeSyntax.self) + self = Syntax(self).replacingChild(at: 6, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(IdentifierTypeSyntax.self) } } public static let structure: SyntaxNodeStructure = .layout([ - \Self.unexpectedBeforeName, + \Self.unexpectedBeforeModuleSelector, + \Self.moduleSelector, + \Self.unexpectedBetweenModuleSelectorAndName, \Self.name, \Self.unexpectedBetweenNameAndGenericArgumentClause, \Self.genericArgumentClause, diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift index 902e11c9a85..956844943fc 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift @@ -2653,6 +2653,7 @@ public struct MacroDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSynt /// - `attributes`: ``AttributeListSyntax`` /// - `modifiers`: ``DeclModifierListSyntax`` /// - `pound`: `#` +/// - `moduleSelector`: `ModuleSelectorSyntax`? /// - `macroName`: `` /// - `genericArgumentClause`: ``GenericArgumentClauseSyntax``? /// - `leftParen`: `(`? @@ -2679,7 +2680,7 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. /// - pound: The `#` sign. /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. - public init( + @_spi(ExperimentalLanguageFeatures) public init( leadingTrivia: Trivia? = nil, _ unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, attributes: AttributeListSyntax = [], @@ -2687,7 +2688,9 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea modifiers: DeclModifierListSyntax = [], _ unexpectedBetweenModifiersAndPound: UnexpectedNodesSyntax? = nil, pound: TokenSyntax = .poundToken(), - _ unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenPoundAndModuleSelector: UnexpectedNodesSyntax? = nil, + moduleSelector: ModuleSelectorSyntax? = nil, + _ unexpectedBetweenModuleSelectorAndMacroName: UnexpectedNodesSyntax? = nil, macroName: TokenSyntax, _ unexpectedBetweenMacroNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, genericArgumentClause: GenericArgumentClauseSyntax? = nil, @@ -2713,7 +2716,9 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea modifiers, unexpectedBetweenModifiersAndPound, pound, - unexpectedBetweenPoundAndMacroName, + unexpectedBetweenPoundAndModuleSelector, + moduleSelector, + unexpectedBetweenModuleSelectorAndMacroName, macroName, unexpectedBetweenMacroNameAndGenericArgumentClause, genericArgumentClause, @@ -2736,7 +2741,9 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea modifiers.raw, unexpectedBetweenModifiersAndPound?.raw, pound.raw, - unexpectedBetweenPoundAndMacroName?.raw, + unexpectedBetweenPoundAndModuleSelector?.raw, + moduleSelector?.raw, + unexpectedBetweenModuleSelectorAndMacroName?.raw, macroName.raw, unexpectedBetweenMacroNameAndGenericArgumentClause?.raw, genericArgumentClause?.raw, @@ -2876,7 +2883,8 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea } } - public var unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? { + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBetweenPoundAndModuleSelector: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 6)?.cast(UnexpectedNodesSyntax.self) } @@ -2885,42 +2893,62 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea } } + @_spi(ExperimentalLanguageFeatures) + public var moduleSelector: ModuleSelectorSyntax? { + get { + return Syntax(self).child(at: 7)?.cast(ModuleSelectorSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 7, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + } + } + + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBetweenModuleSelectorAndMacroName: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 8)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 8, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + } + } + /// ### Tokens /// /// For syntax trees generated by the parser, this is guaranteed to be ``. public var macroName: TokenSyntax { get { - return Syntax(self).child(at: 7)!.cast(TokenSyntax.self) + return Syntax(self).child(at: 9)!.cast(TokenSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 7, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 9, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } public var unexpectedBetweenMacroNameAndGenericArgumentClause: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 8)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 10)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 8, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 10, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } public var genericArgumentClause: GenericArgumentClauseSyntax? { get { - return Syntax(self).child(at: 9)?.cast(GenericArgumentClauseSyntax.self) + return Syntax(self).child(at: 11)?.cast(GenericArgumentClauseSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 9, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 11, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } public var unexpectedBetweenGenericArgumentClauseAndLeftParen: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 10)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 12)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 10, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 12, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } @@ -2929,28 +2957,28 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea /// For syntax trees generated by the parser, this is guaranteed to be `(`. public var leftParen: TokenSyntax? { get { - return Syntax(self).child(at: 11)?.cast(TokenSyntax.self) + return Syntax(self).child(at: 13)?.cast(TokenSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 11, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 13, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } public var unexpectedBetweenLeftParenAndArguments: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 12)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 14)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 12, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 14, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } public var arguments: LabeledExprListSyntax { get { - return Syntax(self).child(at: 13)!.cast(LabeledExprListSyntax.self) + return Syntax(self).child(at: 15)!.cast(LabeledExprListSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 13, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 15, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } @@ -2965,7 +2993,7 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea public func addArgument(_ element: LabeledExprSyntax) -> MacroExpansionDeclSyntax { var collection: RawSyntax let arena = RawSyntaxArena() - if let col = raw.layoutView!.children[13] { + if let col = raw.layoutView!.children[15] { collection = col.layoutView!.appending(element.raw, arena: arena) } else { collection = RawSyntax.makeLayout(kind: SyntaxKind.labeledExprList, @@ -2973,7 +3001,7 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea } return Syntax(self) .replacingChild( - at: 13, + at: 15, with: collection, rawNodeArena: arena, rawAllocationArena: arena @@ -2983,10 +3011,10 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea public var unexpectedBetweenArgumentsAndRightParen: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 14)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 16)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 14, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 16, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } @@ -2995,46 +3023,46 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea /// For syntax trees generated by the parser, this is guaranteed to be `)`. public var rightParen: TokenSyntax? { get { - return Syntax(self).child(at: 15)?.cast(TokenSyntax.self) + return Syntax(self).child(at: 17)?.cast(TokenSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 15, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 17, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } public var unexpectedBetweenRightParenAndTrailingClosure: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 16)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 18)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 16, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 18, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } public var trailingClosure: ClosureExprSyntax? { get { - return Syntax(self).child(at: 17)?.cast(ClosureExprSyntax.self) + return Syntax(self).child(at: 19)?.cast(ClosureExprSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 17, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 19, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } public var unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 18)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 20)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 18, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 20, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } public var additionalTrailingClosures: MultipleTrailingClosureElementListSyntax { get { - return Syntax(self).child(at: 19)!.cast(MultipleTrailingClosureElementListSyntax.self) + return Syntax(self).child(at: 21)!.cast(MultipleTrailingClosureElementListSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 19, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 21, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } @@ -3049,7 +3077,7 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea public func addAdditionalTrailingClosure(_ element: MultipleTrailingClosureElementSyntax) -> MacroExpansionDeclSyntax { var collection: RawSyntax let arena = RawSyntaxArena() - if let col = raw.layoutView!.children[19] { + if let col = raw.layoutView!.children[21] { collection = col.layoutView!.appending(element.raw, arena: arena) } else { collection = RawSyntax.makeLayout(kind: SyntaxKind.multipleTrailingClosureElementList, @@ -3057,7 +3085,7 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea } return Syntax(self) .replacingChild( - at: 19, + at: 21, with: collection, rawNodeArena: arena, rawAllocationArena: arena @@ -3067,10 +3095,10 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea public var unexpectedAfterAdditionalTrailingClosures: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 20)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 22)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 20, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) + self = Syntax(self).replacingChild(at: 22, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionDeclSyntax.self) } } @@ -3081,7 +3109,9 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea \Self.modifiers, \Self.unexpectedBetweenModifiersAndPound, \Self.pound, - \Self.unexpectedBetweenPoundAndMacroName, + \Self.unexpectedBetweenPoundAndModuleSelector, + \Self.moduleSelector, + \Self.unexpectedBetweenModuleSelectorAndMacroName, \Self.macroName, \Self.unexpectedBetweenMacroNameAndGenericArgumentClause, \Self.genericArgumentClause, @@ -3106,6 +3136,7 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea /// ### Children /// /// - `pound`: `#` +/// - `moduleSelector`: `ModuleSelectorSyntax`? /// - `macroName`: `` /// - `genericArgumentClause`: ``GenericArgumentClauseSyntax``? /// - `leftParen`: `(`? @@ -3132,11 +3163,13 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. /// - pound: The `#` sign. /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. - public init( + @_spi(ExperimentalLanguageFeatures) public init( leadingTrivia: Trivia? = nil, _ unexpectedBeforePound: UnexpectedNodesSyntax? = nil, pound: TokenSyntax = .poundToken(), - _ unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenPoundAndModuleSelector: UnexpectedNodesSyntax? = nil, + moduleSelector: ModuleSelectorSyntax? = nil, + _ unexpectedBetweenModuleSelectorAndMacroName: UnexpectedNodesSyntax? = nil, macroName: TokenSyntax, _ unexpectedBetweenMacroNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, genericArgumentClause: GenericArgumentClauseSyntax? = nil, @@ -3158,7 +3191,9 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea self = withExtendedLifetime((RawSyntaxArena(), ( unexpectedBeforePound, pound, - unexpectedBetweenPoundAndMacroName, + unexpectedBetweenPoundAndModuleSelector, + moduleSelector, + unexpectedBetweenModuleSelectorAndMacroName, macroName, unexpectedBetweenMacroNameAndGenericArgumentClause, genericArgumentClause, @@ -3177,7 +3212,9 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea let layout: [RawSyntax?] = [ unexpectedBeforePound?.raw, pound.raw, - unexpectedBetweenPoundAndMacroName?.raw, + unexpectedBetweenPoundAndModuleSelector?.raw, + moduleSelector?.raw, + unexpectedBetweenModuleSelectorAndMacroName?.raw, macroName.raw, unexpectedBetweenMacroNameAndGenericArgumentClause?.raw, genericArgumentClause?.raw, @@ -3227,7 +3264,8 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea } } - public var unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? { + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBetweenPoundAndModuleSelector: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) } @@ -3236,42 +3274,62 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea } } + @_spi(ExperimentalLanguageFeatures) + public var moduleSelector: ModuleSelectorSyntax? { + get { + return Syntax(self).child(at: 3)?.cast(ModuleSelectorSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 3, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + } + } + + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBetweenModuleSelectorAndMacroName: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 4, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + } + } + /// ### Tokens /// /// For syntax trees generated by the parser, this is guaranteed to be ``. public var macroName: TokenSyntax { get { - return Syntax(self).child(at: 3)!.cast(TokenSyntax.self) + return Syntax(self).child(at: 5)!.cast(TokenSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 3, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 5, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } public var unexpectedBetweenMacroNameAndGenericArgumentClause: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 6)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 4, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 6, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } public var genericArgumentClause: GenericArgumentClauseSyntax? { get { - return Syntax(self).child(at: 5)?.cast(GenericArgumentClauseSyntax.self) + return Syntax(self).child(at: 7)?.cast(GenericArgumentClauseSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 5, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 7, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } public var unexpectedBetweenGenericArgumentClauseAndLeftParen: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 6)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 8)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 6, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 8, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } @@ -3280,28 +3338,28 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea /// For syntax trees generated by the parser, this is guaranteed to be `(`. public var leftParen: TokenSyntax? { get { - return Syntax(self).child(at: 7)?.cast(TokenSyntax.self) + return Syntax(self).child(at: 9)?.cast(TokenSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 7, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 9, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } public var unexpectedBetweenLeftParenAndArguments: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 8)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 10)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 8, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 10, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } public var arguments: LabeledExprListSyntax { get { - return Syntax(self).child(at: 9)!.cast(LabeledExprListSyntax.self) + return Syntax(self).child(at: 11)!.cast(LabeledExprListSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 9, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 11, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } @@ -3316,7 +3374,7 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea public func addArgument(_ element: LabeledExprSyntax) -> MacroExpansionExprSyntax { var collection: RawSyntax let arena = RawSyntaxArena() - if let col = raw.layoutView!.children[9] { + if let col = raw.layoutView!.children[11] { collection = col.layoutView!.appending(element.raw, arena: arena) } else { collection = RawSyntax.makeLayout(kind: SyntaxKind.labeledExprList, @@ -3324,7 +3382,7 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea } return Syntax(self) .replacingChild( - at: 9, + at: 11, with: collection, rawNodeArena: arena, rawAllocationArena: arena @@ -3334,10 +3392,10 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea public var unexpectedBetweenArgumentsAndRightParen: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 10)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 12)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 10, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 12, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } @@ -3346,46 +3404,46 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea /// For syntax trees generated by the parser, this is guaranteed to be `)`. public var rightParen: TokenSyntax? { get { - return Syntax(self).child(at: 11)?.cast(TokenSyntax.self) + return Syntax(self).child(at: 13)?.cast(TokenSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 11, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 13, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } public var unexpectedBetweenRightParenAndTrailingClosure: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 12)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 14)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 12, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 14, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } public var trailingClosure: ClosureExprSyntax? { get { - return Syntax(self).child(at: 13)?.cast(ClosureExprSyntax.self) + return Syntax(self).child(at: 15)?.cast(ClosureExprSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 13, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 15, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } public var unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 14)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 16)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 14, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 16, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } public var additionalTrailingClosures: MultipleTrailingClosureElementListSyntax { get { - return Syntax(self).child(at: 15)!.cast(MultipleTrailingClosureElementListSyntax.self) + return Syntax(self).child(at: 17)!.cast(MultipleTrailingClosureElementListSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 15, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 17, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } @@ -3400,7 +3458,7 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea public func addAdditionalTrailingClosure(_ element: MultipleTrailingClosureElementSyntax) -> MacroExpansionExprSyntax { var collection: RawSyntax let arena = RawSyntaxArena() - if let col = raw.layoutView!.children[15] { + if let col = raw.layoutView!.children[17] { collection = col.layoutView!.appending(element.raw, arena: arena) } else { collection = RawSyntax.makeLayout(kind: SyntaxKind.multipleTrailingClosureElementList, @@ -3408,7 +3466,7 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea } return Syntax(self) .replacingChild( - at: 15, + at: 17, with: collection, rawNodeArena: arena, rawAllocationArena: arena @@ -3418,17 +3476,19 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea public var unexpectedAfterAdditionalTrailingClosures: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 16)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 18)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 16, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) + self = Syntax(self).replacingChild(at: 18, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MacroExpansionExprSyntax.self) } } public static let structure: SyntaxNodeStructure = .layout([ \Self.unexpectedBeforePound, \Self.pound, - \Self.unexpectedBetweenPoundAndMacroName, + \Self.unexpectedBetweenPoundAndModuleSelector, + \Self.moduleSelector, + \Self.unexpectedBetweenModuleSelectorAndMacroName, \Self.macroName, \Self.unexpectedBetweenMacroNameAndGenericArgumentClause, \Self.genericArgumentClause, @@ -4208,6 +4268,7 @@ public struct MemberBlockSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNode /// /// - `baseType`: ``TypeSyntax`` /// - `period`: `.` +/// - `moduleSelector`: `ModuleSelectorSyntax`? /// - `name`: (`` | `self`) /// - `genericArgumentClause`: ``GenericArgumentClauseSyntax``? public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyntaxNodeProtocol { @@ -4228,13 +4289,15 @@ public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyn /// - Parameters: /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. - public init( + @_spi(ExperimentalLanguageFeatures) public init( leadingTrivia: Trivia? = nil, _ unexpectedBeforeBaseType: UnexpectedNodesSyntax? = nil, baseType: some TypeSyntaxProtocol, _ unexpectedBetweenBaseTypeAndPeriod: UnexpectedNodesSyntax? = nil, period: TokenSyntax = .periodToken(), - _ unexpectedBetweenPeriodAndName: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenPeriodAndModuleSelector: UnexpectedNodesSyntax? = nil, + moduleSelector: ModuleSelectorSyntax? = nil, + _ unexpectedBetweenModuleSelectorAndName: UnexpectedNodesSyntax? = nil, name: TokenSyntax, _ unexpectedBetweenNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, genericArgumentClause: GenericArgumentClauseSyntax? = nil, @@ -4248,7 +4311,9 @@ public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyn baseType, unexpectedBetweenBaseTypeAndPeriod, period, - unexpectedBetweenPeriodAndName, + unexpectedBetweenPeriodAndModuleSelector, + moduleSelector, + unexpectedBetweenModuleSelectorAndName, name, unexpectedBetweenNameAndGenericArgumentClause, genericArgumentClause, @@ -4259,7 +4324,9 @@ public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyn baseType.raw, unexpectedBetweenBaseTypeAndPeriod?.raw, period.raw, - unexpectedBetweenPeriodAndName?.raw, + unexpectedBetweenPeriodAndModuleSelector?.raw, + moduleSelector?.raw, + unexpectedBetweenModuleSelectorAndName?.raw, name.raw, unexpectedBetweenNameAndGenericArgumentClause?.raw, genericArgumentClause?.raw, @@ -4315,7 +4382,8 @@ public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyn } } - public var unexpectedBetweenPeriodAndName: UnexpectedNodesSyntax? { + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBetweenPeriodAndModuleSelector: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) } @@ -4324,6 +4392,26 @@ public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyn } } + @_spi(ExperimentalLanguageFeatures) + public var moduleSelector: ModuleSelectorSyntax? { + get { + return Syntax(self).child(at: 5)?.cast(ModuleSelectorSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 5, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MemberTypeSyntax.self) + } + } + + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBetweenModuleSelectorAndName: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 6)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 6, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MemberTypeSyntax.self) + } + } + /// ### Tokens /// /// For syntax trees generated by the parser, this is guaranteed to be one of the following kinds: @@ -4331,37 +4419,37 @@ public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyn /// - `self` public var name: TokenSyntax { get { - return Syntax(self).child(at: 5)!.cast(TokenSyntax.self) + return Syntax(self).child(at: 7)!.cast(TokenSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 5, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MemberTypeSyntax.self) + self = Syntax(self).replacingChild(at: 7, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MemberTypeSyntax.self) } } public var unexpectedBetweenNameAndGenericArgumentClause: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 6)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 8)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 6, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MemberTypeSyntax.self) + self = Syntax(self).replacingChild(at: 8, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MemberTypeSyntax.self) } } public var genericArgumentClause: GenericArgumentClauseSyntax? { get { - return Syntax(self).child(at: 7)?.cast(GenericArgumentClauseSyntax.self) + return Syntax(self).child(at: 9)?.cast(GenericArgumentClauseSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 7, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MemberTypeSyntax.self) + self = Syntax(self).replacingChild(at: 9, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MemberTypeSyntax.self) } } public var unexpectedAfterGenericArgumentClause: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 8)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 10)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 8, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MemberTypeSyntax.self) + self = Syntax(self).replacingChild(at: 10, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(MemberTypeSyntax.self) } } @@ -4370,7 +4458,9 @@ public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyn \Self.baseType, \Self.unexpectedBetweenBaseTypeAndPeriod, \Self.period, - \Self.unexpectedBetweenPeriodAndName, + \Self.unexpectedBetweenPeriodAndModuleSelector, + \Self.moduleSelector, + \Self.unexpectedBetweenModuleSelectorAndName, \Self.name, \Self.unexpectedBetweenNameAndGenericArgumentClause, \Self.genericArgumentClause, @@ -5165,6 +5255,137 @@ public struct MissingTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSy public static let structure: SyntaxNodeStructure = .layout([\Self.unexpectedBeforePlaceholder, \Self.placeholder, \Self.unexpectedAfterPlaceholder]) } +// MARK: - ModuleSelectorSyntax + +/// - Note: Requires experimental feature `moduleSelector`. +/// +/// ### Children +/// +/// - `moduleName`: `` +/// - `colonColon`: `::` +/// +/// ### Contained in +/// +/// - ``DeclReferenceExprSyntax``.``DeclReferenceExprSyntax/moduleSelector`` +/// - ``IdentifierTypeSyntax``.``IdentifierTypeSyntax/moduleSelector`` +/// - ``MacroExpansionDeclSyntax``.``MacroExpansionDeclSyntax/moduleSelector`` +/// - ``MacroExpansionExprSyntax``.``MacroExpansionExprSyntax/moduleSelector`` +/// - ``MemberTypeSyntax``.``MemberTypeSyntax/moduleSelector`` +@_spi(ExperimentalLanguageFeatures) +public struct ModuleSelectorSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodeProtocol { + public let _syntaxNode: Syntax + + public init?(_ node: __shared some SyntaxProtocol) { + guard node.raw.kind == .moduleSelector else { + return nil + } + self._syntaxNode = node._syntaxNode + } + + @_transparent + init(unsafeCasting node: Syntax) { + self._syntaxNode = node + } + + /// - Parameters: + /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. + /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. + public init( + leadingTrivia: Trivia? = nil, + _ unexpectedBeforeModuleName: UnexpectedNodesSyntax? = nil, + moduleName: TokenSyntax, + _ unexpectedBetweenModuleNameAndColonColon: UnexpectedNodesSyntax? = nil, + colonColon: TokenSyntax = .colonColonToken(), + _ unexpectedAfterColonColon: UnexpectedNodesSyntax? = nil, + trailingTrivia: Trivia? = nil + ) { + // Extend the lifetime of all parameters so their arenas don't get destroyed + // before they can be added as children of the new arena. + self = withExtendedLifetime((RawSyntaxArena(), ( + unexpectedBeforeModuleName, + moduleName, + unexpectedBetweenModuleNameAndColonColon, + colonColon, + unexpectedAfterColonColon + ))) { (arena, _) in + let layout: [RawSyntax?] = [ + unexpectedBeforeModuleName?.raw, + moduleName.raw, + unexpectedBetweenModuleNameAndColonColon?.raw, + colonColon.raw, + unexpectedAfterColonColon?.raw + ] + let raw = RawSyntax.makeLayout( + kind: SyntaxKind.moduleSelector, + from: layout, + arena: arena, + leadingTrivia: leadingTrivia, + trailingTrivia: trailingTrivia + ) + return Syntax.forRoot(raw, rawNodeArena: arena).cast(Self.self) + } + } + + public var unexpectedBeforeModuleName: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 0)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 0, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(ModuleSelectorSyntax.self) + } + } + + /// ### Tokens + /// + /// For syntax trees generated by the parser, this is guaranteed to be ``. + public var moduleName: TokenSyntax { + get { + return Syntax(self).child(at: 1)!.cast(TokenSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 1, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(ModuleSelectorSyntax.self) + } + } + + public var unexpectedBetweenModuleNameAndColonColon: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 2, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(ModuleSelectorSyntax.self) + } + } + + /// ### Tokens + /// + /// For syntax trees generated by the parser, this is guaranteed to be `::`. + public var colonColon: TokenSyntax { + get { + return Syntax(self).child(at: 3)!.cast(TokenSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 3, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(ModuleSelectorSyntax.self) + } + } + + public var unexpectedAfterColonColon: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 4, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(ModuleSelectorSyntax.self) + } + } + + public static let structure: SyntaxNodeStructure = .layout([ + \Self.unexpectedBeforeModuleName, + \Self.moduleName, + \Self.unexpectedBetweenModuleNameAndColonColon, + \Self.colonColon, + \Self.unexpectedAfterColonColon + ]) +} + // MARK: - MultipleTrailingClosureElementSyntax /// ### Children diff --git a/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift b/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift index 398e1b56af9..5469a229908 100644 --- a/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift +++ b/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift @@ -1043,7 +1043,7 @@ extension KeyPathSubscriptComponentSyntax { extension MacroExpansionDeclSyntax { /// A convenience initializer that allows initializing syntax collections using result builders - public init( + @_spi(ExperimentalLanguageFeatures) public init( leadingTrivia: Trivia? = nil, unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, attributes: AttributeListSyntax = [], @@ -1051,7 +1051,9 @@ extension MacroExpansionDeclSyntax { modifiers: DeclModifierListSyntax = [], unexpectedBetweenModifiersAndPound: UnexpectedNodesSyntax? = nil, pound: TokenSyntax = .poundToken(), - unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? = nil, + unexpectedBetweenPoundAndModuleSelector: UnexpectedNodesSyntax? = nil, + moduleSelector: ModuleSelectorSyntax? = nil, + unexpectedBetweenModuleSelectorAndMacroName: UnexpectedNodesSyntax? = nil, macroName: TokenSyntax, unexpectedBetweenMacroNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, genericArgumentClause: GenericArgumentClauseSyntax? = nil, @@ -1076,7 +1078,9 @@ extension MacroExpansionDeclSyntax { modifiers: modifiers, unexpectedBetweenModifiersAndPound, pound: pound, - unexpectedBetweenPoundAndMacroName, + unexpectedBetweenPoundAndModuleSelector, + moduleSelector: moduleSelector, + unexpectedBetweenModuleSelectorAndMacroName, macroName: macroName, unexpectedBetweenMacroNameAndGenericArgumentClause, genericArgumentClause: genericArgumentClause, @@ -1098,11 +1102,13 @@ extension MacroExpansionDeclSyntax { extension MacroExpansionExprSyntax { /// A convenience initializer that allows initializing syntax collections using result builders - public init( + @_spi(ExperimentalLanguageFeatures) public init( leadingTrivia: Trivia? = nil, unexpectedBeforePound: UnexpectedNodesSyntax? = nil, pound: TokenSyntax = .poundToken(), - unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? = nil, + unexpectedBetweenPoundAndModuleSelector: UnexpectedNodesSyntax? = nil, + moduleSelector: ModuleSelectorSyntax? = nil, + unexpectedBetweenModuleSelectorAndMacroName: UnexpectedNodesSyntax? = nil, macroName: TokenSyntax, unexpectedBetweenMacroNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, genericArgumentClause: GenericArgumentClauseSyntax? = nil, @@ -1123,7 +1129,9 @@ extension MacroExpansionExprSyntax { leadingTrivia: leadingTrivia, unexpectedBeforePound, pound: pound, - unexpectedBetweenPoundAndMacroName, + unexpectedBetweenPoundAndModuleSelector, + moduleSelector: moduleSelector, + unexpectedBetweenModuleSelectorAndMacroName, macroName: macroName, unexpectedBetweenMacroNameAndGenericArgumentClause, genericArgumentClause: genericArgumentClause, diff --git a/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift b/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift index 6629c0a42de..a60a0524b6f 100644 --- a/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift +++ b/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift @@ -599,7 +599,62 @@ extension KeyPathSubscriptComponentSyntax { } extension MacroExpansionDeclSyntax { - @available(*, deprecated, message: "Use an initializer with pound, macroName, genericArgumentClause, arguments argument(s).") + /// A convenience initializer that allows initializing syntax collections using result builders + public init( + leadingTrivia: Trivia? = nil, + unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, + attributes: AttributeListSyntax = [], + unexpectedBetweenAttributesAndModifiers: UnexpectedNodesSyntax? = nil, + modifiers: DeclModifierListSyntax = [], + unexpectedBetweenModifiersAndPound: UnexpectedNodesSyntax? = nil, + pound: TokenSyntax = .poundToken(), + unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? = nil, + macroName: TokenSyntax, + unexpectedBetweenMacroNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, + genericArgumentClause: GenericArgumentClauseSyntax? = nil, + unexpectedBetweenGenericArgumentClauseAndLeftParen: UnexpectedNodesSyntax? = nil, + leftParen: TokenSyntax? = nil, + unexpectedBetweenLeftParenAndArguments: UnexpectedNodesSyntax? = nil, + unexpectedBetweenArgumentsAndRightParen: UnexpectedNodesSyntax? = nil, + rightParen: TokenSyntax? = nil, + unexpectedBetweenRightParenAndTrailingClosure: UnexpectedNodesSyntax? = nil, + trailingClosure: ClosureExprSyntax? = nil, + unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures: UnexpectedNodesSyntax? = nil, + additionalTrailingClosures: MultipleTrailingClosureElementListSyntax = [], + unexpectedAfterAdditionalTrailingClosures: UnexpectedNodesSyntax? = nil, + @LabeledExprListBuilder argumentsBuilder: () throws -> LabeledExprListSyntax, + trailingTrivia: Trivia? = nil + ) rethrows { + try self.init( + leadingTrivia: leadingTrivia, + unexpectedBeforeAttributes, + attributes: attributes, + unexpectedBetweenAttributesAndModifiers, + modifiers: modifiers, + unexpectedBetweenModifiersAndPound, + pound: pound, + unexpectedBetweenPoundAndMacroName, + macroName: macroName, + unexpectedBetweenMacroNameAndGenericArgumentClause, + genericArgumentClause: genericArgumentClause, + unexpectedBetweenGenericArgumentClauseAndLeftParen, + leftParen: leftParen, + unexpectedBetweenLeftParenAndArguments, + arguments: argumentsBuilder(), + unexpectedBetweenArgumentsAndRightParen, + rightParen: rightParen, + unexpectedBetweenRightParenAndTrailingClosure, + trailingClosure: trailingClosure, + unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures, + additionalTrailingClosures: additionalTrailingClosures, + unexpectedAfterAdditionalTrailingClosures, + trailingTrivia: trailingTrivia + ) + } +} + +extension MacroExpansionDeclSyntax { + @available(*, deprecated, message: "Use an initializer with pound, moduleSelector, macroName, genericArgumentClause, arguments argument(s).") @_disfavoredOverload /// A convenience initializer that allows initializing syntax collections using result builders public init( @@ -656,7 +711,54 @@ extension MacroExpansionDeclSyntax { } extension MacroExpansionExprSyntax { - @available(*, deprecated, message: "Use an initializer with pound, macroName, genericArgumentClause, arguments argument(s).") + /// A convenience initializer that allows initializing syntax collections using result builders + public init( + leadingTrivia: Trivia? = nil, + unexpectedBeforePound: UnexpectedNodesSyntax? = nil, + pound: TokenSyntax = .poundToken(), + unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? = nil, + macroName: TokenSyntax, + unexpectedBetweenMacroNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, + genericArgumentClause: GenericArgumentClauseSyntax? = nil, + unexpectedBetweenGenericArgumentClauseAndLeftParen: UnexpectedNodesSyntax? = nil, + leftParen: TokenSyntax? = nil, + unexpectedBetweenLeftParenAndArguments: UnexpectedNodesSyntax? = nil, + unexpectedBetweenArgumentsAndRightParen: UnexpectedNodesSyntax? = nil, + rightParen: TokenSyntax? = nil, + unexpectedBetweenRightParenAndTrailingClosure: UnexpectedNodesSyntax? = nil, + trailingClosure: ClosureExprSyntax? = nil, + unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures: UnexpectedNodesSyntax? = nil, + additionalTrailingClosures: MultipleTrailingClosureElementListSyntax = [], + unexpectedAfterAdditionalTrailingClosures: UnexpectedNodesSyntax? = nil, + @LabeledExprListBuilder argumentsBuilder: () throws -> LabeledExprListSyntax, + trailingTrivia: Trivia? = nil + ) rethrows { + try self.init( + leadingTrivia: leadingTrivia, + unexpectedBeforePound, + pound: pound, + unexpectedBetweenPoundAndMacroName, + macroName: macroName, + unexpectedBetweenMacroNameAndGenericArgumentClause, + genericArgumentClause: genericArgumentClause, + unexpectedBetweenGenericArgumentClauseAndLeftParen, + leftParen: leftParen, + unexpectedBetweenLeftParenAndArguments, + arguments: argumentsBuilder(), + unexpectedBetweenArgumentsAndRightParen, + rightParen: rightParen, + unexpectedBetweenRightParenAndTrailingClosure, + trailingClosure: trailingClosure, + unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures, + additionalTrailingClosures: additionalTrailingClosures, + unexpectedAfterAdditionalTrailingClosures, + trailingTrivia: trailingTrivia + ) + } +} + +extension MacroExpansionExprSyntax { + @available(*, deprecated, message: "Use an initializer with pound, moduleSelector, macroName, genericArgumentClause, arguments argument(s).") @_disfavoredOverload /// A convenience initializer that allows initializing syntax collections using result builders public init( diff --git a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift index 18dbd4a3392..e6f08022546 100644 --- a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift +++ b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift @@ -12,7 +12,7 @@ import SwiftBasicFormat import SwiftParser -import SwiftSyntax +@_spi(ExperimentalLanguageFeatures) import SwiftSyntax @_spi(Testing) import SwiftSyntaxBuilder import XCTest import _SwiftSyntaxTestSupport @@ -695,4 +695,17 @@ final class BasicFormatTest: XCTestCase { expected: "let x: (Int) -> Void" ) } + + func testColonColon() { + assertFormatted( + tree: DeclReferenceExprSyntax( + moduleSelector: ModuleSelectorSyntax( + moduleName: .identifier("Swift"), + colonColon: .colonColonToken() + ), + baseName: TokenSyntax.identifier("print") + ), + expected: "Swift::print" + ) + } } From 989300669cee324c335e2f21ff554e185287322a Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Fri, 30 May 2025 20:19:10 -0700 Subject: [PATCH 08/15] [NFC] Refactor parseQualifiedTypeIdentifier() Changes it to share code with `parseTypeIdentifier()` and clean up the member type parsing a little. Also tweaks call sites of `parseTypeIdentifier()`. --- Sources/SwiftParser/Names.swift | 49 ++++++++++----------------------- Sources/SwiftParser/Types.swift | 27 +++++++++--------- 2 files changed, 28 insertions(+), 48 deletions(-) diff --git a/Sources/SwiftParser/Names.swift b/Sources/SwiftParser/Names.swift index 9ed8d5ac680..2ca27e55e68 100644 --- a/Sources/SwiftParser/Names.swift +++ b/Sources/SwiftParser/Names.swift @@ -188,36 +188,24 @@ extension Parser { } mutating func parseQualifiedTypeIdentifier() -> RawTypeSyntax { - if self.at(.keyword(.Any)) { - return RawTypeSyntax(self.parseAnyType()) - } - let (unexpectedBeforeName, name) = self.expect(anyIn: IdentifierTypeSyntax.NameOptions.self, default: .identifier) - let generics: RawGenericArgumentClauseSyntax? - if self.at(prefix: "<") { - generics = self.parseGenericArguments() - } else { - generics = nil + let identifierType = self.parseTypeIdentifier() + var result = RawTypeSyntax(identifierType) + + // There are no nested types inside `Any`. + if case TokenSpec.keyword(.Any) = identifierType.name { + return result } - var result = RawTypeSyntax( - RawIdentifierTypeSyntax( - moduleSelector: nil, - unexpectedBeforeName, - name: name, - genericArgumentClause: generics, - arena: self.arena - ) - ) + func hasAnotherMember() -> Bool { + // If qualified name base type cannot be parsed from the current + // point (i.e. the next type identifier is not followed by a '.'), + // then the next identifier is the final declaration name component. + var lookahead = self.lookahead() + return lookahead.consume(ifPrefix: ".", as: .period) != nil && lookahead.canParseBaseTypeForQualifiedDeclName() + } - // If qualified name base type cannot be parsed from the current - // point (i.e. the next type identifier is not followed by a '.'), - // then the next identifier is the final declaration name component. - var lookahead = self.lookahead() - guard - lookahead.consume(ifPrefix: ".", as: .period) != nil, - lookahead.canParseBaseTypeForQualifiedDeclName() - else { + guard hasAnotherMember() else { return result } @@ -248,14 +236,7 @@ extension Parser { ) ) - // If qualified name base type cannot be parsed from the current - // point (i.e. the next type identifier is not followed by a '.'), - // then the next identifier is the final declaration name component. - var lookahead = self.lookahead() - guard - lookahead.consume(ifPrefix: ".", as: .period) != nil, - lookahead.canParseBaseTypeForQualifiedDeclName() - else { + guard hasAnotherMember() else { break } diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 23f770347ff..14ac7568c75 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -250,7 +250,7 @@ extension Parser { var base: RawTypeSyntax switch self.at(anyIn: TypeBaseStart.self)?.spec { case .Self, .Any, .identifier: - base = self.parseTypeIdentifier() + base = RawTypeSyntax(self.parseTypeIdentifier()) case .leftParen: base = RawTypeSyntax(self.parseTupleTypeBody()) case .leftSquare: @@ -365,9 +365,9 @@ extension Parser { } /// Parse a type identifier. - mutating func parseTypeIdentifier() -> RawTypeSyntax { + mutating func parseTypeIdentifier() -> RawIdentifierTypeSyntax { if self.at(.keyword(.Any)) { - return RawTypeSyntax(self.parseAnyType()) + return self.parseAnyType() } let (unexpectedBeforeName, name) = self.expect(anyIn: IdentifierTypeSyntax.NameOptions.self, default: .identifier) @@ -378,14 +378,12 @@ extension Parser { generics = nil } - return RawTypeSyntax( - RawIdentifierTypeSyntax( - moduleSelector: nil, - unexpectedBeforeName, - name: name, - genericArgumentClause: generics, - arena: self.arena - ) + return RawIdentifierTypeSyntax( + moduleSelector: nil, + unexpectedBeforeName, + name: name, + genericArgumentClause: generics, + arena: self.arena ) } @@ -1341,9 +1339,7 @@ extension Parser { extension Parser { mutating func parseResultType() -> RawTypeSyntax { - if self.currentToken.isEditorPlaceholder { - return self.parseTypeIdentifier() - } else if self.at(prefix: "<") { + if self.at(prefix: "<") && !self.currentToken.isEditorPlaceholder { let generics = self.parseGenericParameters() let baseType = self.parseType() return RawTypeSyntax( @@ -1360,6 +1356,9 @@ extension Parser { return result } + // The rest of this tries to recover from a missing left square bracket like ` -> [Int]]? {`. We can do this for + // result types because we know there isn't an enclosing expression context. + // If the right square bracket is at a new line, we should just return the result if let rightSquare = self.consume(if: TokenSpec(.rightSquare, allowAtStartOfLine: false)) { result = RawTypeSyntax( From d3ed8038a2e15ae8b22f68e16fb59ff4d398ed3e Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 23 Jul 2025 14:44:23 -0700 Subject: [PATCH 09/15] Parse module selectors in most valid locations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 handle module selectors in scoped `import` statements; the related test has been XFAILed. --- Sources/SwiftParser/Attributes.swift | 6 +- Sources/SwiftParser/Declarations.swift | 6 +- Sources/SwiftParser/Expressions.swift | 34 +- Sources/SwiftParser/Names.swift | 122 +- Sources/SwiftParser/TokenSpecSet.swift | 3 + Sources/SwiftParser/Types.swift | 54 +- .../SyntaxExtensions.swift | 8 + .../translated/ModuleSelectorTests.swift | 2201 +++++++++++++++++ 8 files changed, 2401 insertions(+), 33 deletions(-) create mode 100644 Tests/SwiftParserTest/translated/ModuleSelectorTests.swift diff --git a/Sources/SwiftParser/Attributes.swift b/Sources/SwiftParser/Attributes.swift index bac0de0ba08..9919f580a94 100644 --- a/Sources/SwiftParser/Attributes.swift +++ b/Sources/SwiftParser/Attributes.swift @@ -252,7 +252,11 @@ extension Parser { } mutating func parseAttribute() -> RawAttributeSyntax { - switch peek(isAtAnyIn: DeclarationAttributeWithSpecialSyntax.self) { + // An attribute qualified by a module selector is *always* a custom attribute, even if it has the same name (or + // module name) as a builtin attribute. + let builtinAttr = self.unlessPeekModuleSelector { $0.peek(isAtAnyIn: DeclarationAttributeWithSpecialSyntax.self) } + + switch builtinAttr { case .abi: return parseAttribute(argumentMode: .required) { parser in return (nil, .abiArguments(parser.parseABIAttributeArguments())) diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index a00a76abddb..781ab5452fc 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -2195,11 +2195,15 @@ extension Parser { ) pound = pound.tokenView.withTokenDiagnostic(tokenDiagnostic: diagnostic, arena: self.arena) } + + let moduleSelector: RawModuleSelectorSyntax? let unexpectedBeforeMacro: RawUnexpectedNodesSyntax? let macro: RawTokenSyntax if !self.atStartOfLine { + moduleSelector = self.parseModuleSelectorIfPresent() (unexpectedBeforeMacro, macro) = self.expectIdentifier(allowKeywordsAsIdentifier: true) } else { + moduleSelector = nil unexpectedBeforeMacro = nil macro = self.missingToken(.identifier) } @@ -2247,7 +2251,7 @@ extension Parser { modifiers: attrs.modifiers, unexpectedBeforePound, pound: pound, - moduleSelector: nil, + moduleSelector: moduleSelector, unexpectedBeforeMacro, macroName: macro, genericArgumentClause: generics, diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index 53fa3281edd..d7ee972fc98 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -18,6 +18,12 @@ extension TokenConsumer { mutating func atStartOfExpression() -> Bool { + if self.isAtModuleSelector() { + var lookahead = self.lookahead() + _ = lookahead.consumeModuleSelectorTokensIfPresent() + return lookahead.atStartOfExpression() + } + switch self.at(anyIn: ExpressionStart.self) { case (.awaitTryMove, let handle)?: var lookahead = self.lookahead() @@ -662,7 +668,7 @@ extension Parser { // Parse the name portion. let declName: RawDeclReferenceExprSyntax - if let indexOrSelf = self.consume(if: .integerLiteral, .keyword(.self)) { + if !self.isAtModuleSelector(), let indexOrSelf = self.consume(if: .integerLiteral, .keyword(.self)) { // Handle "x.42" - a tuple index. declName = RawDeclReferenceExprSyntax( moduleSelector: nil, @@ -1241,6 +1247,13 @@ extension Parser { arena: self.arena ) ) + case (.colonColon, _)?, // Module selector with no module name + (.wildcard, _)? where self.isAtModuleSelector(), // Module selectors with invalid module names + (.Any, _)? where self.isAtModuleSelector(), + (.`self`, _)? where self.isAtModuleSelector(), + (.`Self`, _)? where self.isAtModuleSelector(), + (.super, _)? where self.isAtModuleSelector(): + return self.parseIdentifierExpression(flavor: flavor) case (.identifier, let handle)?, (.self, let handle)?, (.`init`, let handle)?, (.`deinit`, let handle)?, (.`subscript`, let handle)?: // If we have "case let x" followed by ".", "(", "[", or a generic @@ -1248,11 +1261,11 @@ extension Parser { // is the start of an enum or expr pattern. if pattern.admitsBinding && self.lookahead().isInBindingPatternPosition() { let identifier = self.eat(handle) - let pattern = RawIdentifierPatternSyntax( + let patternNode = RawIdentifierPatternSyntax( identifier: identifier, arena: self.arena ) - return RawExprSyntax(RawPatternExprSyntax(pattern: pattern, arena: self.arena)) + return RawExprSyntax(RawPatternExprSyntax(pattern: patternNode, arena: self.arena)) } return self.parseIdentifierExpression(flavor: flavor) @@ -1385,6 +1398,7 @@ extension Parser { ) pound = pound.tokenView.withTokenDiagnostic(tokenDiagnostic: diagnostic, arena: self.arena) } + let moduleSelector = parseModuleSelectorIfPresent() let unexpectedBeforeMacroName: RawUnexpectedNodesSyntax? let macroName: RawTokenSyntax if !self.atStartOfLine { @@ -1432,7 +1446,7 @@ extension Parser { return RawMacroExpansionExprSyntax( unexpectedBeforePound, pound: pound, - moduleSelector: nil, + moduleSelector: moduleSelector, unexpectedBeforeMacroName, macroName: macroName, genericArgumentClause: generics, @@ -1969,6 +1983,14 @@ extension Parser { } } +extension TokenConsumer { + mutating func atBinaryOperatorArgument() -> Bool { + var lookahead = self.lookahead() + _ = lookahead.consumeModuleSelectorTokensIfPresent() + return lookahead.at(.binaryOperator) && lookahead.peek(isAt: .comma, .rightParen, .rightSquare) + } +} + extension Parser { /// Parse the elements of an argument list. /// @@ -2020,7 +2042,7 @@ extension Parser { // this case lexes as a binary operator because it neither leads nor // follows a proper subexpression. let expr: RawExprSyntax - if self.at(.binaryOperator) && self.peek(isAt: .comma, .rightParen, .rightSquare) { + if self.atBinaryOperatorArgument() { expr = RawExprSyntax(self.parseDeclReferenceExpr(.operators)) } else { expr = self.parseExpression(flavor: flavor, pattern: pattern) @@ -2400,9 +2422,9 @@ extension Parser { unknownAttr = RawAttributeSyntax( atSign: at, - unexpectedBeforeIdent, attributeName: RawIdentifierTypeSyntax( moduleSelector: nil, + unexpectedBeforeIdent, name: ident, genericArgumentClause: nil, arena: self.arena diff --git a/Sources/SwiftParser/Names.swift b/Sources/SwiftParser/Names.swift index 2ca27e55e68..eebcd58d5ed 100644 --- a/Sources/SwiftParser/Names.swift +++ b/Sources/SwiftParser/Names.swift @@ -45,6 +45,107 @@ extension Parser { } } +extension TokenConsumer { + /// Do the subsequent tokens have the form of a module selector? Encompasses some invalid syntax which nonetheless + /// can be handled by `consumeModuleSelectorTokensIfPresent()`. + /// + /// - Postcondition: If `true`, either the current token or the next token is `.colonColon`. + mutating func isAtModuleSelector() -> Bool { + // If this is a module selector, the next token should be `::`. + guard self.peek(isAt: .colonColon) else { + // ...however, we will also allow the *current* token to be `::`. `consumeModuleSelectorTokensIfPresent()` will + // create a missing identifier. + return self.at(.colonColon) + } + + // Technically the current token *should* be an identifier, but we also want to diagnose other tokens that might be + // used by accident or given special meanings later ('_', certain keywords). + return self.at(.identifier, .wildcard, .keyword(.Any)) + || self.at(.keyword(.self), .keyword(.Self), .keyword(.super)) + } + + mutating func unlessPeekModuleSelector(_ operation: (inout Self) -> T?) -> T? { + var lookahead = self.lookahead() + lookahead.skipSingle() + if lookahead.isAtModuleSelector() { + return nil + } + return operation(&self) + } + + /// If the subsequent tokens have the form of a module selector, valid or otherwise, consume and return them; + /// otherwise consume nothing and return `nil`. Additionally consumes invalid chained module selectors. + /// + /// Returns a tuple comprised of: + /// + /// - `moduleNameOrUnexpected`: The module name if present; in a valid module selector, this will be a present + /// identifier, but either of those can be untrue in invalid code. + /// - `colonColonToken`: The `::` indicating this module selector. Always `.colonColon`, always present. + /// - `extra`: Tokens for additional trailing module selectors. There is no situation in which two module selectors + /// can be validly chained. + mutating func consumeModuleSelectorTokensIfPresent() -> ( + moduleNameOrUnexpected: Token, colonColonToken: Token, extra: [Token] + )? { + guard self.isAtModuleSelector() else { + return nil + } + + let moduleName: Token + let colonColonToken: Token + + // Did we forget the module name? + if let earlyColonColon = self.consume(if: .colonColon) { + moduleName = self.missingToken(.identifier) + colonColonToken = earlyColonColon + } else { + // Consume whatever comes before the `::`, plus the `::` itself. (Whether or not the "name" is an identifier is + // checked elsewhere.) + moduleName = self.consumeAnyToken() + colonColonToken = self.eat(.colonColon) + } + + var extra: [Token] = [] + while self.isAtModuleSelector() { + if !self.at(.colonColon) { + extra.append(self.consumeAnyToken()) + } + extra.append(self.eat(.colonColon)) + } + return (moduleName, colonColonToken, extra) + } +} + +extension Parser { + /// Parses one or more module selectors, if present. + mutating func parseModuleSelectorIfPresent() -> RawModuleSelectorSyntax? { + guard let (moduleNameOrUnexpected, colonColon, extra) = consumeModuleSelectorTokensIfPresent() else { + return nil + } + + let leadingUnexpected: [RawSyntax] + let moduleName: RawTokenSyntax + let trailingUnexpected: [RawSyntax] + + if moduleNameOrUnexpected.tokenKind == .identifier { + leadingUnexpected = [] + moduleName = moduleNameOrUnexpected + } else { + leadingUnexpected = [RawSyntax(moduleNameOrUnexpected)] + moduleName = RawTokenSyntax(missing: .identifier, arena: arena) + } + + trailingUnexpected = extra.map { RawSyntax($0) } + + return RawModuleSelectorSyntax( + RawUnexpectedNodesSyntax(leadingUnexpected, arena: arena), + moduleName: moduleName, + colonColon: colonColon, + RawUnexpectedNodesSyntax(trailingUnexpected, arena: arena), + arena: arena + ) + } +} + extension Parser { struct DeclNameOptions: OptionSet { var rawValue: UInt8 @@ -68,6 +169,12 @@ extension Parser { } mutating func parseDeclReferenceExpr(_ flags: DeclNameOptions = []) -> RawDeclReferenceExprSyntax { + // Consume a module selector if present. + let moduleSelector = self.parseModuleSelectorIfPresent() + + // If a module selector is found, we parse the name after it according to SE-0071 rules. + let allowKeywords = flags.contains(.keywords) || moduleSelector != nil + // Consume the base name. let base: RawTokenSyntax if let identOrSelf = self.consume(if: .identifier, .keyword(.self), .keyword(.Self)) @@ -80,7 +187,7 @@ extension Parser { let special = self.consume(if: .keyword(.`deinit`), .keyword(.`subscript`)) { base = special - } else if flags.contains(.keywords) && self.currentToken.isLexerClassifiedKeyword { + } else if allowKeywords && self.currentToken.isLexerClassifiedKeyword { base = self.consumeAnyToken(remapping: .identifier) } else { base = missingToken(.identifier) @@ -89,7 +196,7 @@ extension Parser { // Parse an argument list, if the flags allow it and it's present. let args = self.parseArgLabelList(flags) return RawDeclReferenceExprSyntax( - moduleSelector: nil, + moduleSelector: moduleSelector, baseName: base, argumentNames: args, arena: self.arena @@ -212,12 +319,8 @@ extension Parser { var keepGoing = self.consume(if: .period) var loopProgress = LoopProgressCondition() while keepGoing != nil && self.hasProgressed(&loopProgress) { - let (unexpectedBeforeName, name) = self.expect( - .identifier, - .keyword(.self), - TokenSpec(.Self, remapping: .identifier), - default: .identifier - ) + let memberModuleSelector = self.parseModuleSelectorIfPresent() + let name = self.parseMemberTypeName() let generics: RawGenericArgumentClauseSyntax? if self.at(prefix: "<") { generics = self.parseGenericArguments() @@ -228,8 +331,7 @@ extension Parser { RawMemberTypeSyntax( baseType: result, period: keepGoing!, - moduleSelector: nil, - unexpectedBeforeName, + moduleSelector: memberModuleSelector, name: name, genericArgumentClause: generics, arena: self.arena diff --git a/Sources/SwiftParser/TokenSpecSet.swift b/Sources/SwiftParser/TokenSpecSet.swift index 4f03301c344..d44c9410047 100644 --- a/Sources/SwiftParser/TokenSpecSet.swift +++ b/Sources/SwiftParser/TokenSpecSet.swift @@ -835,6 +835,7 @@ enum PrimaryExpressionStart: TokenSpecSet { case `Any` case atSign // For recovery case `Self` + case colonColon case `deinit` case dollarIdentifier case `false` @@ -867,6 +868,7 @@ enum PrimaryExpressionStart: TokenSpecSet { case TokenSpec(.Any): self = .Any case TokenSpec(.atSign): self = .atSign case TokenSpec(.Self): self = .Self + case TokenSpec(.colonColon): self = .colonColon case TokenSpec(.deinit): self = .`deinit` case TokenSpec(.dollarIdentifier): self = .dollarIdentifier case TokenSpec(.false): self = .false @@ -902,6 +904,7 @@ enum PrimaryExpressionStart: TokenSpecSet { case .Any: return .keyword(.Any) case .atSign: return .atSign case .Self: return .keyword(.Self) + case .colonColon: return .colonColon case .`deinit`: return .keyword(.`deinit`) case .dollarIdentifier: return .dollarIdentifier case .false: return .keyword(.false) diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 14ac7568c75..6f7b190d222 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -248,7 +248,7 @@ extension Parser { } var base: RawTypeSyntax - switch self.at(anyIn: TypeBaseStart.self)?.spec { + switch self.isAtModuleSelector() ? .identifier : self.at(anyIn: TypeBaseStart.self)?.spec { case .Self, .Any, .identifier: base = RawTypeSyntax(self.parseTypeIdentifier()) case .leftParen: @@ -279,7 +279,9 @@ extension Parser { ) ) break - } else if self.at(.keyword(.Type)) || self.at(.keyword(.Protocol)) { + } + + if !self.isAtModuleSelector() && (self.at(.keyword(.Type)) || self.at(.keyword(.Protocol))) { let metatypeSpecifier = self.consume(if: .keyword(.Type)) ?? self.consume(if: .keyword(.Protocol))! base = RawTypeSyntax( RawMetatypeTypeSyntax( @@ -291,14 +293,8 @@ extension Parser { ) ) } else { - let name: RawTokenSyntax - if let handle = self.at(anyIn: MemberTypeSyntax.NameOptions.self)?.handle { - name = self.eat(handle) - } else if self.currentToken.isLexerClassifiedKeyword { - name = self.consumeAnyToken(remapping: .identifier) - } else { - name = missingToken(.identifier) - } + let memberModuleSelector = self.parseModuleSelectorIfPresent() + let name: RawTokenSyntax = self.parseMemberTypeName() let generics: RawGenericArgumentClauseSyntax? if self.at(prefix: "<") { generics = self.parseGenericArguments() @@ -310,7 +306,7 @@ extension Parser { baseType: base, unexpectedPeriod, period: period, - moduleSelector: nil, + moduleSelector: memberModuleSelector, name: name, genericArgumentClause: generics, arena: self.arena @@ -340,6 +336,18 @@ extension Parser { return base } + /// Parse the name of a member type, which may be a keyword that's + /// interpreted as an identifier (per SE-0071). + mutating func parseMemberTypeName() -> RawTokenSyntax { + if let handle = self.at(anyIn: MemberTypeSyntax.NameOptions.self)?.handle { + return self.eat(handle) + } else if self.currentToken.isLexerClassifiedKeyword { + return self.consumeAnyToken(remapping: .identifier) + } else { + return missingToken(.identifier) + } + } + /// Parse an optional type. mutating func parseOptionalType(_ base: RawTypeSyntax) -> RawOptionalTypeSyntax { let (unexpectedBeforeMark, mark) = self.expect(.postfixQuestionMark) @@ -366,11 +374,21 @@ extension Parser { /// Parse a type identifier. mutating func parseTypeIdentifier() -> RawIdentifierTypeSyntax { - if self.at(.keyword(.Any)) { + let moduleSelector = self.parseModuleSelectorIfPresent() + + if moduleSelector == nil && self.at(.keyword(.Any)) { return self.parseAnyType() } - let (unexpectedBeforeName, name) = self.expect(anyIn: IdentifierTypeSyntax.NameOptions.self, default: .identifier) + let unexpectedBeforeName: RawUnexpectedNodesSyntax? + let name: RawTokenSyntax + if moduleSelector == nil { + (unexpectedBeforeName, name) = self.expect(anyIn: IdentifierTypeSyntax.NameOptions.self, default: .identifier) + } else { + // A name after a module selector gets parsed like a member + unexpectedBeforeName = nil + name = self.parseMemberTypeName() + } let generics: RawGenericArgumentClauseSyntax? if self.at(prefix: "<") { generics = self.parseGenericArguments() @@ -379,7 +397,7 @@ extension Parser { } return RawIdentifierTypeSyntax( - moduleSelector: nil, + moduleSelector: moduleSelector, unexpectedBeforeName, name: name, genericArgumentClause: generics, @@ -997,6 +1015,8 @@ extension Parser.Lookahead { } mutating func canParseTypeIdentifier(allowKeyword: Bool = false) -> Bool { + _ = self.consumeModuleSelectorTokensIfPresent() + if self.at(.keyword(.Any)) { self.consumeAnyToken() return true @@ -1308,7 +1328,11 @@ extension Parser { } mutating func parseTypeAttribute() -> RawAttributeListSyntax.Element { - switch peek(isAtAnyIn: TypeAttribute.self) { + // An attribute qualified by a module selector is *always* a custom attribute, even if it has the same name (or + // module name) as a builtin attribute. + let builtinAttr = self.unlessPeekModuleSelector { $0.peek(isAtAnyIn: TypeAttribute.self) } + + switch builtinAttr { case ._local, ._noMetadata, .async, .escaping, .noDerivative, .noescape, .preconcurrency, .retroactive, .Sendable, .unchecked, .autoclosure: // Known type attribute that doesn't take any arguments diff --git a/Sources/SwiftParserDiagnostics/SyntaxExtensions.swift b/Sources/SwiftParserDiagnostics/SyntaxExtensions.swift index 3dc0aa8e82b..d044e030de5 100644 --- a/Sources/SwiftParserDiagnostics/SyntaxExtensions.swift +++ b/Sources/SwiftParserDiagnostics/SyntaxExtensions.swift @@ -127,6 +127,14 @@ extension SyntaxProtocol { memberDeclItem.firstToken(viewMode: .all) == self.firstToken(viewMode: .all) { return true + } else if let selfToken = self.as(TokenSyntax.self), + selfToken.isMissing, + selfToken.tokenKind.isIdentifier, + let nextToken = self.nextToken(viewMode: .sourceAccurate), + nextToken.isPresent, + nextToken.tokenKind == .colonColon + { + return true } else { return false } diff --git a/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift new file mode 100644 index 00000000000..f939fa574f6 --- /dev/null +++ b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift @@ -0,0 +1,2201 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// This test file has been translated from swift/test/NameLookup/module_selector.swift + +@_spi(ExperimentalLanguageFeatures) import SwiftParser +@_spi(ExperimentalLanguageFeatures) import SwiftSyntax +import XCTest + +final class ModuleSelectorTests: ParserTestCase { + override var experimentalFeatures: Parser.ExperimentalFeatures { + [.moduleSelector] + } + + func testModuleSelectorImports() { + XCTExpectFailure("imports not yet implemented") + + assertParse( + """ + import ctypes::bits // FIXME: ban using :: with submodules? + import struct ModuleSelectorTestingKit::A + """ + ) + } + + func testModuleSelectorCorrectCode() { + assertParse( + """ + extension ModuleSelectorTestingKit::A {} + """, + substructure: ExtensionDeclSyntax( + extendedType: makeType(moduleSelector: "ModuleSelectorTestingKit", name: "A"), + memberBlock: MemberBlockSyntax {} + ) + ) + + assertParse( + """ + extension A: @retroactive Swift::Equatable {} + """, + substructure: ExtensionDeclSyntax( + extendedType: IdentifierTypeSyntax(name: .identifier("A")), + inheritanceClause: InheritanceClauseSyntax( + inheritedTypes: [ + InheritedTypeSyntax( + type: AttributedTypeSyntax( + specifiers: [], + attributes: [ + .attribute( + AttributeSyntax( + attributeName: makeType(name: "retroactive"), + arguments: nil + ) + ) + ], + baseType: makeType(moduleSelector: "Swift", name: "Equatable") + ) + ) + ] + ), + memberBlock: MemberBlockSyntax {} + ) + ) + + assertParse( + """ + @_implements(Swift::Equatable, ==(_:_:)) + public static func equals(_: ModuleSelectorTestingKit::A, _: ModuleSelectorTestingKit::A) -> Swift::Bool { + Swift::fatalError() + } + """, + substructure: FunctionDeclSyntax( + attributes: [ + .attribute( + AttributeSyntax( + attributeName: makeType(name: "_implements"), + leftParen: .leftParenToken(), + arguments: .implementsArguments( + ImplementsAttributeArgumentsSyntax( + type: makeType(moduleSelector: "Swift", name: "Equatable"), + declName: makeDeclRef( + baseName: .binaryOperator("=="), + argumentLabels: [nil, nil] + ) + ) + ), + rightParen: .rightParenToken() + ) + ) + ], + modifiers: [ + DeclModifierSyntax(name: .keyword(.public)), + DeclModifierSyntax(name: .keyword(.static)), + ], + name: .identifier("equals"), + signature: FunctionSignatureSyntax( + parameterClause: FunctionParameterClauseSyntax { + FunctionParameterSyntax( + firstName: .wildcardToken(), + type: makeType(moduleSelector: "ModuleSelectorTestingKit", name: "A") + ) + FunctionParameterSyntax( + firstName: .wildcardToken(), + type: makeType(moduleSelector: "ModuleSelectorTestingKit", name: "A") + ) + }, + returnClause: ReturnClauseSyntax( + type: makeType(moduleSelector: "Swift", name: "Bool") + ) + ), + body: CodeBlockSyntax { + makeCall( + callee: ExprSyntax(makeDeclRef(moduleSelector: "Swift", baseName: "fatalError")), + arguments: [:] + ) + } + ) + ) + + // FIXME: Add tests with autodiff @_differentiable(jvp:vjp:) and + // @_derivative(of:) + + assertParse( + """ + @_dynamicReplacement(for: ModuleSelectorTestingKit::negate()) + mutating func myNegate() {} + """, + substructure: FunctionDeclSyntax( + attributes: [ + .attribute( + AttributeSyntax( + attributeName: makeType(name: "_dynamicReplacement"), + leftParen: .leftParenToken(), + arguments: .dynamicReplacementArguments( + DynamicReplacementAttributeArgumentsSyntax( + declName: makeDeclRef( + moduleSelector: "ModuleSelectorTestingKit", + baseName: "negate", + argumentLabels: [] + ) + ) + ), + rightParen: .rightParenToken() + ) + ) + ], + modifiers: [ + DeclModifierSyntax(name: .keyword(.mutating)) + ], + name: .identifier("myNegate"), + signature: FunctionSignatureSyntax( + parameterClause: FunctionParameterClauseSyntax {} + ), + body: CodeBlockSyntax { + } + ) + ) + + // FIXME: Can we test @convention(witness_method:)? + + assertParse( + """ + let fn: (Swift::Int, Swift::Int) -> Swift::Int = (Swift::+) + """, + substructure: VariableDeclSyntax(bindingSpecifier: .keyword(.let)) { + PatternBindingSyntax( + pattern: IdentifierPatternSyntax(identifier: "fn"), + typeAnnotation: TypeAnnotationSyntax( + type: FunctionTypeSyntax( + parameters: TupleTypeElementListSyntax { + TupleTypeElementSyntax(type: makeType(moduleSelector: "Swift", name: "Int")) + TupleTypeElementSyntax(type: makeType(moduleSelector: "Swift", name: "Int")) + }, + returnClause: ReturnClauseSyntax( + type: makeType(moduleSelector: "Swift", name: "Int") + ) + ) + ), + initializer: InitializerClauseSyntax( + value: TupleExprSyntax { + LabeledExprSyntax(expression: makeDeclRef(moduleSelector: "Swift", baseName: .binaryOperator("+"))) + } + ) + ) + } + ) + + assertParse( + """ + let magnitude: Int.Swift::Magnitude = main::magnitude + """, + substructure: VariableDeclSyntax(bindingSpecifier: .keyword(.let)) { + PatternBindingSyntax( + pattern: IdentifierPatternSyntax(identifier: "magnitude"), + typeAnnotation: TypeAnnotationSyntax( + type: makeMember( + of: makeType(name: "Int"), + moduleSelector: "Swift", + name: "Magnitude" + ) + ), + initializer: InitializerClauseSyntax( + value: makeDeclRef(moduleSelector: "main", baseName: "magnitude") + ) + ) + } + ) + + assertParse( + """ + if Swift::Bool.Swift::random() { + } + """, + substructure: IfExprSyntax( + conditions: ConditionElementListSyntax { + ConditionElementSyntax( + condition: .expression( + ExprSyntax( + makeCall( + callee: MemberAccessExprSyntax( + base: makeDeclRef(moduleSelector: "Swift", baseName: "Bool"), + declName: makeDeclRef(moduleSelector: "Swift", baseName: "random") + ), + arguments: [:] + ) + ) + ) + ) + } + ) {} + ) + + assertParse( + """ + self.ModuleSelectorTestingKit::negate() + """, + substructure: makeCall( + callee: MemberAccessExprSyntax( + base: makeDeclRef(baseName: .keyword(.self)), + declName: makeDeclRef(moduleSelector: "ModuleSelectorTestingKit", baseName: "negate") + ), + arguments: [:] + ) + ) + + assertParse( + """ + self = ModuleSelectorTestingKit::A(value: .Swift::min) + """, + substructure: SequenceExprSyntax { + makeDeclRef(baseName: .keyword(.self)) + AssignmentExprSyntax() + makeCall( + callee: makeDeclRef(moduleSelector: "ModuleSelectorTestingKit", baseName: "A"), + arguments: [ + "value": ExprSyntax( + MemberAccessExprSyntax( + declName: makeDeclRef(moduleSelector: "Swift", baseName: "min") + ) + ) + ] + ) + } + ) + + assertParse( + """ + self = A.ModuleSelectorTestingKit::init(value: .min) + """, + substructure: SequenceExprSyntax { + makeDeclRef(baseName: .keyword(.self)) + AssignmentExprSyntax() + makeCall( + callee: MemberAccessExprSyntax( + base: makeDeclRef(baseName: "A"), + declName: makeDeclRef(moduleSelector: "ModuleSelectorTestingKit", baseName: .keyword(.`init`)) + ), + arguments: [ + "value": ExprSyntax( + MemberAccessExprSyntax( + declName: makeDeclRef(baseName: "min") + ) + ) + ] + ) + } + ) + + assertParse( + """ + self.main::myNegate() + """, + substructure: makeCall( + callee: MemberAccessExprSyntax( + base: makeDeclRef(baseName: .keyword(.self)), + declName: makeDeclRef(moduleSelector: "main", baseName: "myNegate") + ), + arguments: [:] + ) + ) + } + + func testModuleSelectorIncorrectAttrNames() { + // An attribute with a module selector *must* be a custom attribute and should be parsed as such. + assertParse( + """ + @2️⃣main::available(macOS 1️⃣10.15, *) var use1: String { "foo" } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '10.15, *' in attribute" + ) + ] + ) + + assertParse( + """ + @main::available var use2 + """, + substructure: AttributeSyntax( + attributeName: makeType(moduleSelector: "main", name: "available") + ) + ) + + assertParse( + """ + @main::available(foo: bar) var use3 + """, + substructure: AttributeSyntax( + attributeName: makeType(moduleSelector: "main", name: "available"), + leftParen: .leftParenToken(), + arguments: .argumentList( + [ + LabeledExprSyntax( + label: "foo", + colon: .colonToken(), + expression: makeDeclRef(baseName: "bar") + ) + ] + ), + rightParen: .rightParenToken() + ) + ) + + assertParse( + """ + func builderUser2(@main::MyBuilder fn: () -> Void) {} + """, + substructure: FunctionParameterSyntax( + attributes: [ + .attribute( + AttributeSyntax( + attributeName: makeType(moduleSelector: "main", name: "MyBuilder") + ) + ) + ], + firstName: "fn", + type: TypeSyntax("() -> Void") + ) + ) + } + + func testModuleSelectorWhitespace() { + assertParse( + """ + _ = Swift::print + """, + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + ) + assertParse( + """ + _ = Swift:: print + """, + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + ) + assertParse( + """ + _ = Swift ::print + """, + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + ) + assertParse( + """ + _ = Swift :: print + """, + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + ) + assertParse( + """ + _ = Swift:: + print + """, + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + ) + assertParse( + """ + _ = Swift + ::print + """, + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + ) + assertParse( + """ + _ = Swift :: + print + """, + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + ) + assertParse( + """ + _ = Swift + :: print + """, + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + ) + assertParse( + """ + _ = Swift + :: + print + """, + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + ) + } + + func testModuleSelectorIncorrectFuncSignature() { + assertParse( + """ + func main1️⃣::decl1() {} + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code '::decl1' before parameter clause") + ] + ) + assertParse( + """ + func decl1( + main1️⃣::p1: Swift::A + ) {} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::p1' in parameter" + ) + ] + ) + + // Round-tripping failures: + assertParse( + """ + func decl1( + main1️⃣::p1: 2️⃣::A + ) {} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::p1' in parameter" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + ], + fixedSource: """ + func decl1( + main::p1: <#identifier#>::A + ) {} + """ + ) + assertParse( + """ + func decl1( + main1️⃣::p1: Swift::2️⃣ + ) {} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::p1' in parameter" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected identifier in type", + fixIts: ["insert identifier"] + ), + ], + fixedSource: """ + func decl1( + main::p1: Swift::<#identifier#> + ) {} + """ + ) + + assertParse( + """ + func decl1( + main1️⃣::label p2: Swift::inout2️⃣ 3️⃣A + ) {} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::label p2' in parameter" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ',' in parameter", + fixIts: ["insert ','"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected identifier and ':' in parameter", + fixIts: ["insert identifier and ':'"] + ), + ], + fixedSource: """ + func decl1( + main::label p2: Swift::inout, <#identifier#>: A + ) {} + """ + ) + assertParse( + """ + func decl1( + label main1️⃣::p3: @Swift::escaping () -> A + ) {} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::p3' in parameter" + ) + ] + ) + } + + func testModuleSelectorIncorrectBindingDecls() { + assertParse( + """ + let main1️⃣::decl1a = "a" + """, + diagnostics: [ + DiagnosticSpec( + message: "expected '=' in variable", + fixIts: ["insert '='"] + ), + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + ], + fixedSource: """ + let main = <#identifier#>::decl1a = "a" + """ + ) + + // Found by mutation testing: + assertParse( + """ + let let1️⃣::decl1a = "a" + """, + diagnostics: [ + DiagnosticSpec( + message: "expected pattern in value binding pattern", + fixIts: ["insert pattern"] + ), + DiagnosticSpec( + message: "expected '=' in variable", + fixIts: ["insert '='"] + ), + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + ], + fixedSource: """ + let let<#pattern#> = <#identifier#>::decl1a = "a" + """ + ) + + assertParse( + """ + var main1️⃣::decl1b = "b" + """, + diagnostics: [ + DiagnosticSpec( + message: "expected '=' in variable", + fixIts: ["insert '='"] + ), + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + ], + fixedSource: """ + var main = <#identifier#>::decl1b = "b" + """ + ) + assertParse( + """ + let (main1️⃣::decl1c, Swift::decl1d) = ("c", "d") + """, + diagnostics: [ + DiagnosticSpec( + message: "unexpected code '::decl1c, Swift::decl1d' in tuple pattern" + ) + ] + ) + assertParse( + """ + if let (main1️⃣::decl1e, Swift::decl1f) = Optional(("e", "f")) {} + """, + diagnostics: [ + DiagnosticSpec( + message: "unexpected code '::decl1e, Swift::decl1f' in tuple" + ) + ] + ) + assertParse( + """ + guard let (main1️⃣::decl1g, Swift::decl1h) = Optional(("g", "h")) else { return } + """, + diagnostics: [ + DiagnosticSpec( + message: "unexpected code '::decl1g, Swift::decl1h' in tuple" + ) + ] + ) + assertParse( + """ + switch Optional(main::decl1g) { + case Optional.some(let Swift1️⃣::decl1i): + break + case .none: + break + } + """, + diagnostics: [ + // FIXME: Function call??? + DiagnosticSpec( + message: "unexpected code '::decl1i' in function call" + ) + ] + ) + assertParse( + """ + switch Optional(main::decl1g) { + case let Optional.some(Swift1️⃣::decl1j): + break + case .none: + break + } + """, + diagnostics: [ + DiagnosticSpec( + message: "unexpected code '::decl1j' in function call" + ) + ] + ) + assertParse( + """ + switch Optional(main::decl1g) { + case let Swift1️⃣::decl1k?: + break + case .none: + break + } + """, + diagnostics: [ + DiagnosticSpec( + message: "unexpected code '::decl1k?' in switch case" + ) + ] + ) + assertParse( + """ + for main1️⃣::decl1l in "lll" {} + """, + diagnostics: [ + DiagnosticSpec( + message: "unexpected code '::decl1l' in 'for' statement" + ) + ] + ) + } + + func testModuleSelectorIncorrectClosureDecls() { + assertParse( + // This gets radically misinterpreted as two statements followed by some invalid code. + """ + "lll".forEach { [2️⃣Swift::magnitude] + main::elem 1️⃣in print(elem) + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'in print(elem)' in closure" + ) + ] + ) + assertParse( + """ + "lll".forEach { (main1️⃣::elem) in print(elem) } + """, + diagnostics: [ + DiagnosticSpec( + message: "unexpected code '::elem' in parameter clause" + ) + ] + ) + assertParse( + """ + "lll".forEach { (main1️⃣::elem) -> Void in print(elem) } + """, + diagnostics: [ + DiagnosticSpec( + message: "unexpected code '::elem' in parameter clause" + ) + ] + ) + assertParse( + """ + "lll".forEach { (main1️⃣::elem: Character) -> Void in print(elem) } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::elem: Character' in parameter clause" + ) + ] + ) + } + + func testModuleSelectorIncorrectTypeDecls() { + assertParse( + """ + enum main1️⃣::decl2 { + case Swift2️⃣::decl2a + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::decl2' in enum" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code '::decl2a' in enum" + ), + ] + ) + assertParse( + """ + struct main1️⃣::decl3 {} + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code '::decl3' in struct") + ] + ) + assertParse( + """ + class main1️⃣::decl4 {} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::decl4' in class" + ) + ] + ) + assertParse( + """ + typealias main1️⃣::decl5 = Swift::Bool + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::decl5' in typealias declaration" + ) + ] + ) + assertParse( + """ + protocol main1️⃣::decl6 { + associatedtype Swift2️⃣::decl6a + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::decl6' in protocol" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code '::decl6a' in protocol" + ), + ] + ) + } + + func testModuleSelectorIncorrectGlobalVarDecls() { + assertParse( + """ + let main1️⃣::decl7 = 7 + """, + diagnostics: [ + DiagnosticSpec( + message: "expected '=' in variable", + fixIts: ["insert '='"] + ), + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + ], + fixedSource: """ + let main = <#identifier#>::decl7 = 7 + """ + ) + assertParse( + """ + var main1️⃣::decl8 = 8 { + willSet(Swift2️⃣::newValue) {} + didSet(Foo3️⃣::oldValue) {} + } + """, + diagnostics: [ + DiagnosticSpec( + message: "expected '=' in variable", + fixIts: ["insert '='"] + ), + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code '::newValue' in accessor" + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "unexpected code '::oldValue' in accessor" + ), + ], + fixedSource: """ + var main = <#identifier#>::decl8 = 8 { + willSet(Swift::newValue) {} + didSet(Foo::oldValue) {} + } + """ + ) + } + + func testModuleSelectorIncorrectNestedDecls() { + assertParse( + """ + struct Parent { + func main1️⃣::decl1() {} + } + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code '::decl1' before parameter clause") + ] + ) + assertParse( + """ + struct Parent { + enum main1️⃣::decl2 { + case Swift2️⃣::decl2a + } + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::decl2' in enum" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code '::decl2a' in enum" + ), + ] + ) + assertParse( + """ + struct Parent { + struct main1️⃣::decl3 {} + } + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code '::decl3' in struct") + ] + ) + assertParse( + """ + struct Parent { + class main1️⃣::decl4 {} + } + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code '::decl4' in class") + ] + ) + assertParse( + """ + struct Parent { + typealias main1️⃣::decl5 = Swift::Bool + } + """, + diagnostics: [ + DiagnosticSpec( + message: "unexpected code '::decl5' in typealias declaration" + ) + ] + ) + } + + func testModuleSelectorMacroDecls() { + assertParse( + """ + struct CreatesDeclExpectation { + #main::myMacro() + } + """, + substructure: MacroExpansionDeclSyntax( + moduleSelector: ModuleSelectorSyntax(moduleName: "main"), + macroName: "myMacro", + leftParen: .leftParenToken(), + arguments: [], + rightParen: .rightParenToken() + ) + ) + } + + func testModuleSelectorIncorrectRuntimeBaseAttr() { + // Should be diagnosed in ASTGen: + assertParse( + """ + @_swift_native_objc_runtime_base(1️⃣main::BaseClass) + class C1 {} + """, + substructure: AttributeSyntax( + attributeName: makeType(name: "_swift_native_objc_runtime_base"), + leftParen: .leftParenToken(), + arguments: .argumentList( + [ + LabeledExprSyntax(expression: makeDeclRef(moduleSelector: "main", baseName: "BaseClass")) + ] + ), + rightParen: .rightParenToken() + ) + ) + } + + func testModuleSelectorOperatorDecls() { + assertParse( + """ + infix operator <<<<< : Swift1️⃣::AdditionPrecedence + """, + diagnostics: [ + DiagnosticSpec( + message: "consecutive statements on a line must be separated by newline or ';'", + fixIts: ["insert newline", "insert ';'"] + ), + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + ], + fixedSource: """ + infix operator <<<<< : Swift + <#identifier#>::AdditionPrecedence + """ + ) + assertParse( + """ + precedencegroup main1️⃣::PG1 { + higherThan: Swift2️⃣::AdditionPrecedence + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '::PG1' in precedencegroup" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code '::AdditionPrecedence' in precedencegroup" + ), + ] + ) + } + + func testModuleSelectorIllFormedModuleNames() { + assertParse( + """ + var a: 1️⃣::Int + """, + diagnostics: [ + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ) + ], + fixedSource: """ + var a: <#identifier#>::Int + """ + ) + assertParse( + """ + var b: (1️⃣::Int) + """, + diagnostics: [ + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ) + ], + fixedSource: """ + var b: (<#identifier#>::Int) + """ + ) + assertParse( + """ + var c: 1️⃣*::Int + """, + diagnostics: [ + DiagnosticSpec(message: "expected type in type annotation", fixIts: ["insert type"]), + DiagnosticSpec(message: "extraneous code '*::Int' at top level"), + ], + fixedSource: """ + var c: <#type#>*::Int + """ + ) + assertParse( + """ + var d: 1️⃣_::Int + """, + diagnostics: [ + DiagnosticSpec(message: "'_' cannot be used as an identifier here") + ] + ) + assertParse( + """ + var e: 1️⃣Self::Int + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'Self' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var e: `Self`::Int + """ + ) + assertParse( + """ + var f: 1️⃣self::Int + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'self' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var f: `self`::Int + """ + ) + assertParse( + """ + var g: 1️⃣inout2️⃣::Int + """, + diagnostics: [ + DiagnosticSpec( + message: "expected type in type annotation", + fixIts: ["insert type"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected pattern in variable", + fixIts: ["insert pattern"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '=' in variable", + fixIts: ["insert '='"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + ], + fixedSource: """ + var g: <#type#>inout<#pattern#> = <#identifier#>::Int + """ + ) + assertParse( + """ + var h: 1️⃣Any::Int + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'Any' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var h: `Any`::Int + """ + ) + assertParse( + """ + var aArray: [1️⃣::Int] + """, + diagnostics: [ + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ) + ], + fixedSource: """ + var aArray: [<#identifier#>::Int] + """ + ) + assertParse( + """ + var bArray: [(1️⃣::Int)] + """, + diagnostics: [ + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ) + ], + fixedSource: """ + var bArray: [(<#identifier#>::Int)] + """ + ) + assertParse( + """ + var cArray: [1️⃣*::Int] + """, + diagnostics: [ + DiagnosticSpec(message: "expected type in array type", fixIts: ["insert type"]), + DiagnosticSpec(message: "unexpected code '*::Int' in array type"), + ], + fixedSource: """ + var cArray: [<#type#>*::Int] + """ + ) + assertParse( + """ + var dArray: [1️⃣_::Int] + """, + diagnostics: [ + DiagnosticSpec(message: "'_' cannot be used as an identifier here") + ] + ) + assertParse( + """ + var eArray: [1️⃣Self::Int] + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'Self' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var eArray: [`Self`::Int] + """ + ) + assertParse( + """ + var fArray: [1️⃣self::Int] + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'self' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var fArray: [`self`::Int] + """ + ) + assertParse( + """ + var gArray: [1️⃣inout2️⃣::Int3️⃣] + """, + diagnostics: [ + DiagnosticSpec( + message: "expected type and ']' to end array type", + fixIts: ["insert type and ']'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected pattern in variable", + fixIts: ["insert pattern"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '=' in variable", + fixIts: ["insert '='"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "extraneous code ']' at top level" + ), + ], + fixedSource: """ + var gArray: [<#type#>]inout<#pattern#> = <#identifier#>::Int] + """ + ) + assertParse( + """ + var hArray: [1️⃣Any::Int] + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'Any' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var hArray: [`Any`::Int] + """ + ) + assertParse( + """ + var aIndex: String.1️⃣::Index + """, + diagnostics: [ + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ) + ], + fixedSource: """ + var aIndex: String.<#identifier#>::Index + """ + ) + // FIXME: This gets interpreted as a single `.*` operator; may not be ideal. + assertParse( + """ + var cIndex: String1️⃣.*::Index + """, + diagnostics: [ + DiagnosticSpec(message: "extraneous code '.*::Index' at top level") + ] + ) + assertParse( + """ + var dIndex: String.1️⃣_::Index + """, + diagnostics: [ + DiagnosticSpec(message: "'_' cannot be used as an identifier here") + ] + ) + assertParse( + """ + var eIndex: String.1️⃣Self::Index + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'Self' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var eIndex: String.`Self`::Index + """ + ) + assertParse( + """ + var fIndex: String.1️⃣self::Index + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'self' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var fIndex: String.`self`::Index + """ + ) + assertParse( + """ + var gIndex: String.inout1️⃣::Index + """, + diagnostics: [ + DiagnosticSpec( + message: "expected '=' in variable", + fixIts: ["insert '='"] + ), + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + ], + fixedSource: """ + var gIndex: String.inout = <#identifier#>::Index + """ + ) + assertParse( + """ + var hIndex: String.1️⃣Any::Index + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'Any' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var hIndex: String.`Any`::Index + """ + ) + assertParse( + """ + func inExpr() { + 1️⃣::print() + } + """, + diagnostics: [ + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ) + ], + fixedSource: """ + func inExpr() { + <#identifier#>::print() + } + """ + ) + assertParse( + """ + func inExpr() { + (1️⃣::print()) + } + """, + diagnostics: [ + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ) + ], + fixedSource: """ + func inExpr() { + (<#identifier#>::print()) + } + """ + ) + assertParse( + """ + func inExpr() { + 1️⃣*::print() + } + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code '*::print()' in function") + ] + ) + assertParse( + """ + func inExpr() { + 1️⃣_::print() + } + """, + diagnostics: [ + DiagnosticSpec(message: "'_' cannot be used as an identifier here") + ] + ) + assertParse( + """ + func inExpr() { + 1️⃣Self::print() + } + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'Self' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + func inExpr() { + `Self`::print() + } + """ + ) + assertParse( + """ + func inExpr() { + 1️⃣self::print() + } + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'self' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + func inExpr() { + `self`::print() + } + """ + ) + assertParse( + """ + func inExpr() { + inout1️⃣::print() + } + """, + diagnostics: [ + DiagnosticSpec(message: "expected pattern in variable", fixIts: ["insert pattern"]), + DiagnosticSpec(message: "expected '=' in variable", fixIts: ["insert '='"]), + DiagnosticSpec(message: "expected module name in module selector", fixIts: ["insert module name"]), + ], + fixedSource: """ + func inExpr() { + inout<#pattern#> = <#identifier#>::print() + } + """ + ) + assertParse( + """ + func inExpr() { + 1️⃣Any::print() + } + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'Any' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + func inExpr() { + `Any`::print() + } + """ + ) + assertParse( + """ + func inExpr() { + _ = 1.1️⃣::magnitude + } + """, + diagnostics: [ + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ) + ], + fixedSource: """ + func inExpr() { + _ = 1.<#identifier#>::magnitude + } + """ + ) + assertParse( + """ + func inExpr() { + _ = (1.1️⃣::magnitude) + } + """, + diagnostics: [ + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ) + ], + fixedSource: """ + func inExpr() { + _ = (1.<#identifier#>::magnitude) + } + """ + ) + // FIXME: This gets interpreted as a single `.*` operator; may not be ideal. + assertParse( + """ + func inExpr() { + _ = 1.*1️⃣::magnitude + } + """, + diagnostics: [ + DiagnosticSpec( + message: "consecutive statements on a line must be separated by newline or ';'", + fixIts: ["insert newline", "insert ';'"] + ), + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + ], + fixedSource: """ + func inExpr() { + _ = 1.* + <#identifier#>::magnitude + } + """ + ) + assertParse( + """ + func inExpr() { + _ = 1.1️⃣_::magnitude + } + """, + diagnostics: [ + DiagnosticSpec(message: "'_' cannot be used as an identifier here") + ] + ) + assertParse( + """ + func inExpr() { + _ = 1.1️⃣Self::magnitude + } + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'Self' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + func inExpr() { + _ = 1.`Self`::magnitude + } + """ + ) + assertParse( + """ + func inExpr() { + _ = 1.1️⃣self::magnitude + } + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'self' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + func inExpr() { + _ = 1.`self`::magnitude + } + """ + ) + assertParse( + """ + func inExpr() { + _ = 1.inout1️⃣::magnitude + } + """, + diagnostics: [ + DiagnosticSpec( + message: "consecutive statements on a line must be separated by newline or ';'", + fixIts: ["insert newline", "insert ';'"] + ), + DiagnosticSpec( + message: "expected module name in module selector", + fixIts: ["insert module name"] + ), + ], + fixedSource: """ + func inExpr() { + _ = 1.inout + <#identifier#>::magnitude + } + """ + ) + assertParse( + """ + func inExpr() { + _ = 1.1️⃣Any::magnitude + } + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'Any' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + func inExpr() { + _ = 1.`Any`::magnitude + } + """ + ) + } + + func testModuleSelectorAttrs() { + // 'main::Private' should be diagnosed in ASTGen + assertParse( + """ + @_spi(main::Private) + public struct BadImplementsAttr: CustomStringConvertible {} + """, + substructure: AttributeSyntax( + attributeName: makeType(name: "_spi"), + leftParen: .leftParenToken(), + arguments: .argumentList( + [ + LabeledExprSyntax(expression: makeDeclRef(moduleSelector: "main", baseName: "Private")) + ] + ), + rightParen: .rightParenToken() + ) + ) + // 'Swift::description' should be diagnosed in ASTGen + assertParse( + """ + @_implements(main::CustomStringConvertible, Swift::description) + public var stringValue: String { fatalError() } + """, + substructure: AttributeSyntax( + attributeName: makeType(name: "_implements"), + leftParen: .leftParenToken(), + arguments: .implementsArguments( + ImplementsAttributeArgumentsSyntax( + type: makeType(moduleSelector: "main", name: "CustomStringConvertible"), + declName: makeDeclRef(moduleSelector: "Swift", baseName: "description") + ) + ), + rightParen: .rightParenToken() + ) + ) + assertParse( + """ + @_specialize(target: main::fn(), spi: Swift1️⃣::Private, where T == Swift::Int) + public func fn() -> T { fatalError() } + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code '::Private, where T == Swift::Int' in attribute") + ] + ) + assertParse( + """ + func fn(_: @isolated(Swift1️⃣::any) () -> Void) {} + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code '::any' in attribute") + ] + ) + assertParse( + """ + @_documentation(metadata: Swift1️⃣::GroupName) + func fn() {} + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code '::GroupName' in attribute") + ] + ) + assertParse( + """ + @derivative(of: Swift::Foo.Swift::Bar.Swift::baz(), wrt: quux) + func fn() {} + """, + substructure: AttributeSyntax( + attributeName: makeType(name: "derivative"), + leftParen: .leftParenToken(), + arguments: .derivativeRegistrationArguments( + DerivativeAttributeArgumentsSyntax( + originalDeclName: MemberAccessExprSyntax( + base: TypeExprSyntax( + type: makeMember( + of: makeType(moduleSelector: "Swift", name: "Foo"), + moduleSelector: "Swift", + name: "Bar" + ) + ), + declName: makeDeclRef(moduleSelector: "Swift", baseName: "baz", argumentLabels: []) + ), + comma: .commaToken(), + arguments: DifferentiabilityWithRespectToArgumentSyntax( + arguments: .argument( + DifferentiabilityArgumentSyntax(argument: "quux") + ) + ) + ) + ), + rightParen: .rightParenToken() + ) + ) + } + + func testModuleSelectorExpr() { + assertParse( + "let x = Swift::1️⃣do { 1 }", + substructure: FunctionCallExprSyntax( + calledExpression: makeDeclRef(moduleSelector: "Swift", baseName: "do"), + leftParen: nil, + arguments: [], + rightParen: nil, + trailingClosure: ClosureExprSyntax { + CodeBlockItemSyntax(item: .expr(ExprSyntax(IntegerLiteralExprSyntax(integerLiteral: 1)))) + } + ), + experimentalFeatures: [.moduleSelector, .doExpressions] + ) + assertParse( + "let x = Swift::if1️⃣ y { 1 } 2️⃣else { 0 }", + diagnostics: [ + DiagnosticSpec( + message: "consecutive statements on a line must be separated by newline or ';'", + fixIts: ["insert newline", "insert ';'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "extraneous code 'else { 0 }' at top level" + ), + ], + fixedSource: """ + let x = Swift::if + y { 1 } else { 0 } + """ + ) + assertParse( + """ + let x = Swift::switch1️⃣ y2️⃣ { + 3️⃣case true: 1 + 4️⃣case false: 0 + } + """, + diagnostics: [ + DiagnosticSpec( + message: "consecutive statements on a line must be separated by newline or ';'", + fixIts: ["insert newline", "insert ';'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "consecutive statements on a line must be separated by newline or ';'", + fixIts: ["insert newline", "insert ';'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "'case' can only appear inside a 'switch' statement or 'enum' declaration" + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "'case' can only appear inside a 'switch' statement or 'enum' declaration" + ), + ], + fixedSource: """ + let x = Swift::switch + y + { + case true: 1 + case false: 0 + } + """ + ) + assertParse( + "fn(Swift::1️⃣&x)", + diagnostics: [ + DiagnosticSpec( + message: "expected identifier in function call", + fixIts: ["insert identifier"] + ), + DiagnosticSpec(message: "unexpected code '&x' in function call"), + ], + fixedSource: "fn(Swift::<#identifier#>&x)" + ) + assertParse( + #"_ = Swift::1️⃣\main::Foo.BarKit::bar"#, + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: #"_ = Swift::<#identifier#>\main::Foo.BarKit::bar"# + ) + assertParse( + #"_ = \main::Foo.BarKit::bar"#, + substructure: KeyPathExprSyntax( + root: makeType(moduleSelector: "main", name: "Foo"), + components: [ + KeyPathComponentSyntax( + period: .periodToken(), + component: .property( + KeyPathPropertyComponentSyntax( + declName: makeDeclRef(moduleSelector: "BarKit", baseName: "bar") + ) + ) + ) + ] + ) + ) + assertParse( + "_ = Swift::1️⃣-x", + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>-x" + ) + assertParse( + "_ = Swift::1️⃣1", + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>1" + ) + assertParse( + "_ = Swift::1️⃣1.0", + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>1.0" + ) + assertParse( + #"_ = Swift::1️⃣@"fnord""#, + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]), + DiagnosticSpec(message: #"extraneous code '@"fnord"' at top level"#), + ], + fixedSource: #"_ = Swift::<#identifier#>@"fnord""# + ) + assertParse( + #"_ = Swift::1️⃣"fnord""#, + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: #"_ = Swift::<#identifier#>"fnord""# + ) + assertParse( + "_ = Swift::1️⃣/fnord/", + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>/fnord/" + ) + assertParse( + "_ = Swift::nil", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "nil") + ) + assertParse( + "_ = Swift::1️⃣true", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "true") + ) + assertParse( + "_ = Swift::identifier", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "identifier") + ) + assertParse( + "_ = Swift::self", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: .keyword(.self)) + ) + assertParse( + "_ = Swift::init", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: .keyword(.`init`)) + ) + assertParse( + "@attached(extension, names: 1️⃣Swift::deinit) macro m()", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: .keyword(.`deinit`)), + substructureAfterMarker: "1️⃣" + ) + assertParse( + "@attached(extension, names: 1️⃣Swift::subscript) macro m()", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: .keyword(.subscript)), + substructureAfterMarker: "1️⃣" + ) + assertParse( + "_ = Swift::Self", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: .keyword(.`Self`)) + ) + assertParse( + "_ = Swift::1️⃣Any", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "Any") + ) + assertParse( + "_ = Swift::1️⃣$0", + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>$0" + ) + assertParse( + "_ = Swift::$foo", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: .identifier("$foo")) + ) + assertParse( + "_ = Swift::1️⃣_", + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>_" + ) + assertParse( + "Swift::1️⃣_ = 1", + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: "Swift::<#identifier#>_ = 1" + ) + assertParse( + "_ = Swift::1️⃣#foo", + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>#foo" + ) + assertParse( + "_ = #Swift::foo", + substructure: MacroExpansionExprSyntax( + moduleSelector: ModuleSelectorSyntax(moduleName: "Swift"), + macroName: "foo", + arguments: [] + ) + ) + assertParse( + "_ = Swift::1️⃣{ 1 }", + diagnostics: [ + DiagnosticSpec(message: "expected identifier in function call", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#> { 1 }" + ) + assertParse( + "_ = Swift::1️⃣.random()", + diagnostics: [ + DiagnosticSpec(message: "expected identifier in member access", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>.random()" + ) + assertParse( + "_ = Swift::1️⃣.main::random()", + diagnostics: [ + DiagnosticSpec(message: "expected identifier in member access", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>.main::random()" + ) + assertParse( + "_ = .main::random()", + substructure: MemberAccessExprSyntax( + declName: makeDeclRef(moduleSelector: "main", baseName: "random") + ) + ) + assertParse( + "_ = Swift::1️⃣super.foo()", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "super") + ) + assertParse( + "_ = Swift::1️⃣(a, b)", + diagnostics: [ + DiagnosticSpec(message: "expected identifier in function call", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>(a, b)" + ) + assertParse( + "_ = Swift::1️⃣[a, b]", + diagnostics: [ + DiagnosticSpec(message: "expected identifier in subscript", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>[a, b]" + ) + assertParse( + "_ = Swift::1️⃣", + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = Swift::<#identifier#>" + ) + + assertParse( + "_ = x.Swift::y", + substructure: MemberAccessExprSyntax( + base: makeDeclRef(baseName: "x"), + declName: makeDeclRef(moduleSelector: "Swift", baseName: "y") + ) + ) + assertParse( + "_ = x.Swift::1️⃣1", + diagnostics: [ + DiagnosticSpec(message: "expected identifier in member access", fixIts: ["insert identifier"]) + ], + fixedSource: "_ = x.Swift::<#identifier#>1" + ) + // Diagnose in ASTGen? + assertParse( + "_ = x.Swift::1️⃣self", + substructure: MemberAccessExprSyntax( + base: makeDeclRef(baseName: "x"), + declName: makeDeclRef( + moduleSelector: "Swift", + baseName: .keyword(.`self`) + ) + ) + ) + assertParse( + "_ = x.Swift::Self.self", + // FIXME: inconsistent with type syntax + substructure: MemberAccessExprSyntax( + base: MemberAccessExprSyntax( + base: makeDeclRef(baseName: "x"), + declName: makeDeclRef(moduleSelector: "Swift", baseName: .keyword(.`Self`)) + ), + declName: makeDeclRef(baseName: .keyword(.`self`)) + ) + ) + assertParse( + "_ = x.Swift::Type.self", + // FIXME: inconsistent with type syntax + substructure: MemberAccessExprSyntax( + base: MemberAccessExprSyntax( + base: makeDeclRef(baseName: "x"), + declName: makeDeclRef(moduleSelector: "Swift", baseName: "Type") + ), + declName: makeDeclRef(baseName: .keyword(.`self`)) + ) + ) + assertParse( + "_ = x.Swift::Protocol.self", + // FIXME: inconsistent with type syntax + substructure: MemberAccessExprSyntax( + base: MemberAccessExprSyntax( + base: makeDeclRef(baseName: "x"), + declName: makeDeclRef(moduleSelector: "Swift", baseName: "Protocol") + ), + declName: makeDeclRef(baseName: .keyword(.`self`)) + ) + ) + assertParse( + "_ = myArray.reduce(0, 1️⃣Swift::+)", + substructure: makeDeclRef(moduleSelector: "Swift", baseName: .binaryOperator("+")), + substructureAfterMarker: "1️⃣" + ) + } + + func testModuleSelectorStmt() { + assertParse( + "if Swift::1️⃣#available(macOS 15, *) {}", + diagnostics: [ + DiagnosticSpec(message: "expected identifier in 'if' statement", fixIts: ["insert identifier"]), + DiagnosticSpec(message: "unexpected code '#available(macOS 15, *)' in 'if' statement"), + ], + fixedSource: "if Swift::<#identifier#> #available(macOS 15, *) {}" + ) + } + + func testModuleSelectorType() { + assertParse( + "func fn(_: Swift::Self) {}", + substructure: makeType(moduleSelector: "Swift", name: "Self") + ) + assertParse( + "func fn(_: Swift::Any) {}", + substructure: makeType(moduleSelector: "Swift", name: "Any") + ) + assertParse( + "func fn(_: Swift::Foo) {}", + substructure: makeType(moduleSelector: "Swift", name: "Foo") + ) + assertParse( + "func fn(_: Swift::1️⃣(Int, String)) {}", + diagnostics: [ + DiagnosticSpec(message: "expected identifier in type", fixIts: ["insert identifier"]), + DiagnosticSpec(message: "unexpected code '(Int, String)' in parameter clause"), + ], + fixedSource: "func fn(_: Swift::<#identifier#>(Int, String)) {}" + ) + assertParse( + "func fn(_: Swift::1️⃣[Int]) {}", + diagnostics: [ + DiagnosticSpec(message: "expected identifier in type", fixIts: ["insert identifier"]), + DiagnosticSpec(message: "unexpected code '[Int]' in parameter clause"), + ], + fixedSource: "func fn(_: Swift::<#identifier#>[Int]) {}" + ) + assertParse( + "func fn(_: Swift::1️⃣_) {}", + diagnostics: [ + DiagnosticSpec(message: "expected identifier in type", fixIts: ["insert identifier"]), + DiagnosticSpec(message: "unexpected code '_' in parameter clause"), + ], + fixedSource: "func fn(_: Swift::<#identifier#>_) {}" + ) + assertParse( + "func fn(_: Swift::1️⃣) {}", + diagnostics: [ + DiagnosticSpec(message: "expected identifier in type", fixIts: ["insert identifier"]) + ], + fixedSource: "func fn(_: Swift::<#identifier#>) {}" + ) + // TODO: Add equivalent test case for legacy parser + assertParse( + "func fn(_: Foo.1️⃣Swift::Type) {}", + substructure: makeMember( + of: makeType(name: "Foo"), + moduleSelector: "Swift", + name: "Type" + ) + ) + // TODO: Add equivalent test case for legacy parser + assertParse( + "func fn(_: Foo.1️⃣Swift::Protocol) {}", + substructure: makeMember( + of: makeType(name: "Foo"), + moduleSelector: "Swift", + name: "Protocol" + ) + ) + assertParse( + "func fn(_: Foo.Swift::Bar) {}", + substructure: makeMember( + of: makeType(name: "Foo"), + moduleSelector: "Swift", + name: "Bar" + ) + ) + assertParse( + "func fn(_: Foo.Swift::self) {}", + substructure: makeMember( + of: makeType(name: "Foo"), + moduleSelector: "Swift", + name: .keyword(.`self`) + ) + ) + } +} + +// MARK: - Syntax tree construction helpers + +private func makeType(moduleSelector: TokenSyntax? = nil, name: TokenSyntax) -> IdentifierTypeSyntax { + return IdentifierTypeSyntax( + moduleSelector: moduleSelector.map { ModuleSelectorSyntax(moduleName: $0) }, + name: name + ) +} + +private func makeDeclRef( + moduleSelector: TokenSyntax? = nil, + baseName: TokenSyntax, + argumentLabels: [TokenSyntax?]? = nil +) -> DeclReferenceExprSyntax { + return DeclReferenceExprSyntax( + moduleSelector: moduleSelector.map { ModuleSelectorSyntax(moduleName: $0) }, + baseName: baseName, + argumentNames: argumentLabels.map { argumentLabels in + DeclNameArgumentsSyntax( + arguments: DeclNameArgumentListSyntax( + argumentLabels.map { DeclNameArgumentSyntax(name: $0 ?? .wildcardToken()) } + ) + ) + } + ) +} + +private func makeMember( + of base: some TypeSyntaxProtocol, + moduleSelector: TokenSyntax? = nil, + name: TokenSyntax +) -> MemberTypeSyntax { + return MemberTypeSyntax( + baseType: base, + moduleSelector: moduleSelector.map { ModuleSelectorSyntax(moduleName: $0) }, + name: name + ) +} + +private func makeCall( + callee: some ExprSyntaxProtocol, + arguments: KeyValuePairs +) -> FunctionCallExprSyntax { + return FunctionCallExprSyntax( + calledExpression: callee, + leftParen: .leftParenToken(), + arguments: LabeledExprListSyntax( + arguments.map { labelAndExpr in + LabeledExprSyntax( + label: labelAndExpr.0, + colon: labelAndExpr.0 == nil ? nil : .colonToken(), + expression: labelAndExpr.1 + ) + } + ), + rightParen: .rightParenToken() + ) +} From 2b44b9cfd7eaf3155d69e1804b0a0134724d1604 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 2 Jul 2025 20:14:57 -0700 Subject: [PATCH 10/15] Support module selectors in scoped imports --- .../Sources/SyntaxSupport/DeclNodes.swift | 2 +- .../ValidateSyntaxNodes.swift | 4 -- Sources/SwiftParser/Declarations.swift | 70 +++++++++++++++---- .../generated/Parser+TokenSpecSet.swift | 52 ++++++++++++++ .../ParseDiagnosticsGenerator.swift | 34 +++++++++ .../ParserDiagnosticMessages.swift | 3 + .../generated/raw/RawSyntaxValidation.swift | 2 +- .../syntaxNodes/SyntaxNodesGHI.swift | 6 +- .../translated/ModuleSelectorTests.swift | 63 ++++++++++++++++- 9 files changed, 213 insertions(+), 23 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index b87a2a1ac07..4c5a1061d4d 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -28,7 +28,7 @@ public let DECL_NODES: [Node] = [ ), Child( name: "trailingPeriod", - kind: .token(choices: [.token(.period)]), + kind: .token(choices: [.token(.period), .token(.colonColon)]), isOptional: true ), ], diff --git a/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift b/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift index 69a489c0f01..b61533bad21 100644 --- a/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift +++ b/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift @@ -357,10 +357,6 @@ class ValidateSyntaxNodes: XCTestCase { "child 'leadingComma' has a comma keyword as its only token choice and should thus be named 'comma' or 'trailingComma'" ), // This is similar to `TrailingComma` - ValidationFailure( - node: .importPathComponent, - message: "child 'trailingPeriod' has a token as its only token choice and should thus be named 'period'" - ), // `~` is the only operator that’s allowed here ValidationFailure( node: .suppressedType, diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 781ab5452fc..1b04379f967 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -435,7 +435,7 @@ extension Parser { ) -> RawImportDeclSyntax { let (unexpectedBeforeImportKeyword, importKeyword) = self.eat(handle) let kind = self.parseImportKind() - let path = self.parseImportPath() + let path = self.parseImportPath(hasImportKind: kind != nil) return RawImportDeclSyntax( attributes: attrs.attributes, modifiers: attrs.modifiers, @@ -451,21 +451,67 @@ extension Parser { return self.consume(ifAnyIn: ImportDeclSyntax.ImportKindSpecifierOptions.self) } - mutating func parseImportPath() -> RawImportPathComponentListSyntax { + mutating func parseImportPath(hasImportKind: Bool) -> RawImportPathComponentListSyntax { var elements = [RawImportPathComponentSyntax]() - var keepGoing: RawTokenSyntax? = nil - var loopProgress = LoopProgressCondition() - repeat { - let name = self.parseAnyIdentifier() - keepGoing = self.consume(if: .period) - elements.append( + + // Special case: scoped import with module selector-style syntax. This always has exactly two path components + // separated by '::'. + if hasImportKind, + let (moduleNameOrUnexpected, colonColon, unexpectedAfterColonColon) = self.consumeModuleSelectorTokensIfPresent() + { + // Is the token in module name position really a module name? + let unexpectedBeforeModuleName: RawUnexpectedNodesSyntax? + let moduleName: RawTokenSyntax + if moduleNameOrUnexpected.tokenKind == .identifier { + unexpectedBeforeModuleName = nil + moduleName = moduleNameOrUnexpected + } else { + unexpectedBeforeModuleName = RawUnexpectedNodesSyntax([moduleNameOrUnexpected], arena: self.arena) + moduleName = self.missingToken(.identifier) + } + + let declName = self.parseAnyIdentifier() + + elements = [ RawImportPathComponentSyntax( - name: name, - trailingPeriod: keepGoing, + unexpectedBeforeModuleName, + name: moduleName, + trailingPeriod: colonColon, + RawUnexpectedNodesSyntax(unexpectedAfterColonColon, arena: self.arena), arena: self.arena + ), + RawImportPathComponentSyntax( + name: declName, + trailingPeriod: nil, + arena: self.arena + ), + ] + } else { + var keepGoing: RawTokenSyntax? = nil + var loopProgress = LoopProgressCondition() + repeat { + let name = self.parseAnyIdentifier() + keepGoing = self.consume(if: .period) + + // '::' is not valid if we got here, but someone might try to use it anyway. + let unexpectedAfterTrailingPeriod: RawUnexpectedNodesSyntax? + if keepGoing == nil, let colonColon = self.consume(if: .colonColon) { + unexpectedAfterTrailingPeriod = RawUnexpectedNodesSyntax([colonColon], arena: self.arena) + keepGoing = self.missingToken(.period) + } else { + unexpectedAfterTrailingPeriod = nil + } + + elements.append( + RawImportPathComponentSyntax( + name: name, + trailingPeriod: keepGoing, + unexpectedAfterTrailingPeriod, + arena: self.arena + ) ) - ) - } while keepGoing != nil && self.hasProgressed(&loopProgress) + } while keepGoing != nil && self.hasProgressed(&loopProgress) + } return RawImportPathComponentListSyntax(elements: elements, arena: self.arena) } } diff --git a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift index bcdb11f0b95..ecc4bea5e93 100644 --- a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift +++ b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift @@ -2378,6 +2378,58 @@ extension ImportPathComponentSyntax { } } +extension ImportPathComponentSyntax { + @_spi(Diagnostics) + public enum TrailingPeriodOptions: TokenSpecSet { + case period + case colonColon + + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { + switch PrepareForKeywordMatch(lexeme) { + case TokenSpec(.period): + self = .period + case TokenSpec(.colonColon): + self = .colonColon + default: + return nil + } + } + + public init?(token: TokenSyntax) { + switch token { + case TokenSpec(.period): + self = .period + case TokenSpec(.colonColon): + self = .colonColon + default: + return nil + } + } + + var spec: TokenSpec { + switch self { + case .period: + return .period + case .colonColon: + return .colonColon + } + } + + /// Returns a token that satisfies the `TokenSpec` of this case. + /// + /// If the token kind of this spec has variable text, e.g. for an identifier, this returns a token with empty text. + @_spi(Diagnostics) + public var tokenSyntax: TokenSyntax { + switch self { + case .period: + return .periodToken() + case .colonColon: + return .colonColonToken() + } + } + } +} + extension InitializerDeclSyntax { @_spi(Diagnostics) public enum OptionalMarkOptions: TokenSpecSet { diff --git a/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift index 83098cec92b..8ddf99358b1 100644 --- a/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift +++ b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift @@ -1264,6 +1264,40 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor { return .visitChildren } + public override func visit(_ node: ImportPathComponentSyntax) -> SyntaxVisitorContinueKind { + if shouldSkip(node) { + return .skipChildren + } + + if let colonColon = node.unexpectedAfterTrailingPeriod?.first?.as(TokenSyntax.self), + colonColon.tokenKind == .colonColon, + colonColon.isPresent, + let trailingPeriod = node.trailingPeriod, + trailingPeriod.tokenKind == .period, + trailingPeriod.isMissing + { + addDiagnostic( + colonColon, + .submoduleCannotBeImportedUsingModuleSelector, + fixIts: [ + FixIt( + message: ReplaceTokensFixIt(replaceTokens: [colonColon], replacements: [trailingPeriod]), + changes: [ + .makeMissing(colonColon), + .makePresent(trailingPeriod), + ] + ) + ], + handledNodes: [ + colonColon.id, + trailingPeriod.id, + ] + ) + } + + return .visitChildren + } + public override func visit(_ node: InitializerClauseSyntax) -> SyntaxVisitorContinueKind { if shouldSkip(node) { return .skipChildren diff --git a/Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift b/Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift index 07ff8b8d49e..d67c1412de9 100644 --- a/Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift +++ b/Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift @@ -233,6 +233,9 @@ extension DiagnosticMessage where Self == StaticParserError { public static var subscriptsCannotHaveNames: Self { .init("subscripts cannot have a name") } + public static var submoduleCannotBeImportedUsingModuleSelector: Self { + .init("submodule cannot be imported using module selector") + } public static var tooManyClosingPoundDelimiters: Self { .init("too many '#' characters in closing delimiter") } diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index dec95731828..a768f46192f 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -1677,7 +1677,7 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { .tokenKind(.postfixOperator) ])) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 3, verify(layout[3], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.period)])) + assertNoError(kind, 3, verify(layout[3], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.period), .tokenKind(.colonColon)])) assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) } func validateInOutExprSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift index f2ff12fa517..3806f606106 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift @@ -3240,7 +3240,7 @@ public struct ImportDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyn /// ### Children /// /// - `name`: (`` | `` | `` | ``) -/// - `trailingPeriod`: `.`? +/// - `trailingPeriod`: (`.` | `::`)? /// /// ### Contained in /// @@ -3335,7 +3335,9 @@ public struct ImportPathComponentSyntax: SyntaxProtocol, SyntaxHashable, _LeafSy /// ### Tokens /// - /// For syntax trees generated by the parser, this is guaranteed to be `.`. + /// For syntax trees generated by the parser, this is guaranteed to be one of the following kinds: + /// - `.` + /// - `::` public var trailingPeriod: TokenSyntax? { get { return Syntax(self).child(at: 3)?.cast(TokenSyntax.self) diff --git a/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift index f939fa574f6..13666b76aa3 100644 --- a/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift +++ b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift @@ -22,13 +22,70 @@ final class ModuleSelectorTests: ParserTestCase { } func testModuleSelectorImports() { - XCTExpectFailure("imports not yet implemented") - assertParse( """ - import ctypes::bits // FIXME: ban using :: with submodules? import struct ModuleSelectorTestingKit::A + """, + substructure: ImportDeclSyntax( + importKindSpecifier: .keyword(.struct), + path: [ + ImportPathComponentSyntax( + name: .identifier("ModuleSelectorTestingKit"), + trailingPeriod: .colonColonToken() + ), + ImportPathComponentSyntax( + name: .identifier("A") + ), + ] + ) + ) + + assertParse( + """ + import struct 1️⃣_::A + """, + diagnostics: [ + DiagnosticSpec(message: "'_' cannot be used as an identifier here") + ] + ) + + assertParse( + """ + import struct ModuleSelectorTestingKit::1️⃣Submodule::A + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Submodule::' in import") + ] + ) + + assertParse( """ + import struct ModuleSelectorTestingKit.Submodule1️⃣::A + """, + diagnostics: [ + DiagnosticSpec( + message: "submodule cannot be imported using module selector", + fixIts: ["replace '::' with '.'"] + ) + ], + fixedSource: """ + import struct ModuleSelectorTestingKit.Submodule.A + """ + ) + + assertParse( + """ + import ctypes1️⃣::bits + """, + diagnostics: [ + DiagnosticSpec( + message: "submodule cannot be imported using module selector", + fixIts: ["replace '::' with '.'"] + ) + ], + fixedSource: """ + import ctypes.bits + """ ) } From e35f6f9e48ccb9108a6d58c672625db24bd31d22 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 30 Jul 2025 17:43:08 -0700 Subject: [PATCH 11/15] 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. --- Sources/SwiftParser/Declarations.swift | 13 ++- Sources/SwiftParser/Expressions.swift | 9 +- Sources/SwiftParser/Names.swift | 92 +++++++++++------- Sources/SwiftParser/Types.swift | 50 +++++++--- .../translated/ModuleSelectorTests.swift | 97 +++++++++++++++---- 5 files changed, 189 insertions(+), 72 deletions(-) diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 1b04379f967..2d78edfe9cf 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -457,7 +457,8 @@ extension Parser { // Special case: scoped import with module selector-style syntax. This always has exactly two path components // separated by '::'. if hasImportKind, - let (moduleNameOrUnexpected, colonColon, unexpectedAfterColonColon) = self.consumeModuleSelectorTokensIfPresent() + let (moduleNameOrUnexpected, colonColon, unexpectedAfterColonColon, skipQualifiedName) = + self.consumeModuleSelectorTokensIfPresent() { // Is the token in module name position really a module name? let unexpectedBeforeModuleName: RawUnexpectedNodesSyntax? @@ -470,7 +471,7 @@ extension Parser { moduleName = self.missingToken(.identifier) } - let declName = self.parseAnyIdentifier() + let declName = skipQualifiedName ? self.missingToken(.identifier) : self.parseAnyIdentifier() elements = [ RawImportPathComponentSyntax( @@ -2243,13 +2244,17 @@ extension Parser { } let moduleSelector: RawModuleSelectorSyntax? + if !self.atStartOfLine { + (moduleSelector, _) = self.parseModuleSelectorIfPresent() + } else { + moduleSelector = nil + } + let unexpectedBeforeMacro: RawUnexpectedNodesSyntax? let macro: RawTokenSyntax if !self.atStartOfLine { - moduleSelector = self.parseModuleSelectorIfPresent() (unexpectedBeforeMacro, macro) = self.expectIdentifier(allowKeywordsAsIdentifier: true) } else { - moduleSelector = nil unexpectedBeforeMacro = nil macro = self.missingToken(.identifier) } diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index d7ee972fc98..a8dd6b96ee2 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -1398,7 +1398,14 @@ extension Parser { ) pound = pound.tokenView.withTokenDiagnostic(tokenDiagnostic: diagnostic, arena: self.arena) } - let moduleSelector = parseModuleSelectorIfPresent() + + let moduleSelector: RawModuleSelectorSyntax? + if !self.atStartOfLine { + (moduleSelector, _) = self.parseModuleSelectorIfPresent() + } else { + moduleSelector = nil + } + let unexpectedBeforeMacroName: RawUnexpectedNodesSyntax? let macroName: RawTokenSyntax if !self.atStartOfLine { diff --git a/Sources/SwiftParser/Names.swift b/Sources/SwiftParser/Names.swift index eebcd58d5ed..bf15c54febd 100644 --- a/Sources/SwiftParser/Names.swift +++ b/Sources/SwiftParser/Names.swift @@ -83,8 +83,9 @@ extension TokenConsumer { /// - `colonColonToken`: The `::` indicating this module selector. Always `.colonColon`, always present. /// - `extra`: Tokens for additional trailing module selectors. There is no situation in which two module selectors /// can be validly chained. + /// - `skipQualifiedName`: True if the next token should be interpreted as a different statement. mutating func consumeModuleSelectorTokensIfPresent() -> ( - moduleNameOrUnexpected: Token, colonColonToken: Token, extra: [Token] + moduleNameOrUnexpected: Token, colonColonToken: Token, extra: [Token], skipQualifiedName: Bool )? { guard self.isAtModuleSelector() else { return nil @@ -111,15 +112,21 @@ extension TokenConsumer { } extra.append(self.eat(.colonColon)) } - return (moduleName, colonColonToken, extra) + + let afterContainsAnyNewline = self.atStartOfLine + + return (moduleName, colonColonToken, extra, afterContainsAnyNewline) } } extension Parser { /// Parses one or more module selectors, if present. - mutating func parseModuleSelectorIfPresent() -> RawModuleSelectorSyntax? { - guard let (moduleNameOrUnexpected, colonColon, extra) = consumeModuleSelectorTokensIfPresent() else { - return nil + mutating func parseModuleSelectorIfPresent() -> (moduleSelector: RawModuleSelectorSyntax?, skipQualifiedName: Bool) { + guard + let (moduleNameOrUnexpected, colonColon, extra, skipQualifiedName) = + consumeModuleSelectorTokensIfPresent() + else { + return (nil, false) } let leadingUnexpected: [RawSyntax] @@ -136,12 +143,15 @@ extension Parser { trailingUnexpected = extra.map { RawSyntax($0) } - return RawModuleSelectorSyntax( - RawUnexpectedNodesSyntax(leadingUnexpected, arena: arena), - moduleName: moduleName, - colonColon: colonColon, - RawUnexpectedNodesSyntax(trailingUnexpected, arena: arena), - arena: arena + return ( + moduleSelector: RawModuleSelectorSyntax( + RawUnexpectedNodesSyntax(leadingUnexpected, arena: arena), + moduleName: moduleName, + colonColon: colonColon, + RawUnexpectedNodesSyntax(trailingUnexpected, arena: arena), + arena: arena + ), + skipQualifiedName: skipQualifiedName ) } } @@ -169,29 +179,8 @@ extension Parser { } mutating func parseDeclReferenceExpr(_ flags: DeclNameOptions = []) -> RawDeclReferenceExprSyntax { - // Consume a module selector if present. - let moduleSelector = self.parseModuleSelectorIfPresent() - - // If a module selector is found, we parse the name after it according to SE-0071 rules. - let allowKeywords = flags.contains(.keywords) || moduleSelector != nil - - // Consume the base name. - let base: RawTokenSyntax - if let identOrSelf = self.consume(if: .identifier, .keyword(.self), .keyword(.Self)) - ?? self.consume(if: .keyword(.`init`)) - { - base = identOrSelf - } else if flags.contains(.operators), let (_, _) = self.at(anyIn: Operator.self) { - base = self.consumeAnyToken(remapping: .binaryOperator) - } else if flags.contains(.keywordsUsingSpecialNames), - let special = self.consume(if: .keyword(.`deinit`), .keyword(.`subscript`)) - { - base = special - } else if allowKeywords && self.currentToken.isLexerClassifiedKeyword { - base = self.consumeAnyToken(remapping: .identifier) - } else { - base = missingToken(.identifier) - } + // Consume the module selector, if present, and base name. + let (moduleSelector, base) = self.parseDeclReferenceBase(flags) // Parse an argument list, if the flags allow it and it's present. let args = self.parseArgLabelList(flags) @@ -203,6 +192,35 @@ extension Parser { ) } + private mutating func parseDeclReferenceBase( + _ flags: DeclNameOptions + ) -> (moduleSelector: RawModuleSelectorSyntax?, base: RawTokenSyntax) { + // Consume a module selector if present. + let (moduleSelector, skipQualifiedName) = self.parseModuleSelectorIfPresent() + + // Consume the base name. + if !skipQualifiedName { + if let identOrInit = self.consume(if: .identifier, .keyword(.`init`)) { + return (moduleSelector, identOrInit) + } + if moduleSelector == nil, let selfOrSelf = self.consume(if: .keyword(.`self`), .keyword(.`Self`)) { + return (moduleSelector, selfOrSelf) + } + if flags.contains(.operators), let (_, _) = self.at(anyIn: Operator.self) { + return (moduleSelector, self.consumeAnyToken(remapping: .binaryOperator)) + } + if flags.contains(.keywordsUsingSpecialNames), + let special = self.consume(if: .keyword(.`deinit`), .keyword(.`subscript`)) + { + return (moduleSelector, special) + } + if (flags.contains(.keywords) || moduleSelector != nil) && self.currentToken.isLexerClassifiedKeyword { + return (moduleSelector, self.consumeAnyToken(remapping: .identifier)) + } + } + return (moduleSelector, missingToken(.identifier)) + } + mutating func parseArgLabelList(_ flags: DeclNameOptions) -> RawDeclNameArgumentsSyntax? { guard flags.contains(.compoundNames) else { return nil @@ -319,8 +337,8 @@ extension Parser { var keepGoing = self.consume(if: .period) var loopProgress = LoopProgressCondition() while keepGoing != nil && self.hasProgressed(&loopProgress) { - let memberModuleSelector = self.parseModuleSelectorIfPresent() - let name = self.parseMemberTypeName() + let (memberModuleSelector, skipQualifiedName) = self.parseModuleSelectorIfPresent() + let name = self.parseMemberTypeName(moduleSelector: memberModuleSelector, skipName: skipQualifiedName) let generics: RawGenericArgumentClauseSyntax? if self.at(prefix: "<") { generics = self.parseGenericArguments() @@ -338,7 +356,7 @@ extension Parser { ) ) - guard hasAnotherMember() else { + guard !skipQualifiedName && hasAnotherMember() else { break } diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 6f7b190d222..46d150a74b6 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -293,8 +293,8 @@ extension Parser { ) ) } else { - let memberModuleSelector = self.parseModuleSelectorIfPresent() - let name: RawTokenSyntax = self.parseMemberTypeName() + let (memberModuleSelector, skipQualifiedName) = self.parseModuleSelectorIfPresent() + let name = self.parseMemberTypeName(moduleSelector: memberModuleSelector, skipName: skipQualifiedName) let generics: RawGenericArgumentClauseSyntax? if self.at(prefix: "<") { generics = self.parseGenericArguments() @@ -312,6 +312,9 @@ extension Parser { arena: self.arena ) ) + if skipQualifiedName { + break + } } continue } @@ -336,16 +339,39 @@ extension Parser { return base } + /// Parse a type name that has been qualiified by a module selector. This very aggressively interprets keywords as + /// identifiers. + /// + /// - Parameter skipQualifiedName: If `true`, the next token should not be parsed because it includes forbidden whitespace. + mutating func parseTypeNameAfterModuleSelector(skipQualifiedName: Bool) -> RawTokenSyntax { + if !skipQualifiedName { + if let identifier = self.consume(if: .identifier) { + return identifier + } else if self.currentToken.isLexerClassifiedKeyword { + return self.consumeAnyToken(remapping: .identifier) + } + } + return missingToken(.identifier) + } + /// Parse the name of a member type, which may be a keyword that's /// interpreted as an identifier (per SE-0071). - mutating func parseMemberTypeName() -> RawTokenSyntax { - if let handle = self.at(anyIn: MemberTypeSyntax.NameOptions.self)?.handle { - return self.eat(handle) - } else if self.currentToken.isLexerClassifiedKeyword { - return self.consumeAnyToken(remapping: .identifier) - } else { - return missingToken(.identifier) + /// + /// - Parameter moduleSelector: The module selector that will be attached to this name, if any. + /// - Parameter skipName: If `true`, the next token should not be parsed because it includes forbidden whitespace. + mutating func parseMemberTypeName(moduleSelector: RawModuleSelectorSyntax?, skipName: Bool) -> RawTokenSyntax { + if moduleSelector != nil { + return self.parseTypeNameAfterModuleSelector(skipQualifiedName: skipName) + } + + if !skipName { + if let handle = self.at(anyIn: MemberTypeSyntax.NameOptions.self)?.handle { + return self.eat(handle) + } else if self.currentToken.isLexerClassifiedKeyword { + return self.consumeAnyToken(remapping: .identifier) + } } + return missingToken(.identifier) } /// Parse an optional type. @@ -374,7 +400,7 @@ extension Parser { /// Parse a type identifier. mutating func parseTypeIdentifier() -> RawIdentifierTypeSyntax { - let moduleSelector = self.parseModuleSelectorIfPresent() + let (moduleSelector, skipQualifiedName) = self.parseModuleSelectorIfPresent() if moduleSelector == nil && self.at(.keyword(.Any)) { return self.parseAnyType() @@ -385,10 +411,10 @@ extension Parser { if moduleSelector == nil { (unexpectedBeforeName, name) = self.expect(anyIn: IdentifierTypeSyntax.NameOptions.self, default: .identifier) } else { - // A name after a module selector gets parsed like a member unexpectedBeforeName = nil - name = self.parseMemberTypeName() + name = self.parseTypeNameAfterModuleSelector(skipQualifiedName: skipQualifiedName) } + let generics: RawGenericArgumentClauseSyntax? if self.at(prefix: "<") { generics = self.parseGenericArguments() diff --git a/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift index 13666b76aa3..7dd321decf7 100644 --- a/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift +++ b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift @@ -454,10 +454,16 @@ final class ModuleSelectorTests: ParserTestCase { ) assertParse( """ - _ = Swift:: + _ = Swift::1️⃣ print """, - substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: """ + _ = Swift::<#identifier#> + print + """ ) assertParse( """ @@ -468,10 +474,16 @@ final class ModuleSelectorTests: ParserTestCase { ) assertParse( """ - _ = Swift :: + _ = Swift ::1️⃣ print """, - substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: """ + _ = Swift ::<#identifier#> + print + """ ) assertParse( """ @@ -483,10 +495,17 @@ final class ModuleSelectorTests: ParserTestCase { assertParse( """ _ = Swift - :: + ::1️⃣ print """, - substructure: makeDeclRef(moduleSelector: "Swift", baseName: "print") + diagnostics: [ + DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]) + ], + fixedSource: """ + _ = Swift + ::<#identifier#> + print + """ ) } @@ -1781,6 +1800,20 @@ final class ModuleSelectorTests: ParserTestCase { ), experimentalFeatures: [.moduleSelector, .doExpressions] ) + assertParse( + """ + let x = Swift::1️⃣ + do { 1 } + """, + diagnostics: [ + DiagnosticSpec(message: "expected identifier in variable", fixIts: ["insert identifier"]) + ], + fixedSource: """ + let x = Swift::<#identifier#> + do { 1 } + """, + experimentalFeatures: [.moduleSelector, .doExpressions] + ) assertParse( "let x = Swift::if1️⃣ y { 1 } 2️⃣else { 0 }", diagnostics: [ @@ -1798,6 +1831,19 @@ final class ModuleSelectorTests: ParserTestCase { y { 1 } else { 0 } """ ) + assertParse( + """ + let x = Swift::1️⃣ + if y { 1 } else { 0 } + """, + diagnostics: [ + DiagnosticSpec(message: "expected identifier in variable", fixIts: ["insert identifier"]) + ], + fixedSource: """ + let x = Swift::<#identifier#> + if y { 1 } else { 0 } + """ + ) assertParse( """ let x = Swift::switch1️⃣ y2️⃣ { @@ -1833,6 +1879,25 @@ final class ModuleSelectorTests: ParserTestCase { } """ ) + assertParse( + """ + let x = Swift::1️⃣ + switch y { + case true: 1 + case false: 0 + } + """, + diagnostics: [ + DiagnosticSpec(message: "expected identifier in variable", fixIts: ["insert identifier"]) + ], + fixedSource: """ + let x = Swift::<#identifier#> + switch y { + case true: 1 + case false: 0 + } + """ + ) assertParse( "fn(Swift::1️⃣&x)", diagnostics: [ @@ -1924,7 +1989,7 @@ final class ModuleSelectorTests: ParserTestCase { ) assertParse( "_ = Swift::self", - substructure: makeDeclRef(moduleSelector: "Swift", baseName: .keyword(.self)) + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "self") ) assertParse( "_ = Swift::init", @@ -1942,10 +2007,10 @@ final class ModuleSelectorTests: ParserTestCase { ) assertParse( "_ = Swift::Self", - substructure: makeDeclRef(moduleSelector: "Swift", baseName: .keyword(.`Self`)) + substructure: makeDeclRef(moduleSelector: "Swift", baseName: "Self") ) assertParse( - "_ = Swift::1️⃣Any", + "_ = Swift::Any", substructure: makeDeclRef(moduleSelector: "Swift", baseName: "Any") ) assertParse( @@ -2016,7 +2081,7 @@ final class ModuleSelectorTests: ParserTestCase { ) ) assertParse( - "_ = Swift::1️⃣super.foo()", + "_ = Swift::super.foo()", substructure: makeDeclRef(moduleSelector: "Swift", baseName: "super") ) assertParse( @@ -2055,31 +2120,28 @@ final class ModuleSelectorTests: ParserTestCase { ], fixedSource: "_ = x.Swift::<#identifier#>1" ) - // Diagnose in ASTGen? assertParse( - "_ = x.Swift::1️⃣self", + "_ = x.Swift::self", substructure: MemberAccessExprSyntax( base: makeDeclRef(baseName: "x"), declName: makeDeclRef( moduleSelector: "Swift", - baseName: .keyword(.`self`) + baseName: "self" ) ) ) assertParse( "_ = x.Swift::Self.self", - // FIXME: inconsistent with type syntax substructure: MemberAccessExprSyntax( base: MemberAccessExprSyntax( base: makeDeclRef(baseName: "x"), - declName: makeDeclRef(moduleSelector: "Swift", baseName: .keyword(.`Self`)) + declName: makeDeclRef(moduleSelector: "Swift", baseName: "Self") ), declName: makeDeclRef(baseName: .keyword(.`self`)) ) ) assertParse( "_ = x.Swift::Type.self", - // FIXME: inconsistent with type syntax substructure: MemberAccessExprSyntax( base: MemberAccessExprSyntax( base: makeDeclRef(baseName: "x"), @@ -2090,7 +2152,6 @@ final class ModuleSelectorTests: ParserTestCase { ) assertParse( "_ = x.Swift::Protocol.self", - // FIXME: inconsistent with type syntax substructure: MemberAccessExprSyntax( base: MemberAccessExprSyntax( base: makeDeclRef(baseName: "x"), @@ -2192,7 +2253,7 @@ final class ModuleSelectorTests: ParserTestCase { substructure: makeMember( of: makeType(name: "Foo"), moduleSelector: "Swift", - name: .keyword(.`self`) + name: "self" ) ) } From 8f4b13f7e5b2f78a8f773120f419c55bc2330183 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Tue, 12 Aug 2025 11:05:46 -0700 Subject: [PATCH 12/15] Add test cases for invalid submodule selectors And add newline-sensitive behavior matching other uses of module selectors. --- Sources/SwiftParser/Names.swift | 2 +- .../translated/ModuleSelectorTests.swift | 37 ++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Sources/SwiftParser/Names.swift b/Sources/SwiftParser/Names.swift index bf15c54febd..4e483638170 100644 --- a/Sources/SwiftParser/Names.swift +++ b/Sources/SwiftParser/Names.swift @@ -106,7 +106,7 @@ extension TokenConsumer { } var extra: [Token] = [] - while self.isAtModuleSelector() { + while !self.currentToken.isAtStartOfLine && self.isAtModuleSelector() { if !self.at(.colonColon) { extra.append(self.consumeAnyToken()) } diff --git a/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift index 7dd321decf7..b1c3e5bb2ec 100644 --- a/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift +++ b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -// This test file has been translated from swift/test/NameLookup/module_selector.swift +// This test file has been translated from swift/test/Parse/module_selector.swift @_spi(ExperimentalLanguageFeatures) import SwiftParser @_spi(ExperimentalLanguageFeatures) import SwiftSyntax @@ -2257,6 +2257,41 @@ final class ModuleSelectorTests: ParserTestCase { ) ) } + + func testModuleSelectorSubmodule() { + assertParse( + "_ = Foundation::1️⃣NSData::NSData()", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'NSData::' in module selector") + ] + ) + + assertParse( + "_ = Foundation::1️⃣NSData::Fnord::NSData()", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'NSData::Fnord::' in module selector") + ] + ) + + assertParse( + """ + _ = Foundation::1️⃣NSData::2️⃣ + Fnord::NSData() + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'NSData::' in module selector"), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected identifier", + fixIts: ["insert identifier"] + ), + ], + fixedSource: """ + _ = Foundation::NSData::<#identifier#> + Fnord::NSData() + """ + ) + } } // MARK: - Syntax tree construction helpers From 23e5a32c45f69ea23da0d6366c2e6b6587501e60 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Tue, 12 Aug 2025 12:06:57 -0700 Subject: [PATCH 13/15] Diagnose ObjC-style string literals at top level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both Swift parsers have always recognized `@"foo"` as an attempt to write a string literal by a programmer with Objective-C muscle memory, but some of SwiftParser’s lookahead helpers didn’t recognize that token sequence; instead they interpreted the `@` as the beginning of an attribute and therefore a missing declaration. Correct them. --- Sources/SwiftParser/Declarations.swift | 4 +++ Sources/SwiftParser/Expressions.swift | 4 +++ Tests/SwiftParserTest/ExpressionTests.swift | 25 +++++++++++++++++++ .../translated/ModuleSelectorTests.swift | 4 +-- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 2d78edfe9cf..97e2c3e2c8b 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -99,6 +99,10 @@ extension TokenConsumer { if subparser.at(.rightBrace) || subparser.at(.endOfFile) || subparser.at(.poundEndif) { return true } + if subparser.at(.stringQuote) { + // `@"abc"` is an invalid Objective-C-style string literal, not a declaration. + return false + } } let declStartKeyword: DeclarationKeyword? diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index a8dd6b96ee2..5fd9088e689 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -57,6 +57,10 @@ extension TokenConsumer { return true } } + if self.at(.atSign) && self.peek(isAt: .stringQuote) { + // Invalid Objective-C-style string literal + return true + } // 'repeat' is the start of a pack expansion expression. if self.at(.keyword(.repeat)) { diff --git a/Tests/SwiftParserTest/ExpressionTests.swift b/Tests/SwiftParserTest/ExpressionTests.swift index e47abffd938..791620ad652 100644 --- a/Tests/SwiftParserTest/ExpressionTests.swift +++ b/Tests/SwiftParserTest/ExpressionTests.swift @@ -1214,6 +1214,31 @@ final class ExpressionTests: ParserTestCase { DiagnosticSpec(message: "invalid escape sequence in literal") ] ) + + // QoI: Bad error message when using Objective-C literals (@"Hello") + assertParse( + """ + _ = 1️⃣@"a" + """, + diagnostics: [ + DiagnosticSpec(message: "string literals in Swift are not preceded by an '@' sign", fixIts: ["remove '@'"]) + ], + fixedSource: """ + _ = "a" + """ + ) + + assertParse( + """ + 1️⃣@"a" + """, + diagnostics: [ + DiagnosticSpec(message: "string literals in Swift are not preceded by an '@' sign", fixIts: ["remove '@'"]) + ], + fixedSource: """ + "a" + """ + ) } func testAdjacentRawStringLiterals() { diff --git a/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift index b1c3e5bb2ec..4e586e58953 100644 --- a/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift +++ b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift @@ -1957,9 +1957,9 @@ final class ModuleSelectorTests: ParserTestCase { #"_ = Swift::1️⃣@"fnord""#, diagnostics: [ DiagnosticSpec(message: "expected identifier", fixIts: ["insert identifier"]), - DiagnosticSpec(message: #"extraneous code '@"fnord"' at top level"#), + DiagnosticSpec(message: "string literals in Swift are not preceded by an '@' sign", fixIts: ["remove '@'"]), ], - fixedSource: #"_ = Swift::<#identifier#>@"fnord""# + fixedSource: #"_ = Swift::<#identifier#>"fnord""# ) assertParse( #"_ = Swift::1️⃣"fnord""#, From a817228e6ca3e92aac9592d648bd4b9495e362bd Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Tue, 12 Aug 2025 16:15:48 -0700 Subject: [PATCH 14/15] Work around SIL optimizer bug Building for release mode is triggering a SIL verifier failure related to memory management (the return value gets initialized twice). Force the affected function to be optimized for size rather than speed, which avoids the problem. --- Sources/SwiftParser/Names.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/SwiftParser/Names.swift b/Sources/SwiftParser/Names.swift index 4e483638170..3563fd412ee 100644 --- a/Sources/SwiftParser/Names.swift +++ b/Sources/SwiftParser/Names.swift @@ -84,6 +84,7 @@ extension TokenConsumer { /// - `extra`: Tokens for additional trailing module selectors. There is no situation in which two module selectors /// can be validly chained. /// - `skipQualifiedName`: True if the next token should be interpreted as a different statement. + @_optimize(size) // Work around SIL optimizer bug (rdar://158171994) mutating func consumeModuleSelectorTokensIfPresent() -> ( moduleNameOrUnexpected: Token, colonColonToken: Token, extra: [Token], skipQualifiedName: Bool )? { From 0a214ecc43ee95e9b09a1c21e5d9bc981d067380 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Thu, 14 Aug 2025 14:26:37 -0700 Subject: [PATCH 15/15] Work around another SIL optimizer bug rdar://158353230 occurrs while trying to build the CodeGeneration subpackage. --- CodeGeneration/Sources/SyntaxSupport/CompatibilityLayer.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/CodeGeneration/Sources/SyntaxSupport/CompatibilityLayer.swift b/CodeGeneration/Sources/SyntaxSupport/CompatibilityLayer.swift index fa1e2d26afa..ce70152e6e3 100644 --- a/CodeGeneration/Sources/SyntaxSupport/CompatibilityLayer.swift +++ b/CodeGeneration/Sources/SyntaxSupport/CompatibilityLayer.swift @@ -312,6 +312,7 @@ public struct DeprecatedMemberInfo { } } + @_optimize(none) // Workaround for SIL optimizer crash (rdar://158353230) private func firstIndexOfChild(named targetName: String) -> Int { guard let i = children.firstIndex(where: { $0.name == targetName }) else { fatalError(