|
26 | 26 | #include "swift/AST/ExistentialLayout.h"
|
27 | 27 | #include "swift/AST/FileUnit.h"
|
28 | 28 | #include "swift/AST/GenericEnvironment.h"
|
| 29 | +#include "swift/AST/Import.h" |
29 | 30 | #include "swift/AST/ImportCache.h"
|
30 | 31 | #include "swift/AST/LazyResolver.h"
|
31 | 32 | #include "swift/AST/LinkLibrary.h"
|
|
39 | 40 | #include "swift/AST/ProtocolConformance.h"
|
40 | 41 | #include "swift/AST/SourceFile.h"
|
41 | 42 | #include "swift/AST/SynthesizedFileUnit.h"
|
| 43 | +#include "swift/AST/Type.h" |
42 | 44 | #include "swift/AST/TypeCheckRequests.h"
|
43 | 45 | #include "swift/Basic/Compiler.h"
|
44 | 46 | #include "swift/Basic/SourceManager.h"
|
@@ -1287,42 +1289,6 @@ bool ModuleDecl::shouldCollectDisplayDecls() const {
|
1287 | 1289 | return true;
|
1288 | 1290 | }
|
1289 | 1291 |
|
1290 |
| -void swift::collectParsedExportedImports(const ModuleDecl *M, |
1291 |
| - SmallPtrSetImpl<ModuleDecl *> &Imports, |
1292 |
| - llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> &QualifiedImports, |
1293 |
| - llvm::function_ref<bool(AttributedImport<ImportedModule>)> includeImport) { |
1294 |
| - for (const FileUnit *file : M->getFiles()) { |
1295 |
| - if (const SourceFile *source = dyn_cast<SourceFile>(file)) { |
1296 |
| - if (source->hasImports()) { |
1297 |
| - for (auto import : source->getImports()) { |
1298 |
| - if (import.options.contains(ImportFlags::Exported) && |
1299 |
| - (!includeImport || includeImport(import)) && |
1300 |
| - import.module.importedModule->shouldCollectDisplayDecls()) { |
1301 |
| - auto *TheModule = import.module.importedModule; |
1302 |
| - |
1303 |
| - if (import.module.getAccessPath().size() > 0) { |
1304 |
| - if (QualifiedImports.find(TheModule) == QualifiedImports.end()) { |
1305 |
| - QualifiedImports.try_emplace(TheModule); |
1306 |
| - } |
1307 |
| - auto collectDecls = [&](ValueDecl *VD, |
1308 |
| - DeclVisibilityKind reason) { |
1309 |
| - if (reason == DeclVisibilityKind::VisibleAtTopLevel) |
1310 |
| - QualifiedImports[TheModule].insert(VD); |
1311 |
| - }; |
1312 |
| - auto consumer = makeDeclConsumer(std::move(collectDecls)); |
1313 |
| - TheModule->lookupVisibleDecls( |
1314 |
| - import.module.getAccessPath(), consumer, |
1315 |
| - NLKind::UnqualifiedLookup); |
1316 |
| - } else if (!Imports.contains(TheModule)) { |
1317 |
| - Imports.insert(TheModule); |
1318 |
| - } |
1319 |
| - } |
1320 |
| - } |
1321 |
| - } |
1322 |
| - } |
1323 |
| - } |
1324 |
| -} |
1325 |
| - |
1326 | 1292 | void ModuleDecl::getLocalTypeDecls(SmallVectorImpl<TypeDecl*> &Results) const {
|
1327 | 1293 | FORWARD(getLocalTypeDecls, (Results));
|
1328 | 1294 | }
|
@@ -1543,40 +1509,101 @@ SourceFile::getExternalRawLocsForDecl(const Decl *D) const {
|
1543 | 1509 | return Result;
|
1544 | 1510 | }
|
1545 | 1511 |
|
1546 |
| -void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results, bool Recursive) const { |
1547 |
| - if (Recursive && isParsedModule(this)) { |
1548 |
| - SmallPtrSet<ModuleDecl *, 4> Modules; |
1549 |
| - llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> QualifiedImports; |
1550 |
| - collectParsedExportedImports(this, Modules, QualifiedImports); |
1551 |
| - for (const auto &QI : QualifiedImports) { |
1552 |
| - auto Module = QI.getFirst(); |
1553 |
| - if (Modules.contains(Module)) continue; |
| 1512 | +void ModuleDecl::ImportCollector::collect( |
| 1513 | + const ImportedModule &importedModule) { |
| 1514 | + auto *module = importedModule.importedModule; |
1554 | 1515 |
|
1555 |
| - auto &Decls = QI.getSecond(); |
1556 |
| - Results.append(Decls.begin(), Decls.end()); |
1557 |
| - } |
1558 |
| - for (const ModuleDecl *import : Modules) { |
1559 |
| - import->getDisplayDecls(Results, Recursive); |
| 1516 | + if (!module->shouldCollectDisplayDecls()) |
| 1517 | + return; |
| 1518 | + |
| 1519 | + if (importFilter && !importFilter(module)) |
| 1520 | + return; |
| 1521 | + |
| 1522 | + if (importedModule.getAccessPath().size() > 0) { |
| 1523 | + auto collectDecls = [&](ValueDecl *VD, DeclVisibilityKind reason) { |
| 1524 | + if (reason == DeclVisibilityKind::VisibleAtTopLevel) |
| 1525 | + this->qualifiedImports[module].insert(VD); |
| 1526 | + }; |
| 1527 | + auto consumer = makeDeclConsumer(std::move(collectDecls)); |
| 1528 | + module->lookupVisibleDecls(importedModule.getAccessPath(), consumer, |
| 1529 | + NLKind::UnqualifiedLookup); |
| 1530 | + } else { |
| 1531 | + imports.insert(module); |
| 1532 | + } |
| 1533 | +} |
| 1534 | + |
| 1535 | +static void |
| 1536 | +collectExportedImports(const ModuleDecl *module, |
| 1537 | + ModuleDecl::ImportCollector &importCollector) { |
| 1538 | + for (const FileUnit *file : module->getFiles()) { |
| 1539 | + if (const SourceFile *source = dyn_cast<SourceFile>(file)) { |
| 1540 | + if (source->hasImports()) { |
| 1541 | + for (const auto &import : source->getImports()) { |
| 1542 | + if (import.options.contains(ImportFlags::Exported) && |
| 1543 | + import.docVisibility.value_or(AccessLevel::Public) >= |
| 1544 | + importCollector.minimumDocVisibility) { |
| 1545 | + importCollector.collect(import.module); |
| 1546 | + collectExportedImports(import.module.importedModule, |
| 1547 | + importCollector); |
| 1548 | + } |
| 1549 | + } |
| 1550 | + } |
| 1551 | + } else { |
| 1552 | + SmallVector<ImportedModule, 8> exportedImports; |
| 1553 | + file->getImportedModules(exportedImports, |
| 1554 | + ModuleDecl::ImportFilterKind::Exported); |
| 1555 | + for (const auto &im : exportedImports) { |
| 1556 | + // Skip collecting the underlying clang module as we already have the relevant import. |
| 1557 | + if (module->isClangOverlayOf(im.importedModule)) |
| 1558 | + continue; |
| 1559 | + importCollector.collect(im); |
| 1560 | + collectExportedImports(im.importedModule, importCollector); |
| 1561 | + } |
1560 | 1562 | }
|
1561 | 1563 | }
|
1562 |
| - // FIXME: Should this do extra access control filtering? |
1563 |
| - FORWARD(getDisplayDecls, (Results)); |
| 1564 | +} |
1564 | 1565 |
|
1565 |
| -#ifndef NDEBUG |
| 1566 | +void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results, bool Recursive) const { |
1566 | 1567 | if (Recursive) {
|
1567 |
| - llvm::DenseSet<Decl *> visited; |
1568 |
| - for (auto *D : Results) { |
1569 |
| - // decls synthesized from implicit clang decls may appear multiple times; |
1570 |
| - // e.g. if multiple modules with underlying clang modules are re-exported. |
1571 |
| - // including duplicates of these is harmless, so skip them when counting |
1572 |
| - // this assertion |
1573 |
| - if (const auto *CD = D->getClangDecl()) { |
1574 |
| - if (CD->isImplicit()) continue; |
1575 |
| - } |
| 1568 | + ImportCollector importCollector; |
| 1569 | + this->getDisplayDeclsRecursivelyAndImports(Results, importCollector); |
| 1570 | + } else { |
| 1571 | + // FIXME: Should this do extra access control filtering? |
| 1572 | + FORWARD(getDisplayDecls, (Results)); |
| 1573 | + } |
| 1574 | +} |
| 1575 | + |
| 1576 | +void ModuleDecl::getDisplayDeclsRecursivelyAndImports( |
| 1577 | + SmallVectorImpl<Decl *> &results, ImportCollector &importCollector) const { |
| 1578 | + this->getDisplayDecls(results, /*Recursive=*/false); |
| 1579 | + |
| 1580 | + // Look up imports recursively. |
| 1581 | + collectExportedImports(this, importCollector); |
| 1582 | + for (const auto &QI : importCollector.qualifiedImports) { |
| 1583 | + auto Module = QI.getFirst(); |
| 1584 | + if (importCollector.imports.contains(Module)) |
| 1585 | + continue; |
1576 | 1586 |
|
1577 |
| - auto inserted = visited.insert(D).second; |
1578 |
| - assert(inserted && "there should be no duplicate decls"); |
| 1587 | + auto &Decls = QI.getSecond(); |
| 1588 | + results.append(Decls.begin(), Decls.end()); |
| 1589 | + } |
| 1590 | + |
| 1591 | + for (const ModuleDecl *import : importCollector.imports) |
| 1592 | + import->getDisplayDecls(results); |
| 1593 | + |
| 1594 | +#ifndef NDEBUG |
| 1595 | + llvm::DenseSet<Decl *> visited; |
| 1596 | + for (auto *D : results) { |
| 1597 | + // decls synthesized from implicit clang decls may appear multiple times; |
| 1598 | + // e.g. if multiple modules with underlying clang modules are re-exported. |
| 1599 | + // including duplicates of these is harmless, so skip them when counting |
| 1600 | + // this assertion |
| 1601 | + if (const auto *CD = D->getClangDecl()) { |
| 1602 | + if (CD->isImplicit()) |
| 1603 | + continue; |
1579 | 1604 | }
|
| 1605 | + auto inserted = visited.insert(D).second; |
| 1606 | + assert(inserted && "there should be no duplicate decls"); |
1580 | 1607 | }
|
1581 | 1608 | #endif
|
1582 | 1609 | }
|
@@ -2393,7 +2420,7 @@ ModuleDecl::getDeclaringModuleAndBystander() {
|
2393 | 2420 | return *(declaringModuleAndBystander = {nullptr, Identifier()});
|
2394 | 2421 | }
|
2395 | 2422 |
|
2396 |
| -bool ModuleDecl::isClangOverlayOf(ModuleDecl *potentialUnderlying) { |
| 2423 | +bool ModuleDecl::isClangOverlayOf(ModuleDecl *potentialUnderlying) const { |
2397 | 2424 | return getUnderlyingModuleIfOverlay() == potentialUnderlying;
|
2398 | 2425 | }
|
2399 | 2426 |
|
|
0 commit comments