Skip to content

[5.1 04-24-2019][Serialization] Support Swift only system module #24662

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ class alignas(1 << DeclAlignInBits) Decl {
HasAnyUnavailableValues : 1
);

SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1,
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1,
/// If the module was or is being compiled with `-enable-testing`.
TestingEnabled : 1,

Expand All @@ -612,7 +612,10 @@ class alignas(1 << DeclAlignInBits) Decl {
PrivateImportsEnabled : 1,

// If the module is compiled with `-enable-implicit-dynamic`.
ImplicitDynamicEnabled : 1
ImplicitDynamicEnabled : 1,

// Whether the module is a system module.
IsSystemModule : 1
);

SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,
Expand Down
13 changes: 9 additions & 4 deletions include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,15 @@ class ModuleDecl : public DeclContext, public TypeDecl {
Bits.ModuleDecl.RawResilienceStrategy = unsigned(strategy);
}

/// \returns true if this module is a system module; note that the StdLib is
/// considered a system module.
bool isSystemModule() const {
return Bits.ModuleDecl.IsSystemModule;
}
void setIsSystemModule(bool flag = true) {
Bits.ModuleDecl.IsSystemModule = flag;
}

bool isResilient() const {
return getResilienceStrategy() != ResilienceStrategy::Default;
}
Expand Down Expand Up @@ -553,10 +562,6 @@ class ModuleDecl : public DeclContext, public TypeDecl {
/// \returns true if this module is the "SwiftOnoneSupport" module;
bool isOnoneSupportModule() const;

/// \returns true if this module is a system module; note that the StdLib is
/// considered a system module.
bool isSystemModule() const;

/// \returns true if traversal was aborted, false otherwise.
bool walk(ASTWalker &Walker);

Expand Down
2 changes: 1 addition & 1 deletion include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
bool findModule(AccessPathElem moduleID,
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
bool &isFramework);
bool &isFramework, bool &isSystemModule);

/// Attempts to search the provided directory for a loadable serialized
/// .swiftmodule with the provided `ModuleFilename`. Subclasses must
Expand Down
10 changes: 0 additions & 10 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1283,16 +1283,6 @@ bool ModuleDecl::registerEntryPointFile(FileUnit *file, SourceLoc diagLoc,
return true;
}

bool ModuleDecl::isSystemModule() const {
if (isStdlibModule())
return true;
for (auto F : getFiles()) {
if (auto LF = dyn_cast<LoadedFile>(F))
return LF->isSystemModule();
}
return false;
}

template<bool respectVisibility>
static bool
forAllImportedModules(ModuleDecl *topLevel, ModuleDecl::AccessPathTy thisPath,
Expand Down
2 changes: 2 additions & 0 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,7 @@ ModuleDecl *ClangImporter::Implementation::finishLoadingClangModule(
// but that's not correct for submodules.
Identifier name = SwiftContext.getIdentifier((*clangModule).Name);
result = ModuleDecl::create(name, SwiftContext);
result->setIsSystemModule(clangModule->IsSystem);
// Silence error messages about testably importing a Clang module.
result->setTestingEnabled();
result->setHasResolvedImports();
Expand Down Expand Up @@ -1836,6 +1837,7 @@ ClangModuleUnit *ClangImporter::Implementation::getWrapperForModule(
// FIXME: Handle hierarchical names better.
Identifier name = SwiftContext.getIdentifier(underlying->Name);
auto wrapper = ModuleDecl::create(name, SwiftContext);
wrapper->setIsSystemModule(underlying->IsSystem);
// Silence error messages about testably importing a Clang module.
wrapper->setTestingEnabled();
wrapper->setHasResolvedImports();
Expand Down
44 changes: 33 additions & 11 deletions lib/Serialization/SerializedModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,16 @@ enum class SearchPathKind {
/// non-None value. Returns the return value from \p body, or \c None.
Optional<bool> forEachModuleSearchPath(
const ASTContext &Ctx,
llvm::function_ref<Optional<bool>(StringRef, SearchPathKind)> callback) {
llvm::function_ref<Optional<bool>(StringRef, SearchPathKind, bool isSystem)>
callback) {
for (const auto &path : Ctx.SearchPathOpts.ImportSearchPaths)
if (auto result = callback(path, SearchPathKind::Import))
if (auto result =
callback(path, SearchPathKind::Import, /*isSystem=*/false))
return result;

for (const auto &path : Ctx.SearchPathOpts.FrameworkSearchPaths)
if (auto result = callback(path.Path, SearchPathKind::Framework))
if (auto result =
callback(path.Path, SearchPathKind::Framework, path.IsSystem))
return result;

// Apple platforms have extra implicit framework search paths:
Expand All @@ -78,17 +81,20 @@ Optional<bool> forEachModuleSearchPath(
SmallString<128> scratch;
scratch = Ctx.SearchPathOpts.SDKPath;
llvm::sys::path::append(scratch, "System", "Library", "Frameworks");
if (auto result = callback(scratch, SearchPathKind::Framework))
if (auto result =
callback(scratch, SearchPathKind::Framework, /*isSystem=*/true))
return result;

scratch = Ctx.SearchPathOpts.SDKPath;
llvm::sys::path::append(scratch, "Library", "Frameworks");
if (auto result = callback(scratch, SearchPathKind::Framework))
if (auto result =
callback(scratch, SearchPathKind::Framework, /*isSystem=*/true))
return result;
}

for (auto importPath : Ctx.SearchPathOpts.RuntimeLibraryImportPaths) {
if (auto result = callback(importPath, SearchPathKind::RuntimeLibrary))
if (auto result = callback(importPath, SearchPathKind::RuntimeLibrary,
/*isSystem=*/true))
return result;
}

Expand Down Expand Up @@ -150,7 +156,8 @@ void SerializedModuleLoaderBase::collectVisibleTopLevelModuleNamesImpl(
return false;
};

forEachModuleSearchPath(Ctx, [&](StringRef searchPath, SearchPathKind Kind) {
forEachModuleSearchPath(Ctx, [&](StringRef searchPath, SearchPathKind Kind,
bool isSystem) {
switch (Kind) {
case SearchPathKind::Import: {
// Look for:
Expand Down Expand Up @@ -369,7 +376,7 @@ bool
SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
bool &isFramework) {
bool &isFramework, bool &isSystemModule) {
llvm::SmallString<64> moduleName(moduleID.first.str());
ModuleFilenamePair fileNames(moduleName);

Expand Down Expand Up @@ -413,8 +420,11 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
};

auto result = forEachModuleSearchPath(
Ctx, [&](StringRef path, SearchPathKind Kind) -> Optional<bool> {
Ctx,
[&](StringRef path, SearchPathKind Kind,
bool isSystem) -> Optional<bool> {
currPath = path;
isSystemModule = isSystem;

switch (Kind) {
case SearchPathKind::Import:
Expand Down Expand Up @@ -547,6 +557,15 @@ FileUnit *SerializedModuleLoaderBase::loadAST(
loadInfo.status =
loadedModuleFile->associateWithFileContext(fileUnit, diagLocOrInvalid,
treatAsPartialModule);

// FIXME: This seems wrong. Overlay for system Clang module doesn't
// necessarily mean it's "system" module. User can make their own overlay
// in non-system directory.
// Remove this block after we fix the test suite.
if (auto shadowed = loadedModuleFile->getShadowedModule())
if (shadowed->isSystemModule())
M.setIsSystemModule(true);

if (loadInfo.status == serialization::Status::Valid) {
Ctx.bumpGeneration();
LoadedModuleFiles.emplace_back(std::move(loadedModuleFile),
Expand Down Expand Up @@ -748,7 +767,8 @@ bool SerializedModuleLoaderBase::canImportModule(
std::pair<Identifier, SourceLoc> mID) {
// Look on disk.
bool isFramework = false;
return findModule(mID, nullptr, nullptr, isFramework);
bool isSystemModule = false;
return findModule(mID, nullptr, nullptr, isFramework, isSystemModule);
}

bool MemoryBufferSerializedModuleLoader::canImportModule(
Expand All @@ -766,13 +786,14 @@ SerializedModuleLoaderBase::loadModule(SourceLoc importLoc,

auto moduleID = path[0];
bool isFramework = false;
bool isSystemModule = false;

std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer;
std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer;

// Look on disk.
if (!findModule(moduleID, &moduleInputBuffer, &moduleDocInputBuffer,
isFramework)) {
isFramework, isSystemModule)) {
return nullptr;
}
if (dependencyTracker) {
Expand All @@ -786,6 +807,7 @@ SerializedModuleLoaderBase::loadModule(SourceLoc importLoc,
assert(moduleInputBuffer);

auto M = ModuleDecl::create(moduleID.first, Ctx);
M->setIsSystemModule(isSystemModule);
Ctx.LoadedModules[moduleID.first] = M;
SWIFT_DEFER { M->setHasResolvedImports(); };

Expand Down
62 changes: 62 additions & 0 deletions test/IDE/complete_from_swiftonly_systemmodule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// RUN: %empty-directory(%t)
// RUN: %{python} %utils/split_file.py -o %t %s

// RUN: mkdir -p %t/SDK/Frameworks/SomeModule.framework/Modules/SomeModule.swiftmodule
// RUN: %target-swift-frontend \
// RUN: -emit-module \
// RUN: -module-name SomeModule \
// RUN: -o %t/SDK/Frameworks/SomeModule.framework/Modules/SomeModule.swiftmodule/%module-target-triple.swiftmodule \
// RUN: -swift-version 5 \
// RUN: %t/SomeModule.swift

// RUN: %target-swift-ide-test -code-completion -sdk %t/SDK -iframework %t/SDK/Frameworks -source-filename %t/main.swift -code-completion-token=GLOBAL | %FileCheck --check-prefix GLOBAL %s
// RUN: %target-swift-ide-test -code-completion -sdk %t/SDK -iframework %t/SDK/Frameworks -source-filename %t/main.swift -code-completion-token=INSTANCE | %FileCheck --check-prefix INSTANCE %s
// RUN: %target-swift-ide-test -code-completion -sdk %t/SDK -iframework %t/SDK/Frameworks -source-filename %t/main.swift -code-completion-token=INITIALIZER | %FileCheck --check-prefix INITIALIZER %s

// Test that declarations starting with '_' from system module doesn't apper in
// code completion.

// BEGIN SomeModule.swift

public struct SomeValue {
internal var internalValue: Int { return 1 }
public var _secretValue: Int { return 1 }
public var publicValue: Int { return 1 }

internal func internalMethod() -> Int { return 1 }
public func _secretMethod() -> Int { return 1 }
public func publicMethod() -> Int { return 1 }

internal init(internal: Int) {}
public init(_secret: Int) {}
public init(public: Int) {}
}

internal func internalFunc() {}
public func _secretFunc() {}
public func publicFunc() {}

// BEGIN main.swift
import SomeModule

func test(value: SomeValue) {
let _ = #^GLOBAL^#
// GLOBAL: Begin completions
// GLOBAL-NOT: _secretFunc
// GLOBAL-NOT: internalFunc
// GLOBAL-DAG: Decl[Struct]/OtherModule[SomeModule]: SomeValue[#SomeValue#];
// GLOBAL-DAG: Decl[FreeFunction]/OtherModule[SomeModule]: publicFunc()[#Void#];
// GLOBAL: End completions

let _ = value.#^INSTANCE^#
// INSTANCE: Begin completions, 3 items
// INSTANCE-DAG: Keyword[self]/CurrNominal: self[#SomeValue#];
// INSTANCE-DAG: Decl[InstanceVar]/CurrNominal: publicValue[#Int#];
// INSTANCE-DAG: Decl[InstanceMethod]/CurrNominal: publicMethod()[#Int#];
// INSTANCE: End completions

let _ = SomeValue(#^INITIALIZER^#
// INITIALIZER: Begin completions, 1 items
// INITIALIZER-DAG: Decl[Constructor]/CurrNominal: ['(']{#public: Int#}[')'][#SomeValue#];
// INITIALIZER: End completions
}
Loading