Skip to content

Commit

Permalink
Merge pull request swiftlang#20525 from aschwaighofer/code_completion…
Browse files Browse the repository at this point in the history
…_private_imports

Make sure the code completion takes both private imports and testable
  • Loading branch information
aschwaighofer authored Nov 14, 2018
2 parents 9d10068 + 49cdab2 commit 9debb38
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 15 deletions.
13 changes: 12 additions & 1 deletion include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,18 @@ class SourceFile final : public FileUnit {

void addImports(ArrayRef<ImportedModuleDesc> IM);

bool hasTestableOrPrivateImport(AccessLevel accessLevel, const ValueDecl *ofDecl) const;
enum ImportQueryKind {
/// Return the results for testable or private imports.
TestableAndPrivate,
/// Return the results only for testable imports.
TestableOnly,
/// Return the results only for private imports.
PrivateOnly
};

bool
hasTestableOrPrivateImport(AccessLevel accessLevel, const ValueDecl *ofDecl,
ImportQueryKind kind = TestableAndPrivate) const;

void clearLookupCache();

Expand Down
7 changes: 5 additions & 2 deletions include/swift/IDE/CodeCompletionCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class CodeCompletionCache {
std::vector<std::string> AccessPath;
bool ResultsHaveLeadingDot;
bool ForTestableLookup;
bool ForPrivateImportLookup;
bool CodeCompleteInitsInPostfixExpr;

friend bool operator==(const Key &LHS, const Key &RHS) {
Expand All @@ -49,6 +50,7 @@ class CodeCompletionCache {
LHS.AccessPath == RHS.AccessPath &&
LHS.ResultsHaveLeadingDot == RHS.ResultsHaveLeadingDot &&
LHS.ForTestableLookup == RHS.ForTestableLookup &&
LHS.ForPrivateImportLookup == RHS.ForPrivateImportLookup &&
LHS.CodeCompleteInitsInPostfixExpr == RHS.CodeCompleteInitsInPostfixExpr;
}
};
Expand Down Expand Up @@ -106,10 +108,10 @@ template<>
struct DenseMapInfo<swift::ide::CodeCompletionCache::Key> {
using KeyTy = swift::ide::CodeCompletionCache::Key;
static inline KeyTy getEmptyKey() {
return KeyTy{"", "", {}, false, false, false};
return KeyTy{"", "", {}, false, false, false, false};
}
static inline KeyTy getTombstoneKey() {
return KeyTy{"", "", {}, true, false, false};
return KeyTy{"", "", {}, true, false, false, false};
}
static unsigned getHashValue(const KeyTy &Val) {
size_t H = 0;
Expand All @@ -119,6 +121,7 @@ struct DenseMapInfo<swift::ide::CodeCompletionCache::Key> {
H ^= std::hash<std::string>()(Piece);
H ^= std::hash<bool>()(Val.ResultsHaveLeadingDot);
H ^= std::hash<bool>()(Val.ForTestableLookup);
H ^= std::hash<bool>()(Val.ForPrivateImportLookup);
return static_cast<unsigned>(H);
}
static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) {
Expand Down
23 changes: 18 additions & 5 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1389,7 +1389,8 @@ void SourceFile::addImports(ArrayRef<ImportedModuleDesc> IM) {
}

bool SourceFile::hasTestableOrPrivateImport(
AccessLevel accessLevel, const swift::ValueDecl *ofDecl) const {
AccessLevel accessLevel, const swift::ValueDecl *ofDecl,
SourceFile::ImportQueryKind queryKind) const {
auto *module = ofDecl->getModuleContext();
switch (accessLevel) {
case AccessLevel::Internal:
Expand All @@ -1399,10 +1400,19 @@ bool SourceFile::hasTestableOrPrivateImport(
// decls).
return std::any_of(
Imports.begin(), Imports.end(),
[module](ImportedModuleDesc desc) -> bool {
return desc.module.second == module &&
(desc.importOptions.contains(ImportFlags::PrivateImport) ||
desc.importOptions.contains(ImportFlags::Testable));
[module, queryKind](ImportedModuleDesc desc) -> bool {
if (queryKind == ImportQueryKind::TestableAndPrivate)
return desc.module.second == module &&
(desc.importOptions.contains(ImportFlags::PrivateImport) ||
desc.importOptions.contains(ImportFlags::Testable));
else if (queryKind == ImportQueryKind::TestableOnly)
return desc.module.second == module &&
desc.importOptions.contains(ImportFlags::Testable);
else {
assert(queryKind == ImportQueryKind::PrivateOnly);
return desc.module.second == module &&
desc.importOptions.contains(ImportFlags::PrivateImport);
}
});
case AccessLevel::Open:
return true;
Expand All @@ -1412,6 +1422,9 @@ bool SourceFile::hasTestableOrPrivateImport(
break;
}

if (queryKind == ImportQueryKind::TestableOnly)
return false;

auto *DC = ofDecl->getDeclContext();
if (!DC)
return false;
Expand Down
15 changes: 9 additions & 6 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5946,12 +5946,15 @@ void CodeCompletionCallbacksImpl::doneParsing() {
if (!ModuleFilename.empty()) {
auto &Ctx = TheModule->getASTContext();
CodeCompletionCache::Key K{
ModuleFilename,
TheModule->getName().str(),
AccessPath,
Request.NeedLeadingDot,
SF.hasTestableOrPrivateImport(AccessLevel::Internal, TheModule),
Ctx.LangOpts.CodeCompleteInitsInPostfixExpr};
ModuleFilename, TheModule->getName().str(), AccessPath,
Request.NeedLeadingDot,
SF.hasTestableOrPrivateImport(
AccessLevel::Internal, TheModule,
SourceFile::ImportQueryKind::TestableOnly),
SF.hasTestableOrPrivateImport(
AccessLevel::Internal, TheModule,
SourceFile::ImportQueryKind::PrivateOnly),
Ctx.LangOpts.CodeCompleteInitsInPostfixExpr};

using PairType = llvm::DenseSet<swift::ide::CodeCompletionCache::Key,
llvm::DenseMapInfo<CodeCompletionCache::Key>>::iterator;
Expand Down
5 changes: 4 additions & 1 deletion lib/IDE/CodeCompletionCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ static void writeCachedModule(llvm::raw_ostream &out,
OSS << p << "\0";
OSSLE.write(K.ResultsHaveLeadingDot);
OSSLE.write(K.ForTestableLookup);
OSSLE.write(K.ForPrivateImportLookup);
OSSLE.write(K.CodeCompleteInitsInPostfixExpr);
LE.write(static_cast<uint32_t>(OSS.tell())); // Size of debug info
out.write(OSS.str().data(), OSS.str().size()); // Debug info blob
Expand Down Expand Up @@ -423,6 +424,7 @@ static std::string getName(StringRef cacheDirectory,
// name[-dot][-testable][-inits]
OSS << (K.ResultsHaveLeadingDot ? "-dot" : "")
<< (K.ForTestableLookup ? "-testable" : "")
<< (K.ForPrivateImportLookup ? "-private" : "")
<< (K.CodeCompleteInitsInPostfixExpr ? "-inits" : "");

// name[-access-path-components]
Expand Down Expand Up @@ -488,7 +490,8 @@ OnDiskCodeCompletionCache::getFromFile(StringRef filename) {
return None;

// Make up a key for readCachedModule.
CodeCompletionCache::Key K{filename, "<module-name>", {}, false, false, false};
CodeCompletionCache::Key K{filename, "<module-name>", {}, false,
false, false, false};

// Read the cached results.
auto V = CodeCompletionCache::createValue();
Expand Down
14 changes: 14 additions & 0 deletions test/IDE/complete_cache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,20 @@
// Check the individual cache item.
// RUN: %target-swift-ide-test -dump-completion-cache %t.ccp/macros-dot-* | %FileCheck %s -check-prefix=CLANG_QUAL_MACROS_2

// Qualified private with dot.
// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CLANG_QUAL_STRING -completion-cache-path=%t.ccp > %t.string.ccp1.compl.txt
// RUN: %FileCheck %s -check-prefix=CLANG_QUAL_STRING < %t.string.ccp1.compl.txt


// Ensure the testable import showed up mangled correctly.
// RUN: ls %t.ccp/Darwin-testable*
// RUN: ls %t.ccp/AppKit-private*
// REQUIRES: executable_test

import macros
import ctypes
@testable import Darwin
@_private(sourceFile: "AppKit.swift") import AppKit

// CLANG_CTYPES: Begin completions
// CLANG_CTYPES-DAG: Decl[Struct]/OtherModule[ctypes]/keyword[Foo1, Struct1]: FooStruct1[#FooStruct1#]{{; name=.+$}}
Expand Down Expand Up @@ -106,3 +113,10 @@ func testCompleteModuleQualifiedMacros2() {
// CLANG_QUAL_MACROS_2-DAG: Decl[GlobalVar]/OtherModule[macros]: .VERSION_STRING[#String#]{{; name=.+$}}
// CLANG_QUAL_MACROS_2: End completions
}

func testPrivate() {
String.#^CLANG_QUAL_STRING^#
// CLANG_QUAL_STRING: Begin completions
// CLANG_QUAL_STRING: name=someMethod()
// CLANG_QUAL_STRING: End completions
}
4 changes: 4 additions & 0 deletions test/Inputs/clang-importer-sdk/swift-modules/AppKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@
extension String {
public static func someFactoryMethod() -> Int { return 0 }
}

extension String {
static func someMethod() -> Int { return 0 }
}

0 comments on commit 9debb38

Please sign in to comment.