Skip to content

Commit 7337e3b

Browse files
authored
Merge pull request #40566 from bnbarham/synthesized-harmony
[IDE] Only consider synthesized extensions when in the same module
2 parents 4f7a205 + bf0bcfa commit 7337e3b

File tree

4 files changed

+118
-47
lines changed

4 files changed

+118
-47
lines changed

lib/AST/RawComment.cpp

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -197,50 +197,34 @@ RawComment Decl::getRawComment(bool SerializedOK) const {
197197
llvm_unreachable("invalid file kind");
198198
}
199199

200-
static const Decl* getGroupDecl(const Decl *D) {
201-
auto GroupD = D;
202-
203-
// Extensions always exist in the same group with the nominal.
204-
if (auto ED = dyn_cast_or_null<ExtensionDecl>(D->getDeclContext()->
205-
getInnermostTypeContext())) {
206-
if (auto ExtNominal = ED->getExtendedNominal())
207-
GroupD = ExtNominal;
208-
}
209-
return GroupD;
210-
}
211-
212200
Optional<StringRef> Decl::getGroupName() const {
213201
if (hasClangNode())
214202
return None;
215-
if (auto GroupD = getGroupDecl(this)) {
203+
if (auto *Unit =
204+
dyn_cast<FileUnit>(getDeclContext()->getModuleScopeContext())) {
216205
// We can only get group information from deserialized module files.
217-
if (auto *Unit =
218-
dyn_cast<FileUnit>(GroupD->getDeclContext()->getModuleScopeContext())) {
219-
return Unit->getGroupNameForDecl(GroupD);
220-
}
206+
return Unit->getGroupNameForDecl(this);
221207
}
222208
return None;
223209
}
224210

225211
Optional<StringRef> Decl::getSourceFileName() const {
226212
if (hasClangNode())
227213
return None;
228-
if (auto GroupD = getGroupDecl(this)) {
214+
if (auto *Unit =
215+
dyn_cast<FileUnit>(getDeclContext()->getModuleScopeContext())) {
229216
// We can only get group information from deserialized module files.
230-
if (auto *Unit =
231-
dyn_cast<FileUnit>(GroupD->getDeclContext()->getModuleScopeContext())) {
232-
return Unit->getSourceFileNameForDecl(GroupD);
233-
}
217+
return Unit->getSourceFileNameForDecl(this);
234218
}
235219
return None;
236220
}
237221

238222
Optional<unsigned> Decl::getSourceOrder() const {
239223
if (hasClangNode())
240224
return None;
241-
// We can only get source orders from deserialized module files.
242225
if (auto *Unit =
243226
dyn_cast<FileUnit>(this->getDeclContext()->getModuleScopeContext())) {
227+
// We can only get source orders from deserialized module files.
244228
return Unit->getSourceOrderForDecl(this);
245229
}
246230
return None;

lib/IDE/IDETypeChecking.cpp

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ struct SynthesizedExtensionAnalyzer::Implementation {
261261
bool IncludeUnconditional;
262262
PrintOptions Options;
263263
MergeGroupVector AllGroups;
264-
std::unique_ptr<ExtensionInfoMap> InfoMap;
264+
ExtensionInfoMap InfoMap;
265265

266266
Implementation(NominalTypeDecl *Target,
267267
bool IncludeUnconditional,
@@ -416,9 +416,9 @@ struct SynthesizedExtensionAnalyzer::Implementation {
416416
}
417417
}
418418

419-
std::unique_ptr<ExtensionInfoMap>
419+
ExtensionInfoMap
420420
collectSynthesizedExtensionInfoForProtocol(MergeGroupVector &AllGroups) {
421-
std::unique_ptr<ExtensionInfoMap> InfoMap(new ExtensionInfoMap());
421+
ExtensionInfoMap InfoMap;
422422
ExtensionMergeInfoMap MergeInfoMap;
423423
for (auto *E : Target->getExtensions()) {
424424
if (!Options.shouldPrint(E))
@@ -427,12 +427,12 @@ struct SynthesizedExtensionAnalyzer::Implementation {
427427
/*EnablingExt*/ nullptr,
428428
/*Conf*/ nullptr);
429429
if (Pair.first) {
430-
InfoMap->insert({E, Pair.first});
430+
InfoMap.insert({E, Pair.first});
431431
MergeInfoMap.insert({E, Pair.second});
432432
}
433433
}
434-
populateMergeGroup(*InfoMap, MergeInfoMap, AllGroups,
435-
/*AllowMergeWithDefBody*/false);
434+
populateMergeGroup(InfoMap, MergeInfoMap, AllGroups,
435+
/*AllowMergeWithDefBody=*/false);
436436
std::sort(AllGroups.begin(), AllGroups.end());
437437
for (auto &Group : AllGroups) {
438438
Group.sortMembers();
@@ -448,12 +448,13 @@ struct SynthesizedExtensionAnalyzer::Implementation {
448448
return false;
449449
}
450450

451-
std::unique_ptr<ExtensionInfoMap>
451+
ExtensionInfoMap
452452
collectSynthesizedExtensionInfo(MergeGroupVector &AllGroups) {
453453
if (isa<ProtocolDecl>(Target)) {
454454
return collectSynthesizedExtensionInfoForProtocol(AllGroups);
455455
}
456-
std::unique_ptr<ExtensionInfoMap> InfoMap(new ExtensionInfoMap());
456+
457+
ExtensionInfoMap InfoMap;
457458
ExtensionMergeInfoMap MergeInfoMap;
458459
std::vector<NominalTypeDecl*> Unhandled;
459460

@@ -470,7 +471,7 @@ struct SynthesizedExtensionAnalyzer::Implementation {
470471
if (AdjustedOpts.shouldPrint(E)) {
471472
auto Pair = isApplicable(E, Synthesized, EnablingE, Conf);
472473
if (Pair.first) {
473-
InfoMap->insert({E, Pair.first});
474+
InfoMap.insert({E, Pair.first});
474475
MergeInfoMap.insert({E, Pair.second});
475476
}
476477
}
@@ -515,8 +516,8 @@ struct SynthesizedExtensionAnalyzer::Implementation {
515516
}
516517
}
517518

518-
populateMergeGroup(*InfoMap, MergeInfoMap, AllGroups,
519-
/*AllowMergeWithDefBody*/true);
519+
populateMergeGroup(InfoMap, MergeInfoMap, AllGroups,
520+
/*AllowMergeWithDefBody=*/true);
520521

521522
std::sort(AllGroups.begin(), AllGroups.end());
522523
for (auto &Group : AllGroups) {
@@ -531,20 +532,22 @@ struct SynthesizedExtensionAnalyzer::Implementation {
531532
}
532533
};
533534

534-
SynthesizedExtensionAnalyzer::
535-
SynthesizedExtensionAnalyzer(NominalTypeDecl *Target,
536-
PrintOptions Options,
537-
bool IncludeUnconditional):
538-
Impl(*(new Implementation(Target, IncludeUnconditional, Options))) {}
535+
SynthesizedExtensionAnalyzer::SynthesizedExtensionAnalyzer(
536+
NominalTypeDecl *Target, PrintOptions Options, bool IncludeUnconditional)
537+
: Impl(*(new Implementation(Target, IncludeUnconditional, Options))) {}
539538

540539
SynthesizedExtensionAnalyzer::~SynthesizedExtensionAnalyzer() {delete &Impl;}
541540

542-
bool SynthesizedExtensionAnalyzer::
543-
isInSynthesizedExtension(const ValueDecl *VD) {
541+
bool SynthesizedExtensionAnalyzer::isInSynthesizedExtension(
542+
const ValueDecl *VD) {
544543
if (auto Ext = dyn_cast_or_null<ExtensionDecl>(VD->getDeclContext()->
545544
getInnermostTypeContext())) {
546-
return Impl.InfoMap->count(Ext) != 0 &&
547-
Impl.InfoMap->find(Ext)->second.IsSynthesized;
545+
auto It = Impl.InfoMap.find(Ext);
546+
if (It != Impl.InfoMap.end() && It->second.IsSynthesized) {
547+
// A synthesized extension will only be created if the underlying type
548+
// is in the same module
549+
return VD->getModuleContext() == Impl.Target->getModuleContext();
550+
}
548551
}
549552
return false;
550553
}
@@ -565,8 +568,7 @@ forEachExtensionMergeGroup(MergeGroupKind Kind, ExtensionGroupOperation Fn) {
565568
}
566569
}
567570

568-
bool SynthesizedExtensionAnalyzer::
569-
hasMergeGroup(MergeGroupKind Kind) {
571+
bool SynthesizedExtensionAnalyzer::hasMergeGroup(MergeGroupKind Kind) {
570572
for (auto &Group : Impl.AllGroups) {
571573
if (Kind == MergeGroupKind::All)
572574
return true;
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: mkdir -p %t/mods
3+
// RUN: split-file --leading-lines %s %t
4+
5+
// RUN: %target-swift-frontend -module-name Foo -emit-module -emit-module-path %t/mods/Foo.swiftmodule -emit-module-doc -emit-module-doc-path %t/mods/Foo.swiftdoc -group-info-path %t/group.json %t/Foo.swift
6+
// RUN: %target-swift-frontend -module-name Bar -emit-module -emit-module-path %t/mods/Bar.swiftmodule -emit-module-doc -emit-module-doc-path %t/mods/Bar.swiftdoc -I%t/mods %t/Bar.swift
7+
8+
//--- group.json
9+
{
10+
"TestGroup": [
11+
"Foo.swift",
12+
]
13+
}
14+
15+
//--- Foo.swift
16+
public protocol FooProto {
17+
associatedtype T
18+
}
19+
20+
public extension FooProto {
21+
func fooExt() {}
22+
}
23+
24+
public extension FooProto {
25+
func fooExt2() {}
26+
}
27+
28+
public extension FooProto where T == Int {
29+
func fooIntExt() {}
30+
}
31+
32+
public struct FooStruct: FooProto {
33+
public typealias T = Int
34+
public func foo() {}
35+
}
36+
37+
//--- Bar.swift
38+
import Foo
39+
40+
public extension FooProto {
41+
func barExt() {}
42+
}
43+
44+
public extension FooProto where T == Int {
45+
func barIntExt() {}
46+
}
47+
48+
//--- Baz.swift
49+
import Foo
50+
import Bar
51+
52+
// The generated interface for Foo will contain all the extensions as well
53+
// as the "synthesized extension" on FooStruct itself, ie. the extension
54+
// functions are added to FooStruct as if they were written there in the source.
55+
//
56+
// We prefer jumping to these declarations rather than the one in the extension,
57+
// but also have to be careful not to attempt to do so for extensions outside
58+
// of the original module - these will *not* have "synthesized extensions"
59+
// in their generated interface.
60+
func test(f: FooStruct) {
61+
// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):5 %t/Baz.swift -- %t/Baz.swift -I %t/mods -target %target-triple | %FileCheck --check-prefix=CHECK-EXT %t/Baz.swift
62+
f.fooExt()
63+
// CHECK-EXT: 3Foo0A5ProtoPAAE6fooExtyyF::SYNTHESIZED::s:3Foo0A6StructV
64+
// CHECK-EXT: <Group>TestGroup</Group>
65+
66+
// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):5 %t/Baz.swift -- %t/Baz.swift -I %t/mods -target %target-triple | %FileCheck --check-prefix=CHECK-EXT2 %t/Baz.swift
67+
f.fooExt2()
68+
// CHECK-EXT2: s:3Foo0A5ProtoPAAE7fooExt2yyF::SYNTHESIZED::s:3Foo0A6StructV
69+
// CHECK-EXT2: <Group>TestGroup</Group>
70+
71+
// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):5 %t/Baz.swift -- %t/Baz.swift -I %t/mods -target %target-triple | %FileCheck --check-prefix=CHECK-INTEXT %t/Baz.swift
72+
f.fooIntExt()
73+
// CHECK-INTEXT: s:3Foo0A5ProtoPAASi1TRtzrlE9fooIntExtyyF::SYNTHESIZED::s:3Foo0A6StructV
74+
// CHECK-INTEXT: <Group>TestGroup</Group>
75+
76+
// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):5 %t/Baz.swift -- %t/Baz.swift -I %t/mods -target %target-triple | %FileCheck --check-prefix=CHECK-BAREXT %t/Baz.swift
77+
f.barExt()
78+
// CHECK-BAREXT: s:3Foo0A5ProtoP3BarE6barExtyyF
79+
// CHECK-BAREXT-NOT: <Group>TestGroup</Group>
80+
81+
// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):5 %t/Baz.swift -- %t/Baz.swift -I %t/mods -target %target-triple | %FileCheck --check-prefix=CHECK-BARINTEXT %t/Baz.swift
82+
f.barIntExt()
83+
// CHECK-BARINTEXT: s:3Foo0A5ProtoP3BarSi1TRtzrlE9barIntExtyyF
84+
// CHECK-BARINTEXT-NOT: <Group>TestGroup</Group>
85+
}

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ struct DeclInfo {
785785
const ValueDecl *OriginalProperty = nullptr;
786786
bool Unavailable = true;
787787
Type BaseType;
788+
/// Whether the \c VD is in a synthesized extension of \c BaseType
788789
bool InSynthesizedExtension = false;
789790

790791
DeclInfo(const ValueDecl *VD, Type ContainerType, bool IsRef, bool IsDynamic,
@@ -810,9 +811,8 @@ struct DeclInfo {
810811
}
811812

812813
BaseType = findBaseTypeForReplacingArchetype(VD, ContainerType);
813-
InSynthesizedExtension = false;
814814
if (BaseType) {
815-
if (auto Target = BaseType->getAnyNominal()) {
815+
if (auto *Target = BaseType->getAnyNominal()) {
816816
SynthesizedExtensionAnalyzer Analyzer(
817817
Target, PrintOptions::printModuleInterface(
818818
Invoc.getFrontendOptions().PrintFullConvention));

0 commit comments

Comments
 (0)