Skip to content

Commit 677e03d

Browse files
committed
[SourceKit] Vend the localization key found in documentation comments
If a documentation comment has a - LocalizationKey: field, strip it out of the documentation body and report it in cursor/doc info with the key "key.localization_key". rdar://problem/30383329
1 parent 7fa1160 commit 677e03d

File tree

13 files changed

+94
-1
lines changed

13 files changed

+94
-1
lines changed

include/swift/IDE/CommentConversion.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ namespace ide {
2929
/// \returns true if the declaration has a documentation comment.
3030
bool getDocumentationCommentAsXML(const Decl *D, raw_ostream &OS);
3131

32+
/// If the declaration has a documentation comment and a localization key,
33+
/// print it into the given output stream and return true. Else, return false.
34+
bool getLocalizationKey(const Decl *D, raw_ostream &OS);
35+
3236
/// Converts the given comment to Doxygen.
3337
void getDocumentationCommentAsDoxygen(const DocComment *DC, raw_ostream &OS);
3438

include/swift/Markup/AST.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class ParamField;
2828
class ReturnsField;
2929
class TagField;
3030
class ThrowsField;
31+
class LocalizationKeyField;
3132

3233
/// The basic structure of a doc comment attached to a Swift
3334
/// declaration.

include/swift/Markup/ASTNodes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ MARKUP_AST_NODE(PrivateExtension, MarkupASTNode)
6161
MARKUP_AST_NODE(ExperimentField, PrivateExtension)
6262
MARKUP_AST_NODE(ImportantField, PrivateExtension)
6363
MARKUP_AST_NODE(InvariantField, PrivateExtension)
64-
MARKUP_AST_NODE(LocalizationKey, PrivateExtension)
64+
MARKUP_AST_NODE(LocalizationKeyField, PrivateExtension)
6565
MARKUP_AST_NODE(MutatingvariantField, PrivateExtension)
6666
MARKUP_AST_NODE(NonmutatingvariantField, PrivateExtension)
6767
MARKUP_AST_NODE(NoteField, PrivateExtension)

lib/IDE/CommentConversion.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,20 @@ bool ide::getDocumentationCommentAsXML(const Decl *D, raw_ostream &OS) {
443443
return true;
444444
}
445445

446+
bool ide::getLocalizationKey(const Decl *D, raw_ostream &OS) {
447+
swift::markup::MarkupContext MC;
448+
auto DC = getCascadingDocComment(MC, D);
449+
if (!DC.hasValue())
450+
return false;
451+
452+
if (const auto LKF = DC.getValue()->getLocalizationKeyField()) {
453+
printInlinesUnder(LKF.getValue(), OS);
454+
return true;
455+
}
456+
457+
return false;
458+
}
459+
446460
//===----------------------------------------------------------------------===//
447461
// Conversion to Doxygen.
448462
//===----------------------------------------------------------------------===//

test/Inputs/comment_to_something_conversion.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,3 +467,13 @@ public func codeListingWithDefaultLanguage() {}
467467
/// ```
468468
public func codeListingWithOtherLanguage() {}
469469
// CHECK: DocCommentAsXML=[<Function file="{{.*}}" line="{{.*}}" column="{{.*}}"><Name>codeListingWithOtherLanguage()</Name><USR>s:14swift_ide_test28codeListingWithOtherLanguageyyF</USR><Declaration>public func codeListingWithOtherLanguage()</Declaration><Abstract><Para>Brief.</Para></Abstract><Discussion><CodeListing language="c++"><zCodeLineNumbered><![CDATA[Something::Something::create();]]></zCodeLineNumbered><zCodeLineNumbered></zCodeLineNumbered></CodeListing></Discussion></Function>]
470+
471+
/// Brief.
472+
///
473+
/// - LocalizationKey: ABC
474+
public func localizationKeyShouldNotAppearInDocComments() {}
475+
// CHECK: DocCommentAsXML=[<Function file="{{.*}}" line="{{.*}}" column="{{.*}}"><Name>localizationKeyShouldNotAppearInDocComments()</Name><USR>s:14swift_ide_test43localizationKeyShouldNotAppearInDocCommentsyyF</USR><Declaration>public func localizationKeyShouldNotAppearInDocComments()</Declaration><Abstract><Para>Brief.</Para></Abstract></Function>]
476+
477+
/// - LocalizationKey: ABC
478+
public func localizationKeyShouldNotAppearInDocComments2() {}
479+
// CHECK: DocCommentAsXML=[<Function file="{{.*}}" line="{{.*}}" column="{{.*}}"><Name>localizationKeyShouldNotAppearInDocComments2()</Name><USR>s:14swift_ide_test44localizationKeyShouldNotAppearInDocComments2yyF</USR><Declaration>public func localizationKeyShouldNotAppearInDocComments2()</Declaration></Function>]

test/SourceKit/CursorInfo/cursor_info.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,14 @@ func convention5(_: @convention(method) ()->()) {}
206206
func convention6(_: @convention(objc_method) ()->()) {}
207207
func convention7(_: @convention(witness_method) ()->()) {}
208208

209+
/// Brief.
210+
///
211+
/// - LocalizationKey: ABC
212+
struct HasLocalizationKey {}
213+
214+
/// - LocalizationKey: ABC
215+
func hasLocalizationKey2() {}
216+
209217
// RUN: rm -rf %t.tmp
210218
// RUN: mkdir -p %t.tmp
211219
// RUN: %swiftc_driver -emit-module -o %t.tmp/FooSwiftModule.swiftmodule %S/Inputs/FooSwiftModule.swift
@@ -702,3 +710,25 @@ func convention7(_: @convention(witness_method) ()->()) {}
702710
// RUN: %sourcekitd-test -req=cursor -pos=206:6 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK86 %s
703711
// RUN: %sourcekitd-test -req=cursor -pos=207:6 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK86 %s
704712
// CHECK86: <syntaxtype.attribute.builtin><syntaxtype.attribute.name>@convention</syntaxtype.attribute.name>({{[a-z_]*}})</syntaxtype.attribute.builtin>
713+
714+
// RUN: %sourcekitd-test -req=cursor -pos=212:8 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK87 %s
715+
// CHECK87: source.lang.swift.decl.struct (212:8-212:26)
716+
// CHECK87-NEXT: HasLocalizationKey
717+
// CHECK87-NEXT: s:V11cursor_info18HasLocalizationKey
718+
// CHECK87-NEXT: HasLocalizationKey.Type
719+
// CHECK87-NEXT: _Tt
720+
// CHECK87-NEXT: <Declaration>struct HasLocalizationKey</Declaration>
721+
// CHECK87-NEXT: <decl.struct><syntaxtype.keyword>struct</syntaxtype.keyword> <decl.name>HasLocalizationKey</decl.name></decl.struct>
722+
// CHECK87-NEXT: <Class file="{{[^"]+}}cursor_info.swift" line="212" column="8"><Name>HasLocalizationKey</Name><USR>s:V11cursor_info18HasLocalizationKey</USR><Declaration>struct HasLocalizationKey</Declaration><Abstract><Para>Brief.</Para></Abstract></Class>
723+
// CHECK87-NEXT: <LocalizationKey>ABC</LocalizationKey>
724+
725+
// RUN: %sourcekitd-test -req=cursor -pos=215:6 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK88 %s
726+
// CHECK88: source.lang.swift.decl.function.free (215:6-215:27)
727+
// CHECK88-NEXT: hasLocalizationKey2
728+
// CHECK88-NEXT: s:F11cursor_info19hasLocalizationKey2FT_T_
729+
// CHECK88-NEXT: () -> ()
730+
// CHECK88-NEXT: _Tt
731+
// CHECK88-NEXT: <Declaration>func hasLocalizationKey2()</Declaration>
732+
// CHECK88-NEXT: <decl.function.free><syntaxtype.keyword>func</syntaxtype.keyword> <decl.name>hasLocalizationKey2</decl.name>()</decl.function.free>
733+
// CHECK88-NEXT: <Function file="{{[^"]+}}cursor_info.swift" line="215" column="6"><Name>hasLocalizationKey2()</Name><USR>s:F11cursor_info19hasLocalizationKey2FT_T_</USR><Declaration>func hasLocalizationKey2()</Declaration></Function
734+
// CHECK88-NEXT: <LocalizationKey>ABC</LocalizationKey>

tools/SourceKit/include/SourceKit/Core/LangSupport.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ struct CursorInfo {
258258
StringRef DocComment;
259259
StringRef TypeInterface;
260260
StringRef GroupName;
261+
/// A key for documentation comment localization, if it exists in the doc
262+
/// comment for the declaration.
263+
StringRef LocalizationKey;
261264
/// Annotated XML pretty printed declaration.
262265
StringRef AnnotatedDeclaration;
263266
/// Fully annotated XML pretty printed declaration.
@@ -330,6 +333,7 @@ struct DocEntityInfo {
330333
llvm::SmallString<64> ProvideImplementationOfUSR;
331334
llvm::SmallString<64> DocComment;
332335
llvm::SmallString<64> FullyAnnotatedDecl;
336+
llvm::SmallString<64> LocalizationKey;
333337
std::vector<DocGenericParam> GenericParams;
334338
std::vector<std::string> GenericRequirements;
335339
unsigned Offset = 0;

tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,9 @@ static bool initDocEntityInfo(const Decl *D, const Decl *SynthesizedTarget,
378378

379379
initDocGenericParams(D, Info);
380380

381+
llvm::raw_svector_ostream LocalizationKeyOS(Info.LocalizationKey);
382+
ide::getLocalizationKey(D, LocalizationKeyOS);
383+
381384
if (auto *VD = dyn_cast<ValueDecl>(D)) {
382385
llvm::raw_svector_ostream OS(Info.FullyAnnotatedDecl);
383386
if (SynthesizedTarget)

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,17 @@ static bool passCursorInfoForDecl(const ValueDecl *VD,
715715
}
716716
unsigned GroupEnd = SS.size();
717717

718+
unsigned LocalizationBegin = SS.size();
719+
{
720+
llvm::raw_svector_ostream OS(SS);
721+
ide::getLocalizationKey(VD, OS);
722+
}
723+
unsigned LocalizationEnd = SS.size();
724+
718725
DelayedStringRetriever OverUSRsStream(SS);
726+
727+
SmallVector<std::pair<unsigned, unsigned>, 4> OverUSROffs;
728+
719729
ide::walkOverriddenDecls(VD,
720730
[&](llvm::PointerUnion<const ValueDecl*, const clang::NamedDecl*> D) {
721731
OverUSRsStream.startPiece();
@@ -798,6 +808,8 @@ static bool passCursorInfoForDecl(const ValueDecl *VD,
798808
StringRef FullyAnnotatedDecl =
799809
StringRef(SS.begin() + FullDeclBegin, FullDeclEnd - FullDeclBegin);
800810
StringRef GroupName = StringRef(SS.begin() + GroupBegin, GroupEnd - GroupBegin);
811+
StringRef LocalizationKey = StringRef(SS.begin() + LocalizationBegin,
812+
LocalizationEnd - LocalizationBegin);
801813

802814
llvm::Optional<std::pair<unsigned, unsigned>> DeclarationLoc;
803815
StringRef Filename;
@@ -837,6 +849,7 @@ static bool passCursorInfoForDecl(const ValueDecl *VD,
837849
Info.OverrideUSRs = OverUSRs;
838850
Info.AnnotatedRelatedDeclarations = AnnotatedRelatedDecls;
839851
Info.GroupName = GroupName;
852+
Info.LocalizationKey = LocalizationKey;
840853
Info.IsSystem = IsSystem;
841854
Info.TypeInterface = StringRef();
842855
Receiver(Info);

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ static sourcekitd_uid_t KeyOffset;
9292
static sourcekitd_uid_t KeySourceFile;
9393
static sourcekitd_uid_t KeyModuleName;
9494
static sourcekitd_uid_t KeyGroupName;
95+
static sourcekitd_uid_t KeyLocalizationKey;
9596
static sourcekitd_uid_t KeyActionName;
9697
static sourcekitd_uid_t KeySynthesizedExtension;
9798
static sourcekitd_uid_t KeyName;
@@ -215,6 +216,7 @@ static int skt_main(int argc, const char **argv) {
215216
KeySourceFile = sourcekitd_uid_get_from_cstr("key.sourcefile");
216217
KeyModuleName = sourcekitd_uid_get_from_cstr("key.modulename");
217218
KeyGroupName = sourcekitd_uid_get_from_cstr("key.groupname");
219+
KeyLocalizationKey = sourcekitd_uid_get_from_cstr("key.localization_key");
218220
KeyActionName = sourcekitd_uid_get_from_cstr("key.actionname");
219221
KeySynthesizedExtension = sourcekitd_uid_get_from_cstr("key.synthesizedextensions");
220222
KeyName = sourcekitd_uid_get_from_cstr("key.name");
@@ -1191,6 +1193,9 @@ static void printCursorInfo(sourcekitd_variant_t Info, StringRef FilenameIn,
11911193
KeyModuleName);
11921194
const char *GroupName = sourcekitd_variant_dictionary_get_string(Info,
11931195
KeyGroupName);
1196+
1197+
const char *LocalizationKey =
1198+
sourcekitd_variant_dictionary_get_string(Info, KeyLocalizationKey);
11941199
const char *ModuleInterfaceName =
11951200
sourcekitd_variant_dictionary_get_string(Info, KeyModuleInterfaceName);
11961201
const char *TypeInterface =
@@ -1287,6 +1292,9 @@ static void printCursorInfo(sourcekitd_variant_t Info, StringRef FilenameIn,
12871292
OS << FullAnnotDecl << '\n';
12881293
if (DocFullAsXML)
12891294
OS << DocFullAsXML << '\n';
1295+
if (LocalizationKey)
1296+
OS << "<LocalizationKey>" << LocalizationKey;
1297+
OS << "</LocalizationKey>" << '\n';
12901298
OS << "OVERRIDES BEGIN\n";
12911299
for (auto OverUSR : OverrideUSRs)
12921300
OS << OverUSR << '\n';

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ extern SourceKit::UIdent KeyBaseName;
129129
extern SourceKit::UIdent KeyArgNames;
130130
extern SourceKit::UIdent KeySelectorPieces;
131131
extern SourceKit::UIdent KeyNameKind;
132+
extern SourceKit::UIdent KeyLocalizationKey;
132133

133134
/// \brief Used for determining the printing order of dictionary keys.
134135
bool compareDictKeys(SourceKit::UIdent LHS, SourceKit::UIdent RHS);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,8 @@ void SKDocConsumer::addDocEntityInfoToDict(const DocEntityInfo &Info,
12091209
Elem.set(KeyDocFullAsXML, Info.DocComment);
12101210
if (!Info.FullyAnnotatedDecl.empty())
12111211
Elem.set(KeyFullyAnnotatedDecl, Info.FullyAnnotatedDecl);
1212+
if (!Info.LocalizationKey.empty())
1213+
Elem.set(KeyLocalizationKey, Info.LocalizationKey);
12121214

12131215
if (!Info.GenericParams.empty()) {
12141216
auto GPArray = Elem.setArray(KeyGenericParams);
@@ -1384,6 +1386,8 @@ static void reportCursorInfo(const CursorInfo &Info, ResponseReceiver Rec) {
13841386
Elem.set(KeyModuleName, Info.ModuleName);
13851387
if (!Info.GroupName.empty())
13861388
Elem.set(KeyGroupName, Info.GroupName);
1389+
if (!Info.LocalizationKey.empty())
1390+
Elem.set(KeyLocalizationKey, Info.LocalizationKey);
13871391
if (!Info.ModuleInterfaceName.empty())
13881392
Elem.set(KeyModuleInterfaceName, Info.ModuleInterfaceName);
13891393
if (Info.DeclarationLoc.hasValue()) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ UIdent sourcekitd::KeyBaseName("key.basename");
142142
UIdent sourcekitd::KeyArgNames("key.argnames");
143143
UIdent sourcekitd::KeySelectorPieces("key.selectorpieces");
144144
UIdent sourcekitd::KeyNameKind("key.namekind");
145+
UIdent sourcekitd::KeyLocalizationKey("key.localization_key");
145146

146147
/// \brief Order for the keys to use when emitting the debug description of
147148
/// dictionaries.

0 commit comments

Comments
 (0)