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