diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index 112eca5d8c2..dba5a354a43 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -555,6 +555,8 @@ public let DECL_NODES: [Node] = [ nameForDiagnostics: "editor placeholder", documentation: """ An editor placeholder, e.g. `<#declaration#>` that is used in a position that expects a declaration. + + - Warning: This ``EditorPlaceholderDeclSyntax`` node is not generated by the parser anymore. Placeholders are represented by a ``MissingDeclSyntax``. """, traits: [ "WithAttributes", diff --git a/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift b/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift index 1834ec16929..7460496cd08 100644 --- a/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift @@ -792,6 +792,9 @@ public let EXPR_NODES: [Node] = [ kind: .editorPlaceholderExpr, base: .expr, nameForDiagnostics: "editor placeholder", + documentation: """ + - Warning: This ``EditorPlaceholderExprSyntax`` node is not generated by the parser anymore. Placeholders are represented by a ``DeclReferenceExprSyntax``. + """, children: [ Child( name: "placeholder", diff --git a/Release Notes/511.md b/Release Notes/511.md index dc9a55c00cf..7b4d0b4a0bb 100644 --- a/Release Notes/511.md +++ b/Release Notes/511.md @@ -30,6 +30,10 @@ - Issue: https://github.com/apple/swift-syntax/issues/2267 - Pull request: https://github.com/apple/swift-syntax/pull/2272 +- `EditorPlaceholderDeclSyntax` and `EditorPlaceholderExprSyntax`: + - Description: `EditorPlaceholderDeclSyntax` and `EditorPlaceholderExprSyntax` are now deprecated and placeholders are instead parsed as identifiers within a `MissingDeclSyntax` or `DeclReferenceExprSyntax`. + - Pull request: https://github.com/apple/swift-syntax/pull/2237 + ## API-Incompatible Changes - Effect specifiers: diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 907bb26b06a..90a5f934461 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -275,9 +275,9 @@ extension Parser { } if self.currentToken.isEditorPlaceholder { - let placeholder = self.consumeAnyToken() + let placeholder = self.parseAnyIdentifier() return RawDeclSyntax( - RawEditorPlaceholderDeclSyntax( + RawMissingDeclSyntax( attributes: attrs.attributes, modifiers: attrs.modifiers, placeholder: placeholder, diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index 390d9a79b10..53c46fe68bf 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -1241,14 +1241,6 @@ extension Parser { mutating func parseIdentifierExpression() -> RawExprSyntax { let declName = self.parseDeclReferenceExpr(.compoundNames) guard self.withLookahead({ $0.canParseAsGenericArgumentList() }) else { - if declName.baseName.tokenText.isEditorPlaceholder && declName.argumentNames == nil { - return RawExprSyntax( - RawEditorPlaceholderExprSyntax( - placeholder: declName.baseName, - arena: self.arena - ) - ) - } return RawExprSyntax(declName) } diff --git a/Sources/SwiftParserDiagnostics/MissingNodesError.swift b/Sources/SwiftParserDiagnostics/MissingNodesError.swift index 0c5ad2ca6ca..c61992ead8c 100644 --- a/Sources/SwiftParserDiagnostics/MissingNodesError.swift +++ b/Sources/SwiftParserDiagnostics/MissingNodesError.swift @@ -381,7 +381,18 @@ extension ParseDiagnosticsGenerator { // Walk all upcoming sibling to see if they are also missing to handle them in this diagnostic. // If this is the case, handle all of them in this diagnostic. - var missingNodes = [Syntax(node)] + var missingNodes: [Syntax] = [Syntax(node)] + + // If the node is an `MissingDeclSyntax` and the placeholder is an editor placeholder + // we should not add a diagnostic that it's missing. + // Instead, we should emit a diagnostic about the fact that there is an editor placeholder in the source file. + if let missing = missingNodes.first?.as(MissingDeclSyntax.self), + missing.placeholder.isEditorPlaceholder, + !missing.placeholder.isMissing + { + return .visitChildren + } + if let parentWithTokens = ancestorWithMoreTokens, let index { let siblings = parentWithTokens.children(viewMode: .all) let siblingsAfter = siblings[siblings.index(after: index)...] diff --git a/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift index ed1d63a6e75..0c5c45bd40f 100644 --- a/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift +++ b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift @@ -678,7 +678,7 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor { if shouldSkip(node) { return .skipChildren } - if node.statements.only?.item.is(EditorPlaceholderExprSyntax.self) == true { + if let item = node.statements.only?.item.as(DeclReferenceExprSyntax.self), item.baseName.isEditorPlaceholder { // Only emit a single diagnostic about the editor placeholder and none for the missing '{' and '}'. addDiagnostic(node, .editorPlaceholderInSourceFile, handledNodes: [node.id]) return .skipChildren diff --git a/Sources/SwiftRefactor/ExpandEditorPlaceholder.swift b/Sources/SwiftRefactor/ExpandEditorPlaceholder.swift index 996e6909b0f..8498b60ea54 100644 --- a/Sources/SwiftRefactor/ExpandEditorPlaceholder.swift +++ b/Sources/SwiftRefactor/ExpandEditorPlaceholder.swift @@ -135,7 +135,8 @@ public struct ExpandEditorPlaceholder: EditRefactoringProvider { /// Expansion on `closure1` and `normalArg` is the same as `ExpandEditorPlaceholder`. public struct ExpandEditorPlaceholders: EditRefactoringProvider { public static func textRefactor(syntax token: TokenSyntax, in context: Void) -> [SourceEdit] { - guard let placeholder = token.parent?.as(EditorPlaceholderExprSyntax.self), + guard let placeholder = token.parent?.as(DeclReferenceExprSyntax.self), + placeholder.baseName.isEditorPlaceholder, let arg = placeholder.parent?.as(LabeledExprSyntax.self), let argList = arg.parent?.as(LabeledExprListSyntax.self), let call = argList.parent?.as(FunctionCallExprSyntax.self) @@ -190,8 +191,8 @@ extension FunctionTypeSyntax { placeholder = ExpandEditorPlaceholder.wrapInTypePlaceholder(ret, type: ret) } - let statementPlaceholder = EditorPlaceholderExprSyntax( - placeholder: .identifier(placeholder) + let statementPlaceholder = DeclReferenceExprSyntax( + baseName: .identifier(placeholder) ) let closureStatement = CodeBlockItemSyntax( item: .expr(ExprSyntax(statementPlaceholder)) @@ -234,8 +235,9 @@ extension FunctionCallExprSyntax { var includedArg = false var argsToExpand = 0 for arg in arguments.reversed() { - guard let expr = arg.expression.as(EditorPlaceholderExprSyntax.self), - let data = EditorPlaceholderData(token: expr.placeholder), + guard let expr = arg.expression.as(DeclReferenceExprSyntax.self), + expr.baseName.isEditorPlaceholder, + let data = EditorPlaceholderData(token: expr.baseName), case let .typed(_, type) = data, type.is(FunctionTypeSyntax.self) else { @@ -253,7 +255,7 @@ extension FunctionCallExprSyntax { var expandedArgs = [LabeledExprSyntax]() for arg in arguments.suffix(argsToExpand) { - let edits = ExpandEditorPlaceholder.textRefactor(syntax: arg.expression.cast(EditorPlaceholderExprSyntax.self).placeholder) + let edits = ExpandEditorPlaceholder.textRefactor(syntax: arg.expression.cast(DeclReferenceExprSyntax.self).baseName) guard edits.count == 1, let edit = edits.first, !edit.replacement.isEmpty else { return nil } diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift index ef2bf67687c..8eab4d6d8e9 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift @@ -15,6 +15,8 @@ // MARK: - EditorPlaceholderDeclSyntax /// An editor placeholder, e.g. `<#declaration#>` that is used in a position that expects a declaration. +/// +/// - Warning: This ``EditorPlaceholderDeclSyntax`` node is not generated by the parser anymore. Placeholders are represented by a ``MissingDeclSyntax``. /// /// ### Children /// @@ -220,6 +222,8 @@ public struct EditorPlaceholderDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _ // MARK: - EditorPlaceholderExprSyntax +/// - Warning: This ``EditorPlaceholderExprSyntax`` node is not generated by the parser anymore. Placeholders are represented by a ``DeclReferenceExprSyntax``. +/// /// ### Children /// /// - `placeholder`: `` diff --git a/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index 2ce74a29529..c663596a512 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -2313,7 +2313,7 @@ final class DeclarationTests: ParserTestCase { 1️⃣<#code#> } """, - substructure: MemberBlockItemSyntax(decl: EditorPlaceholderDeclSyntax(placeholder: .identifier("<#code#>"))), + substructure: MemberBlockItemSyntax(decl: MissingDeclSyntax(placeholder: .identifier("<#code#>"))), diagnostics: [ DiagnosticSpec(message: "editor placeholder in source file") ] @@ -2847,8 +2847,8 @@ final class DeclarationTests: ParserTestCase { CodeBlockItemSyntax( item: .expr( ExprSyntax( - EditorPlaceholderExprSyntax( - placeholder: .identifier("<#function body#>") + DeclReferenceExprSyntax( + baseName: .identifier("<#function body#>") ) ) ) @@ -2892,8 +2892,8 @@ final class DeclarationTests: ParserTestCase { CodeBlockItemSyntax( item: .expr( ExprSyntax( - EditorPlaceholderExprSyntax( - placeholder: .identifier("<#function body#>") + DeclReferenceExprSyntax( + baseName: .identifier("<#function body#>") ) ) ) diff --git a/Tests/SwiftParserTest/PatternTests.swift b/Tests/SwiftParserTest/PatternTests.swift index 15a212eb5b8..a55e76a19ec 100644 --- a/Tests/SwiftParserTest/PatternTests.swift +++ b/Tests/SwiftParserTest/PatternTests.swift @@ -180,8 +180,8 @@ final class PatternTests: ParserTestCase { identifier: .identifier("<#name#>") ), initializer: InitializerClauseSyntax( - value: EditorPlaceholderExprSyntax( - placeholder: .identifier("<#value#>") + value: DeclReferenceExprSyntax( + baseName: .identifier("<#value#>") ) ) ) diff --git a/Tests/SwiftParserTest/translated/TrailingClosuresTests.swift b/Tests/SwiftParserTest/translated/TrailingClosuresTests.swift index c6ff24d0183..b99f3a4054c 100644 --- a/Tests/SwiftParserTest/translated/TrailingClosuresTests.swift +++ b/Tests/SwiftParserTest/translated/TrailingClosuresTests.swift @@ -185,7 +185,7 @@ final class TrailingClosuresTests: ParserTestCase { leftBrace: .leftBraceToken(presence: .missing), statements: CodeBlockItemListSyntax([ CodeBlockItemSyntax( - item: .init(EditorPlaceholderExprSyntax(placeholder: .identifier("<#T##() -> Void#>"))) + item: .init(DeclReferenceExprSyntax(baseName: .identifier("<#T##() -> Void#>"))) ) ]), rightBrace: .rightBraceToken(presence: .missing) diff --git a/Tests/SwiftRefactorTest/ExpandEditorPlaceholderTests.swift b/Tests/SwiftRefactorTest/ExpandEditorPlaceholderTests.swift index d85c9835465..638b06d8423 100644 --- a/Tests/SwiftRefactorTest/ExpandEditorPlaceholderTests.swift +++ b/Tests/SwiftRefactorTest/ExpandEditorPlaceholderTests.swift @@ -103,7 +103,7 @@ fileprivate func assertRefactorPlaceholder( } else { var parser = Parser(placeholder) let expr = ExprSyntax.parse(from: &parser) - token = try XCTUnwrap(expr.as(EditorPlaceholderExprSyntax.self)?.placeholder, file: file, line: line) + token = try XCTUnwrap(expr.as(DeclReferenceExprSyntax.self)?.baseName, file: file, line: line) } try assertRefactor(token, context: (), provider: ExpandEditorPlaceholder.self, expected: [SourceEdit.replace(token, with: expected)], file: file, line: line) diff --git a/Tests/SwiftRefactorTest/ExpandEditorPlaceholdersTests.swift b/Tests/SwiftRefactorTest/ExpandEditorPlaceholdersTests.swift index 813727a0c80..b84d6f00e87 100644 --- a/Tests/SwiftRefactorTest/ExpandEditorPlaceholdersTests.swift +++ b/Tests/SwiftRefactorTest/ExpandEditorPlaceholdersTests.swift @@ -112,7 +112,7 @@ fileprivate func assertRefactorPlaceholderCall( var parser = Parser(expr) let call = try XCTUnwrap(ExprSyntax.parse(from: &parser).as(FunctionCallExprSyntax.self), file: file, line: line) let arg = call.arguments[call.arguments.index(at: placeholder)] - let token: TokenSyntax = try XCTUnwrap(arg.expression.as(EditorPlaceholderExprSyntax.self), file: file, line: line).placeholder + let token: TokenSyntax = try XCTUnwrap(arg.expression.as(DeclReferenceExprSyntax.self), file: file, line: line).baseName try assertRefactor(token, context: (), provider: ExpandEditorPlaceholders.self, expected: [SourceEdit.replace(call, with: expected)], file: file, line: line) } @@ -127,7 +127,7 @@ fileprivate func assertRefactorPlaceholderToken( var parser = Parser(expr) let call = try XCTUnwrap(ExprSyntax.parse(from: &parser).as(FunctionCallExprSyntax.self), file: file, line: line) let arg = call.arguments[call.arguments.index(at: placeholder)] - let token: TokenSyntax = try XCTUnwrap(arg.expression.as(EditorPlaceholderExprSyntax.self), file: file, line: line).placeholder + let token: TokenSyntax = try XCTUnwrap(arg.expression.as(DeclReferenceExprSyntax.self), file: file, line: line).baseName try assertRefactor(token, context: (), provider: ExpandEditorPlaceholders.self, expected: [SourceEdit.replace(token, with: expected)], file: file, line: line) }