-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[CodeCompletion] Complete Swift only module name after 'import' #24455
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
[CodeCompletion] Complete Swift only module name after 'import' #24455
Conversation
e3bfbc0
to
3f3ff69
Compare
@swift-ci Please smoke test |
if (ModuleName.str().startswith("_")) | ||
continue; | ||
if (ModuleName == Ctx.SwiftShimsModuleName) | ||
continue; |
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.
Are there other module names we should hide? e.g. SwiftOnoneSupport
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.
Yeah, that one seems worth hiding. That's probably all we want to hardcode in the tools.
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.
+1 to skipping OnoneSupport (looks like the name is in Strings.h). Other modules we should skip: __C
, __C_Synthesized
, Builtin
. I'm guessing they are already hidden because they're not on the file system, but please add CHECK-NOT
s for them.
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.
_InternalSwiftSyntaxParser
is another one we don't want to show. Should already be covered, but again, worth a test to make sure.
} | ||
case SearchPathKind::Framework: { | ||
// Look for: | ||
// $PATH/{name}.framework/Modules/{name}.swiftmodule/{arch}.{extension} |
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.
Not sure we need to handle frameworks practically. If framework always have Clang module (module.modulemap
) with corresponding module name, ClangImporter
can find them.
@jrose-apple Is pure Swift only framework possible?
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.
Yes, unfortunately.
fb5c6f3
to
3b099bb
Compare
@swift-ci Please test |
Build failed |
Build failed |
@swift-ci Please test |
Build failed |
Build failed |
lib/IDE/CodeCompletion.cpp
Outdated
auto MD = ModuleDecl::create(Ctx.getIdentifier(ModuleName), Ctx); | ||
if (ModuleName == mainModuleName) | ||
continue; | ||
if (ModuleName.str().startswith("_")) |
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 not happy about this case, but since it's just been copied okay...
if (ModuleName.str().startswith("_")) | ||
continue; | ||
if (ModuleName == Ctx.SwiftShimsModuleName) | ||
continue; |
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.
+1 to skipping OnoneSupport (looks like the name is in Strings.h). Other modules we should skip: __C
, __C_Synthesized
, Builtin
. I'm guessing they are already hidden because they're not on the file system, but please add CHECK-NOT
s for them.
|
||
// Check whether target specific module file exists or not in given directory. | ||
// $PATH/{arch}.{extension} | ||
auto checkTargetFiles = [&](StringRef path) -> bool { |
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.
Is there any point in checking these instead of just detecting the presence of the .swiftmodule directory/file? We aren't checking if the module is importable.
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.
That'd be faster but might mean less common code between both code paths.
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.
Good point. I'm okay with this if it's not a big perf issue and keeps the code simpler.
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 haven't taken a close look at the refactoring for SerializedModuleLoaderBase yet, but here's some initial comments. (Seems intricate…)
if (ModuleName.str().startswith("_")) | ||
continue; | ||
if (ModuleName == Ctx.SwiftShimsModuleName) | ||
continue; |
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.
Yeah, that one seems worth hiding. That's probably all we want to hardcode in the tools.
@@ -70,6 +70,11 @@ class SkipNonTransparentFunctions : public DelayedParsingCallbacks { | |||
|
|||
} // unnamed namespace | |||
|
|||
void SourceLoader::collectVisibleTopLevelModuleNames( | |||
SmallVectorImpl<Identifier> &names) const { | |||
// TODO: Implement? |
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.
Nah, SourceLoader's going away soon. (As soon as I can convert the tests over to using module interfaces.)
|
||
/// Apply \c body for each target-specific module file base name to search. | ||
void forEachTargetModuleBasename(const ASTContext &Ctx, | ||
llvm::function_ref<void(StringRef)> body) { |
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.
Nitpick: LLVM style is to double-indent the wrapped line (and then single-indent the following lines), and I think we consistently wrap all parameters if any of them can't be aligned to the open paren.
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.
Ah, I forgot to apply clang-format
to this block. Thanks!
} | ||
case SearchPathKind::Framework: { | ||
// Look for: | ||
// $PATH/{name}.framework/Modules/{name}.swiftmodule/{arch}.{extension} |
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.
Yes, unfortunately.
Initial reaction is that I like the module loading refactoring quite a bit, but I'll need to study it more to see if it preserves behavior. |
cce47c6
to
9b83c3e
Compare
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.
The SerializedModuleLoaderBase
refactoring is so nice. I knew there was a small, sensible function struggling to escape from that mess.
return result; | ||
|
||
// Apple platforms have extra implicit framework search paths: | ||
// $SDKROOT/System/Library/Frameworks/ ; and |
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.
This comment seems to have picked up a semicolon in the move.
// Apply \p body for each directory entry in \p dirPath. | ||
auto forEachDirectoryEntryPath = | ||
[&](StringRef dirPath, llvm::function_ref<void(StringRef)> body) { | ||
std::error_code errorCode; |
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 suppose you're intentionally ignoring the error code here?
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.
errorCode
is handled in for
condition. for (; !errorCode && DI != End;...
// Look for: | ||
// (Darwin OS) $PATH/{name}.swiftmodule/{arch}.{extension} | ||
// (Other OS) $PATH/{name}.{extension} | ||
bool requireTargetSpecificModule = Ctx.LangOpts.Target.isOSDarwin(); |
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.
This isOSDarwin()
test for RuntimeLibrary
is written twice. Could we centralize it somehow? Maybe by splitting RuntimeLibrary
into TargetSpecificRuntimeLibrary
and TargetIndependentRuntimeLibrary
?
Alternatively, maybe forEachModuleSearchPath()
could pass additional parameters with flags for "can be target independent" and "can be target dependent" (or a single tri-state value). That might allow you to unify more of the framework and non-framework paths in these functions.
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.
That seems to be a good idea. Let me try it in follow-ups.
@@ -228,6 +401,7 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID, | |||
|
|||
// We can only get here if all targetFileNamePairs failed with | |||
// 'std::errc::no_such_file_or_directory'. | |||
auto normalizedTarget = getTargetSpecificModuleTriple(Ctx.LangOpts.Target); |
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.
We're going to recompute this pretty often if it's inside the lambda, but I guess it'll be swamped by I/O anyway.
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.
This is diagnostics code path. I don't expect this code is going to be executed so often. Am I missing something?
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.
If we end up at the return None;
after this, we may still successfully load a module from a later search path. But I guess that only happens if there's a .swiftmodule directory and the directory doesn't contain any accessible .swiftmodule files, so it's not likely to happen repeatedly.
(Hmm, I don't think failed #if canImport(...)
results are cached anywhere...unrelated, just something I noticed.)
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.
Ah, that's true. Thank you for explanation!
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.
Decided to use the first name from forEachTargetModuleBasename()
if (ModuleName.str().startswith("_")) | ||
continue; | ||
if (ModuleName == Ctx.SwiftShimsModuleName) | ||
continue; |
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.
_InternalSwiftSyntaxParser
is another one we don't want to show. Should already be covered, but again, worth a test to make sure.
1d317fd
to
334685b
Compare
@swift-ci Please smoke test |
1 similar comment
@swift-ci Please smoke test |
3fd99cf
to
334685b
Compare
rdar://problem/39392446
- forEachTargetModuleBasename(): Iterate through target names to search - forEachModuleSearchPath(): Iterate through search paths
334685b
to
d02f170
Compare
@swift-ci Please smoke test |
Maintain an invariant that forEachTargetModuleBasename() iterates names from most to least desiable.
d02f170
to
0d43e5a
Compare
@swift-ci Please smoke test |
*sigh* I think the tri-state |
@jrose-apple Could you elaborate? Did I make a mistake? |
I'm not sure. This morning I'm thinking about it more and I think you didn't make a mistake, but I'm still taking this as evidence that the code isn't as easy-to-read as it could be. |
(The issue is that ParseableInterfaceModuleLoader is failing but the compilation process overall is "succeeding", i.e. exiting with an exit code of 0.) |
For each
ModuleLoader
, newly implementcollectVisibleTopLevelModuleNames()
which collects visible module names. It doesn't care about the actual content of the file though. So it doesn't guarantee the module is loadable.rdar://problem/39392446