Skip to content
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 include/swift/AST/Identifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -663,8 +663,12 @@ class DeclName {
///
/// \param skipEmptyArgumentNames When true, don't print the argument labels
/// if they are all empty.
///
/// \param escapeIfNeeded When true, escape identifiers with backticks
/// when required.
llvm::raw_ostream &print(llvm::raw_ostream &os,
bool skipEmptyArgumentNames = false) const;
bool skipEmptyArgumentNames = false,
bool escapeIfNeeded = false) const;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably ought to default to true, but I'm leaving that for a future PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we print raw identifiers in textual interfaces properly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do, the ASTPrinter has its own implementation of this


/// Print a "pretty" representation of this declaration name to the given
/// stream.
Expand Down
19 changes: 15 additions & 4 deletions lib/AST/Identifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,15 @@ StringRef DeclName::getString(llvm::SmallVectorImpl<char> &scratch,
}

llvm::raw_ostream &DeclName::print(llvm::raw_ostream &os,
bool skipEmptyArgumentNames) const {
bool skipEmptyArgumentNames,
bool escapeIfNeeded) const {
// Print the base name.
os << getBaseName();
auto baseName = getBaseName();
if (escapeIfNeeded && baseName.mustAlwaysBeEscaped()) {
os << "`" << baseName << "`";
} else {
os << baseName;
}

// If this is a simple name, we're done.
if (isSimpleName())
Expand All @@ -193,8 +199,13 @@ llvm::raw_ostream &DeclName::print(llvm::raw_ostream &os,

// Print the argument names.
os << "(";
for (auto c : getArgumentNames()) {
os << c << ':';
for (auto argName : getArgumentNames()) {
if (escapeIfNeeded && argName.mustAlwaysBeEscaped()) {
os << "`" << argName << "`";
} else {
os << argName;
}
os << ':';
}
os << ")";
return os;
Expand Down
13 changes: 13 additions & 0 deletions test/SourceKit/DocumentStructure/Inputs/raw-identifiers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
struct `A.B` {
func `foo bar`(`a b`: Int, c: Int, `$`: String) {}
func `3four`() {}
func `baz`(`x`: Int) {}
}
extension `A.B` {}

struct Outer {
struct Inner {}
}
extension Outer.Inner {}

func + (lhs: `A.B`, rhs: `A.B`) -> `A.B` { lhs }
3 changes: 3 additions & 0 deletions test/SourceKit/DocumentStructure/structure.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
// RUN: %sourcekitd-test -req=structure %S/../Inputs/placeholders.swift | %sed_clean > %t.placeholders.response
// RUN: %diff -u %s.placeholders.response %t.placeholders.response

// RUN: %sourcekitd-test -req=structure %S/Inputs/raw-identifiers.swift | %sed_clean > %t.raw-identifiers.swift.response
// RUN: %diff -u %s.raw-identifiers.swift.response %t.raw-identifiers.swift.response

// RUN: %sourcekitd-test -req=structure %S/Inputs/main.swift -name -foobar | %sed_clean > %t.foobar.response
// RUN: %diff -u %s.foobar.response %t.foobar.response

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@
key.kind: source.lang.swift.decl.var.global,
key.accessibility: source.lang.swift.accessibility.internal,
key.setter_accessibility: source.lang.swift.accessibility.internal,
key.name: "$",
key.name: "`$`",
key.offset: 1982,
key.length: 24,
key.nameoffset: 1999,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@
key.kind: source.lang.swift.decl.var.global,
key.accessibility: source.lang.swift.accessibility.internal,
key.setter_accessibility: source.lang.swift.accessibility.internal,
key.name: "$",
key.name: "`$`",
key.offset: 1982,
key.length: 24,
key.nameoffset: 1999,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
{
key.kind: source.lang.swift.decl.class,
key.accessibility: source.lang.swift.accessibility.internal,
key.name: "3",
key.name: "`3`",
key.offset: 84,
key.length: 10,
key.nameoffset: 90,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{
key.kind: source.lang.swift.decl.class,
key.accessibility: source.lang.swift.accessibility.internal,
key.name: "<#MyCls#>",
key.name: "`<#MyCls#>`",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is consistent with how we classify raw identifiers, but admittedly does seem a little odd. It does reflect how placeholders are treated in decl name position though, they are effectively raw identifiers, e.g:

struct S {
  static func <#foo#>() {}
}
S.<#foo#>() // resolves to <#foo#>
S.<#bar#>() // error: type 'S' has no member '<#bar#>'

Any thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely a bit of an odd case. I think my preference here would be to only add backticks if the name itself actually has backticks vs just being a placeholder. I assume a placeholder within backticks causes all sorts of weirdness though?

Copy link
Contributor Author

@hamishknight hamishknight Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's a weird case, really I would prefer if we could just ban editor placeholders in raw identifiers, although that would probably need some evolution discussion.

I think my preference here would be to only add backticks if the name itself actually has backticks

Trouble is that DeclName doesn't currently have that information, we'd either need to plumb it through, or this decision would need to be left up to the clients

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy leaving it for this PR 👍

key.offset: 0,
key.length: 35,
key.nameoffset: 6,
Expand All @@ -29,7 +29,7 @@
{
key.kind: source.lang.swift.decl.function.free,
key.accessibility: source.lang.swift.accessibility.internal,
key.name: "<#test1#>()",
key.name: "`<#test1#>`()",
key.offset: 37,
key.length: 52,
key.nameoffset: 42,
Expand All @@ -56,7 +56,7 @@
key.substructure: [
{
key.kind: source.lang.swift.decl.var.local,
key.name: "<#name#>",
key.name: "`<#name#>`",
key.offset: 63,
key.length: 8,
key.nameoffset: 63,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
{
key.offset: 0,
key.length: 246,
key.diagnostic_stage: source.diagnostic.stage.swift.parse,
key.substructure: [
{
key.kind: source.lang.swift.decl.struct,
key.accessibility: source.lang.swift.accessibility.internal,
key.name: "`A.B`",
key.offset: 0,
key.length: 115,
key.nameoffset: 7,
key.namelength: 3,
key.bodyoffset: 14,
key.bodylength: 100,
key.substructure: [
{
key.kind: source.lang.swift.decl.function.method.instance,
key.accessibility: source.lang.swift.accessibility.internal,
key.name: "`foo bar`(`a b`:c:`$`:)",
key.offset: 17,
key.length: 50,
key.nameoffset: 22,
key.namelength: 42,
key.bodyoffset: 66,
key.bodylength: 0,
key.substructure: [
{
key.kind: source.lang.swift.decl.var.parameter,
key.name: "`a b`",
key.offset: 32,
key.length: 10,
key.typename: "Int",
key.nameoffset: 32,
key.namelength: 3
},
{
key.kind: source.lang.swift.decl.var.parameter,
key.name: "c",
key.offset: 44,
key.length: 6,
key.typename: "Int",
key.nameoffset: 44,
key.namelength: 1
},
{
key.kind: source.lang.swift.decl.var.parameter,
key.name: "`$`",
key.offset: 52,
key.length: 11,
key.typename: "String",
key.nameoffset: 52,
key.namelength: 1
}
]
},
{
key.kind: source.lang.swift.decl.function.method.instance,
key.accessibility: source.lang.swift.accessibility.internal,
key.name: "`3four`()",
key.offset: 70,
key.length: 17,
key.nameoffset: 75,
key.namelength: 9,
key.bodyoffset: 86,
key.bodylength: 0
},
{
key.kind: source.lang.swift.decl.function.method.instance,
key.accessibility: source.lang.swift.accessibility.internal,
key.name: "baz(x:)",
key.offset: 90,
key.length: 23,
key.nameoffset: 95,
key.namelength: 15,
key.bodyoffset: 112,
key.bodylength: 0,
key.substructure: [
{
key.kind: source.lang.swift.decl.var.parameter,
key.name: "x",
key.offset: 101,
key.length: 8,
key.typename: "Int",
key.nameoffset: 101,
key.namelength: 1
}
]
}
]
},
{
key.kind: source.lang.swift.decl.extension,
key.name: "`A.B`",
key.offset: 116,
key.length: 18,
key.nameoffset: 126,
key.namelength: 5,
key.bodyoffset: 133,
key.bodylength: 0
},
{
key.kind: source.lang.swift.decl.struct,
key.accessibility: source.lang.swift.accessibility.internal,
key.name: "Outer",
key.offset: 136,
key.length: 34,
key.nameoffset: 143,
key.namelength: 5,
key.bodyoffset: 150,
key.bodylength: 19,
key.substructure: [
{
key.kind: source.lang.swift.decl.struct,
key.accessibility: source.lang.swift.accessibility.internal,
key.name: "Inner",
key.offset: 153,
key.length: 15,
key.nameoffset: 160,
key.namelength: 5,
key.bodyoffset: 167,
key.bodylength: 0
}
]
},
{
key.kind: source.lang.swift.decl.extension,
key.name: "Outer.Inner",
key.offset: 171,
key.length: 24,
key.nameoffset: 181,
key.namelength: 11,
key.bodyoffset: 194,
key.bodylength: 0
},
{
key.kind: source.lang.swift.decl.function.free,
key.accessibility: source.lang.swift.accessibility.internal,
key.name: "+(_:_:)",
key.offset: 197,
key.length: 48,
key.typename: "`A.B`",
key.nameoffset: 202,
key.namelength: 26,
key.bodyoffset: 239,
key.bodylength: 5,
key.substructure: [
{
key.kind: source.lang.swift.decl.var.parameter,
key.name: "lhs",
key.offset: 205,
key.length: 10,
key.typename: "`A.B`"
},
{
key.kind: source.lang.swift.decl.var.parameter,
key.name: "rhs",
key.offset: 217,
key.length: 10,
key.typename: "`A.B`"
}
]
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@
key.kind: source.lang.swift.decl.var.global,
key.accessibility: source.lang.swift.accessibility.internal,
key.setter_accessibility: source.lang.swift.accessibility.internal,
key.name: "$",
key.name: "`$`",
key.offset: 1982,
key.length: 24,
key.nameoffset: 1999,
Expand Down
3 changes: 2 additions & 1 deletion tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,8 @@ bool SwiftLangSupport::printDisplayName(const swift::ValueDecl *D,
if (!D->hasName())
return true;

OS << D->getName();
D->getName().print(OS, /*skipEmptyArgumentNames*/ false,
/*escapeIfNeeded*/ true);
return false;
}

Expand Down