Skip to content

Add diagnostic message for identifier editor placeholder #1380

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Sources/SwiftParser/Lexer/Cursor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2044,6 +2044,7 @@ extension Lexer.Cursor {
extension Lexer.Cursor {
mutating func tryLexEditorPlaceholder(sourceBufferStart: Lexer.Cursor) -> Lexer.Result {
precondition(self.is(at: "<") && self.is(offset: 1, at: "#"))
let start = self
var ptr = self
let leftAngleConsumed = ptr.advance(matching: "<")
let poundConsumed = ptr.advance(matching: "#")
Expand All @@ -2058,7 +2059,10 @@ extension Lexer.Cursor {
let closingAngleConsumed = ptr.advance(matching: ">")
precondition(closingAngleConsumed)
self = ptr
return Lexer.Result(.identifier)
return Lexer.Result(
.identifier,
error: LexingDiagnostic(.editorPlaceholder, position: start)
)
default:
break
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public extension TokenError {

/// Please order the cases in this enum alphabetically by case name.
public enum StaticTokenError: String, DiagnosticMessage {
case editorPlaceholder = "editor placeholder in source file"
case expectedBinaryExponentInHexFloatLiteral = "hexadecimal floating point literal must end with an exponent"
case expectedClosingBraceInUnicodeEscape = #"expected '}' in \u{...} escape sequence"#
case expectedDigitInFloatLiteral = "expected a digit in floating point exponent"
Expand Down Expand Up @@ -132,6 +133,7 @@ public extension SwiftSyntax.TokenDiagnostic {
}

switch self.kind {
case .editorPlaceholder: return StaticTokenError.editorPlaceholder
case .expectedBinaryExponentInHexFloatLiteral: return StaticTokenError.expectedBinaryExponentInHexFloatLiteral
case .expectedClosingBraceInUnicodeEscape: return StaticTokenError.expectedClosingBraceInUnicodeEscape
case .expectedDigitInFloatLiteral: return StaticTokenError.expectedDigitInFloatLiteral
Expand Down
2 changes: 2 additions & 0 deletions Sources/SwiftSyntax/TokenDiagnostic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public struct TokenDiagnostic: Hashable {
public enum Kind {
// Please order these alphabetically

case editorPlaceholder
case expectedBinaryExponentInHexFloatLiteral
case expectedClosingBraceInUnicodeEscape
case expectedDigitInFloatLiteral
Expand Down Expand Up @@ -94,6 +95,7 @@ public struct TokenDiagnostic: Hashable {

public var severity: Severity {
switch kind {
case .editorPlaceholder: return .error
case .expectedBinaryExponentInHexFloatLiteral: return .error
case .expectedClosingBraceInUnicodeEscape: return .error
case .expectedDigitInFloatLiteral: return .error
Expand Down
2 changes: 1 addition & 1 deletion Tests/SwiftParserTest/Assertions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private func assertTokens(
var lexemeStartOffset = 0
for (actualLexeme, expectedLexeme) in zip(actual, expected) {
defer {
lexemeStartOffset = actualLexeme.byteLength
lexemeStartOffset += actualLexeme.byteLength
}
if actualLexeme.rawTokenKind != expectedLexeme.rawTokenKind {
XCTFail(
Expand Down
7 changes: 5 additions & 2 deletions Tests/SwiftParserTest/DeclarationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1379,12 +1379,15 @@ final class DeclarationTests: XCTestCase {
assertParse(
"""
class Foo {
<#code#>
1️⃣<#code#>
}
""",
substructure: Syntax(
MemberDeclListItemSyntax(decl: EditorPlaceholderDeclSyntax(identifier: .identifier("<#code#>")))
)
),
diagnostics: [
DiagnosticSpec(message: "editor placeholder in source file")
]
)
}

Expand Down
25 changes: 22 additions & 3 deletions Tests/SwiftParserTest/ExpressionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -838,9 +838,28 @@ final class ExpressionTests: XCTestCase {
}

func testCodeCompletionExpressions() {
assertParse("if !<#b1#> && !<#b2#> {}")
assertParse("if <#test#> {}")
assertParse("if <#b1#>, <#b2#> {}")
assertParse(
"if !1️⃣<#b1#> && !2️⃣<#b2#> {}",
diagnostics: [
DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file"),
DiagnosticSpec(locationMarker: "2️⃣", message: "editor placeholder in source file"),
]
)

assertParse(
"if 1️⃣<#test#> {}",
diagnostics: [
DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file")
]
)

assertParse(
"if 1️⃣<#b1#>, 2️⃣<#b2#> {}",
diagnostics: [
DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file"),
DiagnosticSpec(locationMarker: "2️⃣", message: "editor placeholder in source file"),
]
)
}

func testKeywordApplyExpression() {
Expand Down
10 changes: 5 additions & 5 deletions Tests/SwiftParserTest/LexerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -663,20 +663,20 @@ public class LexerTests: XCTestCase {

func testEditorPlaceholders() {
assertLexemes(
"!<#b1#> && !<#b2#>",
"!1️⃣<#b1#> && !2️⃣<#b2#>",
lexemes: [
LexemeSpec(.prefixOperator, text: "!"),
LexemeSpec(.identifier, text: "<#b1#>", trailing: " "),
LexemeSpec(.identifier, text: "<#b1#>", trailing: " ", errorLocationMarker: "1️⃣", diagnostic: "editor placeholder in source file"),
LexemeSpec(.binaryOperator, text: "&&", trailing: " "),
LexemeSpec(.prefixOperator, text: "!"),
LexemeSpec(.identifier, text: "<#b2#>"),
LexemeSpec(.identifier, text: "<#b2#>", errorLocationMarker: "2️⃣", diagnostic: "editor placeholder in source file"),
]
)

assertLexemes(
"<##>",
"1️⃣<##>",
lexemes: [
LexemeSpec(.identifier, text: "<##>", trailing: "")
LexemeSpec(.identifier, text: "<##>", trailing: "", diagnostic: "editor placeholder in source file")
]
)
}
Expand Down
4 changes: 2 additions & 2 deletions Tests/SwiftParserTest/translated/IdentifiersTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ final class IdentifiersTests: XCTestCase {
assertParse(
"""
// Placeholders are recognized as identifiers but with error.
func <#some name#>() {}
func 1️⃣<#some name#>() {}
""",
diagnostics: [
// TODO: (good first issue) Old parser expected error on line 2: editor placeholder in source file
DiagnosticSpec(message: "editor placeholder in source file")
]
)
}
Expand Down