diff --git a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift index 3347cf8bb41..92907db68b4 100644 --- a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift @@ -576,7 +576,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/CodeGeneration/Sources/SyntaxSupport/CommonNodes.swift b/CodeGeneration/Sources/SyntaxSupport/CommonNodes.swift index 7247e17a909..b5bcc0a7f87 100644 --- a/CodeGeneration/Sources/SyntaxSupport/CommonNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/CommonNodes.swift @@ -330,6 +330,24 @@ public let COMMON_NODES: [Node] = [ ] ), + Node( + kind: .moduleSelector, + base: .syntax, + 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/ExperimentalFeatures.swift b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift index aa36cd8ba53..a8837ed5b0b 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 inlineArrayTypeSugar + 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 .inlineArrayTypeSugar: return "InlineArrayTypeSugar" + case .moduleSelector: + return "ModuleSelector" } } @@ -68,6 +71,8 @@ public enum ExperimentalFeature: String, CaseIterable { return "`_move` and `_borrow` as ownership operators" case .inlineArrayTypeSugar: return "sugar type for InlineArray" + case .moduleSelector: + return "Module selector syntax (`ModName::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 6e50fe39500..ba76ed42402 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/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/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift index 3d65755fa45..d4f96b2e665 100644 --- a/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift @@ -355,6 +355,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)]), @@ -501,6 +508,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/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 c29fa786846..7119beea169 100644 --- a/Sources/SwiftParser/Attributes.swift +++ b/Sources/SwiftParser/Attributes.swift @@ -227,7 +227,11 @@ extension Parser { ) } - 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())) @@ -297,7 +301,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, @@ -322,7 +331,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, @@ -332,7 +343,9 @@ extension RawLabeledExprSyntax { label: nil, colon: nil, expression: RawDeclReferenceExprSyntax( - unexpectedBeforeIdentifier, + unexpectedBeforeModuleSelector, + moduleSelector: moduleSelector, + unexpectedBetweenModuleSelectorAndIdentifier, baseName: identifier, argumentNames: nil, arena: arena @@ -354,6 +367,7 @@ extension Parser { let roleTrailingComma = self.consume(if: .comma) let roleElement = RawLabeledExprSyntax( + moduleSelector: nil, unexpectedBeforeRole, identifier: role, trailingComma: roleTrailingComma, @@ -383,7 +397,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), @@ -524,8 +543,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), @@ -547,7 +571,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), @@ -602,8 +631,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, @@ -627,7 +656,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, @@ -654,7 +684,11 @@ extension Parser { case (.target, let handle)?: let label = self.eat(handle) let (unexpectedBeforeColon, colon) = self.expect(.colon) - let declName = self.parseDeclReferenceExpr([.zeroArgCompoundNames, .keywordsUsingSpecialNames, .operators]) + let moduleSelector = self.parseModuleSelector() + let declName = self.parseDeclReferenceExpr( + moduleSelector: moduleSelector, + [.zeroArgCompoundNames, .keywordsUsingSpecialNames, .operators] + ) let comma = self.consume(if: .comma) elements.append( .specializeTargetFunctionArgument( @@ -707,7 +741,7 @@ extension Parser { case (.kind, let handle)?: let label = self.eat(handle) let (unexpectedBeforeColon, colon) = self.expect(.colon) - let valueLabel = self.parseAnyIdentifier() + let (unexpectedBeforeValue, value) = self.parseAnyIdentifier() let comma = self.consume(if: .comma) elements.append( .labeledSpecializeArgument( @@ -715,7 +749,8 @@ extension Parser { label: label, unexpectedBeforeColon, colon: colon, - value: valueLabel, + unexpectedBeforeValue, + value: value, trailingComma: comma, arena: self.arena ) @@ -725,7 +760,7 @@ extension Parser { (.spi, let handle)?: let label = self.eat(handle) let (unexpectedBeforeColon, colon) = self.expect(.colon) - let valueLabel = self.consumeAnyToken() + let (unexpectedBeforeValue, value) = self.expectIdentifier() let comma = self.consume(if: .comma) elements.append( .labeledSpecializeArgument( @@ -733,7 +768,8 @@ extension Parser { label: label, unexpectedBeforeColon, colon: colon, - value: valueLabel, + unexpectedBeforeValue, + value: value, trailingComma: comma, arena: self.arena ) @@ -757,14 +793,17 @@ extension Parser { mutating func parseImplementsAttributeArguments() -> RawImplementsAttributeArgumentsSyntax { let type = self.parseType() let (unexpectedBeforeComma, comma) = self.expect(.comma) - let declName = self.parseDeclReferenceExpr([ - .zeroArgCompoundNames, - .operators, - ]) + + // You can't put a module selector on the member name--it's meaningless because the member has to come from the + // same module as the protocol. + let moduleSelector = self.parseModuleSelector() + let declName = self.parseDeclReferenceExpr(moduleSelector: nil, [.zeroArgCompoundNames, .operators]) + return RawImplementsAttributeArgumentsSyntax( type: type, unexpectedBeforeComma, comma: comma, + unexpected(moduleSelector), declName: declName, arena: self.arena ) @@ -776,6 +815,7 @@ extension Parser { let (unexpectedBeforeIsolationKind, isolationKind) = self.expectIdentifier(allowKeywordsAsIdentifier: true) let isolationKindElement = RawLabeledExprSyntax( + moduleSelector: nil, unexpectedBeforeIsolationKind, identifier: isolationKind, arena: self.arena @@ -903,17 +943,21 @@ extension Parser { mutating func parseDynamicReplacementAttributeArguments() -> RawDynamicReplacementAttributeArgumentsSyntax { let (unexpectedBeforeLabel, label) = self.expect(.keyword(.for)) let (unexpectedBeforeColon, colon) = self.expect(.colon) + 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 ) } else { - declName = self.parseDeclReferenceExpr([ - .zeroArgCompoundNames, .keywordsUsingSpecialNames, .operators, - ]) + let moduleSelector = self.parseModuleSelector() + declName = self.parseDeclReferenceExpr( + moduleSelector: moduleSelector, + [.zeroArgCompoundNames, .keywordsUsingSpecialNames, .operators] + ) } return RawDynamicReplacementAttributeArgumentsSyntax( unexpectedBeforeLabel, @@ -978,7 +1022,7 @@ extension Parser { unexpectedBeforeValue = unexpected value = .token(token) case "metadata": - unexpectedBeforeValue = nil + unexpectedBeforeValue = unexpected(self.parseModuleSelector()) if let identifier = self.consume(if: .identifier) { value = .token(identifier) } else { diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index a9e4a01f449..3f6220302dd 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -140,6 +140,8 @@ extension TokenConsumer { // Otherwise, parse it as an expression. return false + case .rhs(let introducer): + return subparser.shouldParsePatternBinding(introducer: introducer) case .some(_): // All other decl start keywords unconditionally start a decl. return true @@ -353,11 +355,12 @@ extension Parser { } if self.currentToken.isEditorPlaceholder { - let placeholder = self.parseAnyIdentifier() + let (unexpectedBeforePlaceholder, placeholder) = self.parseAnyIdentifier() return RawDeclSyntax( RawMissingDeclSyntax( attributes: attrs.attributes, modifiers: attrs.modifiers, + unexpectedBeforePlaceholder, placeholder: placeholder, arena: self.arena ) @@ -425,10 +428,11 @@ extension Parser { var keepGoing: RawTokenSyntax? = nil var loopProgress = LoopProgressCondition() repeat { - let name = self.parseAnyIdentifier() + let (unexpectedBeforeName, name) = self.parseAnyIdentifier() keepGoing = self.consume(if: .period) elements.append( RawImportPathComponentSyntax( + unexpectedBeforeName, name: name, trailingPeriod: keepGoing, arena: self.arena @@ -531,6 +535,7 @@ extension Parser { unexpectedBeforeInherited = RawUnexpectedNodesSyntax([classKeyword], arena: self.arena) inherited = RawTypeSyntax( RawIdentifierTypeSyntax( + moduleSelector: nil, name: missingToken(.identifier, text: "AnyObject"), genericArgumentClause: nil, arena: self.arena @@ -1229,7 +1234,7 @@ extension Parser { (unexpectedBeforeIdentifier, identifier) = self.expectIdentifier(keywordRecovery: true) if currentToken.isEditorPlaceholder { - let editorPlaceholder = self.parseAnyIdentifier() + let (_, editorPlaceholder) = self.parseAnyIdentifier() unexpectedAfterIdentifier = RawUnexpectedNodesSyntax([editorPlaceholder], arena: self.arena) } else { unexpectedAfterIdentifier = nil diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index 70e2a433f56..1e00f6f63ff 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.consumeModuleSelectorTokens() + return lookahead.atStartOfExpression() + } + switch self.at(anyIn: ExpressionStart.self) { case (.awaitTryMove, let handle)?: var lookahead = self.lookahead() @@ -572,6 +578,11 @@ extension Parser { flavor: ExprFlavor, pattern: PatternContext = .none ) -> RawExprSyntax { + if let moduleSelector = self.parseModuleSelector() { + let qualifiedExpr = self.parseUnaryExpression(flavor: flavor, pattern: pattern) + return attach(moduleSelector, to: qualifiedExpr) + } + // Try parse a single value statement as an expression (e.g do/if/switch). // Note we do this here in parseUnaryExpression as we don't allow postfix // syntax to be attached to such expressions to avoid ambiguities such as postfix @@ -652,6 +663,7 @@ extension Parser { if skipMemberName { let missingIdentifier = missingToken(.identifier) let declName = RawDeclReferenceExprSyntax( + moduleSelector: nil, baseName: missingIdentifier, argumentNames: nil, arena: self.arena @@ -659,18 +671,22 @@ extension Parser { return (unexpectedPeriod, period, declName, nil) } + let moduleSelector = parseModuleSelector() + // Parse the name portion. let declName: RawDeclReferenceExprSyntax if let indexOrSelf = self.consume(if: .integerLiteral, .keyword(.self)) { // Handle "x.42" - a tuple index. declName = RawDeclReferenceExprSyntax( + unexpected(moduleSelector), + moduleSelector: nil, baseName: indexOrSelf, argumentNames: nil, arena: self.arena ) } else { // Handle an arbitrary declaration name. - declName = self.parseDeclReferenceExpr([.keywords, .compoundNames]) + declName = self.parseDeclReferenceExpr(moduleSelector: moduleSelector, [.keywords, .compoundNames]) } // Parse the generic arguments, if any. @@ -1246,11 +1262,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) @@ -1276,6 +1292,7 @@ extension Parser { let poundAvailable = self.parsePoundAvailableConditionElement() return RawExprSyntax( RawDeclReferenceExprSyntax( + moduleSelector: nil, RawUnexpectedNodesSyntax([poundAvailable], arena: self.arena), baseName: missingToken(.identifier), argumentNames: nil, @@ -1313,7 +1330,10 @@ extension Parser { ) } - let declName = self.parseDeclReferenceExpr([.keywords, .compoundNames]) + // If there's a module selector after the period, parse and use it. + let moduleSelector = self.parseModuleSelector() + let declName = self.parseDeclReferenceExpr(moduleSelector: moduleSelector, [.keywords, .compoundNames]) + return RawExprSyntax( RawMemberAccessExprSyntax( base: nil, @@ -1351,7 +1371,8 @@ extension Parser { case .attributeArguments: options.insert(.keywordsUsingSpecialNames) } - let declName = self.parseDeclReferenceExpr(options) + // If something up the call stack has parsed a module selector, it will be attached using `attach(_:to:)`. + let declName = self.parseDeclReferenceExpr(moduleSelector: nil, options) guard self.withLookahead({ $0.canParseAsGenericArgumentList() }) else { return RawExprSyntax(declName) } @@ -1382,6 +1403,7 @@ extension Parser { ) pound = pound.tokenView.withTokenDiagnostic(tokenDiagnostic: diagnostic, arena: self.arena) } + let moduleSelector = parseModuleSelector() let unexpectedBeforeMacroName: RawUnexpectedNodesSyntax? let macroName: RawTokenSyntax if !self.atStartOfLine { @@ -1429,6 +1451,7 @@ extension Parser { return RawMacroExpansionExprSyntax( unexpectedBeforePound, pound: pound, + moduleSelector: moduleSelector, unexpectedBeforeMacroName, macroName: macroName, genericArgumentClause: generics, @@ -1742,7 +1765,9 @@ extension Parser { extension Parser { mutating func parseAnonymousClosureArgument() -> RawDeclReferenceExprSyntax { let (unexpectedBeforeBaseName, baseName) = self.expect(.dollarIdentifier) + // If something up the call stack has parsed a module selector, it will be attached using `attach(_:to:)`. return RawDeclReferenceExprSyntax( + moduleSelector: nil, unexpectedBeforeBaseName, baseName: baseName, argumentNames: nil, @@ -1874,14 +1899,7 @@ extension Parser { // Parse identifier (',' identifier)* var keepGoing: RawTokenSyntax? = nil repeat { - let unexpected: RawUnexpectedNodesSyntax? - let name: RawTokenSyntax - if let identifier = self.consume(if: .identifier) { - unexpected = nil - name = identifier - } else { - (unexpected, name) = self.expect(.wildcard) - } + let (unexpected, name) = self.expect(.identifier, .wildcard, default: .identifier) keepGoing = consume(if: .comma) params.append( RawClosureShorthandParameterSyntax( @@ -1964,6 +1982,14 @@ extension Parser { } } +extension TokenConsumer { + mutating func atBinaryOperatorArgument() -> Bool { + var lookahead = self.lookahead() + _ = lookahead.consumeModuleSelectorTokens() + return lookahead.at(.binaryOperator) && lookahead.peek(isAt: .comma, .rightParen, .rightSquare) + } +} + extension Parser { /// Parse the elements of an argument list. /// @@ -1998,7 +2024,7 @@ extension Parser { let unexpectedBeforeLabel: RawUnexpectedNodesSyntax? let label: RawTokenSyntax? let colon: RawTokenSyntax? - if self.atArgumentLabel(allowDollarIdentifier: true) && self.peek(isAt: .colon) { + if self.atArgumentLabel(allowDollarIdentifier: true, followedByColon: true) { (unexpectedBeforeLabel, label) = parseArgumentLabel() colon = consumeAnyToken() } else if let _colon = self.consume(if: .colon) { @@ -2015,8 +2041,9 @@ 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) { - expr = RawExprSyntax(self.parseDeclReferenceExpr(.operators)) + if self.atBinaryOperatorArgument() { + let moduleSelector = self.parseModuleSelector() + expr = RawExprSyntax(self.parseDeclReferenceExpr(moduleSelector: moduleSelector, .operators)) } else { expr = self.parseExpression(flavor: flavor, pattern: pattern) } @@ -2080,9 +2107,8 @@ extension Parser.Lookahead { // Fast path: the next two tokens must be a label and a colon. // But 'default:' is ambiguous with switch cases and we disallow it // (unless escaped) even outside of switches. - if !self.atArgumentLabel() + if !self.atArgumentLabel(followedByColon: true) || self.at(.keyword(.default)) - || self.peek().rawTokenKind != .colon { return false } @@ -2395,8 +2421,13 @@ extension Parser { unknownAttr = RawAttributeSyntax( atSign: at, - unexpectedBeforeIdent, - attributeName: RawIdentifierTypeSyntax(name: ident, genericArgumentClause: nil, arena: self.arena), + attributeName: RawIdentifierTypeSyntax( + moduleSelector: nil, + unexpectedBeforeIdent, + name: ident, + genericArgumentClause: nil, + arena: self.arena + ), leftParen: nil, arguments: nil, rightParen: nil, @@ -2577,6 +2608,7 @@ extension Parser.Lookahead { } } else if lookahead.at(.identifier) || lookahead.at(.wildcard) { // Parse identifier (',' identifier)* + _ = lookahead.consumeModuleSelectorTokens() lookahead.consumeAnyToken() /// If the next token is a colon, interpret is as a type annotation and consume a type after it. @@ -2593,6 +2625,7 @@ extension Parser.Lookahead { while consumeOptionalTypeAnnotation() && lookahead.consume(if: .comma) != nil && lookahead.hasProgressed(¶metersProgress) { + _ = lookahead.consumeModuleSelectorTokens() if lookahead.at(.identifier) || lookahead.at(.wildcard) { lookahead.consumeAnyToken() continue diff --git a/Sources/SwiftParser/Lexer/Cursor.swift b/Sources/SwiftParser/Lexer/Cursor.swift index 13d2af8c289..311367fef0e 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 @@ -940,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) == "!" { @@ -2460,7 +2471,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 } @@ -2476,13 +2487,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! @@ -2503,7 +2519,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/Lexer/RegexLiteralLexer.swift b/Sources/SwiftParser/Lexer/RegexLiteralLexer.swift index c5c565405cd..227b06a27b8 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/Names.swift b/Sources/SwiftParser/Names.swift index 3a9efe5878f..e05f6bd34a3 100644 --- a/Sources/SwiftParser/Names.swift +++ b/Sources/SwiftParser/Names.swift @@ -17,34 +17,315 @@ #endif extension Parser { - mutating func parseAnyIdentifier() -> RawTokenSyntax { + /// Parse an identifier or operator. + /// + /// - Note: If you expect a module selector, parse it before calling this method; it will consume module selectors + /// as unexpected syntax. + mutating func parseAnyIdentifier() -> (RawUnexpectedNodesSyntax?, RawTokenSyntax) { + let moduleSelector = unexpected(self.parseModuleSelector()) if let token = self.consume(if: .identifier) { - return token + return (moduleSelector, token) } else if let (_, handle) = self.at(anyIn: Operator.self) { - return self.eat(handle) + return (moduleSelector, self.eat(handle)) } else { - return RawTokenSyntax(missing: .identifier, arena: arena) + return (moduleSelector, RawTokenSyntax(missing: .identifier, arena: arena)) } } mutating func parseArgumentLabel() -> (RawUnexpectedNodesSyntax?, RawTokenSyntax) { + let unexpectedSelector = unexpected(self.parseModuleSelector()) guard self.atArgumentLabel(allowDollarIdentifier: true) else { - return (nil, missingToken(.identifier)) + return (unexpectedSelector, missingToken(.identifier)) } if let dollarIdent = self.consume(if: .dollarIdentifier) { return ( - RawUnexpectedNodesSyntax([dollarIdent], arena: self.arena), + RawUnexpectedNodesSyntax(combining: unexpectedSelector, dollarIdent, arena: self.arena), self.missingToken(.identifier) ) } else { if let wildcardToken = self.consume(if: .wildcard) { - return (nil, wildcardToken) + return (unexpectedSelector, wildcardToken) } - return (nil, self.consumeAnyToken(remapping: .identifier)) + return (unexpectedSelector, self.consumeAnyToken(remapping: .identifier)) } } } +private enum StructuralTokens: TokenSpecSet { + case comma + case colon + case leftParen + case leftBrace + case leftSquare + case leftAngle + case rightParen + case rightBrace + case rightSquare + case rightAngle + + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { + switch lexeme.rawTokenKind { + case .comma: self = .comma + case .colon: self = .colon + case .leftParen: self = .leftParen + case .leftBrace: self = .leftBrace + case .leftSquare: self = .leftSquare + case .leftAngle : self = .leftAngle + case .rightParen: self = .rightParen + case .rightBrace: self = .rightBrace + case .rightSquare: self = .rightSquare + case .rightAngle: self = .rightAngle + default: return nil + } + } + + var spec: TokenSpec { + switch self { + case .comma: return .comma + case .colon: return .colon + case .leftParen: return .leftParen + case .leftBrace: return .leftBrace + case .leftSquare: return .leftSquare + case .leftAngle: return .leftAngle + case .rightParen: return .rightParen + case .rightBrace: return .rightBrace + case .rightSquare: return .rightSquare + case .rightAngle: return .rightAngle + } + } +} + +extension TokenConsumer { + /// Do the subsequent tokens have the form of a module selector? Encompasses some invalid syntax which nonetheless + /// can be handled by `consumeModuleSelectorTokens()`. + /// + /// - 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 `::`. `consumeModuleSelectorTokens()` 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 (particularly keywords and `_`). However, we don't want to consume tokens which would make the + // surrounding structure mis-parse. + return self.at(anyIn: StructuralTokens.self) == nil + } + + 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 consumeModuleSelectorTokens() -> (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 parseModuleSelector() -> RawModuleSelectorSyntax? { + guard let (moduleNameOrUnexpected, colonColon, extra) = consumeModuleSelectorTokens() 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.init(missing: .identifier, arena: arena) + } + + trailingUnexpected = extra.map { RawSyntax($0) } + + return RawModuleSelectorSyntax( + RawUnexpectedNodesSyntax(elements: leadingUnexpected, arena: arena), + moduleName: moduleName, + colonColon: colonColon, + RawUnexpectedNodesSyntax(elements: trailingUnexpected, arena: arena), + arena: arena + ) + } + + /// Convert a raw syntax node to `RawUnexpectedNodesSyntax` by extracting its tokens. + func unexpected(_ node: (some RawSyntaxNodeProtocol)?) -> RawUnexpectedNodesSyntax? { + var tokens: [RawTokenSyntax] = [] + + func collect(from child: (some RawSyntaxNodeProtocol)?) { + guard let child else { return } + + guard let token = child.as(RawTokenSyntax.self) else { + for child in child.raw.layoutView!.children { + collect(from: child) + } + return + } + + if !token.isMissing { + tokens.append(token) + } + } + + collect(from: node) + + guard !tokens.isEmpty else { + return nil + } + return RawUnexpectedNodesSyntax(tokens, arena: self.arena) + } + + /// Inject `moduleSelector` into `node`, its first child, its first child's first child, etc. If necessary, + /// `moduleSelector`'s tokens will be inserted into an unexpected syntax node rather than the selector itself being + /// inserted. This should only be called when `node` comes *immediately* after `moduleSelector`. + /// + /// Use this method to "prepend" a module selector to a tree of syntax nodes. Doing so can avoid threading the module + /// selector through a lot of code, which can consume a lot of stack space and be fairly error-prone. + /// + /// - Precondition: `node` must, at minimum, have a descendant with an unexpected nodes child; it therefore cannot be + /// a token or an empty collection. + func attach(_ moduleSelector: RawModuleSelectorSyntax?, to node: Node) -> Node { + guard let moduleSelector else { + return node + } + + /// Recursively walk `node` and its descendants, looking for a place to attach `moduleSelector`. + /// + /// - Returns: `nil` if no suitable attachment point was found inside `node`; otherwise, a copy of `node` with + /// `moduleSelector` or its tokens injected somewhere. + func rewrite(attachingTo node: ChildNode) -> ChildNode? { + // If we hit a token, we won't be able to insert here. The parent will have to take care of it. + guard let layout = node.raw.layoutView else { + return nil + } + + /// Returns a copy of `node` with the child at `index` replaced by `newChild`. + func makeNode(withChildAt index: Int, replacedBy newChild: (some RawSyntaxNodeProtocol)?) -> ChildNode { + return layout.replacingChild( + at: index, with: newChild?.raw, arena: self.arena + ).cast(ChildNode.self) + } + + // Try to incorporate `self` into `node` or one of its children in a node-specific way. + switch node.raw.kind { + case .token: + fatalError("should have early returned") + + case .moduleSelector: + // Don't try to insert within a module selector. + return nil + + case .unexpectedNodes: + // We can just insert `self` here. + return RawUnexpectedNodesSyntax( + combining: unexpected(moduleSelector), node.cast(RawUnexpectedNodesSyntax.self), + arena: self.arena + )?.cast(ChildNode.self) + + case .declReferenceExpr, .identifierType: + // This node has an expected module selector at child 1. + let nodeUnexpectedBeforeModuleSelector = layout.children[0] + let nodeModuleSelector = layout.children[1] + + // If `node` doesn't already have a module selector or some unexpected syntax before one, attach + // `moduleSelector` there. + // + // Note: The `nodeModuleSelector` check here is defensive. It's probably impossible for only + // `nodeModuleSelector` to be non-nil because the `parseModuleSelector()` call that created `moduleSelector` + // should have consumed the tokens that would have gone into `nodeModuleSelector`. However, if it *does* turn + // out to be possible, we may want to insert `nodeModuleSelector` into + // `moduleSelector.unexpectedAfterColonColon` to get slightly nicer diagnostics. + if nodeUnexpectedBeforeModuleSelector == nil && nodeModuleSelector == nil { + return makeNode(withChildAt: 1, replacedBy: moduleSelector) + } + + default: + // Try to attach `moduleSelector` to the first suitable child. + func isInsertionPoint(_ child: RawSyntax?) -> Bool { + guard let child else { + return false + } + // Skip empty collections, but don't skip nodes with missing tokens (which are also `isEmpty`). + return !child.isEmpty || !child.kind.isSyntaxCollection + } + + if let childIndex = layout.children.firstIndex(where: isInsertionPoint(_:)), + let replacementChild = rewrite(attachingTo: layout.children[childIndex]!) { + return makeNode(withChildAt: childIndex, replacedBy: replacementChild) + } + } + + // Last chance: If this is *not* a collection, child 0 is unexpected nodes; we can put `moduleSelector` there. + if !node.raw.kind.isSyntaxCollection { + assert(layout.children[0] == nil) + return makeNode(withChildAt: 0, replacedBy: unexpected(moduleSelector)) + } + + // Out of options. + return nil + } + + guard let rewrittenNode = rewrite(attachingTo: node) else { + // We should *never* parse a module selector and then have nothing to attach it to; if there's a situation where + // we do, we should not have parsed it in the first place. + preconditionFailure( + """ + No way to attach module selector to node! + Module selector: \(String(reflecting: moduleSelector)) + Attachment point: \(String(reflecting: node)) + """ + ) + } + + return rewrittenNode + } +} + extension Parser { struct DeclNameOptions: OptionSet { var rawValue: UInt8 @@ -67,7 +348,7 @@ extension Parser { static let zeroArgCompoundNames: Self = [.compoundNames, Self(rawValue: 1 << 5)] } - mutating func parseDeclReferenceExpr(_ flags: DeclNameOptions = []) -> RawDeclReferenceExprSyntax { + mutating func parseDeclReferenceExpr(moduleSelector: RawModuleSelectorSyntax?, _ flags: DeclNameOptions = []) -> RawDeclReferenceExprSyntax { // Consume the base name. let base: RawTokenSyntax if let identOrSelf = self.consume(if: .identifier, .keyword(.self), .keyword(.Self)) @@ -89,6 +370,7 @@ extension Parser { // Parse an argument list, if the flags allow it and it's present. let args = self.parseArgLabelList(flags) return RawDeclReferenceExprSyntax( + moduleSelector: moduleSelector, baseName: base, argumentNames: args, arena: self.arena @@ -129,7 +411,7 @@ extension Parser { var loopProgress = LoopProgressCondition() while !self.at(.endOfFile, .rightParen) && self.hasProgressed(&loopProgress) { // Check to see if there is an argument label. - precondition(self.atArgumentLabel() && self.peek(isAt: .colon)) + precondition(self.atArgumentLabel(followedByColon: true)) let name = self.consumeAnyToken() let (unexpectedBeforeColon, colon) = self.expect(.colon) elements.append( @@ -167,11 +449,11 @@ extension Parser { period = nil } - let declName = self.parseDeclReferenceExpr([ - .zeroArgCompoundNames, - .keywordsUsingSpecialNames, - .operators, - ]) + let moduleSelector = self.parseModuleSelector() + let declName = self.parseDeclReferenceExpr( + moduleSelector: moduleSelector, + [.zeroArgCompoundNames, .keywordsUsingSpecialNames, .operators] + ) if let period = period { return RawExprSyntax( RawMemberAccessExprSyntax( @@ -187,41 +469,31 @@ extension Parser { } mutating func parseQualifiedTypeIdentifier() -> RawTypeSyntax { - if self.at(.keyword(.Any)) { - return RawTypeSyntax(self.parseAnyType()) - } + let moduleSelector = self.parseModuleSelector() + let identifierType = attach(moduleSelector, to: self.parseTypeIdentifier()) + var result = RawTypeSyntax(identifierType) - let (unexpectedBeforeName, name) = self.expect(anyIn: IdentifierTypeSyntax.NameOptions.self, default: .identifier) - let generics: RawGenericArgumentClauseSyntax? - if self.at(prefix: "<") { - generics = self.parseGenericArguments() - } else { - generics = nil + // There are no nested types inside `Any`. + if case TokenSpec.keyword(.Any) = identifierType.name { + return result } - var result = RawTypeSyntax( - RawIdentifierTypeSyntax( - 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 } var keepGoing = self.consume(if: .period) var loopProgress = LoopProgressCondition() while keepGoing != nil && self.hasProgressed(&loopProgress) { + let memberModuleSelector = self.parseModuleSelector() let (unexpectedBeforeName, name) = self.expect( .identifier, .keyword(.self), @@ -238,6 +510,7 @@ extension Parser { RawMemberTypeSyntax( baseType: result, period: keepGoing!, + moduleSelector: memberModuleSelector, unexpectedBeforeName, name: name, genericArgumentClause: generics, @@ -245,14 +518,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 } @@ -266,6 +532,7 @@ extension Parser { extension Parser.Lookahead { func canParseBaseTypeForQualifiedDeclName() -> Bool { var lookahead = self.lookahead() + _ = lookahead.consumeModuleSelectorTokens() guard lookahead.canParseTypeIdentifier() else { return false } @@ -283,7 +550,7 @@ extension Parser.Lookahead { var loopProgress = LoopProgressCondition() while !lookahead.at(.endOfFile, .rightParen) && lookahead.hasProgressed(&loopProgress) { // Check to see if there is an argument label. - guard lookahead.atArgumentLabel() && lookahead.peek().rawTokenKind == .colon else { + guard lookahead.atArgumentLabel(followedByColon: true) else { return false } diff --git a/Sources/SwiftParser/Parameters.swift b/Sources/SwiftParser/Parameters.swift index 1a40901237b..c8483db460c 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 @@ -297,16 +298,31 @@ extension Parser { // MARK: - Parameter Modifiers extension Parser { + mutating func canParseParameterModifier() -> Bool { + var lookahead = self.lookahead() + _ = lookahead.consumeModuleSelectorTokens() + return lookahead.at(anyIn: ParameterModifier.self) != nil + } + mutating func parseParameterModifiers(isClosure: Bool) -> RawDeclModifierListSyntax { var elements = [RawDeclModifierSyntax]() var loopProgress = LoopProgressCondition() while self.hasProgressed(&loopProgress) { - guard let match = self.at(anyIn: ParameterModifier.self), + + guard self.canParseParameterModifier(), !withLookahead({ $0.startsParameterName(isClosure: isClosure, allowMisplacedSpecifierRecovery: false) }) else { break } - elements.append(RawDeclModifierSyntax(name: self.eat(match.handle), detail: nil, arena: self.arena)) + let moduleSelector = self.parseModuleSelector() + elements.append( + RawDeclModifierSyntax( + unexpected(moduleSelector), + name: self.eat(self.at(anyIn: ParameterModifier.self)!.handle), + detail: nil, + arena: self.arena + ) + ) } if elements.isEmpty { return self.emptyCollection(RawDeclModifierListSyntax.self) diff --git a/Sources/SwiftParser/Parser.swift b/Sources/SwiftParser/Parser.swift index 6d6e8b37cb3..10ea9b68f3a 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) @@ -556,19 +560,21 @@ extension Parser { /// Implements the paradigm shared across all `expect` methods. @inline(__always) private mutating func expectImpl( + skipUnexpectedModuleSelector: Bool = true, consume: (inout Parser) -> RawTokenSyntax?, canRecoverTo: (inout Lookahead) -> RecoveryConsumptionHandle?, makeMissing: (inout Parser) -> RawTokenSyntax ) -> (unexpected: RawUnexpectedNodesSyntax?, token: RawTokenSyntax) { + let unexpectedSelector = skipUnexpectedModuleSelector ? unexpected(self.parseModuleSelector()) : nil if let tok = consume(&self) { - return (nil, tok) + return (unexpectedSelector, tok) } var lookahead = self.lookahead() if let handle = canRecoverTo(&lookahead) { let (unexpectedTokens, token) = self.eat(handle) - return (unexpectedTokens, token) + return (RawUnexpectedNodesSyntax(combining: unexpectedSelector, unexpectedTokens, arena: self.arena), token) } - return (nil, makeMissing(&self)) + return (unexpectedSelector, makeMissing(&self)) } /// Attempts to consume a token that matches the given `spec`. @@ -577,6 +583,8 @@ extension Parser { /// specified by `spec` 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. + /// - Note: If you expect a module selector, parse it before calling this method; it will consume module selectors + /// as unexpected syntax. @inline(__always) mutating func expect( _ spec: TokenSpec @@ -595,6 +603,8 @@ extension Parser { /// kinds occurs after the unexpected. /// 2. If the token couldn't be found after skipping unexpected, it synthesizes /// a missing token of `defaultKind`. + /// - Note: If you expect a module selector, parse it before calling this method; it will consume module selectors + /// as unexpected syntax. @inline(__always) mutating func expect( _ spec1: TokenSpec, @@ -615,6 +625,8 @@ extension Parser { /// kinds occurs after the unexpected. /// 2. If the token couldn't be found after skipping unexpected, it synthesizes /// a missing token of `defaultKind`. + /// - Note: If you expect a module selector, parse it before calling this method; it will consume module selectors + /// as unexpected syntax. @inline(__always) mutating func expect( _ spec1: TokenSpec, @@ -629,6 +641,15 @@ extension Parser { ) } + /// Attempts to consume a token that matches the given `specSet`. + /// If it cannot be found, the parser tries + /// 1. To eat unexpected tokens that have lower ``TokenPrecedence`` than the + /// lowest precedence of the spec and see if a token of the requested + /// kinds occurs after the unexpected. + /// 2. If the token couldn't be found after skipping unexpected, it synthesizes + /// a missing token of `defaultKind`. + /// - Note: If you expect a module selector, parse it before calling this method; it will consume module selectors + /// as unexpected syntax. @inline(__always) mutating func expect( anyIn specSet: SpecSet.Type, @@ -641,6 +662,29 @@ 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. + /// - Note: If you expect a module selector, parse it before calling this method; it will consume module selectors + /// as unexpected syntax (except when used to split a colon). + @inline(__always) + mutating func expect( + prefix: SyntaxText, as tokenKind: RawTokenKind + ) -> (unexpected: RawUnexpectedNodesSyntax?, token: RawTokenSyntax) { + let spec = TokenSpec(tokenKind) + return expectImpl( + // Don't consume a .colonColon if we're trying to split it + skipUnexpectedModuleSelector: !prefix.hasPrefix(":"), + 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. @@ -668,16 +712,20 @@ extension Parser { /// to and identifier. /// - Returns: The consumed token and any unexpected tokens that were skipped. /// The token is always guaranteed to be of `TokenKind.identifier` + /// - Note: If you expect a module selector, parse it before calling this method; it will consume module selectors + /// as unexpected syntax. mutating func expectIdentifier( keywordRecovery: Bool = false, allowSelfOrCapitalSelfAsIdentifier: Bool = false, allowKeywordsAsIdentifier: Bool = false ) -> (RawUnexpectedNodesSyntax?, RawTokenSyntax) { + let unexpectedSelector = unexpected(self.parseModuleSelector()) + if let identifier = self.consume(if: .identifier) { - return (nil, identifier) + return (unexpectedSelector, identifier) } if allowKeywordsAsIdentifier, self.currentToken.isLexerClassifiedKeyword { - return (nil, self.consumeAnyToken(remapping: .identifier)) + return (unexpectedSelector, self.consumeAnyToken(remapping: .identifier)) } if allowSelfOrCapitalSelfAsIdentifier, let selfOrCapitalSelf = self.consume( @@ -685,17 +733,17 @@ extension Parser { TokenSpec(.Self, remapping: .identifier) ) { - return (nil, selfOrCapitalSelf) + return (unexpectedSelector, selfOrCapitalSelf) } if let unknown = self.consume(if: .unknown) { return ( - RawUnexpectedNodesSyntax([unknown], arena: self.arena), + RawUnexpectedNodesSyntax(combining: unexpectedSelector, unknown, arena: self.arena), self.missingToken(.identifier) ) } if let number = self.consume(if: .integerLiteral, .floatLiteral, .dollarIdentifier) { return ( - RawUnexpectedNodesSyntax([number], arena: self.arena), + RawUnexpectedNodesSyntax(combining: unexpectedSelector, number, arena: self.arena), self.missingToken(.identifier) ) } else if keywordRecovery, @@ -704,12 +752,12 @@ extension Parser { { let keyword = self.consumeAnyToken() return ( - RawUnexpectedNodesSyntax([keyword], arena: self.arena), + RawUnexpectedNodesSyntax(combining: unexpectedSelector, keyword, arena: self.arena), self.missingToken(.identifier) ) } return ( - nil, + unexpectedSelector, self.missingToken(.identifier) ) } diff --git a/Sources/SwiftParser/Patterns.swift b/Sources/SwiftParser/Patterns.swift index b58d68e51b0..063eb07377c 100644 --- a/Sources/SwiftParser/Patterns.swift +++ b/Sources/SwiftParser/Patterns.swift @@ -19,6 +19,10 @@ extension Parser { /// Parse a pattern. mutating func parsePattern() -> RawPatternSyntax { + if let moduleSelector = self.parseModuleSelector() { + return attach(moduleSelector, to: self.parsePattern()) + } + enum PatternOnlyExpectedTokens: TokenSpecSet { case leftParen case wildcard @@ -272,14 +276,19 @@ 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 + // Other keywords can be parsed *almost* unconditionally. + return !isAtModuleSelector() } } mutating func canParsePattern() -> Bool { + _ = self.consumeModuleSelectorTokens() + enum PurePatternStartTokens: TokenSpecSet { case identifier case wildcard @@ -359,7 +368,9 @@ extension Parser.Lookahead { } // If the next token is ':', this is a name. - let nextTok = self.peek() + var lookahead = self.lookahead() + _ = lookahead.consumeModuleSelectorTokens() + let nextTok = lookahead.peek() if nextTok.rawTokenKind == .colon { return true } @@ -367,17 +378,17 @@ extension Parser.Lookahead { // If the next token can be an argument label, we might have a name. if nextTok.isArgumentLabel(allowDollarIdentifier: true) { // If the first name wasn't a contextual keyword, we're done. - if !self.at(.keyword(.isolated)) - && !self.at(.keyword(.some)) - && !self.at(.keyword(.any)) - && !self.at(.keyword(.each)) - && !self.at(.keyword(.repeat)) - && !self.at(.keyword(.__shared)) - && !self.at(.keyword(.__owned)) - && !self.at(.keyword(._const)) - && !self.at(.keyword(.borrowing)) - && !self.at(.keyword(.consuming)) - && !self.at(.keyword(.sending)) + if !lookahead.at(.keyword(.isolated)) + && !lookahead.at(.keyword(.some)) + && !lookahead.at(.keyword(.any)) + && !lookahead.at(.keyword(.each)) + && !lookahead.at(.keyword(.repeat)) + && !lookahead.at(.keyword(.__shared)) + && !lookahead.at(.keyword(.__owned)) + && !lookahead.at(.keyword(._const)) + && !lookahead.at(.keyword(.borrowing)) + && !lookahead.at(.keyword(.consuming)) + && !lookahead.at(.keyword(.sending)) { return true } @@ -386,11 +397,11 @@ extension Parser.Lookahead { // so look ahead one more token (two total) see if we have a ':' that would // indicate that this is an argument label. do { - if self.at(.colon) { + if lookahead.at(.colon) { return true // isolated : } self.consumeAnyToken() - return self.atArgumentLabel(allowDollarIdentifier: true) && self.peek().rawTokenKind == .colon + return self.atArgumentLabel(allowDollarIdentifier: true, followedByColon: true) } } diff --git a/Sources/SwiftParser/Statements.swift b/Sources/SwiftParser/Statements.swift index b6834a69af5..474ee8f0008 100644 --- a/Sources/SwiftParser/Statements.swift +++ b/Sources/SwiftParser/Statements.swift @@ -209,6 +209,11 @@ extension Parser { /// /// `lastBindingKind` will be used to get a correct fall back, when there is missing `var` or `let` in a `if` statement etc. mutating func parseConditionElement(lastBindingKind: RawTokenSyntax?) -> RawConditionElementSyntax.Condition { + // Module selectors aren't allowed here except on expressions, but we recover better if we parse them early. + if let moduleSelector = self.parseModuleSelector() { + return attach(moduleSelector, to: self.parseConditionElement(lastBindingKind: lastBindingKind)) + } + // Parse a leading #available/#unavailable condition if present. if self.at(.poundAvailable, .poundUnavailable) { return self.parsePoundAvailableConditionElement() @@ -969,6 +974,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/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/TokenConsumer.swift b/Sources/SwiftParser/TokenConsumer.swift index 2a603b77ae1..b5e9cfcfd92 100644 --- a/Sources/SwiftParser/TokenConsumer.swift +++ b/Sources/SwiftParser/TokenConsumer.swift @@ -387,7 +387,12 @@ extension TokenConsumer { } /// Whether the current token can be a function argument label. - func atArgumentLabel(allowDollarIdentifier: Bool = false) -> Bool { - return self.currentToken.isArgumentLabel(allowDollarIdentifier: allowDollarIdentifier) + mutating func atArgumentLabel(allowDollarIdentifier: Bool = false, followedByColon: Bool = false) -> Bool { + var lookahead = self.lookahead() + _ = lookahead.consumeModuleSelectorTokens() + guard lookahead.currentToken.isArgumentLabel(allowDollarIdentifier: allowDollarIdentifier) else { + return false + } + return !followedByColon || lookahead.peek(isAt: .colon) } } diff --git a/Sources/SwiftParser/TokenPrecedence.swift b/Sources/SwiftParser/TokenPrecedence.swift index 01fdbc06f78..6192e21c1e0 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/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/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 67c7604ce0f..0d1efc565d0 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -19,6 +19,10 @@ extension Parser { /// Parse a type. mutating func parseType(misplacedSpecifiers: [RawTokenSyntax] = []) -> RawTypeSyntax { + if let moduleSelector = self.parseModuleSelector() { + return attach(moduleSelector, to: self.parseType(misplacedSpecifiers: misplacedSpecifiers)) + } + // Parse pack expansion 'repeat T'. if let repeatKeyword = self.consume(if: .keyword(.repeat)) { let repetitionPattern = self.parseTypeScalar(misplacedSpecifiers: misplacedSpecifiers) @@ -35,6 +39,10 @@ extension Parser { } mutating func parseTypeScalar(misplacedSpecifiers: [RawTokenSyntax] = []) -> RawTypeSyntax { + if let moduleSelector = self.parseModuleSelector() { + return attach(moduleSelector, to: self.parseTypeScalar(misplacedSpecifiers: misplacedSpecifiers)) + } + let specifiersAndAttributes = self.parseTypeAttributeList(misplacedSpecifiers: misplacedSpecifiers) var base = self.parseSimpleOrCompositionType() if self.withLookahead({ $0.canParseFunctionTypeArrow() }) { @@ -111,6 +119,10 @@ extension Parser { /// Parse a protocol composition involving at least one element. mutating func parseSimpleOrCompositionType() -> RawTypeSyntax { + if let moduleSelector = self.parseModuleSelector() { + return attach(moduleSelector, to: self.parseSimpleOrCompositionType()) + } + // 'each' is a contextual keyword for a pack reference. if let each = consume(if: .keyword(.each)) { let packType = parseSimpleType() @@ -194,6 +206,32 @@ extension Parser { 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 { + if let moduleSelector = self.parseModuleSelector() { + let qualifiedType = parseUnsuppressedSimpleType( + allowMemberTypes: allowMemberTypes, forAttributeName: forAttributeName + ) + return attach(moduleSelector, to: qualifiedType) + } + enum TypeBaseStart: TokenSpecSet { case `Self` case `Any` @@ -226,27 +264,10 @@ 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: - base = self.parseTypeIdentifier() + base = RawTypeSyntax(self.parseTypeIdentifier()) case .leftParen: base = RawTypeSyntax(self.parseTupleTypeBody()) case .leftSquare: @@ -254,7 +275,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() @@ -268,19 +289,24 @@ extension Parser { baseType: base, unexpectedPeriod, period: period, + moduleSelector: nil, name: missingIdentifier, genericArgumentClause: nil, arena: self.arena ) ) break - } else if self.at(.keyword(.Type)) || self.at(.keyword(.Protocol)) { + } + + let memberModuleSelector = self.parseModuleSelector() + if self.at(.keyword(.Type)) || self.at(.keyword(.Protocol)) { let metatypeSpecifier = self.consume(if: .keyword(.Type)) ?? self.consume(if: .keyword(.Protocol))! base = RawTypeSyntax( RawMetatypeTypeSyntax( baseType: base, unexpectedPeriod, period: period, + unexpected(memberModuleSelector), metatypeSpecifier: metatypeSpecifier, arena: self.arena ) @@ -305,6 +331,7 @@ extension Parser { baseType: base, unexpectedPeriod, period: period, + moduleSelector: memberModuleSelector, name: name, genericArgumentClause: generics, arena: self.arena @@ -331,8 +358,6 @@ extension Parser { break } - base = wrapInTilde(base) - return base } @@ -361,9 +386,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) @@ -374,13 +399,13 @@ extension Parser { generics = nil } - return RawTypeSyntax( - RawIdentifierTypeSyntax( - unexpectedBeforeName, - name: name, - genericArgumentClause: generics, - arena: self.arena - ) + return RawIdentifierTypeSyntax( + // Will be attached by caller if present. + moduleSelector: nil, + unexpectedBeforeName, + name: name, + genericArgumentClause: generics, + arena: self.arena ) } @@ -388,6 +413,7 @@ extension Parser { mutating func parseAnyType() -> RawIdentifierTypeSyntax { let (unexpectedBeforeName, name) = self.expect(.keyword(.Any)) return RawIdentifierTypeSyntax( + moduleSelector: nil, unexpectedBeforeName, name: name, genericArgumentClause: nil, @@ -399,6 +425,7 @@ extension Parser { mutating func parsePlaceholderType() -> RawIdentifierTypeSyntax { let (unexpectedBeforeName, name) = self.expect(.wildcard) return RawIdentifierTypeSyntax( + moduleSelector: nil, unexpectedBeforeName, name: name, genericArgumentClause: nil, @@ -496,7 +523,7 @@ extension Parser { second = nil unexpectedBeforeColon = nil colon = parsedColon - } else if self.atArgumentLabel(allowDollarIdentifier: true) && self.peek(isAt: .colon) { + } else if self.atArgumentLabel(allowDollarIdentifier: true, followedByColon: true) { (unexpectedBeforeSecond, second) = self.parseArgumentLabel() (unexpectedBeforeColon, colon) = self.expect(.colon) } else { @@ -529,7 +556,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 @@ -1281,7 +1313,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 @@ -1308,9 +1344,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( @@ -1327,6 +1361,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( diff --git a/Sources/SwiftParser/generated/ExperimentalFeatures.swift b/Sources/SwiftParser/generated/ExperimentalFeatures.swift index 9513b06aac7..b809fa19046 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 sugar type for InlineArray. public static let inlineArrayTypeSugar = 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 "InlineArrayTypeSugar": self = .inlineArrayTypeSugar + 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/ParseDiagnosticsGenerator.swift b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift index 20b7c7702fd..0a12c61979d 100644 --- a/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift +++ b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift @@ -1085,53 +1085,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/SyntaxExtensions.swift b/Sources/SwiftParserDiagnostics/SyntaxExtensions.swift index 3dc0aa8e82b..07be44e5766 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/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 9a9d00393e7..92af65110ee 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: @@ -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/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/Documentation.docc/generated/SwiftSyntax.md b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md index ee9216345d3..2fcd74ec841 100644 --- a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md +++ b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md @@ -359,6 +359,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code. - - - +- - - - diff --git a/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift b/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift index a7333a7838d..29ea8474c2c 100644 --- a/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift +++ b/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift @@ -190,6 +190,18 @@ extension DeclGroupSyntax { } } +extension DeclReferenceExprSyntax { + @available(*, deprecated, renamed: "unexpectedBetweenModuleSelectorAndBaseName") + public var unexpectedBeforeBaseName: UnexpectedNodesSyntax? { + get { + return unexpectedBetweenModuleSelectorAndBaseName + } + set(value) { + unexpectedBetweenModuleSelectorAndBaseName = value + } + } +} + extension ClosureCaptureSyntax { @available(*, deprecated, renamed: "unexpectedBetweenNameAndInitializer") public var unexpectedBetweenNameAndAssignToken: UnexpectedNodesSyntax? { @@ -683,6 +695,18 @@ extension GenericRequirementSyntax { @available(*, deprecated, renamed: "NamedDeclSyntax") public typealias IdentifiedDeclSyntax = NamedDeclSyntax +extension IdentifierTypeSyntax { + @available(*, deprecated, renamed: "unexpectedBetweenModuleSelectorAndName") + public var unexpectedBeforeName: UnexpectedNodesSyntax? { + get { + return unexpectedBetweenModuleSelectorAndName + } + set(value) { + unexpectedBetweenModuleSelectorAndName = value + } + } +} + extension KeyPathPropertyComponentSyntax { @available(*, deprecated, renamed: "declName.baseName") public var identifier: TokenSyntax { @@ -705,6 +729,30 @@ extension KeyPathPropertyComponentSyntax { } } +extension MacroExpansionExprSyntax { + @available(*, deprecated, renamed: "unexpectedBetweenModuleSelectorAndMacroName") + public var unexpectedBetweenPoundAndMacroName: UnexpectedNodesSyntax? { + get { + return unexpectedBetweenModuleSelectorAndMacroName + } + set(value) { + unexpectedBetweenModuleSelectorAndMacroName = value + } + } +} + +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 802b6ae8003..a97d4cf5f92 100644 --- a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift +++ b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift @@ -820,8 +820,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: @@ -1648,8 +1652,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: @@ -2168,8 +2176,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: @@ -2272,8 +2284,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: @@ -2340,6 +2356,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..7bc167b9d48 100644 --- a/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift +++ b/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift @@ -1473,13 +1473,13 @@ extension ConsumeExprSyntax { } extension DeclReferenceExprSyntax { - @available(*, deprecated, renamed: "unexpectedBeforeBaseName") - public var unexpectedBeforeIdentifier: UnexpectedNodesSyntax? { + @available(*, deprecated, renamed: "unexpectedBetweenModuleSelectorAndBaseName") + public var unexpectedBetweenModuleSelectorAndIdentifier: UnexpectedNodesSyntax? { get { - return unexpectedBeforeBaseName + return unexpectedBetweenModuleSelectorAndBaseName } set { - unexpectedBeforeBaseName = newValue + unexpectedBetweenModuleSelectorAndBaseName = newValue } } @@ -1523,11 +1523,13 @@ extension DeclReferenceExprSyntax { } } - @available(*, deprecated, renamed: "init(leadingTrivia:_:baseName:_:argumentNames:_:trailingTrivia:)") + @available(*, deprecated, renamed: "init(leadingTrivia:_:moduleSelector:_:baseName:_:argumentNames:_:trailingTrivia:)") @_disfavoredOverload public init( leadingTrivia: Trivia? = nil, - _ unexpectedBeforeIdentifier: UnexpectedNodesSyntax? = nil, + _ unexpectedBeforeModuleSelector: UnexpectedNodesSyntax? = nil, + moduleSelector: ModuleSelectorSyntax? = nil, + _ unexpectedBetweenModuleSelectorAndIdentifier: UnexpectedNodesSyntax? = nil, identifier: TokenSyntax, _ unexpectedBetweenIdentifierAndDeclNameArguments: UnexpectedNodesSyntax? = nil, declNameArguments: DeclNameArgumentsSyntax? = nil, @@ -1536,7 +1538,9 @@ extension DeclReferenceExprSyntax { ) { self.init( leadingTrivia: leadingTrivia, - unexpectedBeforeIdentifier, + unexpectedBeforeModuleSelector, + moduleSelector: moduleSelector, + unexpectedBetweenModuleSelectorAndIdentifier, baseName: identifier, unexpectedBetweenIdentifierAndDeclNameArguments, argumentNames: declNameArguments, @@ -4823,13 +4827,23 @@ extension MacroExpansionExprSyntax { } } - @available(*, deprecated, renamed: "unexpectedBetweenPoundAndMacroName") - public var unexpectedBetweenPoundTokenAndMacro: UnexpectedNodesSyntax? { + @available(*, deprecated, renamed: "unexpectedBetweenPoundAndModuleSelector") + public var unexpectedBetweenPoundTokenAndModuleSelector: UnexpectedNodesSyntax? { get { - return unexpectedBetweenPoundAndMacroName + return unexpectedBetweenPoundAndModuleSelector } set { - unexpectedBetweenPoundAndMacroName = newValue + unexpectedBetweenPoundAndModuleSelector = newValue + } + } + + @available(*, deprecated, renamed: "unexpectedBetweenModuleSelectorAndMacroName") + public var unexpectedBetweenModuleSelectorAndMacro: UnexpectedNodesSyntax? { + get { + return unexpectedBetweenModuleSelectorAndMacroName + } + set { + unexpectedBetweenModuleSelectorAndMacroName = newValue } } @@ -4903,13 +4917,15 @@ extension MacroExpansionExprSyntax { } } - @available(*, deprecated, renamed: "init(leadingTrivia:_:pound:_:macroName:_:genericArgumentClause:_:leftParen:_:arguments:_:rightParen:_:trailingClosure:_:additionalTrailingClosures:_:trailingTrivia:)") + @available(*, deprecated, renamed: "init(leadingTrivia:_:pound:_:moduleSelector:_:macroName:_:genericArgumentClause:_:leftParen:_:arguments:_:rightParen:_:trailingClosure:_:additionalTrailingClosures:_:trailingTrivia:)") @_disfavoredOverload public init( leadingTrivia: Trivia? = nil, _ unexpectedBeforePoundToken: UnexpectedNodesSyntax? = nil, poundToken: TokenSyntax = .poundToken(), - _ unexpectedBetweenPoundTokenAndMacro: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenPoundTokenAndModuleSelector: UnexpectedNodesSyntax? = nil, + moduleSelector: ModuleSelectorSyntax? = nil, + _ unexpectedBetweenModuleSelectorAndMacro: UnexpectedNodesSyntax? = nil, macro: TokenSyntax, _ unexpectedBetweenMacroAndGenericArguments: UnexpectedNodesSyntax? = nil, genericArguments: GenericArgumentClauseSyntax? = nil, @@ -4930,7 +4946,9 @@ extension MacroExpansionExprSyntax { leadingTrivia: leadingTrivia, unexpectedBeforePoundToken, pound: poundToken, - unexpectedBetweenPoundTokenAndMacro, + unexpectedBetweenPoundTokenAndModuleSelector, + moduleSelector: moduleSelector, + unexpectedBetweenModuleSelectorAndMacro, macroName: macro, unexpectedBetweenMacroAndGenericArguments, genericArgumentClause: genericArguments, diff --git a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift index 761e69e41d9..aebe7fc1a6c 100644 --- a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift @@ -1551,6 +1551,14 @@ open class SyntaxAnyVisitor: SyntaxVisitor { visitAnyPost(node._syntaxNode) } + override open func visit(_ node: ModuleSelectorSyntax) -> SyntaxVisitorContinueKind { + return visitAny(node._syntaxNode) + } + + 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 8c1a8444f88..60e8dabc81c 100644 --- a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift +++ b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift @@ -1695,6 +1695,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 5f70ddd32a8..5a4769b1258 100644 --- a/Sources/SwiftSyntax/generated/SyntaxEnum.swift +++ b/Sources/SwiftSyntax/generated/SyntaxEnum.swift @@ -211,6 +211,7 @@ public enum SyntaxEnum: Sendable { case missingStmt(MissingStmtSyntax) case missing(MissingSyntax) case missingType(MissingTypeSyntax) + case moduleSelector(ModuleSelectorSyntax) case multipleTrailingClosureElementList(MultipleTrailingClosureElementListSyntax) case multipleTrailingClosureElement(MultipleTrailingClosureElementSyntax) case namedOpaqueReturnType(NamedOpaqueReturnTypeSyntax) @@ -692,6 +693,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 f1d00716562..8e26ce98440 100644 --- a/Sources/SwiftSyntax/generated/SyntaxKind.swift +++ b/Sources/SwiftSyntax/generated/SyntaxKind.swift @@ -211,6 +211,7 @@ public enum SyntaxKind: Sendable { case missingStmt case missing case missingType + case moduleSelector case multipleTrailingClosureElementList case multipleTrailingClosureElement case namedOpaqueReturnType @@ -817,6 +818,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 06778189fb7..1849d6dec0e 100644 --- a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift +++ b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift @@ -1398,6 +1398,13 @@ 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 + 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 @@ -3087,6 +3094,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))) @@ -4003,6 +4015,8 @@ open class SyntaxRewriter { return self.visitMissingSyntaxImpl(_:) case .missingType: return self.visitMissingTypeSyntaxImpl(_:) + case .moduleSelector: + return self.visitModuleSelectorSyntaxImpl(_:) case .multipleTrailingClosureElementList: return self.visitMultipleTrailingClosureElementListSyntaxImpl(_:) case .multipleTrailingClosureElement: @@ -4589,6 +4603,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/SyntaxVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift index d600655152f..0d06961ef3c 100644 --- a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift @@ -2265,6 +2265,18 @@ open class SyntaxVisitor { open func visitPost(_ node: MissingTypeSyntax) { } + /// Visiting ``ModuleSelectorSyntax`` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: how should we continue visiting. + open func visit(_ node: ModuleSelectorSyntax) -> SyntaxVisitorContinueKind { + return .visitChildren + } + + /// The function called after visiting ``ModuleSelectorSyntax`` and its descendants. + /// - node: the node we just finished visiting. + open func visitPost(_ node: ModuleSelectorSyntax) { + } + /// Visiting ``MultipleTrailingClosureElementListSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: how should we continue visiting. @@ -5006,6 +5018,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 { @@ -6234,6 +6254,8 @@ open class SyntaxVisitor { return self.visitMissingSyntaxImpl(_:) case .missingType: return self.visitMissingTypeSyntaxImpl(_:) + case .moduleSelector: + return self.visitModuleSelectorSyntaxImpl(_:) case .multipleTrailingClosureElementList: return self.visitMultipleTrailingClosureElementListSyntaxImpl(_:) case .multipleTrailingClosureElement: @@ -6820,6 +6842,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/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/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesD.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesD.swift index d9f5b337aea..27b9dc9578d 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 dfe5fc4d0e6..98dd27f0db7 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..442c95bcbce 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesJKLMN.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesJKLMN.swift @@ -1591,7 +1591,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 +1611,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 +1644,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 +2196,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 +2206,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 +2239,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 +2722,76 @@ public struct RawMissingTypeSyntax: RawTypeSyntaxNodeProtocol { } } +@_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 0ca5359f6e7..0798917da05 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -913,9 +913,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"), @@ -926,9 +928,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) @@ -1563,17 +1565,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() { @@ -1987,24 +1991,26 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 20, verify(layout[20], 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) @@ -2060,16 +2066,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) @@ -2121,6 +2129,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)) @@ -3498,6 +3514,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..4b77d211391 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``? /// @@ -658,7 +659,9 @@ public struct DeclReferenceExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Leaf /// - 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, - _ 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 6fd799b9e7f..ab2dfa4f646 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift @@ -1706,6 +1706,7 @@ public struct IdentifierPatternSyntax: PatternSyntaxProtocol, SyntaxHashable, _L /// ### Children /// +/// - `moduleSelector`: ``ModuleSelectorSyntax``? /// - `name`: (`` | `Self` | `Any` | `_`) /// - `genericArgumentClause`: ``GenericArgumentClauseSyntax``? public struct IdentifierTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyntaxNodeProtocol { @@ -1728,7 +1729,9 @@ public struct IdentifierTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp /// - 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, - _ unexpectedBeforeName: UnexpectedNodesSyntax? = nil, + _ unexpectedBeforeModuleSelector: UnexpectedNodesSyntax? = nil, + moduleSelector: ModuleSelectorSyntax? = nil, + _ unexpectedBetweenModuleSelectorAndName: UnexpectedNodesSyntax? = nil, name: TokenSyntax, _ unexpectedBetweenNameAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, genericArgumentClause: GenericArgumentClauseSyntax? = nil, @@ -1738,14 +1741,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, @@ -1762,7 +1769,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) } @@ -1771,6 +1779,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: @@ -1780,42 +1808,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..579e9d06f67 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift @@ -3106,6 +3106,7 @@ public struct MacroExpansionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _Lea /// ### Children /// /// - `pound`: `#` +/// - `moduleSelector`: ``ModuleSelectorSyntax``? /// - `macroName`: `` /// - `genericArgumentClause`: ``GenericArgumentClauseSyntax``? /// - `leftParen`: `(`? @@ -3136,7 +3137,9 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea 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 +3161,9 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea self = withExtendedLifetime((RawSyntaxArena(), ( unexpectedBeforePound, pound, - unexpectedBetweenPoundAndMacroName, + unexpectedBetweenPoundAndModuleSelector, + moduleSelector, + unexpectedBetweenModuleSelectorAndMacroName, macroName, unexpectedBetweenMacroNameAndGenericArgumentClause, genericArgumentClause, @@ -3177,7 +3182,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 +3234,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 +3244,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 +3308,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 +3344,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 +3352,7 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea } return Syntax(self) .replacingChild( - at: 9, + at: 11, with: collection, rawNodeArena: arena, rawAllocationArena: arena @@ -3334,10 +3362,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 +3374,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 +3428,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 +3436,7 @@ public struct MacroExpansionExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Lea } return Syntax(self) .replacingChild( - at: 15, + at: 17, with: collection, rawNodeArena: arena, rawAllocationArena: arena @@ -3418,17 +3446,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 +4238,7 @@ public struct MemberBlockSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNode /// /// - `baseType`: ``TypeSyntax`` /// - `period`: `.` +/// - `moduleSelector`: ``ModuleSelectorSyntax``? /// - `name`: (`` | `self`) /// - `genericArgumentClause`: ``GenericArgumentClauseSyntax``? public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyntaxNodeProtocol { @@ -4234,7 +4265,9 @@ public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyn 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 +4281,9 @@ public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyn baseType, unexpectedBetweenBaseTypeAndPeriod, period, - unexpectedBetweenPeriodAndName, + unexpectedBetweenPeriodAndModuleSelector, + moduleSelector, + unexpectedBetweenModuleSelectorAndName, name, unexpectedBetweenNameAndGenericArgumentClause, genericArgumentClause, @@ -4259,7 +4294,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 +4352,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 +4362,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 +4389,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 +4428,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 +5225,133 @@ public struct MissingTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSy public static let structure: SyntaxNodeStructure = .layout([\Self.unexpectedBeforePlaceholder, \Self.placeholder, \Self.unexpectedAfterPlaceholder]) } +// MARK: - ModuleSelectorSyntax + +/// ### Children +/// +/// - `moduleName`: `` +/// - `colonColon`: `::` +/// +/// ### Contained in +/// +/// - ``DeclReferenceExprSyntax``.``DeclReferenceExprSyntax/moduleSelector`` +/// - ``IdentifierTypeSyntax``.``IdentifierTypeSyntax/moduleSelector`` +/// - ``MacroExpansionExprSyntax``.``MacroExpansionExprSyntax/moduleSelector`` +/// - ``MemberTypeSyntax``.``MemberTypeSyntax/moduleSelector`` +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..755fe5080f9 100644 --- a/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift +++ b/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift @@ -1102,7 +1102,9 @@ extension MacroExpansionExprSyntax { 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 +1125,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..3dcaeda8299 100644 --- a/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift +++ b/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift @@ -663,7 +663,9 @@ extension MacroExpansionExprSyntax { leadingTrivia: Trivia? = nil, unexpectedBeforePoundToken: UnexpectedNodesSyntax? = nil, poundToken: TokenSyntax = .poundToken(), - unexpectedBetweenPoundTokenAndMacro: UnexpectedNodesSyntax? = nil, + unexpectedBetweenPoundTokenAndModuleSelector: UnexpectedNodesSyntax? = nil, + moduleSelector: ModuleSelectorSyntax? = nil, + unexpectedBetweenModuleSelectorAndMacro: UnexpectedNodesSyntax? = nil, macro: TokenSyntax, unexpectedBetweenMacroAndGenericArguments: UnexpectedNodesSyntax? = nil, genericArguments: GenericArgumentClauseSyntax? = nil, @@ -684,7 +686,9 @@ extension MacroExpansionExprSyntax { leadingTrivia: leadingTrivia, unexpectedBeforePoundToken, poundToken: poundToken, - unexpectedBetweenPoundTokenAndMacro, + unexpectedBetweenPoundTokenAndModuleSelector, + moduleSelector: moduleSelector, + unexpectedBetweenModuleSelectorAndMacro, macro: macro, unexpectedBetweenMacroAndGenericArguments, genericArguments: genericArguments, diff --git a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift index 801c5e5e7ff..43ad18f3cd6 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" + ) + } } diff --git a/Tests/SwiftParserTest/Assertions.swift b/Tests/SwiftParserTest/Assertions.swift index cb537012a3c..45916b34d1f 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,7 @@ 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/AttributeTests.swift b/Tests/SwiftParserTest/AttributeTests.swift index 5d82301c61e..f9e101f94b7 100644 --- a/Tests/SwiftParserTest/AttributeTests.swift +++ b/Tests/SwiftParserTest/AttributeTests.swift @@ -158,11 +158,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 910d61c4510..b894431d7ee 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 fileprivate func lex(_ sourceBytes: [UInt8], body: ([Lexer.Lexeme]) throws -> Void) rethrows { @@ -22,7 +22,7 @@ fileprivate func lex(_ sourceBytes: [UInt8], body: ([Lexer.Lexeme]) throws -> Vo 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 { @@ -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#>", diff --git a/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift new file mode 100644 index 00000000000..efc0b3c6f29 --- /dev/null +++ b/Tests/SwiftParserTest/translated/ModuleSelectorTests.swift @@ -0,0 +1,1631 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +import XCTest +@_spi(ExperimentalLanguageFeatures) import SwiftSyntax +@_spi(ExperimentalLanguageFeatures) import SwiftParser + +final class ModuleSelectorTests: ParserTestCase { + // FIXME: This test doesn't really cover: + // + // * Key paths + // * Custom type attributes (and coverage of type attrs generally is sparse) + // * Macros + + 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 {} + + extension A: @retroactive Swift::Equatable { + @_implements(Swift::Equatable, ==(_:_:)) + public static func equals(_: ModuleSelectorTestingKit::A, _: ModuleSelectorTestingKit::A) -> Swift::Bool { + Swift::fatalError() + } + + // FIXME: Add tests with autodiff @_differentiable(jvp:vjp:) and + // @_derivative(of:) + + @_dynamicReplacement(for: ModuleSelectorTestingKit::negate()) + mutating func myNegate() { + let fn: (Swift::Int, Swift::Int) -> Swift::Int = (Swift::+) + + let magnitude: Int.Swift::Magnitude = main::magnitude + + _ = (fn, magnitude) + + if Swift::Bool.Swift::random() { + self.ModuleSelectorTestingKit::negate() + } + else { + self = ModuleSelectorTestingKit::A(value: .Swift::min) + self = A.ModuleSelectorTestingKit::init(value: .min) + } + + self.main::myNegate() + + Swift::fatalError() + } + + // FIXME: Can we test @convention(witness_method:)? + } + """ + ) + } + + 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( + """ + @1️⃣main::available var use2 + """ + ) + + assertParse( + """ + func builderUser2(@1️⃣main::MyBuilder fn: () -> Void) {} + """ + ) + } + + func testModuleSelectorWhitespace() { + assertParse( + """ + _ = 1️⃣Swift::print + """ + ) + assertParse( + """ + _ = 1️⃣Swift:: print + """ + ) + assertParse( + """ + _ = 1️⃣Swift ::print + """ + ) + assertParse( + """ + _ = 1️⃣Swift :: print + """ + ) + assertParse( + """ + _ = 1️⃣Swift:: + print + """ + ) + assertParse( + """ + _ = 1️⃣Swift + ::print + """ + ) + assertParse( + """ + _ = 1️⃣Swift :: + print + """ + ) + assertParse( + """ + _ = 1️⃣Swift + :: print + """ + ) + assertParse( + """ + _ = 1️⃣Swift + :: + print + """ + ) + } + + func testModuleSelectorIncorrectFuncSignature() { + assertParse( + """ + func 1️⃣main::decl1() {} + // expected-error@-1 {{name in function declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{6-12=}} + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'main::' in function") + ] + ) + assertParse( + """ + func decl1( + 1️⃣main::p1: 2️⃣Swift::A + // expected-error@-1 {{argument label cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{3-9=}} + ) {} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before parameter" + ), + ] + ) + + // Round-tripping failures: + assertParse( + """ + func decl1( + 1️⃣main::p1: 2️⃣::A + ) {} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before 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( + 1️⃣main::p1: 2️⃣Swift::3️⃣ + ) {} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before parameter" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' before type" + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected type in parameter", + fixIts: ["insert type"] + ), + ], + fixedSource: """ + func decl1( + main::p1: Swift::<#type#> + ) {} + """ + ) + + assertParse( + """ + func decl1( + 1️⃣main::label p2: 2️⃣Swift::inout A + // expected-error@-1 {{argument label cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{3-9=}} + // FIXME: expected-error@-2 {{expected identifier in dotted type}} should be something like {{type 'inout' is not imported through module 'main'}} + ) {} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before parameter" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' before type specifier" + ) + ] + ) + assertParse( + """ + func decl1( + label 1️⃣main::p3: @Swift::escaping () -> A + // expected-error@-1 {{parameter name cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{9-15=}} + // FIXME: expected-error@-2 {{attribute can only be applied to declarations, not types}} should be something like {{type 'escaping' is not imported through module 'main'}} + // FIXME: expected-error@-3 {{expected parameter type following ':'}} + ) {} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' in parameter" + ), + ] + ) + } + + func testModuleSelectorIncorrectBindingDecls() { + assertParse( + """ + let 1️⃣main::decl1a = "a" + // expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{7-13=}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before pattern" + ), + ] + ) + assertParse( + """ + var 1️⃣main::decl1b = "b" + // expected-error@-1 {{name in variable declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{7-13=}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before pattern" + ), + ] + ) + assertParse( + """ + let (1️⃣main::decl1c, 2️⃣Swift::decl1d) = ("c", "d") + // expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{8-14=}} + // expected-error@-2 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-2 {{remove module selector from this name}} {{22-28=}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before pattern" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' before pattern" + ) + ] + ) + assertParse( + """ + if let (1️⃣main::decl1e, 2️⃣Swift::decl1f) = Optional(("e", "f")) {} + // expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{11-17=}} + // expected-error@-2 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-2 {{remove module selector from this name}} {{25-31=}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before pattern" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' before pattern" + ) + ] + ) + assertParse( + """ + guard let (1️⃣main::decl1g, 2️⃣Swift::decl1h) = Optional(("g", "h")) else { return } + // expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{14-20=}} + // expected-error@-2 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-2 {{remove module selector from this name}} {{28-34=}} + // From uses in the switch statements below: expected-note@-3 3 {{did you mean the local declaration?}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before pattern" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' before pattern" + ) + ] + ) + assertParse( + """ + switch Optional(2️⃣main::decl1g) { + case Optional.some(let 1️⃣Swift::decl1i): + // expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{26-32=}} + break + case .none: + break + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'Swift::' before pattern" + ), + ] + ) + assertParse( + """ + switch Optional(2️⃣main::decl1g) { + case let Optional.some(1️⃣Swift::decl1j): + // expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{26-32=}} + break + case .none: + break + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'Swift::' before pattern" + ), + ] + ) + assertParse( + """ + switch Optional(2️⃣main::decl1g) { + case let 1️⃣Swift::decl1k?: + // expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{11-17=}} + break + case .none: + break + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'Swift::' before pattern" + ), + ] + ) + assertParse( + """ + for 1️⃣main::decl1l in "lll" {} + // expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{7-13=}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before pattern" + ), + ] + ) + } + + func testModuleSelectorIncorrectClosureDecls() { + assertParse( + """ + "lll".forEach { [2️⃣Swift::magnitude] + // expected-error@-1 {{captured variable name cannot be qualified with a module selector}} + // expected-note@-2 {{remove module selector from this name}} {{20-26=}} + // expected-note@-3 {{explicitly capture into a variable named 'magnitude'}} {{20-20=magnitude = }} + 1️⃣main::elem in print(elem) + // expected-error@-1 {{parameter name cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{5-11=}} + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' before closure capture" + ), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before closure parameter" + ), + ] + ) + assertParse( + """ + "lll".forEach { (1️⃣main::elem) in print(elem) } + // expected-error@-1 {{parameter name cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{20-26=}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before parameter" + ), + ] + ) + assertParse( + """ + "lll".forEach { (1️⃣main::elem) -> Void in print(elem) } + // expected-error@-1 {{parameter name cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{20-26=}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before parameter" + ), + ] + ) + assertParse( + """ + "lll".forEach { (1️⃣main::elem: Character) -> Void in print(elem) } + // expected-error@-1 {{parameter name cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{20-26=}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before parameter" + ), + ] + ) + } + + func testModuleSelectorIncorrectTypeDecls() { + assertParse( + """ + enum 1️⃣main::decl2 { + // expected-error@-1 {{name in enum declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{6-12=}} + + case 2️⃣Swift::decl2a + // expected-error@-1 {{name in enum 'case' declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{8-14=}} + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' in enum" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' in enum case" + ), + ] + ) + assertParse( + """ + struct 1️⃣main::decl3 {} + // expected-error@-1 {{name in struct declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{8-14=}} + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'main::' in struct"), + ] + ) + assertParse( + """ + class 1️⃣main::decl4<2️⃣Swift::T> {} + // expected-error@-1 {{name in class declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{7-13=}} + // expected-error@-2 {{generic parameter name cannot be qualified with a module selector}} expected-note@-2 {{remove module selector from this name}} {{19-25=}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' in class" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' before generic parameter" + ), + ] + ) + assertParse( + """ + typealias 1️⃣main::decl5 = 2️⃣Swift::Bool + // expected-error@-1 {{name in typealias declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{11-17=}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' in typealias declaration" + ), + ] + ) + assertParse( + """ + protocol 1️⃣main::decl6 { + // expected-error@-1 {{name in protocol declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{10-16=}} + + associatedtype 2️⃣Swift::decl6a + // expected-error@-1 {{name in associatedtype declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{18-24=}} + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' in protocol" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' in associatedtype declaration" + ), + ] + ) + } + + func testModuleSelectorIncorrectGlobalVarDecls() { + assertParse( + """ + let 1️⃣main::decl7 = 7 + // expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{5-11=}} + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before pattern" + ), + ] + ) + assertParse( + """ + var 1️⃣main::decl8 = 8 { + // expected-error@-1 {{name in variable declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{5-11=}} + + willSet(2️⃣Swift::newValue) {} + // expected-error@-1 {{parameter name cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{11-17=}} + + didSet(3️⃣Foo::oldValue) {} + // expected-error@-1 {{parameter name cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{10-16=}} + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' before pattern" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' in accessor" + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "unexpected code 'Foo::' in accessor" + ), + ] + ) + } + + func testModuleSelectorIncorrectNestedDecls() { + assertParse( + """ + struct Parent { + func 1️⃣main::decl1() {} + // expected-error@-1 {{name in function declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{8-14=}} + } + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'main::' in function"), + ] + ) + assertParse( + """ + struct Parent { + enum 1️⃣main::decl2 { + // expected-error@-1 {{name in enum declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{8-14=}} + + case 2️⃣Swift::decl2a + // expected-error@-1 {{name in enum 'case' declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{10-16=}} + } + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' in enum" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' in enum case" + ), + ] + ) + assertParse( + """ + struct Parent { + struct 1️⃣main::decl3 {} + // expected-error@-1 {{name in struct declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{10-16=}} + } + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'main::' in struct"), + ] + ) + assertParse( + """ + struct Parent { + class 1️⃣main::decl4 {} + // expected-error@-1 {{name in class declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{9-15=}} + } + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'main::' in class"), + ] + ) + assertParse( + """ + struct Parent { + typealias 1️⃣main::decl5 = 2️⃣Swift::Bool + // expected-error@-1 {{name in typealias declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{13-19=}} + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' in typealias declaration" + ), + ] + ) + } + + func testModuleSelectorIncorrectRuntimeBaseAttr() { + // Should be diagnosed in ASTGen: + assertParse( + """ + @_swift_native_objc_runtime_base(1️⃣main::BaseClass) + // expected-error@-1 {{attribute parameter value cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{34-40=}} + class C1 {} + """ + ) + } + + func testModuleSelectorOperatorDecls() { + assertParse( + """ + infix operator <<<<< : 1️⃣Swift::AdditionPrecedence + // expected-error@-1 {{precedence group name cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{24-31=}} + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' in operator declaration"), + ] + ) + assertParse( + """ + precedencegroup 1️⃣main::PG1 { + // expected-error@-1 {{precedence group name cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{17-23=}} + + higherThan: 2️⃣Swift::AdditionPrecedence + // expected-error@-1 {{precedence group name cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{15-22=}} + } + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'main::' in precedencegroup" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'Swift::' in 'relation' property of 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: "'*' is not a valid identifier") + ] + ) + 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️⃣inout::Int + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'inout' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var g: `inout`::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: "'*' is not a valid identifier") + ] + ) + 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️⃣inout::Int] + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'inout' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var gArray: [`inout`::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: "expected '=' in variable", + fixIts: ["insert '='"] + ), + DiagnosticSpec(message: "'.*' is not a valid identifier"), + ], + fixedSource: """ + var cIndex: String = .*::Index + """ + ) + 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.1️⃣inout::Index + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'inout' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + var gIndex: String.`inout`::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: "'*' is not a valid identifier"), + ] + ) + 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() { + 1️⃣inout::print() + } + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'inout' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + func inExpr() { + `inout`::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.1️⃣inout::magnitude + } + """, + diagnostics: [ + DiagnosticSpec( + message: "keyword 'inout' cannot be used as an identifier here", + fixIts: ["if this name is unavoidable, use backticks to escape it"] + ) + ], + fixedSource: """ + func inExpr() { + _ = 1.`inout`::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() { + assertParse( + """ + @_spi(main::Private) + // expected-error@-1 {{SPI group cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{7-13=}} + public struct BadImplementsAttr: CustomStringConvertible {} + """ + ) + assertParse( + """ + @_implements(main::CustomStringConvertible, 1️⃣Swift::description) + // expected-error@-1 {{name of sibling declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{41-48=}} + public var stringValue: String { fatalError() } + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' in @_implements arguments"), + ] + ) + assertParse( + """ + @_specialize(target: main::fn(), spi: 1️⃣Swift::Private, where T == Swift::Int) + // expected-error@-1 {{SPI group cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{21-27=}} + public func fn() -> T { fatalError() } + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' in attribute argument") + ] + ) + assertParse( + """ + func fn(_: @isolated(1️⃣Swift::any) () -> Void) {} + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' in attribute") + ] + ) + assertParse( + """ + @_documentation(metadata: 1️⃣Swift::GroupName) + func fn() {} + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' in @_documentation argument") + ] + ) + assertParse( + """ + @derivative(of: Swift::Foo.Swift::Bar.Swift::baz(), wrt: quux) + func fn() {} + """ + ) + } + + func testModuleSelectorExpr() { + assertParse( + "let x = 1️⃣Swift::do { 1 }", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before 'do' block") + ], + experimentalFeatures: [.moduleSelector, .doExpressions] + ) + assertParse( + "let x = 1️⃣Swift::if y { 1 } else { 0 }", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before 'if' statement") + ] + ) + assertParse( + """ + let x = 1️⃣Swift::switch y { + case true: 1 + case false: 0 + } + """, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before 'switch' statement") + ] + ) + assertParse( + "fn(1️⃣Swift::&x)", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before inout expression") + ] + ) + assertParse( + #"_ = 1️⃣Swift::\main::Foo.BarKit::bar"#, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before key path") + ] + ) + assertParse( + "_ = 1️⃣Swift::-x", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before operator") + ] + ) + assertParse( + "_ = 1️⃣Swift::1", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before integer literal") + ] + ) + assertParse( + "_ = 1️⃣Swift::1.0", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before floating literal") + ] + ) + assertParse( + #"_ = 1️⃣Swift::@"fnord""#, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::@' before string literal") + ] + ) + assertParse( + #"_ = 1️⃣Swift::"fnord""#, + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before string literal") + ] + ) + assertParse( + "_ = 1️⃣Swift::/fnord/", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before regex literal") + ] + ) + assertParse( + "_ = 1️⃣Swift::nil", + diagnostics: [ + // FIXME: improve location wording + DiagnosticSpec(message: "unexpected code 'Swift::' in source file") + ] + ) + assertParse( + "_ = 1️⃣Swift::true", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before bool literal") + ] + ) + assertParse( + "_ = Swift::identifier" + ) + assertParse( + "_ = Swift::self" + ) + assertParse( + "_ = Swift::init" + ) + assertParse( + "@attached(extension, names: Swift::deinit) macro m()" + ) + assertParse( + "@attached(extension, names: Swift::subscript) macro m()", + ) + assertParse( + "_ = Swift::Self" + ) + assertParse( + "_ = Swift::Any" + ) + assertParse( + "_ = Swift::$0" + ) + assertParse( + "_ = Swift::$foo" + ) + assertParse( + "_ = 1️⃣Swift::_", + diagnostics: [ + // FIXME: improve location wording + DiagnosticSpec(message: "unexpected code 'Swift::' in source file") + ] + ) + assertParse( + "1️⃣Swift::_ = 1", + diagnostics: [ + // FIXME: improve location wording + DiagnosticSpec(message: "unexpected code 'Swift::' in source file") + ] + ) + assertParse( + "_ = 1️⃣Swift::#foo", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before macro expansion") + ] + ) + assertParse( + "_ = #Swift::foo" + ) + assertParse( + "_ = 1️⃣Swift::{ 1 }", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before closure") + ] + ) + assertParse( + "_ = 1️⃣Swift::.random()", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before member access") + ] + ) + assertParse( + "_ = 1️⃣Swift::.main::random()", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before member access") + ] + ) + assertParse( + "_ = .main::random()" + ) + assertParse( + "_ = 1️⃣Swift::super.foo()", + diagnostics: [ + // FIXME: improve location wording + DiagnosticSpec(message: "unexpected code 'Swift::' in member access") + ] + ) + assertParse( + "_ = 1️⃣Swift::(a, b)", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before tuple") + ] + ) + assertParse( + "_ = 1️⃣Swift::[a, b]", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before array") + ] + ) + assertParse( + "_ = 1️⃣Swift::2️⃣", + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'Swift::' before expression" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected expression", + fixIts: ["insert expression"] + ) + ], + fixedSource: "_ = Swift::<#expression#>" + ) + + assertParse( + "_ = x.Swift::y" + ) + assertParse( + "_ = x.1️⃣Swift::1", + diagnostics: [ + // FIXME: improve location wording + DiagnosticSpec(message: "unexpected code 'Swift::' in member access") + ] + ) + assertParse( + "_ = x.1️⃣Swift::self", + diagnostics: [ + // FIXME: improve location wording + DiagnosticSpec(message: "unexpected code 'Swift::' in member access") + ] + ) + assertParse( + "_ = x.Swift::Self.self" + // FIXME: inconsistent with type syntax + ) + assertParse( + "_ = x.Swift::Type.self" + // FIXME: inconsistent with type syntax + ) + assertParse( + "_ = x.Swift::Protocol.self" + // FIXME: inconsistent with type syntax + ) + assertParse( + "_ = myArray.reduce(0, Swift::+)" + ) + } + + func testModuleSelectorStmt() { + assertParse( + "if 1️⃣Swift::#available(macOS 15, *) {}", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before availability condition") + ] + ) + } + + func testModuleSelectorType() { + assertParse( + "func fn(_: Swift::Self) {}" + ) + assertParse( + "func fn(_: Swift::Any) {}" + ) + assertParse( + "func fn(_: Swift::Foo) {}" + ) + assertParse( + "func fn(_: 1️⃣Swift::(Int, String)) {}", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before tuple type") + ] + ) + assertParse( + "func fn(_: 1️⃣Swift::[Int]) {}", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' before array type") + ] + ) + assertParse( + "func fn(_: Swift::_) {}" + ) + assertParse( + "func fn(_: 1️⃣Swift::2️⃣) {}", + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'Swift::' before type" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected type in parameter", + fixIts: ["insert type"] + ), + ], + fixedSource: "func fn(_: Swift::<#type#>) {}" + ) + assertParse( + "func fn(_: Foo.1️⃣Swift::Type) {}", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' in metatype") + ] + ) + assertParse( + "func fn(_: Foo.1️⃣Swift::Protocol) {}", + diagnostics: [ + DiagnosticSpec(message: "unexpected code 'Swift::' in metatype") + ] + ) + assertParse( + "func fn(_: Foo.Swift::Bar) {}" + ) + assertParse( + "func fn(_: Foo.Swift::self) {}" + ) + } +}