-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[SymbolGraphGen] Emit symbols from exported modules #41577
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -788,7 +788,7 @@ bool ModuleDecl::shouldCollectDisplayDecls() const { | |
return true; | ||
} | ||
|
||
static void collectParsedExportedImports(const ModuleDecl *M, SmallPtrSetImpl<ModuleDecl *> &Imports) { | ||
void swift::collectParsedExportedImports(const ModuleDecl *M, SmallPtrSetImpl<ModuleDecl *> &Imports) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Imports is just returned data so consider returning it directly (RVO means you won't incur the extra copy). However, having had a quick look the usage pattern for the Imports set seems to be very much a case of doing the insertions here and the clients only querying the set. You might be better off using the sorted vector approach described here https://llvm.org/docs/ProgrammersManual.html#id64 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: Daniel and I discussed this further and opted to keep the code as-is to align with other functions of this type. |
||
for (const FileUnit *file : M->getFiles()) { | ||
if (const SourceFile *source = dyn_cast<SourceFile>(file)) { | ||
if (source->hasImports()) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -674,12 +674,12 @@ bool SymbolGraph::isUnconditionallyUnavailableOnAllPlatforms(const Decl *D) cons | |
|
||
/// Returns `true` if the symbol should be included as a node in the graph. | ||
bool SymbolGraph::canIncludeDeclAsNode(const Decl *D) const { | ||
// If this decl isn't in this module, don't record it, | ||
// If this decl isn't in this module or module that this module imported with `@_exported`, don't record it, | ||
// as it will appear elsewhere in its module's symbol graph. | ||
if (D->getModuleContext()->getName() != M.getName()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something feels off about removing this change entirely. It's probably fine as-is, but i wonder if we could have the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, I agree. I added that check back with a |
||
if (D->getModuleContext()->getName() != M.getName() && !Walker.isFromExportedImportedModule(D)) { | ||
return false; | ||
} | ||
|
||
if (!isa<ValueDecl>(D)) { | ||
return false; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,9 +22,11 @@ using namespace swift; | |
using namespace symbolgraphgen; | ||
|
||
SymbolGraphASTWalker::SymbolGraphASTWalker(ModuleDecl &M, | ||
const SmallPtrSet<ModuleDecl *, 4> ExportedImportedModules, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you use the sorted vector approach described in the comment on |
||
const SymbolGraphOptions &Options) | ||
: Options(Options), | ||
M(M), | ||
ExportedImportedModules(ExportedImportedModules), | ||
MainGraph(*this, M, None, Ctx) {} | ||
|
||
/// Get a "sub" symbol graph for the parent module of a type that | ||
|
@@ -51,6 +53,11 @@ SymbolGraph *SymbolGraphASTWalker::getModuleSymbolGraph(const Decl *D) { | |
// should put actual extensions of that module into the main graph | ||
return &MainGraph; | ||
} | ||
|
||
if (isFromExportedImportedModule(D)) { | ||
return &MainGraph; | ||
} | ||
|
||
auto Found = ExtendedModuleGraphs.find(M->getNameStr()); | ||
if (Found != ExtendedModuleGraphs.end()) { | ||
return Found->getValue(); | ||
|
@@ -208,3 +215,11 @@ bool SymbolGraphASTWalker::walkToDeclPre(Decl *D, CharSourceRange Range) { | |
|
||
return true; | ||
} | ||
|
||
bool SymbolGraphASTWalker::isFromExportedImportedModule(const Decl* D) const { | ||
auto *M = D->getModuleContext(); | ||
|
||
return llvm::any_of(ExportedImportedModules, [&M](const auto *MD) { | ||
return M->getNameStr().equals(MD->getModuleContext()->getNameStr()); | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
// RUN: %empty-directory(%t) | ||
// RUN: %target-build-swift %s -module-name BasicExtension -emit-module -emit-module-path %t/ | ||
// RUN: %target-swift-symbolgraph-extract -module-name BasicExtension -I %t -pretty-print -output-dir %t | ||
// RUN: %FileCheck %s --input-file %t/[email protected] | ||
// RUN: %FileCheck %s --input-file %t/[email protected] --check-prefix EXTRACT | ||
|
||
// RUN: %empty-directory(%t) | ||
// RUN: %target-build-swift %s -module-name BasicExtension -emit-module -emit-module-path %t/ -emit-symbol-graph -emit-symbol-graph-dir %t | ||
// RUN: %FileCheck %s --input-file %t/[email protected] --check-prefix BUILD | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added this test to verify the during-the-build behaviour didn't regress. |
||
|
||
extension String { | ||
/// Return something. | ||
|
@@ -10,17 +14,28 @@ extension String { | |
} | ||
} | ||
|
||
// CHECK: module | ||
// CHECK-NEXT: "name": "BasicExtension" | ||
// EXTRACT: module | ||
// EXTRACT-NEXT: "name": "BasicExtension" | ||
|
||
// BUILD: module | ||
// BUILD: "name":"BasicExtension" | ||
|
||
// CHECK: "precise": "s:SS14BasicExtensionE9somethingSSvp" | ||
// EXTRACT: "precise": "s:SS14BasicExtensionE9somethingSSvp" | ||
|
||
// CHECK: "kind": "memberOf" | ||
// CHECK-NEXT: "source": "s:SS14BasicExtensionE9somethingSSvp" | ||
// CHECK-NEXT: "target": "s:SS" | ||
// BUILD: "precise":"s:SS14BasicExtensionE9somethingSSvp" | ||
|
||
// EXTRACT: "kind": "memberOf" | ||
// EXTRACT-NEXT: "source": "s:SS14BasicExtensionE9somethingSSvp" | ||
// EXTRACT-NEXT: "target": "s:SS" | ||
|
||
// BUILD: "kind":"memberOf" | ||
// BUILD: "source":"s:SS14BasicExtensionE9somethingSSvp" | ||
// BUILD: "target":"s:SS" | ||
|
||
// Extending `String` creates a memberOf relationship above. | ||
// However, it should not be included as a node because `String` | ||
// is owned by the Swift module. | ||
// rdar://58876107 | ||
// CHECK-NOT: "precise": "s:SS" | ||
// EXTRACT-NOT: "precise": "s:SS" | ||
|
||
// BUILD-NOT: "precise":"s:SS" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// RUN: %empty-directory(%t) | ||
// RUN: %target-swift-frontend %S/Inputs/ExportedImport/A.swift -module-name A -emit-module -emit-module-path %t/A.swiftmodule | ||
// RUN: %target-swift-frontend %s -module-name ExportedImport -emit-module -emit-module-path /dev/null -I %t -emit-symbol-graph -emit-symbol-graph-dir %t/ | ||
// RUN: %FileCheck %s --input-file %t/ExportedImport.symbols.json | ||
// RUN: ls %t | %FileCheck %s --check-prefix FILES | ||
|
||
@_exported import A | ||
|
||
// CHECK: "precise":"s:1A11SymbolFromAV" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it might also be worth adding a test that makes sure that
Again, mainly just me being overly paranoid here. 😅 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, that's a great idea 👍 Added. |
||
// CHECK-NOT: InternalSymbolFromA | ||
|
||
// FIXME: Symbols from `@_exported import` do not get emitted when using swift-symbolgraph-extract | ||
// This is tracked by https://bugs.swift.org/browse/SR-15921. | ||
|
||
// FILES-NOT: [email protected] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
public struct SymbolFromA {} | ||
|
||
struct InternalSymbolFromA {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm willing to bet that this is the cause of SR-15921. This function only works on parsed modules, i.e. ones where the files are all
SourceFile
s. The ones seen byswift-symbolgraph-extract
(and during the build on an-emit-module
build) are all going to beSerializedASTFile
s, which won't work with this function. We may need to fall back to a manual decl crawl for modules which aren't parsed directly fromSourceFile
s.Leaving this as-is may suit our purposes now, but i feel like having multiple entry points to "get a symbol graph" that have different behaviors will bite us later. If it's possible to add it to this PR, i'd love to see it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, interesting. I'd have to look more into that. I'd prefer if we could land this as-is and look into that issue separately as this unblocks me for what I'm trying to do.