Skip to content

Commit fd82d87

Browse files
author
Nathan Hawes
authored
Merge pull request swiftlang#30402 from nathawes/cross-import-code-completion
[IDE/CodeCompletion] Add code completion support for cross import overlays.
2 parents cd7bc73 + 6363610 commit fd82d87

20 files changed

+387
-32
lines changed

include/swift/AST/SourceFile.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,16 @@ class SourceFile final : public FileUnit {
194194
/// mechanism which is not SourceFile-dependent.)
195195
SeparatelyImportedOverlayMap separatelyImportedOverlays;
196196

197+
using SeparatelyImportedOverlayReverseMap =
198+
llvm::SmallDenseMap<ModuleDecl *, ModuleDecl *>;
199+
200+
/// A lazily populated mapping from a separately imported overlay to its
201+
/// underlying shadowed module.
202+
///
203+
/// This is used by tooling to substitute the name of the underlying module
204+
/// wherever the overlay's name would otherwise be reported.
205+
SeparatelyImportedOverlayReverseMap separatelyImportedOverlaysReversed;
206+
197207
/// A pointer to PersistentParserState with a function reference to its
198208
/// deleter to handle the fact that it's forward declared.
199209
using ParserStatePtr =
@@ -382,6 +392,7 @@ class SourceFile final : public FileUnit {
382392
/// \returns true if the overlay was added; false if it already existed.
383393
bool addSeparatelyImportedOverlay(ModuleDecl *overlay,
384394
ModuleDecl *declaring) {
395+
separatelyImportedOverlaysReversed.clear();
385396
return std::get<1>(separatelyImportedOverlays[declaring].insert(overlay));
386397
}
387398

@@ -399,6 +410,12 @@ class SourceFile final : public FileUnit {
399410
overlays.append(value.begin(), value.end());
400411
}
401412

413+
/// Retrieves a module shadowed by the provided separately imported overlay
414+
/// \p shadowed. If such a module is returned, it should be presented to users
415+
/// as owning the symbols in \p overlay.
416+
ModuleDecl *
417+
getModuleShadowedBySeparatelyImportedOverlay(const ModuleDecl *overlay);
418+
402419
void cacheVisibleDecls(SmallVectorImpl<ValueDecl *> &&globals) const;
403420
const SmallVectorImpl<ValueDecl *> &getCachedVisibleDecls() const;
404421

lib/AST/Module.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,6 +1907,27 @@ bool SourceFile::shouldCrossImport() const {
19071907
getASTContext().LangOpts.EnableCrossImportOverlays;
19081908
}
19091909

1910+
ModuleDecl*
1911+
SourceFile::getModuleShadowedBySeparatelyImportedOverlay(const ModuleDecl *overlay) {
1912+
if (separatelyImportedOverlaysReversed.empty() &&
1913+
!separatelyImportedOverlays.empty()) {
1914+
for (auto &entry: separatelyImportedOverlays) {
1915+
ModuleDecl *shadowed = entry.first;
1916+
for (ModuleDecl *overlay: entry.second) {
1917+
// If for some reason the same overlay shadows more than one module,
1918+
// pick the one whose name is alphabetically first.
1919+
ModuleDecl *old = separatelyImportedOverlaysReversed[overlay];
1920+
if (!old || shadowed->getNameStr() < old->getNameStr())
1921+
separatelyImportedOverlaysReversed[overlay] = shadowed;
1922+
}
1923+
}
1924+
}
1925+
auto i = separatelyImportedOverlaysReversed.find(overlay);
1926+
return i != separatelyImportedOverlaysReversed.end()
1927+
? std::get<1>(*i)
1928+
: nullptr;
1929+
};
1930+
19101931
void ModuleDecl::clearLookupCache() {
19111932
getASTContext().getImportCache().clear();
19121933

lib/IDE/CodeCompletion.cpp

Lines changed: 65 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -767,17 +767,29 @@ void CodeCompletionResultBuilder::addChunkWithText(
767767
addChunkWithTextNoCopy(Kind, copyString(*Sink.Allocator, Text));
768768
}
769769

770-
void CodeCompletionResultBuilder::setAssociatedDecl(const Decl *D) {
770+
void CodeCompletionResultBuilder::setAssociatedDecl(const Decl *D,
771+
SourceFile *SF) {
771772
assert(Kind == CodeCompletionResult::ResultKind::Declaration);
772773
AssociatedDecl = D;
773-
774774
if (auto *ClangD = D->getClangDecl())
775775
CurrentModule = ClangD->getImportedOwningModule();
776776
// FIXME: macros
777777
// FIXME: imported header module
778778

779-
if (!CurrentModule)
780-
CurrentModule = D->getModuleContext();
779+
if (!CurrentModule) {
780+
ModuleDecl *MD = D->getModuleContext();
781+
// If this is an underscored cross-import overlay, map it to its underlying
782+
// module instead.
783+
if (SF) {
784+
while (MD->getNameStr().startswith("_")) {
785+
auto *Underlying = SF->getModuleShadowedBySeparatelyImportedOverlay(MD);
786+
if (!Underlying)
787+
break;
788+
MD = Underlying;
789+
}
790+
}
791+
CurrentModule = MD;
792+
}
781793

782794
if (D->getAttrs().getDeprecated(D->getASTContext()))
783795
setNotRecommended(CodeCompletionResult::Deprecated);
@@ -1549,6 +1561,15 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
15491561
Builder.addDeclDocCommentWords(llvm::makeArrayRef(Pairs));
15501562
}
15511563

1564+
/// Sets the given declaration \p D as the associated declaration of the
1565+
/// completion result being built in \p Builder.
1566+
void setAssociatedDecl(const Decl *D, CodeCompletionResultBuilder &Builder) {
1567+
SourceFile *SF = nullptr;
1568+
if (CurrDeclContext)
1569+
SF = CurrDeclContext->getParentSourceFile();
1570+
Builder.setAssociatedDecl(D, SF);
1571+
}
1572+
15521573
bool shouldUseFunctionReference(AbstractFunctionDecl *D) {
15531574
if (PreferFunctionReferencesToCalls)
15541575
return true;
@@ -1726,7 +1747,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
17261747
SemanticContextKind::None,
17271748
expectedTypeContext);
17281749
auto MD = ModuleDecl::create(Ctx.getIdentifier(Pair.first), Ctx);
1729-
Builder.setAssociatedDecl(MD);
1750+
setAssociatedDecl(MD, Builder);
17301751
Builder.addTextChunk(MD->getNameStr());
17311752
Builder.addTypeAnnotation("Module");
17321753
if (Pair.second)
@@ -1740,7 +1761,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
17401761
ImportFilter |= ModuleDecl::ImportFilterKind::Public;
17411762
ImportFilter |= ModuleDecl::ImportFilterKind::Private;
17421763
ImportFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
1743-
// FIXME: ImportFilterKind::ShadowedBySeparateOverlay?
17441764

17451765
SmallVector<ModuleDecl::ImportedModule, 16> Imported;
17461766
SmallVector<ModuleDecl::ImportedModule, 16> FurtherImported;
@@ -1755,21 +1775,27 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
17551775
MD->getImportedModules(FurtherImported,
17561776
ModuleDecl::ImportFilterKind::Public);
17571777
Imported.append(FurtherImported.begin(), FurtherImported.end());
1758-
for (auto SubMod : FurtherImported) {
1759-
Imported.push_back(SubMod);
1760-
}
17611778
}
17621779
}
17631780

17641781
void addModuleName(
17651782
const ModuleDecl *MD,
17661783
Optional<CodeCompletionResult::NotRecommendedReason> R = None) {
1784+
1785+
// Don't add underscored cross-import overlay modules.
1786+
if (CurrDeclContext && MD->getNameStr().startswith("_")) {
1787+
if (auto SF = CurrDeclContext->getParentSourceFile()) {
1788+
if (SF->getModuleShadowedBySeparatelyImportedOverlay(MD))
1789+
return;
1790+
}
1791+
}
1792+
17671793
CodeCompletionResultBuilder Builder(
17681794
Sink,
17691795
CodeCompletionResult::ResultKind::Declaration,
17701796
SemanticContextKind::None,
17711797
expectedTypeContext);
1772-
Builder.setAssociatedDecl(MD);
1798+
setAssociatedDecl(MD, Builder);
17731799
Builder.addTextChunk(MD->getNameStr());
17741800
Builder.addTypeAnnotation("Module");
17751801
if (R)
@@ -2163,7 +2189,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
21632189
CodeCompletionResultBuilder Builder(
21642190
Sink, CodeCompletionResult::ResultKind::Declaration,
21652191
getSemanticContext(VD, Reason, dynamicLookupInfo), expectedTypeContext);
2166-
Builder.setAssociatedDecl(VD);
2192+
setAssociatedDecl(VD, Builder);
21672193
addLeadingDot(Builder);
21682194
addValueBaseName(Builder, Name);
21692195
setClangDeclKeywords(VD, Pairs, Builder);
@@ -2413,7 +2439,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
24132439
Sink, CodeCompletionResult::ResultKind::Declaration,
24142440
SemanticContext ? *SemanticContext : getSemanticContextKind(SD),
24152441
expectedTypeContext);
2416-
Builder.setAssociatedDecl(SD);
2442+
setAssociatedDecl(SD, Builder);
24172443
setClangDeclKeywords(SD, Pairs, Builder);
24182444
if (!HaveLParen)
24192445
Builder.addLeftBracket();
@@ -2452,7 +2478,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
24522478
SemanticContext ? *SemanticContext : getSemanticContextKind(AFD),
24532479
expectedTypeContext);
24542480
if (AFD) {
2455-
Builder.setAssociatedDecl(AFD);
2481+
setAssociatedDecl(AFD, Builder);
24562482
setClangDeclKeywords(AFD, Pairs, Builder);
24572483
}
24582484

@@ -2583,7 +2609,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25832609
getSemanticContext(FD, Reason, dynamicLookupInfo),
25842610
expectedTypeContext);
25852611
setClangDeclKeywords(FD, Pairs, Builder);
2586-
Builder.setAssociatedDecl(FD);
2612+
setAssociatedDecl(FD, Builder);
25872613
addLeadingDot(Builder);
25882614
addValueBaseName(Builder, Name);
25892615
if (IsDynamicLookup)
@@ -2696,7 +2722,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
26962722
getSemanticContext(CD, Reason, dynamicLookupInfo),
26972723
expectedTypeContext);
26982724
setClangDeclKeywords(CD, Pairs, Builder);
2699-
Builder.setAssociatedDecl(CD);
2725+
setAssociatedDecl(CD, Builder);
27002726
if (needInit) {
27012727
assert(addName.empty());
27022728
addLeadingDot(Builder);
@@ -2787,7 +2813,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
27872813
CodeCompletionResultBuilder Builder(
27882814
Sink, CodeCompletionResult::ResultKind::Declaration,
27892815
getSemanticContext(SD, Reason, dynamicLookupInfo), expectedTypeContext);
2790-
Builder.setAssociatedDecl(SD);
2816+
setAssociatedDecl(SD, Builder);
27912817
setClangDeclKeywords(SD, Pairs, Builder);
27922818

27932819
// '\TyName#^TOKEN^#' requires leading dot.
@@ -2822,7 +2848,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28222848
Sink, CodeCompletionResult::ResultKind::Declaration,
28232849
getSemanticContext(NTD, Reason, dynamicLookupInfo),
28242850
expectedTypeContext);
2825-
Builder.setAssociatedDecl(NTD);
2851+
setAssociatedDecl(NTD, Builder);
28262852
setClangDeclKeywords(NTD, Pairs, Builder);
28272853
addLeadingDot(Builder);
28282854
Builder.addTextChunk(NTD->getName().str());
@@ -2838,7 +2864,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28382864
Sink, CodeCompletionResult::ResultKind::Declaration,
28392865
getSemanticContext(TAD, Reason, dynamicLookupInfo),
28402866
expectedTypeContext);
2841-
Builder.setAssociatedDecl(TAD);
2867+
setAssociatedDecl(TAD, Builder);
28422868
setClangDeclKeywords(TAD, Pairs, Builder);
28432869
addLeadingDot(Builder);
28442870
Builder.addTextChunk(TAD->getName().str());
@@ -2868,7 +2894,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28682894
Sink, CodeCompletionResult::ResultKind::Declaration,
28692895
getSemanticContext(GP, Reason, dynamicLookupInfo), expectedTypeContext);
28702896
setClangDeclKeywords(GP, Pairs, Builder);
2871-
Builder.setAssociatedDecl(GP);
2897+
setAssociatedDecl(GP, Builder);
28722898
addLeadingDot(Builder);
28732899
Builder.addTextChunk(GP->getName().str());
28742900
addTypeAnnotation(Builder, GP->getDeclaredInterfaceType());
@@ -2882,7 +2908,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28822908
Sink, CodeCompletionResult::ResultKind::Declaration,
28832909
getSemanticContext(AT, Reason, dynamicLookupInfo), expectedTypeContext);
28842910
setClangDeclKeywords(AT, Pairs, Builder);
2885-
Builder.setAssociatedDecl(AT);
2911+
setAssociatedDecl(AT, Builder);
28862912
addLeadingDot(Builder);
28872913
Builder.addTextChunk(AT->getName().str());
28882914
if (Type T = getAssociatedTypeType(AT))
@@ -2897,7 +2923,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28972923
semanticContext, {});
28982924

28992925
builder.addTextChunk(PGD->getName().str());
2900-
builder.setAssociatedDecl(PGD);
2926+
setAssociatedDecl(PGD, builder);
29012927
};
29022928

29032929
void addEnumElementRef(const EnumElementDecl *EED, DeclVisibilityKind Reason,
@@ -2914,7 +2940,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
29142940
HasTypeContext ? SemanticContextKind::ExpressionSpecific
29152941
: getSemanticContext(EED, Reason, dynamicLookupInfo),
29162942
expectedTypeContext);
2917-
Builder.setAssociatedDecl(EED);
2943+
setAssociatedDecl(EED, Builder);
29182944
setClangDeclKeywords(EED, Pairs, Builder);
29192945
addLeadingDot(Builder);
29202946
addValueBaseName(Builder, EED->getName());
@@ -2996,7 +3022,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
29963022
getSemanticContext(AFD, Reason, dynamicLookupInfo),
29973023
expectedTypeContext);
29983024
setClangDeclKeywords(AFD, Pairs, Builder);
2999-
Builder.setAssociatedDecl(AFD);
3025+
setAssociatedDecl(AFD, Builder);
30003026

30013027
// Base name
30023028
addLeadingDot(Builder);
@@ -3469,7 +3495,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
34693495
// FIXME: handle variable amounts of space.
34703496
if (HaveLeadingSpace)
34713497
builder.setNumBytesToErase(1);
3472-
builder.setAssociatedDecl(op);
3498+
setAssociatedDecl(op, builder);
34733499
builder.addTextChunk(op->getName().str());
34743500
assert(resultType);
34753501
addTypeAnnotation(builder, resultType);
@@ -3515,7 +3541,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
35153541
CodeCompletionResultBuilder builder(
35163542
Sink, CodeCompletionResult::ResultKind::Declaration, semanticContext,
35173543
{});
3518-
builder.setAssociatedDecl(op);
3544+
setAssociatedDecl(op, builder);
35193545

35203546
if (HaveLeadingSpace)
35213547
builder.addAnnotatedWhitespace(" ");
@@ -4179,6 +4205,15 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
41794205
bool hasOverridabilityModifier = false;
41804206
bool hasStaticOrClass = false;
41814207

4208+
/// Sets the given declaration \p D as the associated declaration of the
4209+
/// completion result being built in \p Builder.
4210+
void setAssociatedDecl(const Decl *D, CodeCompletionResultBuilder &Builder) {
4211+
SourceFile *SF = nullptr;
4212+
if (CurrDeclContext)
4213+
SF = CurrDeclContext->getParentSourceFile();
4214+
Builder.setAssociatedDecl(D, SF);
4215+
}
4216+
41824217
public:
41834218
CompletionOverrideLookup(CodeCompletionResultSink &Sink, ASTContext &Ctx,
41844219
const DeclContext *CurrDeclContext,
@@ -4407,7 +4442,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
44074442
SemanticContextKind::Super, {});
44084443
Builder.setExpectedTypeRelation(
44094444
CodeCompletionResult::ExpectedTypeRelation::NotApplicable);
4410-
Builder.setAssociatedDecl(FD);
4445+
setAssociatedDecl(FD, Builder);
44114446
addValueOverride(FD, Reason, dynamicLookupInfo, Builder, hasFuncIntroducer);
44124447
Builder.addBraceStmtWithCursor();
44134448
}
@@ -4425,7 +4460,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
44254460
CodeCompletionResultBuilder Builder(
44264461
Sink, CodeCompletionResult::ResultKind::Declaration,
44274462
SemanticContextKind::Super, {});
4428-
Builder.setAssociatedDecl(VD);
4463+
setAssociatedDecl(VD, Builder);
44294464
addValueOverride(VD, Reason, dynamicLookupInfo, Builder, hasVarIntroducer);
44304465
}
44314466

@@ -4436,7 +4471,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
44364471
SemanticContextKind::Super, {});
44374472
Builder.setExpectedTypeRelation(
44384473
CodeCompletionResult::ExpectedTypeRelation::NotApplicable);
4439-
Builder.setAssociatedDecl(SD);
4474+
setAssociatedDecl(SD, Builder);
44404475
addValueOverride(SD, Reason, dynamicLookupInfo, Builder, false);
44414476
Builder.addBraceStmtWithCursor();
44424477
}
@@ -4448,7 +4483,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
44484483
SemanticContextKind::Super, {});
44494484
Builder.setExpectedTypeRelation(
44504485
CodeCompletionResult::ExpectedTypeRelation::NotApplicable);
4451-
Builder.setAssociatedDecl(ATD);
4486+
setAssociatedDecl(ATD, Builder);
44524487
if (!hasTypealiasIntroducer && !hasAccessModifier)
44534488
addAccessControl(ATD, Builder);
44544489
if (!hasTypealiasIntroducer)
@@ -4466,7 +4501,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
44664501
SemanticContextKind::Super, {});
44674502
Builder.setExpectedTypeRelation(
44684503
CodeCompletionResult::ExpectedTypeRelation::NotApplicable);
4469-
Builder.setAssociatedDecl(CD);
4504+
setAssociatedDecl(CD, Builder);
44704505

44714506
if (!hasAccessModifier)
44724507
addAccessControl(CD, Builder);
@@ -5732,7 +5767,6 @@ void CodeCompletionCallbacksImpl::doneParsing() {
57325767
ImportFilter |= ModuleDecl::ImportFilterKind::Public;
57335768
ImportFilter |= ModuleDecl::ImportFilterKind::Private;
57345769
ImportFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
5735-
// FIXME: ImportFilterKind::ShadowedBySeparateOverlay?
57365770
SmallVector<ModuleDecl::ImportedModule, 4> Imports;
57375771
auto *SF = CurDeclContext->getParentSourceFile();
57385772
SF->getImportedModules(Imports, ImportFilter);

lib/IDE/CodeCompletionResultBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class CodeCompletionResultBuilder {
114114
NumBytesToErase = N;
115115
}
116116

117-
void setAssociatedDecl(const Decl *D);
117+
void setAssociatedDecl(const Decl *D, SourceFile *SF);
118118

119119
void setLiteralKind(CodeCompletionLiteralKind kind) { LiteralKind = kind; }
120120
void setKeywordKind(CodeCompletionKeywordKind kind) { KeywordKind = kind; }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
%YAML 1.2
2+
---
3+
version: 1
4+
modules:
5+
- name: _ABAdditions
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -swift-version 5 -enable-library-evolution -module-name A
3+
4+
import Swift
5+
6+
public func fromA()
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -swift-version 5 -enable-library-evolution -module-name B
3+
4+
import Swift
5+
6+
public func fromB()

0 commit comments

Comments
 (0)