Skip to content

Commit 8d09160

Browse files
committed
[Completion] Add convertible type relation for attached macros
Resolves rdar://108678938.
1 parent db14ae8 commit 8d09160

File tree

8 files changed

+71
-80
lines changed

8 files changed

+71
-80
lines changed

include/swift/IDE/CodeCompletionResult.h

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ CodeCompletionMacroRoles getCompletionMacroRoles(CodeCompletionFilter filter);
349349

350350
CodeCompletionFilter getCompletionFilter(CodeCompletionMacroRoles roles);
351351

352+
CodeCompletionResultTypeRelation getMacroTypeRelation(CodeCompletionMacroRoles roles,
353+
OptionSet<CustomAttributeKind> expectedKinds);
354+
352355
/// The parts of a \c CodeCompletionResult that are not dependent on the context
353356
/// it appears in and can thus be cached.
354357
class ContextFreeCodeCompletionResult {
@@ -545,9 +548,11 @@ class ContextFreeCodeCompletionResult {
545548

546549
const CodeCompletionResultType &getResultType() const { return ResultType; }
547550

548-
ContextFreeNotRecommendedReason getNotRecommendedReason() const {
549-
return NotRecommended;
550-
}
551+
ContextFreeNotRecommendedReason getNotRecommendedReason() const { return NotRecommended; }
552+
553+
ContextualNotRecommendedReason calculateContextualNotRecommendedReason(ContextualNotRecommendedReason explicitReason, bool canCurrDeclContextHandleAsync) const;
554+
555+
CodeCompletionResultTypeRelation calculateContextualTypeRelation(const DeclContext *dc, const ExpectedTypeContext *typeContext, const USRBasedTypeContext *usrTypeContext) const;
551556

552557
CodeCompletionDiagnosticSeverity getDiagnosticSeverity() const {
553558
return DiagnosticSeverity;
@@ -611,6 +616,7 @@ class CodeCompletionResult {
611616
CodeCompletionResultTypeRelation TypeDistance : 3;
612617
static_assert(int(CodeCompletionResultTypeRelation::MAX_VALUE) < 1 << 3, "");
613618

619+
public:
614620
/// Memberwise initializer
615621
/// The \c ContextFree result must outlive this result. Typically, this is
616622
/// done by allocating the two in the same sink or adopting the context free
@@ -624,25 +630,6 @@ class CodeCompletionResult {
624630
Flair(Flair.toRaw()), NotRecommended(NotRecommended),
625631
NumBytesToErase(NumBytesToErase), TypeDistance(TypeDistance) {}
626632

627-
public:
628-
/// Enrich a \c ContextFreeCodeCompletionResult with the following contextual
629-
/// information.
630-
/// This computes the type relation between the completion item and its
631-
/// expected type context.
632-
/// See \c CodeCompletionResultType::calculateTypeRelation for documentation
633-
/// on \p USRTypeContext.
634-
/// The \c ContextFree result must outlive this result. Typically, this is
635-
/// done by allocating the two in the same sink or adopting the context free
636-
/// sink in the sink that allocates this result.
637-
CodeCompletionResult(const ContextFreeCodeCompletionResult &ContextFree,
638-
SemanticContextKind SemanticContext,
639-
CodeCompletionFlair Flair, uint8_t NumBytesToErase,
640-
const ExpectedTypeContext *TypeContext,
641-
const DeclContext *DC,
642-
const USRBasedTypeContext *USRTypeContext,
643-
bool CanCurrDeclContextHandleAsync,
644-
ContextualNotRecommendedReason NotRecommended);
645-
646633
const ContextFreeCodeCompletionResult &getContextFreeResult() const {
647634
return ContextFree;
648635
}

lib/IDE/CodeCompletionConsumer.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,15 @@ static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
8080
if (!shouldIncludeResult(contextFreeResult)) {
8181
continue;
8282
}
83+
84+
CodeCompletionResultTypeRelation typeRelation =
85+
contextFreeResult->calculateContextualTypeRelation(DC, TypeContext, &USRTypeContext);
86+
ContextualNotRecommendedReason notRecommendedReason = contextFreeResult->calculateContextualNotRecommendedReason(ContextualNotRecommendedReason::None, CanCurrDeclContextHandleAsync);
87+
8388
auto contextualResult = new (*targetSink.Allocator) CodeCompletionResult(
8489
*contextFreeResult, SemanticContextKind::OtherModule,
8590
CodeCompletionFlair(),
86-
/*numBytesToErase=*/0, TypeContext, DC, &USRTypeContext,
87-
CanCurrDeclContextHandleAsync, ContextualNotRecommendedReason::None);
91+
/*numBytesToErase=*/0, typeRelation, notRecommendedReason);
8892
targetSink.Results.push_back(contextualResult);
8993
}
9094

lib/IDE/CodeCompletionResult.cpp

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,16 @@ swift::ide::getCompletionFilter(CodeCompletionMacroRoles roles) {
114114
return filter;
115115
}
116116

117+
CodeCompletionResultTypeRelation swift::ide::getMacroTypeRelation(
118+
CodeCompletionMacroRoles roles,
119+
OptionSet<CustomAttributeKind> expectedKinds) {
120+
CodeCompletionMacroRoles expectedRoles = getCompletionMacroRoles(expectedKinds);
121+
if (roles & expectedRoles) {
122+
return CodeCompletionResultTypeRelation::Convertible;
123+
}
124+
return CodeCompletionResultTypeRelation::Unrelated;
125+
}
126+
117127
// MARK: - ContextFreeCodeCompletionResult
118128

119129
ContextFreeCodeCompletionResult *
@@ -392,39 +402,31 @@ bool ContextFreeCodeCompletionResult::getDeclIsSystem(const Decl *D) {
392402
return D->getModuleContext()->isNonUserModule();
393403
}
394404

395-
// MARK: - CodeCompletionResult
396-
397-
static ContextualNotRecommendedReason
398-
getNotRecommenedReason(const ContextFreeCodeCompletionResult &ContextFree,
399-
bool CanCurrDeclContextHandleAsync,
400-
ContextualNotRecommendedReason ExplicitReason) {
401-
if (ExplicitReason != ContextualNotRecommendedReason::None) {
402-
return ExplicitReason;
405+
ContextualNotRecommendedReason ContextFreeCodeCompletionResult::calculateContextualNotRecommendedReason(ContextualNotRecommendedReason explicitReason, bool canCurrDeclContextHandleAsync) const {
406+
if (explicitReason != ContextualNotRecommendedReason::None) {
407+
return explicitReason;
403408
}
404-
if (ContextFree.isAsync() && !CanCurrDeclContextHandleAsync) {
409+
if (IsAsync && !canCurrDeclContextHandleAsync) {
405410
return ContextualNotRecommendedReason::InvalidAsyncContext;
406411
}
407-
if (ContextFree.hasAsyncAlternative() && CanCurrDeclContextHandleAsync) {
408-
return ContextualNotRecommendedReason::
409-
NonAsyncAlternativeUsedInAsyncContext;
412+
if (HasAsyncAlternative && canCurrDeclContextHandleAsync) {
413+
return ContextualNotRecommendedReason::NonAsyncAlternativeUsedInAsyncContext;
410414
}
411415
return ContextualNotRecommendedReason::None;
412416
}
413417

414-
CodeCompletionResult::CodeCompletionResult(
415-
const ContextFreeCodeCompletionResult &ContextFree,
416-
SemanticContextKind SemanticContext, CodeCompletionFlair Flair,
417-
uint8_t NumBytesToErase, const ExpectedTypeContext *TypeContext,
418-
const DeclContext *DC, const USRBasedTypeContext *USRTypeContext,
419-
bool CanCurrDeclContextHandleAsync,
420-
ContextualNotRecommendedReason NotRecommended)
421-
: ContextFree(ContextFree), SemanticContext(SemanticContext),
422-
Flair(Flair.toRaw()),
423-
NotRecommended(getNotRecommenedReason(
424-
ContextFree, CanCurrDeclContextHandleAsync, NotRecommended)),
425-
NumBytesToErase(NumBytesToErase),
426-
TypeDistance(ContextFree.getResultType().calculateTypeRelation(
427-
TypeContext, DC, USRTypeContext)) {}
418+
CodeCompletionResultTypeRelation ContextFreeCodeCompletionResult::calculateContextualTypeRelation(const DeclContext *dc, const ExpectedTypeContext *typeContext, const USRBasedTypeContext *usrTypeContext) const {
419+
CodeCompletionResultTypeRelation typeRelation = getResultType().calculateTypeRelation(typeContext, dc, usrTypeContext);
420+
if (typeRelation >= CodeCompletionResultTypeRelation::Convertible || !typeContext)
421+
return typeRelation;
422+
423+
CodeCompletionMacroRoles expectedRoles = getCompletionMacroRoles(typeContext->getExpectedCustomAttributeKinds());
424+
if (MacroRoles & expectedRoles)
425+
return CodeCompletionResultTypeRelation::Convertible;
426+
return typeRelation;
427+
}
428+
429+
// MARK: - CodeCompletionResult
428430

429431
CodeCompletionResult *
430432
CodeCompletionResult::withFlair(CodeCompletionFlair NewFlair,

lib/IDE/CodeCompletionResultBuilder.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,22 +162,23 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
162162
// we don't need to compute any contextual properties.
163163
return new (Allocator) CodeCompletionResult(
164164
*ContextFreeResult, SemanticContextKind::None, CodeCompletionFlair(),
165-
/*NumBytesToErase=*/0, /*TypeContext=*/nullptr,
166-
/*DC=*/nullptr, /*USRTypeContext=*/nullptr,
167-
/*CanCurrDeclContextHandleAsync=*/false,
168-
ContextualNotRecommendedReason::None);
165+
/*NumBytesToErase=*/0, CodeCompletionResultTypeRelation::Unrelated, ContextualNotRecommendedReason::None);
169166
} else {
170167
assert(
171168
ContextFreeResult != nullptr &&
172169
"ContextFreeResult should have been constructed by the switch above");
170+
173171
// We know that the ContextFreeResult has an AST-based type because it was
174172
// just computed and not read from the cache and
175173
// Sink.shouldProduceContextFreeResults() is false. So we can pass nullptr
176174
// for USRTypeContext.
175+
CodeCompletionResultTypeRelation typeRelation =
176+
ContextFreeResult->calculateContextualTypeRelation(DC, TypeContext, /*usrTypeContext=*/nullptr);
177+
ContextualNotRecommendedReason notRecommendedReason = ContextFreeResult->calculateContextualNotRecommendedReason(ContextualNotRecReason, CanCurrDeclContextHandleAsync);
178+
177179
return new (Allocator) CodeCompletionResult(
178180
*ContextFreeResult, SemanticContext, Flair, NumBytesToErase,
179-
TypeContext, DC, /*USRTypeContext=*/nullptr,
180-
CanCurrDeclContextHandleAsync, ContextualNotRecReason);
181+
typeRelation, notRecommendedReason);
181182
}
182183
}
183184

test/IDE/complete_macros.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ import MacroDefinitions
6565
@#^STRUCT_ATTR?check=NOMINAL_ATTR^# struct S{}
6666
// NOMINAL_ATTR-NOT: freestanding
6767
// NOMINAL_ATTR-NOT: AttachedAccessorMacro
68-
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberMacro[#Void#]; name=AttachedMemberMacro
69-
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberMacroWithArgs({#arg1: Int#})[#Void#]; name=AttachedMemberMacroWithArgs
70-
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberAttributeMacro[#Void#]; name=AttachedMemberAttributeMacro
71-
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro
72-
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedConformanceMacro[#Void#]; name=AttachedConformanceMacro
73-
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro
68+
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedMemberMacro[#Void#]; name=AttachedMemberMacro
69+
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedMemberMacroWithArgs({#arg1: Int#})[#Void#]; name=AttachedMemberMacroWithArgs
70+
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedMemberAttributeMacro[#Void#]; name=AttachedMemberAttributeMacro
71+
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro
72+
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedConformanceMacro[#Void#]; name=AttachedConformanceMacro
73+
// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: EverythingMacro[#Void#]; name=EverythingMacro
7474

7575
@#^FUNC_ATTR?check=DECL_ATTR^# func method() {}
7676
struct MethodAttrs {
@@ -83,8 +83,8 @@ struct MethodAttrs {
8383
// DECL_ATTR-NOT: AttachedMemberMacro
8484
// DECL_ATTR-NOT: AttachedMemberMacroWithArgs
8585
// DECL_ATTR-NOT: AttachedConformanceMacro
86-
// DECL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro
87-
// DECL_ATTR-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro
86+
// DECL_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro
87+
// DECL_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: EverythingMacro[#Void#]; name=EverythingMacro
8888

8989
@#^GLOBAL_ATTR?check=VAR_ATTR^# var globalVar
9090
struct PropAttr {
@@ -98,9 +98,9 @@ struct PropAttr {
9898
// VAR_ATTR-NOT: AttachedMemberMacroWithArgs
9999
// VAR_ATTR-NOT: AttachedMemberAttributeMacro
100100
// VAR_ATTR-NOT: AttachedConformanceMacro
101-
// VAR_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedAccessorMacro[#Void#]; name=AttachedAccessorMacro
102-
// VAR_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro
103-
// VAR_ATTR-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro
101+
// VAR_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedAccessorMacro[#Void#]; name=AttachedAccessorMacro
102+
// VAR_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro
103+
// VAR_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: EverythingMacro[#Void#]; name=EverythingMacro
104104

105105
func paramAttr(@#^PARAM_ATTR?check=PARAM_ATTR^#) {}
106106
func paramAttr2(@#^PARAM2_ATTR?check=PARAM_ATTR^# arg: Int) {}
@@ -163,10 +163,10 @@ struct LastMember {
163163
@#^INDEPENDENT?check=INDEPENDENT_ATTR^#
164164
// INDEPENDENT_ATTR-NOT: freestandingExprMacro
165165
// INDEPENDENT_ATTR-NOT: freestandingDeclMacro
166-
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedAccessorMacro[#Void#]; name=AttachedAccessorMacro
167-
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberMacro[#Void#]; name=AttachedMemberMacro
168-
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberMacroWithArgs({#arg1: Int#})[#Void#]; name=AttachedMemberMacroWithArgs
169-
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberAttributeMacro[#Void#]; name=AttachedMemberAttributeMacro
170-
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro
171-
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedConformanceMacro[#Void#]; name=AttachedConformanceMacro
172-
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro
166+
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedAccessorMacro[#Void#]; name=AttachedAccessorMacro
167+
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedMemberMacro[#Void#]; name=AttachedMemberMacro
168+
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedMemberMacroWithArgs({#arg1: Int#})[#Void#]; name=AttachedMemberMacroWithArgs
169+
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedMemberAttributeMacro[#Void#]; name=AttachedMemberAttributeMacro
170+
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro
171+
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: AttachedConformanceMacro[#Void#]; name=AttachedConformanceMacro
172+
// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: EverythingMacro[#Void#]; name=EverythingMacro

tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,7 @@ bool SourceKit::CodeCompletion::addCustomCompletions(
142142
auto *swiftResult = new (sink.allocator) CodeCompletion::SwiftResult(
143143
*contextFreeResult, SemanticContextKind::Local,
144144
CodeCompletionFlairBit::ExpressionSpecific,
145-
/*NumBytesToErase=*/0, /*TypeContext=*/nullptr, /*DC=*/nullptr,
146-
/*USRTypeContext=*/nullptr, /*CanCurrDeclContextHandleAsync=*/false,
145+
/*NumBytesToErase=*/0, CodeCompletionResultTypeRelation::Unrelated,
147146
ContextualNotRecommendedReason::None);
148147

149148
CompletionBuilder builder(sink, *swiftResult);

tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -920,8 +920,7 @@ static void transformAndForwardResults(
920920
*contextFreeResult, SemanticContextKind::CurrentNominal,
921921
CodeCompletionFlairBit::ExpressionSpecific,
922922
exactMatch ? exactMatch->getNumBytesToErase() : 0,
923-
/*TypeContext=*/nullptr, /*DC=*/nullptr, /*USRTypeContext=*/nullptr,
924-
/*CanCurrDeclContextHandleAsync=*/false,
923+
CodeCompletionResultTypeRelation::Unrelated,
925924
ContextualNotRecommendedReason::None);
926925

927926
SwiftCompletionInfo info;

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4310,8 +4310,7 @@ int main(int argc, char *argv[]) {
43104310
auto contextualResult = new CodeCompletionResult(
43114311
*contextFreeResult, SemanticContextKind::OtherModule,
43124312
CodeCompletionFlair(),
4313-
/*numBytesToErase=*/0, /*TypeContext=*/nullptr, /*DC=*/nullptr,
4314-
/*USRTypeContext=*/nullptr, /*CanCurrDeclContextHandleAsync=*/false,
4313+
/*numBytesToErase=*/0, CodeCompletionResultTypeRelation::Unrelated,
43154314
ContextualNotRecommendedReason::None);
43164315
contextualResults.push_back(contextualResult);
43174316
}

0 commit comments

Comments
 (0)