mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[CodeCompletion] Suggest #selector and #keyPath after # only if applicable
Also, add type annotation, and make it `TypeRelation[Identical]`. 'ExprSpecific' is too strong.
This commit is contained in:
@@ -2246,15 +2246,9 @@ public:
|
||||
// #selector is only available when the Objective-C runtime is.
|
||||
if (!Ctx.LangOpts.EnableObjCInterop) return;
|
||||
|
||||
// After #, this is a very likely result. When just in a String context,
|
||||
// it's not.
|
||||
auto semanticContext = needPound ? SemanticContextKind::None
|
||||
: SemanticContextKind::ExpressionSpecific;
|
||||
|
||||
CodeCompletionResultBuilder Builder(
|
||||
Sink,
|
||||
CodeCompletionResult::ResultKind::Keyword,
|
||||
semanticContext, expectedTypeContext);
|
||||
Sink, CodeCompletionResult::ResultKind::Keyword,
|
||||
SemanticContextKind::None, {});
|
||||
if (needPound)
|
||||
Builder.addTextChunk("#selector");
|
||||
else
|
||||
@@ -2262,21 +2256,19 @@ public:
|
||||
Builder.addLeftParen();
|
||||
Builder.addSimpleTypedParameter("@objc method", /*IsVarArg=*/false);
|
||||
Builder.addRightParen();
|
||||
Builder.addTypeAnnotation("Selector");
|
||||
// This function is called only if the context type is 'Selector'.
|
||||
Builder.setExpectedTypeRelation(
|
||||
CodeCompletionResult::ExpectedTypeRelation::Identical);
|
||||
}
|
||||
|
||||
void addPoundKeyPath(bool needPound) {
|
||||
// #keyPath is only available when the Objective-C runtime is.
|
||||
if (!Ctx.LangOpts.EnableObjCInterop) return;
|
||||
|
||||
// After #, this is a very likely result. When just in a String context,
|
||||
// it's not.
|
||||
auto semanticContext = needPound ? SemanticContextKind::None
|
||||
: SemanticContextKind::ExpressionSpecific;
|
||||
|
||||
CodeCompletionResultBuilder Builder(
|
||||
Sink,
|
||||
CodeCompletionResult::ResultKind::Keyword,
|
||||
semanticContext, expectedTypeContext);
|
||||
Sink, CodeCompletionResult::ResultKind::Keyword,
|
||||
SemanticContextKind::None, {});
|
||||
if (needPound)
|
||||
Builder.addTextChunk("#keyPath");
|
||||
else
|
||||
@@ -2285,6 +2277,10 @@ public:
|
||||
Builder.addSimpleTypedParameter("@objc property sequence",
|
||||
/*IsVarArg=*/false);
|
||||
Builder.addRightParen();
|
||||
Builder.addTypeAnnotation("String");
|
||||
// This function is called only if the context type is 'String'.
|
||||
Builder.setExpectedTypeRelation(
|
||||
CodeCompletionResult::ExpectedTypeRelation::Identical);
|
||||
}
|
||||
|
||||
SemanticContextKind getSemanticContextKind(const ValueDecl *VD) {
|
||||
@@ -3679,6 +3675,38 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void addObjCPoundKeywordCompletions(bool needPound) {
|
||||
if (!Ctx.LangOpts.EnableObjCInterop)
|
||||
return;
|
||||
|
||||
// If the expected type is ObjectiveC.Selector, add #selector. If
|
||||
// it's String, add #keyPath.
|
||||
bool addedSelector = false;
|
||||
bool addedKeyPath = false;
|
||||
|
||||
for (auto T : expectedTypeContext.possibleTypes) {
|
||||
T = T->lookThroughAllOptionalTypes();
|
||||
if (auto structDecl = T->getStructOrBoundGenericStruct()) {
|
||||
if (!addedSelector && structDecl->getName() == Ctx.Id_Selector &&
|
||||
structDecl->getParentModule()->getName() == Ctx.Id_ObjectiveC) {
|
||||
addPoundSelector(needPound);
|
||||
if (addedKeyPath)
|
||||
break;
|
||||
addedSelector = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!addedKeyPath && T->getAnyNominal() == Ctx.getStringDecl()) {
|
||||
addPoundKeyPath(needPound);
|
||||
if (addedSelector)
|
||||
break;
|
||||
addedKeyPath = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FilteredDeclConsumer : public swift::VisibleDeclConsumer {
|
||||
swift::VisibleDeclConsumer &Consumer;
|
||||
DeclFilter Filter;
|
||||
@@ -3742,33 +3770,7 @@ public:
|
||||
addPoundLiteralCompletions(/*needPound=*/true);
|
||||
}
|
||||
|
||||
|
||||
// If the expected type is ObjectiveC.Selector, add #selector. If
|
||||
// it's String, add #keyPath.
|
||||
if (Ctx.LangOpts.EnableObjCInterop) {
|
||||
bool addedSelector = false;
|
||||
bool addedKeyPath = false;
|
||||
for (auto T : expectedTypeContext.possibleTypes) {
|
||||
T = T->lookThroughAllOptionalTypes();
|
||||
if (auto structDecl = T->getStructOrBoundGenericStruct()) {
|
||||
if (!addedSelector &&
|
||||
structDecl->getName() == Ctx.Id_Selector &&
|
||||
structDecl->getParentModule()->getName() == Ctx.Id_ObjectiveC) {
|
||||
addPoundSelector(/*needPound=*/true);
|
||||
if (addedKeyPath) break;
|
||||
addedSelector = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!addedKeyPath && T->getAnyNominal() == Ctx.getStringDecl()) {
|
||||
addPoundKeyPath(/*needPound=*/true);
|
||||
if (addedSelector) break;
|
||||
addedKeyPath = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
addObjCPoundKeywordCompletions(/*needPound=*/true);
|
||||
}
|
||||
|
||||
void getUnresolvedMemberCompletions(Type T) {
|
||||
@@ -5475,8 +5477,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
|
||||
|
||||
Lookup.addPoundAvailable(ParentStmtKind);
|
||||
Lookup.addPoundLiteralCompletions(/*needPound=*/false);
|
||||
Lookup.addPoundSelector(/*needPound=*/false);
|
||||
Lookup.addPoundKeyPath(/*needPound=*/false);
|
||||
Lookup.addObjCPoundKeywordCompletions(/*needPound=*/false);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user