[SourceKit] Print backticks if needed in printDisplayName

Ensure we print raw identifier names with backticks for e.g the
document structure request.

rdar://152524780
This commit is contained in:
Hamish Knight
2025-06-24 17:13:07 +01:00
parent 0839675e6d
commit 0c8468e0ee
11 changed files with 210 additions and 13 deletions

View File

@@ -663,8 +663,12 @@ public:
///
/// \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;
/// Print a "pretty" representation of this declaration name to the given
/// stream.

View File

@@ -164,9 +164,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())
@@ -191,8 +197,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;

View File

@@ -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 }

View File

@@ -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

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -6,7 +6,7 @@
{
key.kind: source.lang.swift.decl.class,
key.accessibility: source.lang.swift.accessibility.internal,
key.name: "<#MyCls#>",
key.name: "`<#MyCls#>`",
key.offset: 0,
key.length: 35,
key.nameoffset: 6,
@@ -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,
@@ -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,

View File

@@ -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`"
}
]
}
]
}

View File

@@ -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,

View File

@@ -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;
}