Skip to content

Commit 6cbcb7b

Browse files
committed
[SourceKit] Introduce a new request for demangling symbol names.
This is SourceKit support for the swift_demangle_getDemangledName/swift_demangle_getSimplifiedDemangledName APIs. rdar://23525281
1 parent 404acac commit 6cbcb7b

File tree

8 files changed

+161
-1
lines changed

8 files changed

+161
-1
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %sourcekitd-test -req=demangle unmangled _TtBf80_ _TtP3foo3bar_ | FileCheck %s
2+
// CHECK: START DEMANGLE
3+
// CHECK-NEXT: <empty>
4+
// CHECK-NEXT: Builtin.Float80
5+
// CHECK-NEXT: foo.bar
6+
// CHECK-NEXT: END DEMANGLE
7+
8+
// RUN: %sourcekitd-test -req=demangle unmangled _TtBf80_ _TtP3foo3bar_ -simplified-demangling | FileCheck %s -check-prefix=SIMPLIFIED
9+
// SIMPLIFIED: START DEMANGLE
10+
// SIMPLIFIED-NEXT: <empty>
11+
// SIMPLIFIED-NEXT: Builtin.Float80
12+
// SIMPLIFIED-NEXT: bar
13+
// SIMPLIFIED-NEXT: END DEMANGLE

tools/SourceKit/tools/sourcekitd-test/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,6 @@ def print_response_as_json : Flag<["-"], "print-response-as-json">,
6969

7070
def group_name : Separate<["-"], "group-name">,
7171
HelpText<"Module group name to print">;
72+
73+
def simplified_demangling : Flag<["-"], "simplified-demangling">,
74+
HelpText<"Use simplified demangling for the 'demangle' request">;

tools/SourceKit/tools/sourcekitd-test/TestOptions.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ bool TestOptions::parseArgs(llvm::ArrayRef<const char *> Args) {
103103
case OPT_req:
104104
Request = llvm::StringSwitch<SourceKitRequest>(InputArg->getValue())
105105
.Case("version", SourceKitRequest::ProtocolVersion)
106+
.Case("demangle", SourceKitRequest::DemangleNames)
106107
.Case("index", SourceKitRequest::Index)
107108
.Case("complete", SourceKitRequest::CodeComplete)
108109
.Case("complete.open", SourceKitRequest::CodeCompleteOpen)
@@ -131,7 +132,7 @@ bool TestOptions::parseArgs(llvm::ArrayRef<const char *> Args) {
131132
.Default(SourceKitRequest::None);
132133
if (Request == SourceKitRequest::None) {
133134
llvm::errs() << "error: invalid request, expected one of "
134-
<< "version/index/complete/cursor/related-idents/syntax-map/structure/"
135+
<< "version/demangle/index/complete/cursor/related-idents/syntax-map/structure/"
135136
"format/expand-placeholder/doc-info/sema/interface-gen/interface-gen-open/"
136137
"find-usr/find-interface/open/edit/print-annotations/extract-comment/"
137138
"module-groups\n";
@@ -216,12 +217,17 @@ bool TestOptions::parseArgs(llvm::ArrayRef<const char *> Args) {
216217
case OPT_INPUT:
217218
SourceFile = InputArg->getValue();
218219
SourceText = llvm::None;
220+
Inputs.push_back(InputArg->getValue());
219221
break;
220222

221223
case OPT_json_request_path:
222224
JsonRequestPath = InputArg->getValue();
223225
break;
224226

227+
case OPT_simplified_demangling:
228+
SimplifiedDemangling = true;
229+
break;
230+
225231
case OPT_UNKNOWN:
226232
llvm::errs() << "error: unknown argument: "
227233
<< InputArg->getAsString(ParsedArgs) << '\n';

tools/SourceKit/tools/sourcekitd-test/TestOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace sourcekitd_test {
2222
enum class SourceKitRequest {
2323
None,
2424
ProtocolVersion,
25+
DemangleNames,
2526
Index,
2627
CodeComplete,
2728
CodeCompleteOpen,
@@ -51,6 +52,7 @@ enum class SourceKitRequest {
5152

5253
struct TestOptions {
5354
SourceKitRequest Request = SourceKitRequest::None;
55+
std::vector<std::string> Inputs;
5456
std::string SourceFile;
5557
std::string TextInputFile;
5658
std::string JsonRequestPath;
@@ -71,6 +73,7 @@ struct TestOptions {
7173
bool CheckInterfaceIsASCII = false;
7274
bool UsedSema = false;
7375
bool PrintResponseAsJSON = false;
76+
bool SimplifiedDemangling = false;
7477

7578
bool parseArgs(llvm::ArrayRef<const char *> Args);
7679
};

tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/ADT/StringSwitch.h"
2020
#include "llvm/Support/CommandLine.h"
2121
#include "llvm/Support/MemoryBuffer.h"
22+
#include "llvm/Support/Regex.h"
2223
#include "llvm/Support/raw_ostream.h"
2324
#include "llvm/Support/Signals.h"
2425
#include "llvm/Support/FileSystem.h"
@@ -53,6 +54,10 @@ static void expandPlaceholders(llvm::MemoryBuffer *SourceBuf,
5354
static void printModuleGroupNames(sourcekitd_variant_t Info,
5455
llvm::raw_ostream &OS);
5556

57+
static void prepareDemangleRequest(sourcekitd_object_t Req,
58+
const TestOptions &Opts);
59+
static void printDemangleResults(sourcekitd_variant_t Info, raw_ostream &OS);
60+
5661
static unsigned resolveFromLineCol(unsigned Line, unsigned Col,
5762
StringRef Filename);
5863
static unsigned resolveFromLineCol(unsigned Line, unsigned Col,
@@ -76,6 +81,7 @@ static sourcekitd_uid_t KeySourceFile;
7681
static sourcekitd_uid_t KeyModuleName;
7782
static sourcekitd_uid_t KeyGroupName;
7883
static sourcekitd_uid_t KeyName;
84+
static sourcekitd_uid_t KeyNames;
7985
static sourcekitd_uid_t KeyFilePath;
8086
static sourcekitd_uid_t KeyModuleInterfaceName;
8187
static sourcekitd_uid_t KeyLength;
@@ -105,8 +111,10 @@ static sourcekitd_uid_t KeyPopular;
105111
static sourcekitd_uid_t KeyUnpopular;
106112
static sourcekitd_uid_t KeyTypeInterface;
107113
static sourcekitd_uid_t KeyModuleGroups;
114+
static sourcekitd_uid_t KeySimplified;
108115

109116
static sourcekitd_uid_t RequestProtocolVersion;
117+
static sourcekitd_uid_t RequestDemangle;
110118
static sourcekitd_uid_t RequestIndex;
111119
static sourcekitd_uid_t RequestCodeComplete;
112120
static sourcekitd_uid_t RequestCodeCompleteOpen;
@@ -164,6 +172,7 @@ static int skt_main(int argc, const char **argv) {
164172
KeyModuleName = sourcekitd_uid_get_from_cstr("key.modulename");
165173
KeyGroupName = sourcekitd_uid_get_from_cstr("key.groupname");
166174
KeyName = sourcekitd_uid_get_from_cstr("key.name");
175+
KeyNames = sourcekitd_uid_get_from_cstr("key.names");
167176
KeyFilePath = sourcekitd_uid_get_from_cstr("key.filepath");
168177
KeyModuleInterfaceName = sourcekitd_uid_get_from_cstr("key.module_interface_name");
169178
KeyLength = sourcekitd_uid_get_from_cstr("key.length");
@@ -195,6 +204,7 @@ static int skt_main(int argc, const char **argv) {
195204
KeyUnpopular = sourcekitd_uid_get_from_cstr("key.unpopular");
196205
KeyTypeInterface = sourcekitd_uid_get_from_cstr("key.typeinterface");
197206
KeyModuleGroups = sourcekitd_uid_get_from_cstr("key.modulegroups");
207+
KeySimplified = sourcekitd_uid_get_from_cstr("key.simplified");
198208

199209
SemaDiagnosticStage = sourcekitd_uid_get_from_cstr("source.diagnostic.stage.swift.sema");
200210

@@ -203,6 +213,7 @@ static int skt_main(int argc, const char **argv) {
203213
semaSemaphore = dispatch_semaphore_create(0);
204214

205215
RequestProtocolVersion = sourcekitd_uid_get_from_cstr("source.request.protocol_version");
216+
RequestDemangle = sourcekitd_uid_get_from_cstr("source.request.demangle");
206217
RequestIndex = sourcekitd_uid_get_from_cstr("source.request.indexsource");
207218
RequestCodeComplete = sourcekitd_uid_get_from_cstr("source.request.codecomplete");
208219
RequestCodeCompleteOpen = sourcekitd_uid_get_from_cstr("source.request.codecomplete.open");
@@ -341,6 +352,9 @@ static int handleTestInvocation(ArrayRef<const char *> Args,
341352
if (Optargc < Args.size())
342353
Opts.CompilerArgs = Args.slice(Optargc+1);
343354

355+
if (Opts.Request == SourceKitRequest::DemangleNames)
356+
Opts.SourceFile.clear();
357+
344358
std::string SourceFile = Opts.SourceFile;
345359
if (!SourceFile.empty()) {
346360
llvm::SmallString<64> AbsSourceFile;
@@ -380,6 +394,10 @@ static int handleTestInvocation(ArrayRef<const char *> Args,
380394
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestProtocolVersion);
381395
break;
382396

397+
case SourceKitRequest::DemangleNames:
398+
prepareDemangleRequest(Req, Opts);
399+
break;
400+
383401
case SourceKitRequest::Index:
384402
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestIndex);
385403
break;
@@ -642,6 +660,10 @@ static int handleTestInvocation(ArrayRef<const char *> Args,
642660
KeepResponseAlive = true;
643661
break;
644662

663+
case SourceKitRequest::DemangleNames:
664+
printDemangleResults(sourcekitd_response_get_value(Resp), outs());
665+
break;
666+
645667
case SourceKitRequest::ProtocolVersion:
646668
case SourceKitRequest::Index:
647669
case SourceKitRequest::CodeComplete:
@@ -1107,6 +1129,59 @@ static void printRelatedIdents(sourcekitd_variant_t Info, StringRef Filename,
11071129
OS << "END RANGES\n";
11081130
}
11091131

1132+
static void prepareDemangleRequest(sourcekitd_object_t Req,
1133+
const TestOptions &Opts) {
1134+
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestDemangle);
1135+
if (Opts.SimplifiedDemangling)
1136+
sourcekitd_request_dictionary_set_int64(Req, KeySimplified, 1);
1137+
sourcekitd_object_t arr = sourcekitd_request_array_create(nullptr, 0);
1138+
sourcekitd_request_dictionary_set_value(Req, KeyNames, arr);
1139+
1140+
auto addName = [&](StringRef MangledName) {
1141+
sourcekitd_request_array_set_stringbuf(arr, SOURCEKITD_ARRAY_APPEND,
1142+
MangledName.data(), MangledName.size());
1143+
};
1144+
1145+
if (Opts.Inputs.empty()) {
1146+
auto input = llvm::MemoryBuffer::getSTDIN();
1147+
if (!input) {
1148+
llvm::errs() << input.getError().message() << '\n';
1149+
::exit(1);
1150+
}
1151+
llvm::StringRef inputContents = input.get()->getBuffer();
1152+
1153+
// This doesn't handle Unicode symbols, but maybe that's okay.
1154+
llvm::Regex maybeSymbol("_T[_a-zA-Z0-9$]+");
1155+
llvm::SmallVector<llvm::StringRef, 1> matches;
1156+
while (maybeSymbol.match(inputContents, &matches)) {
1157+
addName(matches.front());
1158+
}
1159+
1160+
} else {
1161+
for (llvm::StringRef name : Opts.Inputs) {
1162+
addName(name);
1163+
}
1164+
}
1165+
1166+
sourcekitd_request_release(arr);
1167+
}
1168+
1169+
static void printDemangleResults(sourcekitd_variant_t Info, raw_ostream &OS) {
1170+
OS << "START DEMANGLE\n";
1171+
sourcekitd_variant_t results =
1172+
sourcekitd_variant_dictionary_get_value(Info, KeyResults);
1173+
sourcekitd_variant_array_apply(results, ^bool(size_t index, sourcekitd_variant_t value) {
1174+
StringRef name = sourcekitd_variant_dictionary_get_string(value, KeyName);
1175+
if (name.empty())
1176+
OS << "<empty>";
1177+
else
1178+
OS << name;
1179+
OS << '\n';
1180+
return true;
1181+
});
1182+
OS << "END DEMANGLE\n";
1183+
}
1184+
11101185
static void initializeRewriteBuffer(StringRef Input,
11111186
clang::RewriteBuffer &RewriteBuf) {
11121187
RewriteBuf.Initialize(Input);

tools/SourceKit/tools/sourcekitd/lib/API/DictionaryKeys.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ extern SourceKit::UIdent KeyNextRequestStart;
101101
extern SourceKit::UIdent KeyPopular;
102102
extern SourceKit::UIdent KeyUnpopular;
103103
extern SourceKit::UIdent KeyHide;
104+
extern SourceKit::UIdent KeySimplified;
104105

105106
extern SourceKit::UIdent KeyIsUnavailable;
106107
extern SourceKit::UIdent KeyIsDeprecated;

tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "SourceKit/Support/Logging.h"
2323
#include "SourceKit/Support/UIdent.h"
2424

25+
#include "swift/Basic/DemangleWrappers.h"
26+
2527
#include "llvm/ADT/ArrayRef.h"
2628
#include "llvm/ADT/SmallString.h"
2729
#include "llvm/ADT/StringRef.h"
@@ -58,6 +60,9 @@ class LazySKDUID {
5860

5961
static LazySKDUID RequestProtocolVersion("source.request.protocol_version");
6062

63+
static LazySKDUID RequestDemangle("source.request.demangle");
64+
static LazySKDUID RequestMangleSimpleClass("source.request.mangle_simple_class");
65+
6166
static LazySKDUID RequestIndex("source.request.indexsource");
6267
static LazySKDUID RequestDocInfo("source.request.docinfo");
6368
static LazySKDUID RequestCodeComplete("source.request.codecomplete");
@@ -139,6 +144,9 @@ static SourceKit::Context &getGlobalContext() {
139144
return *GlobalCtx;
140145
}
141146

147+
static sourcekitd_response_t demangleNames(ArrayRef<const char *> MangledNames,
148+
bool Simplified);
149+
142150
static sourcekitd_response_t indexSource(StringRef Filename,
143151
ArrayRef<const char *> Args,
144152
StringRef KnownHash);
@@ -300,6 +308,18 @@ void handleRequestImpl(sourcekitd_object_t ReqObj, ResponseReceiver Rec) {
300308
return Rec(RB.createResponse());
301309
}
302310

311+
if (ReqUID == RequestDemangle) {
312+
SmallVector<const char *, 8> MangledNames;
313+
bool Failed = Req.getStringArray(KeyNames, MangledNames, /*isOptional=*/true);
314+
if (Failed) {
315+
return Rec(createErrorRequestInvalid(
316+
"'key.names' not an array of strings"));
317+
}
318+
int64_t Simplified = false;
319+
Req.getInt64(KeySimplified, Simplified, /*isOptional=*/true);
320+
return Rec(demangleNames(MangledNames, Simplified));
321+
}
322+
303323
// Just accept 'source.request.buildsettings.register' for now, don't do
304324
// anything else.
305325
// FIXME: Heavy WIP here.
@@ -927,6 +947,44 @@ class SKDocConsumer : public DocInfoConsumer {
927947
};
928948
}
929949

950+
static bool isSwiftPrefixed(StringRef MangledName) {
951+
if (MangledName.size() < 2)
952+
return false;
953+
return (MangledName[0] == '_' && MangledName[1] == 'T');
954+
}
955+
956+
static sourcekitd_response_t demangleNames(ArrayRef<const char *> MangledNames,
957+
bool Simplified) {
958+
swift::Demangle::DemangleOptions DemangleOptions;
959+
if (Simplified) {
960+
DemangleOptions =
961+
swift::Demangle::DemangleOptions::SimplifiedUIDemangleOptions();
962+
}
963+
964+
auto getDemangledName = [&](StringRef MangledName) -> std::string {
965+
if (!isSwiftPrefixed(MangledName))
966+
return std::string(); // Not a mangled name
967+
968+
std::string Result = swift::demangle_wrappers::demangleSymbolAsString(
969+
MangledName, DemangleOptions);
970+
971+
if (Result == MangledName)
972+
return std::string(); // Not a mangled name
973+
974+
return Result;
975+
};
976+
977+
ResponseBuilder RespBuilder;
978+
auto Arr = RespBuilder.getDictionary().setArray(KeyResults);
979+
for (auto MangledName : MangledNames) {
980+
std::string Result = getDemangledName(MangledName);
981+
auto Entry = Arr.appendDictionary();
982+
Entry.set(KeyName, Result.c_str());
983+
}
984+
985+
return RespBuilder.createResponse();
986+
}
987+
930988
static sourcekitd_response_t reportDocInfo(llvm::MemoryBuffer *InputBuf,
931989
StringRef ModuleName,
932990
ArrayRef<const char *> Args) {

tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ UIdent sourcekitd::KeyNextRequestStart("key.nextrequeststart");
114114
UIdent sourcekitd::KeyPopular("key.popular");
115115
UIdent sourcekitd::KeyUnpopular("key.unpopular");
116116
UIdent sourcekitd::KeyHide("key.hide");
117+
UIdent sourcekitd::KeySimplified("key.simplified");
117118

118119
UIdent sourcekitd::KeyIsDeprecated("key.is_deprecated");
119120
UIdent sourcekitd::KeyIsUnavailable("key.is_unavailable");

0 commit comments

Comments
 (0)