Skip to content

Commit 747c7cf

Browse files
authored
Merge pull request swiftlang#41139 from rintaro/ide-completion-rdar80602940
[CodeCompletion] Handle clang async attributes for visibilities
2 parents 74dc00f + a9bbc1f commit 747c7cf

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

lib/AST/Decl.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3368,8 +3368,32 @@ bool ValueDecl::shouldHideFromEditor() const {
33683368
if (AvailableAttr::isUnavailable(this))
33693369
return true;
33703370

3371+
// Hide 'swift_private' clang decls. They are imported with '__' prefix.
33713372
if (auto *ClangD = getClangDecl()) {
3372-
if (ClangD->hasAttr<clang::SwiftPrivateAttr>())
3373+
bool bypassSwiftPrivate = false;
3374+
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(this)) {
3375+
if (AFD->getForeignAsyncConvention().hasValue()) {
3376+
// For imported 'async' declartions, visibility can be controlled by
3377+
// 'swift_async(...)' attribute.
3378+
if (auto *asyncAttr = ClangD->getAttr<clang::SwiftAsyncAttr>()) {
3379+
bypassSwiftPrivate = true;
3380+
switch (asyncAttr->getKind()) {
3381+
case clang::SwiftAsyncAttr::None:
3382+
// Should be unreachable.
3383+
return true;
3384+
case clang::SwiftAsyncAttr::SwiftPrivate:
3385+
// Hide 'swift_async(swift_private, ...)'.
3386+
return true;
3387+
case clang::SwiftAsyncAttr::NotSwiftPrivate:
3388+
break;
3389+
}
3390+
} else if (ClangD->getAttr<clang::SwiftAsyncNameAttr>()) {
3391+
// Manually specifying the name bypasses 'swift_private' attr.
3392+
bypassSwiftPrivate = true;
3393+
}
3394+
}
3395+
}
3396+
if (!bypassSwiftPrivate && ClangD->hasAttr<clang::SwiftPrivateAttr>())
33733397
return true;
33743398
}
33753399

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// REQUIRES: objc_interop
2+
// REQUIRES: concurrency
3+
4+
// RUN: %empty-directory(%t)
5+
// RUN: %empty-directory(%t/out)
6+
// RUN: split-file %s %t
7+
// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -swift-version 5.6 -batch-code-completion -source-filename %t/test.swift -filecheck %raw-FileCheck -completion-output-dir %t/out -import-objc-header %t/ObjC.h -enable-objc-interop
8+
9+
10+
//--- ObjC.h
11+
12+
13+
@import Foundation;
14+
15+
_Pragma("clang assume_nonnull begin")
16+
17+
@interface MyObjCClass: NSObject
18+
19+
- (void)method1WithCompletionHandler:(void (^)(NSError * _Nullable err))completionHandler;
20+
- (void)method2WithCompletionHandler:(void (^)(NSError * _Nullable err))completionHandler __attribute__((swift_private));
21+
- (void)method3WithCompletionHandler:(void (^)(NSError * _Nullable err))completionHandler __attribute__((swift_private)) __attribute__((swift_async_name("named3()")));
22+
- (void)method4WithCompletionHandler:(void (^)(NSError * _Nullable err))completionHandler __attribute__((swift_async(swift_private, 1)));
23+
- (void)method5WithCompletionHandler:(void (^)(NSError * _Nullable err))completionHandler __attribute__((swift_async(swift_private, 1))) __attribute__((swift_async_name("named5()")));
24+
- (void)method6WithCompletionHandler:(void (^)(NSError * _Nullable err))completionHandler __attribute__((swift_async(not_swift_private, 1)));
25+
- (void)method7WithCompletionHandler:(void (^)(NSError * _Nullable err))completionHandler __attribute__((swift_async(not_swift_private, 1))) __attribute__((swift_async_name("named7()")));
26+
27+
@end
28+
29+
_Pragma("clang assume_nonnull end")
30+
31+
//--- test.swift
32+
33+
func test(obj: MyObjCClass) async throws {
34+
obj.#^COMPLETE^#
35+
// COMPLETE: Begin completions
36+
// COMPLETE-NOT: method2(
37+
// COMPLETE-NOT: method4()
38+
// COMPLETE-NOT: method5()
39+
// COMPLETE-DAG: Keyword[self]/CurrNominal: self[#MyObjCClass#]; name=self
40+
// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: method1({#completionHandler: (Error?) -> Void##(Error?) -> Void#})[#Void#];
41+
// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: method1()[' async'][' throws'][#Void#];
42+
// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: named3()[' async'][' throws'][#Void#];
43+
// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: method4({#completionHandler: (Error?) -> Void##(Error?) -> Void#})[#Void#];
44+
// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: method5({#completionHandler: (Error?) -> Void##(Error?) -> Void#})[#Void#];
45+
// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: method6({#completionHandler: (Error?) -> Void##(Error?) -> Void#})[#Void#];
46+
// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: method6()[' async'][' throws'][#Void#];
47+
// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: method7({#completionHandler: (Error?) -> Void##(Error?) -> Void#})[#Void#];
48+
// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: named7()[' async'][' throws'][#Void#];
49+
// COMPLETE: End completions
50+
}

0 commit comments

Comments
 (0)