Skip to content

Commit 05ebc79

Browse files
committed
[Completion] Add convertible type relation for attached macros
Resolves rdar://108678938. (cherry picked from commit f7d1cc8)
1 parent 554cce9 commit 05ebc79

File tree

8 files changed

+77
-75
lines changed

8 files changed

+77
-75
lines changed

include/swift/IDE/CodeCompletionResult.h

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,14 @@ class ContextFreeCodeCompletionResult {
549549
return NotRecommended;
550550
}
551551

552+
ContextualNotRecommendedReason calculateContextualNotRecommendedReason(
553+
ContextualNotRecommendedReason explicitReason,
554+
bool canCurrDeclContextHandleAsync) const;
555+
556+
CodeCompletionResultTypeRelation calculateContextualTypeRelation(
557+
const DeclContext *dc, const ExpectedTypeContext *typeContext,
558+
const USRBasedTypeContext *usrTypeContext) const;
559+
552560
CodeCompletionDiagnosticSeverity getDiagnosticSeverity() const {
553561
return DiagnosticSeverity;
554562
}
@@ -611,6 +619,7 @@ class CodeCompletionResult {
611619
CodeCompletionResultTypeRelation TypeDistance : 3;
612620
static_assert(int(CodeCompletionResultTypeRelation::MAX_VALUE) < 1 << 3, "");
613621

622+
public:
614623
/// Memberwise initializer
615624
/// The \c ContextFree result must outlive this result. Typically, this is
616625
/// done by allocating the two in the same sink or adopting the context free
@@ -624,25 +633,6 @@ class CodeCompletionResult {
624633
Flair(Flair.toRaw()), NotRecommended(NotRecommended),
625634
NumBytesToErase(NumBytesToErase), TypeDistance(TypeDistance) {}
626635

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-
646636
const ContextFreeCodeCompletionResult &getContextFreeResult() const {
647637
return ContextFree;
648638
}

lib/IDE/CodeCompletionConsumer.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,19 @@ static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
8080
if (!shouldIncludeResult(contextFreeResult)) {
8181
continue;
8282
}
83+
84+
CodeCompletionResultTypeRelation typeRelation =
85+
contextFreeResult->calculateContextualTypeRelation(DC, TypeContext,
86+
&USRTypeContext);
87+
ContextualNotRecommendedReason notRecommendedReason =
88+
contextFreeResult->calculateContextualNotRecommendedReason(
89+
ContextualNotRecommendedReason::None,
90+
CanCurrDeclContextHandleAsync);
91+
8392
auto contextualResult = new (*targetSink.Allocator) CodeCompletionResult(
8493
*contextFreeResult, SemanticContextKind::OtherModule,
8594
CodeCompletionFlair(),
86-
/*numBytesToErase=*/0, TypeContext, DC, &USRTypeContext,
87-
CanCurrDeclContextHandleAsync, ContextualNotRecommendedReason::None);
95+
/*numBytesToErase=*/0, typeRelation, notRecommendedReason);
8896
targetSink.Results.push_back(contextualResult);
8997
}
9098

lib/IDE/CodeCompletionResult.cpp

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -392,39 +392,41 @@ bool ContextFreeCodeCompletionResult::getDeclIsSystem(const Decl *D) {
392392
return D->getModuleContext()->isNonUserModule();
393393
}
394394

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;
403-
}
404-
if (ContextFree.isAsync() && !CanCurrDeclContextHandleAsync) {
395+
ContextualNotRecommendedReason
396+
ContextFreeCodeCompletionResult::calculateContextualNotRecommendedReason(
397+
ContextualNotRecommendedReason explicitReason,
398+
bool canCurrDeclContextHandleAsync) const {
399+
if (explicitReason != ContextualNotRecommendedReason::None) {
400+
return explicitReason;
401+
}
402+
if (IsAsync && !canCurrDeclContextHandleAsync) {
405403
return ContextualNotRecommendedReason::InvalidAsyncContext;
406404
}
407-
if (ContextFree.hasAsyncAlternative() && CanCurrDeclContextHandleAsync) {
405+
if (HasAsyncAlternative && canCurrDeclContextHandleAsync) {
408406
return ContextualNotRecommendedReason::
409407
NonAsyncAlternativeUsedInAsyncContext;
410408
}
411409
return ContextualNotRecommendedReason::None;
412410
}
413411

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)) {}
412+
CodeCompletionResultTypeRelation
413+
ContextFreeCodeCompletionResult::calculateContextualTypeRelation(
414+
const DeclContext *dc, const ExpectedTypeContext *typeContext,
415+
const USRBasedTypeContext *usrTypeContext) const {
416+
CodeCompletionResultTypeRelation typeRelation =
417+
getResultType().calculateTypeRelation(typeContext, dc, usrTypeContext);
418+
if (typeRelation >= CodeCompletionResultTypeRelation::Convertible ||
419+
!typeContext)
420+
return typeRelation;
421+
422+
CodeCompletionMacroRoles expectedRoles =
423+
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: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,22 +162,27 @@ 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,
165+
/*NumBytesToErase=*/0, CodeCompletionResultTypeRelation::Unrelated,
168166
ContextualNotRecommendedReason::None);
169167
} else {
170168
assert(
171169
ContextFreeResult != nullptr &&
172170
"ContextFreeResult should have been constructed by the switch above");
171+
173172
// We know that the ContextFreeResult has an AST-based type because it was
174173
// just computed and not read from the cache and
175174
// Sink.shouldProduceContextFreeResults() is false. So we can pass nullptr
176175
// for USRTypeContext.
176+
CodeCompletionResultTypeRelation typeRelation =
177+
ContextFreeResult->calculateContextualTypeRelation(
178+
DC, TypeContext, /*usrTypeContext=*/nullptr);
179+
ContextualNotRecommendedReason notRecommendedReason =
180+
ContextFreeResult->calculateContextualNotRecommendedReason(
181+
ContextualNotRecReason, CanCurrDeclContextHandleAsync);
182+
177183
return new (Allocator) CodeCompletionResult(
178184
*ContextFreeResult, SemanticContext, Flair, NumBytesToErase,
179-
TypeContext, DC, /*USRTypeContext=*/nullptr,
180-
CanCurrDeclContextHandleAsync, ContextualNotRecReason);
185+
typeRelation, notRecommendedReason);
181186
}
182187
}
183188

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
@@ -4305,8 +4305,7 @@ int main(int argc, char *argv[]) {
43054305
auto contextualResult = new CodeCompletionResult(
43064306
*contextFreeResult, SemanticContextKind::OtherModule,
43074307
CodeCompletionFlair(),
4308-
/*numBytesToErase=*/0, /*TypeContext=*/nullptr, /*DC=*/nullptr,
4309-
/*USRTypeContext=*/nullptr, /*CanCurrDeclContextHandleAsync=*/false,
4308+
/*numBytesToErase=*/0, CodeCompletionResultTypeRelation::Unrelated,
43104309
ContextualNotRecommendedReason::None);
43114310
contextualResults.push_back(contextualResult);
43124311
}

0 commit comments

Comments
 (0)