Skip to content

Commit cdd65d1

Browse files
committed
Use Clang node USR for decls synthesized for Error enums, and allow requesting the Swift USR.
The Error enum synthesized declarations, e.g. the struct and its static accessors, should generally appear to be identical to the underlying Clang definitions. There are some specific use cases where the synthesized declarations are necessary though. I've added an option for USR generation to override the Clang node and emit the USR of the synthesized Swift declaration. This is used by SwiftDocSupport so that the USRs of the synthesized declarations are emitted. Fixes 79912
1 parent 5a92bc5 commit cdd65d1

File tree

9 files changed

+119
-30
lines changed

9 files changed

+119
-30
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -713,20 +713,45 @@ class RequirementRequest :
713713
bool isCached() const;
714714
};
715715

716+
struct USRGenerationOptions {
717+
/// @brief Whether to emit USRs using the Swift declaration when it is
718+
// synthesized from a Clang based declaration. Useful in cases where Swift
719+
// declarations are synthesized from Clang nodes but the caller actually
720+
// wants the USR of the Swift declaration.
721+
bool emit_synthesized_decls;
722+
723+
friend llvm::hash_code hash_value(const USRGenerationOptions &options) {
724+
return llvm::hash_value(options.emit_synthesized_decls);
725+
}
726+
727+
friend bool operator==(const USRGenerationOptions &lhs,
728+
const USRGenerationOptions &rhs) {
729+
return lhs.emit_synthesized_decls == rhs.emit_synthesized_decls;
730+
}
731+
732+
friend bool operator!=(const USRGenerationOptions &lhs,
733+
const USRGenerationOptions &rhs) {
734+
return !(lhs == rhs);
735+
}
736+
};
737+
738+
void simple_display(llvm::raw_ostream &out,
739+
const USRGenerationOptions &options);
740+
716741
/// Generate the USR for the given declaration.
717-
class USRGenerationRequest :
718-
public SimpleRequest<USRGenerationRequest,
719-
std::string(const ValueDecl*),
720-
RequestFlags::Cached>
721-
{
742+
class USRGenerationRequest
743+
: public SimpleRequest<USRGenerationRequest,
744+
std::string(const ValueDecl *, USRGenerationOptions),
745+
RequestFlags::Cached> {
722746
public:
723747
using SimpleRequest::SimpleRequest;
724748

725749
private:
726750
friend SimpleRequest;
727751

728752
// Evaluation.
729-
std::string evaluate(Evaluator &eval, const ValueDecl *d) const;
753+
std::string evaluate(Evaluator &eval, const ValueDecl *d,
754+
USRGenerationOptions options) const;
730755

731756
public:
732757
// Caching

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ SWIFT_REQUEST(TypeChecker, TypeCheckASTNodeAtLocRequest,
366366
Uncached, NoLocationInfo)
367367
SWIFT_REQUEST(TypeChecker, UnderlyingTypeRequest, Type(TypeAliasDecl *),
368368
SeparatelyCached, NoLocationInfo)
369-
SWIFT_REQUEST(TypeChecker, USRGenerationRequest, std::string(const ValueDecl *),
369+
SWIFT_REQUEST(TypeChecker, USRGenerationRequest,
370+
std::string(const ValueDecl *, USRGenerationOptions),
370371
Cached, NoLocationInfo)
371372
SWIFT_REQUEST(TypeChecker, IsABICompatibleOverrideRequest,
372373
bool(ValueDecl *), Cached, NoLocationInfo)

include/swift/AST/USRGeneration.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ bool printDeclTypeUSR(const ValueDecl *D, raw_ostream &OS);
4444

4545
/// Prints out the USR for the given ValueDecl.
4646
/// \returns true if it failed, false on success.
47-
bool printValueDeclUSR(const ValueDecl *D, raw_ostream &OS);
47+
bool printValueDeclUSR(const ValueDecl *D, raw_ostream &OS,
48+
bool emit_synthesized_decls = false);
4849

4950
/// Prints out the USR for the given ModuleEntity.
5051
/// In case module aliasing is used, it prints the real module name. For example,

lib/AST/USRGeneration.cpp

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,26 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "swift/AST/USRGeneration.h"
1314
#include "swift/AST/ASTContext.h"
15+
#include "swift/AST/ASTMangler.h"
1416
#include "swift/AST/ClangModuleLoader.h"
1517
#include "swift/AST/GenericParamList.h"
1618
#include "swift/AST/Module.h"
17-
#include "swift/AST/USRGeneration.h"
18-
#include "swift/AST/ASTMangler.h"
1919
#include "swift/AST/SwiftNameTranslation.h"
2020
#include "swift/AST/TypeCheckRequests.h"
2121
#include "swift/AST/USRGeneration.h"
2222
#include "swift/Basic/Assertions.h"
23+
#include "swift/ClangImporter/ClangModule.h"
2324
#include "swift/Demangling/Demangler.h"
24-
#include "llvm/ADT/SmallString.h"
25-
#include "llvm/ADT/StringRef.h"
26-
#include "llvm/Support/raw_ostream.h"
2725
#include "clang/AST/ASTContext.h"
2826
#include "clang/AST/Attr.h"
2927
#include "clang/Index/USRGeneration.h"
3028
#include "clang/Lex/PreprocessingRecord.h"
3129
#include "clang/Lex/Preprocessor.h"
30+
#include "llvm/ADT/SmallString.h"
31+
#include "llvm/ADT/StringRef.h"
32+
#include "llvm/Support/raw_ostream.h"
3233

3334
using namespace swift;
3435
using namespace ide;
@@ -170,9 +171,15 @@ static bool shouldUseObjCUSR(const Decl *D) {
170171
return false;
171172
}
172173

174+
void swift::simple_display(llvm::raw_ostream &out,
175+
const USRGenerationOptions &options) {
176+
out << "USRGenerationOptions (emit_synthesized_decls: "
177+
<< options.emit_synthesized_decls << ")";
178+
}
179+
173180
std::string
174-
swift::USRGenerationRequest::evaluate(Evaluator &evaluator,
175-
const ValueDecl *D) const {
181+
swift::USRGenerationRequest::evaluate(Evaluator &evaluator, const ValueDecl *D,
182+
USRGenerationOptions options) const {
176183
if (auto *VD = dyn_cast<VarDecl>(D))
177184
D = VD->getCanonicalVarDecl();
178185

@@ -184,8 +191,10 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator,
184191
if (isa<ModuleDecl>(D))
185192
return std::string(); // Ignore.
186193

187-
auto interpretAsClangNode = [](const ValueDecl *D)->ClangNode {
188-
ClangNode ClangN = D->getClangNode();
194+
auto interpretAsClangNode = [&options](const ValueDecl *D) -> ClangNode {
195+
auto &ctx = D->getASTContext();
196+
auto *importer = static_cast<ClangImporter *>(ctx.getClangModuleLoader());
197+
ClangNode ClangN = importer->getEffectiveClangNode(D);
189198
if (auto ClangD = ClangN.getAsDecl()) {
190199
// NSErrorDomain causes the clang enum to be imported like this:
191200
//
@@ -203,10 +212,17 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator,
203212
// But we want unique USRs for the above symbols, so use the clang USR
204213
// for the enum cases, and the Swift USR for the vars.
205214
//
206-
if (auto *ClangEnumConst = dyn_cast<clang::EnumConstantDecl>(ClangD)) {
207-
if (auto *ClangEnum = dyn_cast<clang::EnumDecl>(ClangEnumConst->getDeclContext())) {
208-
if (ClangEnum->hasAttr<clang::NSErrorDomainAttr>() && isa<VarDecl>(D))
209-
return ClangNode();
215+
if (options.emit_synthesized_decls) {
216+
if (auto *ClangEnumConst = dyn_cast<clang::EnumConstantDecl>(ClangD)) {
217+
if (auto *ClangEnum =
218+
dyn_cast<clang::EnumDecl>(ClangEnumConst->getDeclContext())) {
219+
if (ClangEnum->hasAttr<clang::NSErrorDomainAttr>() &&
220+
isa<VarDecl>(D))
221+
return ClangNode();
222+
}
223+
}
224+
if (D->getAttrs().hasAttribute<ClangImporterSynthesizedTypeAttr>()) {
225+
return ClangNode();
210226
}
211227
}
212228
}
@@ -292,10 +308,11 @@ bool ide::printModuleUSR(ModuleEntity Mod, raw_ostream &OS) {
292308
}
293309
}
294310

295-
bool ide::printValueDeclUSR(const ValueDecl *D, raw_ostream &OS) {
296-
auto result = evaluateOrDefault(D->getASTContext().evaluator,
297-
USRGenerationRequest { D },
298-
std::string());
311+
bool ide::printValueDeclUSR(const ValueDecl *D, raw_ostream &OS,
312+
bool emit_synthesized_decls) {
313+
auto result = evaluateOrDefault(
314+
D->getASTContext().evaluator,
315+
USRGenerationRequest{D, {emit_synthesized_decls}}, std::string());
299316
if (result.empty())
300317
return true;
301318
OS << result;

lib/PrintAsClang/ClangSyntaxPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ void ClangSyntaxPrinter::printSymbolUSRAttribute(const ValueDecl *D) const {
472472
return;
473473
}
474474
auto result = evaluateOrDefault(D->getASTContext().evaluator,
475-
USRGenerationRequest{D}, std::string());
475+
USRGenerationRequest{D, {}}, std::string());
476476
if (result.empty())
477477
return;
478478
os << " SWIFT_SYMBOL(\"" << result << "\")";

test/Index/index_imported_objc.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@
2121
@property int categoryAddedProperty;
2222
@end
2323
24+
extern NSErrorDomain const TestErrorDomain;
25+
26+
typedef NS_ERROR_ENUM(TestErrorDomain, TestError){
27+
TestErrorFoo = 0,
28+
TestErrorBar = 1,
29+
};
30+
31+
typedef NS_ENUM(NSInteger, ErrCategory) {
32+
ErrCategoryA = 0,
33+
ErrCategoryB = 1,
34+
};
35+
2436
//--- module.modulemap
2537
module objc_decls {
2638
header "objc_decls.h"
@@ -48,3 +60,34 @@ class SubObjCClass: ObjCClass {
4860
// CHECK-NEXT: RelOver | instance-method/Swift | protocolAddedMethod() | c:objc(pl)MemberAdding(im)protocolAddedMethod
4961
// CHECK-NEXT: RelChild | class/Swift | SubObjCClass | c:@M@swift_ide_test@objc(cs)SubObjCClass
5062
}
63+
func testEnumIndex() {
64+
let _: TestError.Code = .bar
65+
// CHECK: [[@LINE-1]]:10 | struct/Swift | TestError | c:@E@TestError | Ref | rel: 0
66+
// CHECK: [[@LINE-2]]:20 | enum/Swift | Code | c:@E@TestError | Ref,RelCont | rel: 1
67+
// CHECK: [[@LINE-3]]:28 | enumerator/Swift | bar | c:@E@TestError@TestErrorBar | Ref,RelCont | rel: 1
68+
let e = TestError.foo
69+
// CHECK: [[@LINE-1]]:11 | struct/Swift | TestError | c:@E@TestError | Ref,RelCont | rel: 1
70+
// CHECK: [[@LINE-2]]:21 | static-property/Swift | foo | c:@E@TestError@TestErrorFoo | Ref,Read,RelCont | rel: 1
71+
switch e {
72+
case TestError.foo: break
73+
// CHECK: [[@LINE-1]]:10 | struct/Swift | TestError | c:@E@TestError | Ref,RelCont | rel: 1
74+
// CHECK: [[@LINE-2]]:20 | static-property/Swift | foo | c:@E@TestError@TestErrorFoo | Ref,Read,RelCont | rel: 1
75+
case .bar: break
76+
// CHECK: [[@LINE-1]]:11 | enumerator/Swift | bar | c:@E@TestError@TestErrorBar | Ref,RelCont | rel: 1
77+
default: break
78+
}
79+
let _ = ErrCategory.B
80+
// CHECK: [[@LINE-1]]:11 | enum/Swift | ErrCategory | c:@E@ErrCategory | Ref,RelCont | rel: 1
81+
// CHECK: [[@LINE-2]]:23 | enumerator/Swift | B | c:@E@ErrCategory@ErrCategoryB | Ref,RelCont | rel: 1
82+
let c: ErrCategory = .A
83+
// CHECK: [[@LINE-1]]:10 | enum/Swift | ErrCategory | c:@E@ErrCategory | Ref,RelCont | rel: 1
84+
// CHECK: [[@LINE-2]]:25 | enumerator/Swift | A | c:@E@ErrCategory@ErrCategoryA | Ref,RelCont | rel: 1
85+
switch c {
86+
case ErrCategory.A: break
87+
// CHECK: [[@LINE-1]]:22 | enumerator/Swift | A | c:@E@ErrCategory@ErrCategoryA | Ref,RelCont | rel: 1
88+
// CHECK: [[@LINE-2]]:10 | enum/Swift | ErrCategory | c:@E@ErrCategory | Ref,RelCont | rel: 1
89+
// CHECK: [[@LINE-3]]:22 | enum/Swift | ErrCategory | c:@E@ErrCategory | Ref,RelCont | rel: 1
90+
case .B: break
91+
// CHECK: [[@LINE-1]]:11 | enumerator/Swift | B | c:@E@ErrCategory@ErrCategoryB | Ref,RelCont | rel: 1
92+
}
93+
}

tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ static bool initDocEntityInfo(const Decl *D,
431431
SwiftLangSupport::printDisplayName(VD, NameOS);
432432
{
433433
llvm::raw_svector_ostream OS(Info.USR);
434-
SwiftLangSupport::printUSR(VD, OS);
434+
SwiftLangSupport::printUSR(VD, OS, true);
435435
if (SynthesizedTarget) {
436436
OS << SwiftLangSupport::SynthesizedUSRSeparator;
437437
SwiftLangSupport::printUSR(SynthesizedTargetNTD, OS);

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -898,8 +898,9 @@ bool SwiftLangSupport::printDisplayName(const swift::ValueDecl *D,
898898
return false;
899899
}
900900

901-
bool SwiftLangSupport::printUSR(const ValueDecl *D, llvm::raw_ostream &OS) {
902-
return ide::printValueDeclUSR(D, OS);
901+
bool SwiftLangSupport::printUSR(const ValueDecl *D, llvm::raw_ostream &OS,
902+
bool emit_synthesized_decls) {
903+
return ide::printValueDeclUSR(D, OS, emit_synthesized_decls);
903904
}
904905

905906
bool SwiftLangSupport::printDeclTypeUSR(const ValueDecl *D, llvm::raw_ostream &OS) {

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,8 @@ class SwiftLangSupport : public LangSupport {
457457

458458
/// Generate a USR for a Decl, including the prefix.
459459
/// \returns true if the results should be ignored, false otherwise.
460-
static bool printUSR(const swift::ValueDecl *D, llvm::raw_ostream &OS);
460+
static bool printUSR(const swift::ValueDecl *D, llvm::raw_ostream &OS,
461+
bool emit_synthesized_decls = false);
461462

462463
/// Generate a USR for the Type of a given decl.
463464
/// \returns true if the results should be ignored, false otherwise.

0 commit comments

Comments
 (0)