mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[CodeCompletion] Give up fast-completion if dependent files are modified
Check if dependencies are modified since the last checking. Dependencies: - Other source files in the current module - Dependent files collected by the dependency tracker When: - If the last dependency check was over N (defaults to 5) seconds ago Invalidate if: - The dependency file is missing - The modification time of the dependecy is greater than the last check - If the modification time is zero, compare the content using the file system from the previous completion and the current completion rdar://problem/62336432
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/Support/Chrono.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/Support/VirtualFileSystem.h"
|
#include "llvm/Support/VirtualFileSystem.h"
|
||||||
|
|
||||||
@@ -38,13 +39,20 @@ makeCodeCompletionMemoryBuffer(const llvm::MemoryBuffer *origBuf,
|
|||||||
/// Manages \c CompilerInstance for completion like operations.
|
/// Manages \c CompilerInstance for completion like operations.
|
||||||
class CompletionInstance {
|
class CompletionInstance {
|
||||||
unsigned MaxASTReuseCount = 100;
|
unsigned MaxASTReuseCount = 100;
|
||||||
|
unsigned DependencyCheckIntervalSecond = 5;
|
||||||
|
|
||||||
std::mutex mtx;
|
std::mutex mtx;
|
||||||
|
|
||||||
std::unique_ptr<CompilerInstance> CachedCI;
|
std::unique_ptr<CompilerInstance> CachedCI;
|
||||||
llvm::hash_code CachedArgHash;
|
llvm::hash_code CachedArgHash;
|
||||||
|
llvm::sys::TimePoint<> DependencyCheckedTimestamp;
|
||||||
unsigned CachedReuseCount = 0;
|
unsigned CachedReuseCount = 0;
|
||||||
|
|
||||||
|
void cacheCompilerInstance(std::unique_ptr<CompilerInstance> CI,
|
||||||
|
llvm::hash_code ArgsHash);
|
||||||
|
|
||||||
|
bool shouldCheckDependencies() const;
|
||||||
|
|
||||||
/// Calls \p Callback with cached \c CompilerInstance if it's usable for the
|
/// Calls \p Callback with cached \c CompilerInstance if it's usable for the
|
||||||
/// specified completion request.
|
/// specified completion request.
|
||||||
/// Returns \c if the callback was called. Returns \c false if the compiler
|
/// Returns \c if the callback was called. Returns \c false if the compiler
|
||||||
@@ -52,6 +60,7 @@ class CompletionInstance {
|
|||||||
/// in function bodies, or the interface hash of the file has changed.
|
/// in function bodies, or the interface hash of the file has changed.
|
||||||
bool performCachedOperationIfPossible(
|
bool performCachedOperationIfPossible(
|
||||||
const swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
|
const swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
|
||||||
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
||||||
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
|
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
|
||||||
DiagnosticConsumer *DiagC,
|
DiagnosticConsumer *DiagC,
|
||||||
llvm::function_ref<void(CompilerInstance &, bool)> Callback);
|
llvm::function_ref<void(CompilerInstance &, bool)> Callback);
|
||||||
@@ -69,6 +78,8 @@ class CompletionInstance {
|
|||||||
llvm::function_ref<void(CompilerInstance &, bool)> Callback);
|
llvm::function_ref<void(CompilerInstance &, bool)> Callback);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void setDependencyCheckIntervalSecond(unsigned Value);
|
||||||
|
|
||||||
/// Calls \p Callback with a \c CompilerInstance which is prepared for the
|
/// Calls \p Callback with a \c CompilerInstance which is prepared for the
|
||||||
/// second pass. \p Callback is resposible to perform the second pass on it.
|
/// second pass. \p Callback is resposible to perform the second pass on it.
|
||||||
/// The \c CompilerInstance may be reused from the previous completions,
|
/// The \c CompilerInstance may be reused from the previous completions,
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
#include "swift/AST/Module.h"
|
#include "swift/AST/Module.h"
|
||||||
#include "swift/AST/PrettyStackTrace.h"
|
#include "swift/AST/PrettyStackTrace.h"
|
||||||
#include "swift/AST/SourceFile.h"
|
#include "swift/AST/SourceFile.h"
|
||||||
|
#include "swift/Serialization/SerializedModuleLoader.h"
|
||||||
|
#include "swift/ClangImporter/ClangModule.h"
|
||||||
#include "swift/Basic/LangOptions.h"
|
#include "swift/Basic/LangOptions.h"
|
||||||
#include "swift/Basic/PrettyStackTrace.h"
|
#include "swift/Basic/PrettyStackTrace.h"
|
||||||
#include "swift/Basic/SourceManager.h"
|
#include "swift/Basic/SourceManager.h"
|
||||||
@@ -28,6 +30,7 @@
|
|||||||
#include "swift/Subsystems.h"
|
#include "swift/Subsystems.h"
|
||||||
#include "llvm/ADT/Hashing.h"
|
#include "llvm/ADT/Hashing.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
#include "clang/AST/ASTContext.h"
|
||||||
|
|
||||||
using namespace swift;
|
using namespace swift;
|
||||||
using namespace ide;
|
using namespace ide;
|
||||||
@@ -162,10 +165,77 @@ static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC,
|
|||||||
return newDC;
|
return newDC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if any dependent files are modified since \p timestamp.
|
||||||
|
bool areAnyDependentFilesInvalidated(CompilerInstance &CI,
|
||||||
|
llvm::vfs::FileSystem &FS,
|
||||||
|
StringRef currentFileName,
|
||||||
|
llvm::sys::TimePoint<> timestamp) {
|
||||||
|
|
||||||
|
auto isInvalidated = [&](StringRef filePath) -> bool {
|
||||||
|
auto stat = FS.status(filePath);
|
||||||
|
if (!stat)
|
||||||
|
// Missing.
|
||||||
|
return true;
|
||||||
|
|
||||||
|
auto lastModTime = stat->getLastModificationTime();
|
||||||
|
if (lastModTime > timestamp)
|
||||||
|
// Modified.
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// If the last modification time is zero, this file is probably from a
|
||||||
|
// virtual file system. We need to check the content.
|
||||||
|
if (lastModTime == llvm::sys::TimePoint<>()) {
|
||||||
|
if (&CI.getFileSystem() == &FS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto oldContent = CI.getFileSystem().getBufferForFile(filePath);
|
||||||
|
auto newContent = FS.getBufferForFile(filePath);
|
||||||
|
if (!oldContent || !newContent)
|
||||||
|
// (unreachable?)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (oldContent.get()->getBuffer() != newContent.get()->getBuffer())
|
||||||
|
// Different content.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check files in the current module.
|
||||||
|
for (FileUnit *file : CI.getMainModule()->getFiles()) {
|
||||||
|
StringRef filename;
|
||||||
|
if (auto SF = dyn_cast<SourceFile>(file))
|
||||||
|
filename = SF->getFilename();
|
||||||
|
else if (auto LF = dyn_cast<LoadedFile>(file))
|
||||||
|
filename = LF->getFilename();
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Ignore the current file and synthesized files.
|
||||||
|
if (filename.empty() || filename.front() == '<' ||
|
||||||
|
filename.equals(currentFileName))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (isInvalidated(filename))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check other non-system depenencies (e.g. modules, headers).
|
||||||
|
for (auto &dep : CI.getDependencyTracker()->getDependencies()) {
|
||||||
|
if (isInvalidated(dep))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All loaded module files are not modified since the timestamp.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool CompletionInstance::performCachedOperationIfPossible(
|
bool CompletionInstance::performCachedOperationIfPossible(
|
||||||
const swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
|
const swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
|
||||||
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
||||||
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
|
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
|
||||||
DiagnosticConsumer *DiagC,
|
DiagnosticConsumer *DiagC,
|
||||||
llvm::function_ref<void(CompilerInstance &, bool)> Callback) {
|
llvm::function_ref<void(CompilerInstance &, bool)> Callback) {
|
||||||
@@ -187,10 +257,17 @@ bool CompletionInstance::performCachedOperationIfPossible(
|
|||||||
auto &oldInfo = oldState->getCodeCompletionDelayedDeclState();
|
auto &oldInfo = oldState->getCodeCompletionDelayedDeclState();
|
||||||
|
|
||||||
auto &SM = CI.getSourceMgr();
|
auto &SM = CI.getSourceMgr();
|
||||||
if (SM.getIdentifierForBuffer(SM.getCodeCompletionBufferID()) !=
|
auto bufferName = completionBuffer->getBufferIdentifier();
|
||||||
completionBuffer->getBufferIdentifier())
|
if (SM.getIdentifierForBuffer(SM.getCodeCompletionBufferID()) != bufferName)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (shouldCheckDependencies()) {
|
||||||
|
if (areAnyDependentFilesInvalidated(CI, *FileSystem, bufferName,
|
||||||
|
DependencyCheckedTimestamp))
|
||||||
|
return false;
|
||||||
|
DependencyCheckedTimestamp = std::chrono::system_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the new buffer into temporary SourceFile.
|
// Parse the new buffer into temporary SourceFile.
|
||||||
SourceManager tmpSM;
|
SourceManager tmpSM;
|
||||||
auto tmpBufferID = tmpSM.addMemBufferCopy(completionBuffer);
|
auto tmpBufferID = tmpSM.addMemBufferCopy(completionBuffer);
|
||||||
@@ -263,8 +340,7 @@ bool CompletionInstance::performCachedOperationIfPossible(
|
|||||||
completionBuffer->getBuffer().slice(startOffset, endOffset);
|
completionBuffer->getBuffer().slice(startOffset, endOffset);
|
||||||
auto newOffset = Offset - startOffset;
|
auto newOffset = Offset - startOffset;
|
||||||
|
|
||||||
newBufferID = SM.addMemBufferCopy(sourceText,
|
newBufferID = SM.addMemBufferCopy(sourceText, bufferName);
|
||||||
completionBuffer->getBufferIdentifier());
|
|
||||||
SM.openVirtualFile(SM.getLocForBufferStart(newBufferID),
|
SM.openVirtualFile(SM.getLocForBufferStart(newBufferID),
|
||||||
tmpSM.getDisplayNameForLoc(startLoc),
|
tmpSM.getDisplayNameForLoc(startLoc),
|
||||||
tmpSM.getLineAndColumn(startLoc).first - 1);
|
tmpSM.getLineAndColumn(startLoc).first - 1);
|
||||||
@@ -310,8 +386,7 @@ bool CompletionInstance::performCachedOperationIfPossible(
|
|||||||
endOffset = tmpSM.getLocOffsetInBuffer(endLoc, tmpBufferID);
|
endOffset = tmpSM.getLocOffsetInBuffer(endLoc, tmpBufferID);
|
||||||
sourceText = sourceText.slice(0, endOffset);
|
sourceText = sourceText.slice(0, endOffset);
|
||||||
}
|
}
|
||||||
newBufferID = SM.addMemBufferCopy(sourceText,
|
newBufferID = SM.addMemBufferCopy(sourceText, bufferName);
|
||||||
completionBuffer->getBufferIdentifier());
|
|
||||||
SM.setCodeCompletionPoint(newBufferID, Offset);
|
SM.setCodeCompletionPoint(newBufferID, Offset);
|
||||||
|
|
||||||
// Create a new module and a source file using the current AST context.
|
// Create a new module and a source file using the current AST context.
|
||||||
@@ -369,7 +444,15 @@ bool CompletionInstance::performNewOperation(
|
|||||||
llvm::function_ref<void(CompilerInstance &, bool)> Callback) {
|
llvm::function_ref<void(CompilerInstance &, bool)> Callback) {
|
||||||
llvm::PrettyStackTraceString trace("While performing new completion");
|
llvm::PrettyStackTraceString trace("While performing new completion");
|
||||||
|
|
||||||
|
auto isCachedCompletionRequested = ArgsHash.hasValue();
|
||||||
|
|
||||||
auto TheInstance = std::make_unique<CompilerInstance>();
|
auto TheInstance = std::make_unique<CompilerInstance>();
|
||||||
|
|
||||||
|
// Track dependencies in fast-completion mode to invalidate the compiler
|
||||||
|
// instance if any dependent files are modified.
|
||||||
|
if (isCachedCompletionRequested)
|
||||||
|
TheInstance->createDependencyTracker(false);
|
||||||
|
|
||||||
{
|
{
|
||||||
auto &CI = *TheInstance;
|
auto &CI = *TheInstance;
|
||||||
if (DiagC)
|
if (DiagC)
|
||||||
@@ -407,15 +490,34 @@ bool CompletionInstance::performNewOperation(
|
|||||||
Callback(CI, /*reusingASTContext=*/false);
|
Callback(CI, /*reusingASTContext=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ArgsHash.hasValue()) {
|
// Cache the compiler instance if fast completion is enabled.
|
||||||
CachedCI = std::move(TheInstance);
|
if (isCachedCompletionRequested)
|
||||||
CachedArgHash = *ArgsHash;
|
cacheCompilerInstance(std::move(TheInstance), *ArgsHash);
|
||||||
CachedReuseCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompletionInstance::cacheCompilerInstance(
|
||||||
|
std::unique_ptr<CompilerInstance> CI, llvm::hash_code ArgsHash) {
|
||||||
|
CachedCI = std::move(CI);
|
||||||
|
CachedArgHash = ArgsHash;
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
DependencyCheckedTimestamp = now;
|
||||||
|
CachedReuseCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CompletionInstance::shouldCheckDependencies() const {
|
||||||
|
assert(CachedCI);
|
||||||
|
using namespace std::chrono;
|
||||||
|
auto now = system_clock::now();
|
||||||
|
return DependencyCheckedTimestamp + seconds(DependencyCheckIntervalSecond) < now;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompletionInstance::setDependencyCheckIntervalSecond(unsigned Value) {
|
||||||
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
DependencyCheckIntervalSecond = Value;
|
||||||
|
}
|
||||||
|
|
||||||
bool swift::ide::CompletionInstance::performOperation(
|
bool swift::ide::CompletionInstance::performOperation(
|
||||||
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
|
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
|
||||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
||||||
@@ -451,8 +553,9 @@ bool swift::ide::CompletionInstance::performOperation(
|
|||||||
// the cached completion instance.
|
// the cached completion instance.
|
||||||
std::lock_guard<std::mutex> lock(mtx);
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
|
||||||
if (performCachedOperationIfPossible(Invocation, ArgsHash, completionBuffer,
|
if (performCachedOperationIfPossible(Invocation, ArgsHash, FileSystem,
|
||||||
Offset, DiagC, Callback))
|
completionBuffer, Offset, DiagC,
|
||||||
|
Callback))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (performNewOperation(ArgsHash, Invocation, FileSystem, completionBuffer,
|
if (performNewOperation(ArgsHash, Invocation, FileSystem, completionBuffer,
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
#import <ClangFW/Funcs.h>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#ifndef CLANGFW_FUNCS_H
|
||||||
|
#define CLANGFW_FUNCS_H
|
||||||
|
int clangFWFunc();
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
framework module ClangFW {
|
||||||
|
umbrella header "ClangFW.h"
|
||||||
|
export *
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#ifndef CLANGFW_FUNCS_H
|
||||||
|
#define CLANGFW_FUNCS_H
|
||||||
|
int clangFWFunc_mod();
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#import "LocalCFunc.h"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
func localSwiftFunc() -> Int {}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef MYPROJECT_LOCALCFUNC_H
|
||||||
|
#define MYPROJECT_LOCALCFUNC_H
|
||||||
|
|
||||||
|
int localClangFunc();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
func localSwiftFunc_mod() -> Int {}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef MYPROJECT_LOCALCFUNC_H
|
||||||
|
#define MYPROJECT_LOCALCFUNC_H
|
||||||
|
|
||||||
|
int localClangFunc_mod();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
public func swiftFWFunc() -> Int { return 1 }
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
public func swiftFWFunc_mod() -> Int { return 1 }
|
||||||
5
test/SourceKit/CodeComplete/Inputs/checkdeps/test.swift
Normal file
5
test/SourceKit/CodeComplete/Inputs/checkdeps/test.swift
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import Foundation
|
||||||
|
import ClangFW // < 500 headers framework
|
||||||
|
func foo() {
|
||||||
|
/* HERE */
|
||||||
|
}
|
||||||
72
test/SourceKit/CodeComplete/complete_checkdeps_bridged.swift
Normal file
72
test/SourceKit/CodeComplete/complete_checkdeps_bridged.swift
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import ClangFW
|
||||||
|
import SwiftFW
|
||||||
|
|
||||||
|
func foo() {
|
||||||
|
/*HERE*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// RUN: %empty-directory(%t/Frameworks)
|
||||||
|
// RUN: %empty-directory(%t/MyProject)
|
||||||
|
|
||||||
|
// RUN: COMPILER_ARGS=( \
|
||||||
|
// RUN: -target %target-triple \
|
||||||
|
// RUN: -module-name MyProject \
|
||||||
|
// RUN: -F %t/Frameworks \
|
||||||
|
// RUN: -I %t/MyProject \
|
||||||
|
// RUN: -import-objc-header %t/MyProject/Bridging.h \
|
||||||
|
// RUN: %t/MyProject/Library.swift \
|
||||||
|
// RUN: %s \
|
||||||
|
// RUN: )
|
||||||
|
// RUN: INPUT_DIR=%S/Inputs/checkdeps
|
||||||
|
// RUN: DEPCHECK_INTERVAL=1
|
||||||
|
// RUN: SLEEP_TIME=2
|
||||||
|
|
||||||
|
// RUN: cp -R $INPUT_DIR/MyProject %t/
|
||||||
|
// RUN: cp -R $INPUT_DIR/ClangFW.framework %t/Frameworks/
|
||||||
|
// RUN: %empty-directory(%t/Frameworks/SwiftFW.framework/Modules/SwiftFW.swiftmodule)
|
||||||
|
// RUN: %target-swift-frontend -emit-module -module-name SwiftFW -o %t/Frameworks/SwiftFW.framework/Modules/SwiftFW.swiftmodule/%target-swiftmodule-name $INPUT_DIR/SwiftFW_src/Funcs.swift
|
||||||
|
|
||||||
|
// RUN: %sourcekitd-test \
|
||||||
|
// RUN: -req=global-config -completion-check-dependency-interval ${DEPCHECK_INTERVAL} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo "### Initial" == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo '### Modify bridging header library file' == \
|
||||||
|
// RUN: -shell -- cp -R $INPUT_DIR/MyProject_mod/LocalCFunc.h %t/MyProject/ == \
|
||||||
|
// RUN: -shell -- sleep $SLEEP_TIME == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo '### Fast completion' == \
|
||||||
|
// RUN: -shell -- sleep $SLEEP_TIME == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} \
|
||||||
|
|
||||||
|
// RUN: | %FileCheck %s
|
||||||
|
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Initial
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK-NOT: key.reusingastcontext: 1
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Modify bridging header library file
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc_mod()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK-NOT: key.reusingastcontext: 1
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Fast completion
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc_mod()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK: key.reusingastcontext: 1
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import ClangFW
|
||||||
|
import SwiftFW
|
||||||
|
|
||||||
|
func foo() {
|
||||||
|
/*HERE*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// RUN: %empty-directory(%t/Frameworks)
|
||||||
|
// RUN: %empty-directory(%t/MyProject)
|
||||||
|
|
||||||
|
// RUN: COMPILER_ARGS=( \
|
||||||
|
// RUN: -target %target-triple \
|
||||||
|
// RUN: -module-name MyProject \
|
||||||
|
// RUN: -F %t/Frameworks \
|
||||||
|
// RUN: -I %t/MyProject \
|
||||||
|
// RUN: -import-objc-header %t/MyProject/Bridging.h \
|
||||||
|
// RUN: %t/MyProject/Library.swift \
|
||||||
|
// RUN: %s \
|
||||||
|
// RUN: )
|
||||||
|
// RUN: INPUT_DIR=%S/Inputs/checkdeps
|
||||||
|
// RUN: DEPCHECK_INTERVAL=1
|
||||||
|
// RUN: SLEEP_TIME=2
|
||||||
|
|
||||||
|
// RUN: cp -R $INPUT_DIR/MyProject %t/
|
||||||
|
// RUN: cp -R $INPUT_DIR/ClangFW.framework %t/Frameworks/
|
||||||
|
// RUN: %empty-directory(%t/Frameworks/SwiftFW.framework/Modules/SwiftFW.swiftmodule)
|
||||||
|
// RUN: %target-swift-frontend -emit-module -module-name SwiftFW -o %t/Frameworks/SwiftFW.framework/Modules/SwiftFW.swiftmodule/%target-swiftmodule-name $INPUT_DIR/SwiftFW_src/Funcs.swift
|
||||||
|
|
||||||
|
// RUN: %sourcekitd-test \
|
||||||
|
// RUN: -req=global-config -completion-check-dependency-interval ${DEPCHECK_INTERVAL} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo "### Initial" == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo '### Modify framework (c)' == \
|
||||||
|
// RUN: -shell -- cp -R $INPUT_DIR/ClangFW.framework_mod/* %t/Frameworks/ClangFW.framework/ == \
|
||||||
|
// RUN: -shell -- sleep $SLEEP_TIME == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo '### Fast completion' == \
|
||||||
|
// RUN: -shell -- sleep $SLEEP_TIME == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} \
|
||||||
|
|
||||||
|
// RUN: | %FileCheck %s
|
||||||
|
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Initial
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK-NOT: key.reusingastcontext: 1
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Modify framework (c)
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc_mod()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK-NOT: key.reusingastcontext: 1
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Fast completion
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc_mod()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK: key.reusingastcontext: 1
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import ClangFW
|
||||||
|
import SwiftFW
|
||||||
|
|
||||||
|
func foo() {
|
||||||
|
/*HERE*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// RUN: %empty-directory(%t/Frameworks)
|
||||||
|
// RUN: %empty-directory(%t/MyProject)
|
||||||
|
|
||||||
|
// RUN: COMPILER_ARGS=( \
|
||||||
|
// RUN: -target %target-triple \
|
||||||
|
// RUN: -module-name MyProject \
|
||||||
|
// RUN: -F %t/Frameworks \
|
||||||
|
// RUN: -I %t/MyProject \
|
||||||
|
// RUN: -import-objc-header %t/MyProject/Bridging.h \
|
||||||
|
// RUN: %t/MyProject/Library.swift \
|
||||||
|
// RUN: %s \
|
||||||
|
// RUN: )
|
||||||
|
// RUN: INPUT_DIR=%S/Inputs/checkdeps
|
||||||
|
// RUN: DEPCHECK_INTERVAL=1
|
||||||
|
// RUN: SLEEP_TIME=2
|
||||||
|
|
||||||
|
// RUN: cp -R $INPUT_DIR/MyProject %t/
|
||||||
|
// RUN: cp -R $INPUT_DIR/ClangFW.framework %t/Frameworks/
|
||||||
|
// RUN: %empty-directory(%t/Frameworks/SwiftFW.framework/Modules/SwiftFW.swiftmodule)
|
||||||
|
// RUN: %target-swift-frontend -emit-module -module-name SwiftFW -o %t/Frameworks/SwiftFW.framework/Modules/SwiftFW.swiftmodule/%target-swiftmodule-name $INPUT_DIR/SwiftFW_src/Funcs.swift
|
||||||
|
|
||||||
|
// RUN: %sourcekitd-test \
|
||||||
|
// RUN: -req=global-config -completion-check-dependency-interval ${DEPCHECK_INTERVAL} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo "### Initial" == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo "### Modify local library file" == \
|
||||||
|
// RUN: -shell -- cp -R $INPUT_DIR/MyProject_mod/Library.swift %t/MyProject/ == \
|
||||||
|
// RUN: -shell -- sleep $SLEEP_TIME == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo '### Fast completion' == \
|
||||||
|
// RUN: -shell -- sleep $SLEEP_TIME == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} \
|
||||||
|
|
||||||
|
// RUN: | %FileCheck %s
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Initial
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK-NOT: key.reusingastcontext: 1
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Modify local library file
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc_mod()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK-NOT: key.reusingastcontext: 1
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Fast completion
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc_mod()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK: key.reusingastcontext: 1
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import ClangFW
|
||||||
|
import SwiftFW
|
||||||
|
|
||||||
|
func foo() {
|
||||||
|
/*HERE*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// RUN: %empty-directory(%t/Frameworks)
|
||||||
|
// RUN: %empty-directory(%t/MyProject)
|
||||||
|
|
||||||
|
// RUN: COMPILER_ARGS=( \
|
||||||
|
// RUN: -target %target-triple \
|
||||||
|
// RUN: -module-name MyProject \
|
||||||
|
// RUN: -F %t/Frameworks \
|
||||||
|
// RUN: -I %t/MyProject \
|
||||||
|
// RUN: -import-objc-header %t/MyProject/Bridging.h \
|
||||||
|
// RUN: %t/MyProject/Library.swift \
|
||||||
|
// RUN: %s \
|
||||||
|
// RUN: )
|
||||||
|
// RUN: INPUT_DIR=%S/Inputs/checkdeps
|
||||||
|
// RUN: DEPCHECK_INTERVAL=1
|
||||||
|
// RUN: SLEEP_TIME=2
|
||||||
|
|
||||||
|
// RUN: cp -R $INPUT_DIR/MyProject %t/
|
||||||
|
// RUN: cp -R $INPUT_DIR/ClangFW.framework %t/Frameworks/
|
||||||
|
// RUN: %empty-directory(%t/Frameworks/SwiftFW.framework/Modules/SwiftFW.swiftmodule)
|
||||||
|
// RUN: %target-swift-frontend -emit-module -module-name SwiftFW -o %t/Frameworks/SwiftFW.framework/Modules/SwiftFW.swiftmodule/%target-swiftmodule-name $INPUT_DIR/SwiftFW_src/Funcs.swift
|
||||||
|
|
||||||
|
// RUN: %sourcekitd-test \
|
||||||
|
// RUN: -req=global-config -completion-check-dependency-interval ${DEPCHECK_INTERVAL} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo "### Initial" == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo '### Modify framework (s)' == \
|
||||||
|
// RUN: -shell -- %target-swift-frontend -emit-module -module-name SwiftFW -o %t/Frameworks/SwiftFW.framework/Modules/SwiftFW.swiftmodule/%target-swiftmodule-name $INPUT_DIR/SwiftFW_src_mod/Funcs.swift == \
|
||||||
|
// RUN: -shell -- sleep $SLEEP_TIME == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} == \
|
||||||
|
|
||||||
|
// RUN: -shell -- echo '### Fast completion' == \
|
||||||
|
// RUN: -shell -- sleep $SLEEP_TIME == \
|
||||||
|
// RUN: -req=complete -pos=5:3 %s -- ${COMPILER_ARGS[@]} \
|
||||||
|
|
||||||
|
// RUN: | %FileCheck %s
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Initial
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK-NOT: key.reusingastcontext: 1
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Modify framework (s)
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc_mod()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK-NOT: key.reusingastcontext: 1
|
||||||
|
|
||||||
|
// CHECK-LABEL: ### Fast completion
|
||||||
|
// CHECK: key.results: [
|
||||||
|
// CHECK-DAG: key.description: "clangFWFunc()"
|
||||||
|
// CHECK-DAG: key.description: "swiftFWFunc_mod()"
|
||||||
|
// CHECK-DAG: key.description: "localClangFunc()"
|
||||||
|
// CHECK-DAG: key.description: "localSwiftFunc()"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK: key.reusingastcontext: 1
|
||||||
@@ -36,6 +36,9 @@ public:
|
|||||||
///
|
///
|
||||||
/// At the time of writing this just means ignoring .swiftsourceinfo files.
|
/// At the time of writing this just means ignoring .swiftsourceinfo files.
|
||||||
bool OptimizeForIDE = false;
|
bool OptimizeForIDE = false;
|
||||||
|
|
||||||
|
/// Interval second for checking dependencies in fast code completion.
|
||||||
|
unsigned CompletionCheckDependencyInterval = 5;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -43,8 +46,10 @@ private:
|
|||||||
mutable llvm::sys::Mutex Mtx;
|
mutable llvm::sys::Mutex Mtx;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Settings update(Optional<bool> OptimizeForIDE);
|
Settings update(Optional<bool> OptimizeForIDE,
|
||||||
|
Optional<unsigned> CompletionCheckDependencyInterval);
|
||||||
bool shouldOptimizeForIDE() const;
|
bool shouldOptimizeForIDE() const;
|
||||||
|
unsigned getCompletionCheckDependencyInterval() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Context {
|
class Context {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class SourceFileSyntax;
|
|||||||
} // namespace swift
|
} // namespace swift
|
||||||
|
|
||||||
namespace SourceKit {
|
namespace SourceKit {
|
||||||
|
class GlobalConfig;
|
||||||
|
|
||||||
struct EntityInfo {
|
struct EntityInfo {
|
||||||
UIdent Kind;
|
UIdent Kind;
|
||||||
@@ -651,6 +652,8 @@ public:
|
|||||||
|
|
||||||
virtual ~LangSupport() { }
|
virtual ~LangSupport() { }
|
||||||
|
|
||||||
|
virtual void globalConfigurationUpdated(std::shared_ptr<GlobalConfig> Config) {};
|
||||||
|
|
||||||
virtual void indexSource(StringRef Filename,
|
virtual void indexSource(StringRef Filename,
|
||||||
IndexingConsumer &Consumer,
|
IndexingConsumer &Consumer,
|
||||||
ArrayRef<const char *> Args) = 0;
|
ArrayRef<const char *> Args) = 0;
|
||||||
|
|||||||
@@ -17,10 +17,13 @@
|
|||||||
using namespace SourceKit;
|
using namespace SourceKit;
|
||||||
|
|
||||||
GlobalConfig::Settings
|
GlobalConfig::Settings
|
||||||
GlobalConfig::update(Optional<bool> OptimizeForIDE) {
|
GlobalConfig::update(Optional<bool> OptimizeForIDE,
|
||||||
|
Optional<unsigned> CompletionCheckDependencyInterval) {
|
||||||
llvm::sys::ScopedLock L(Mtx);
|
llvm::sys::ScopedLock L(Mtx);
|
||||||
if (OptimizeForIDE.hasValue())
|
if (OptimizeForIDE.hasValue())
|
||||||
State.OptimizeForIDE = *OptimizeForIDE;
|
State.OptimizeForIDE = *OptimizeForIDE;
|
||||||
|
if (CompletionCheckDependencyInterval.hasValue())
|
||||||
|
State.CompletionCheckDependencyInterval = *CompletionCheckDependencyInterval;
|
||||||
return State;
|
return State;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,6 +31,10 @@ bool GlobalConfig::shouldOptimizeForIDE() const {
|
|||||||
llvm::sys::ScopedLock L(Mtx);
|
llvm::sys::ScopedLock L(Mtx);
|
||||||
return State.OptimizeForIDE;
|
return State.OptimizeForIDE;
|
||||||
}
|
}
|
||||||
|
unsigned GlobalConfig::getCompletionCheckDependencyInterval() const {
|
||||||
|
llvm::sys::ScopedLock L(Mtx);
|
||||||
|
return State.CompletionCheckDependencyInterval;
|
||||||
|
}
|
||||||
|
|
||||||
SourceKit::Context::Context(StringRef RuntimeLibPath,
|
SourceKit::Context::Context(StringRef RuntimeLibPath,
|
||||||
llvm::function_ref<std::unique_ptr<LangSupport>(Context &)>
|
llvm::function_ref<std::unique_ptr<LangSupport>(Context &)>
|
||||||
|
|||||||
@@ -257,6 +257,13 @@ class InMemoryFileSystemProvider: public SourceKit::FileSystemProvider {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
configureCompletionInstance(std::shared_ptr<CompletionInstance> CompletionInst,
|
||||||
|
std::shared_ptr<GlobalConfig> GlobalConfig) {
|
||||||
|
CompletionInst->setDependencyCheckIntervalSecond(
|
||||||
|
GlobalConfig->getCompletionCheckDependencyInterval());
|
||||||
|
}
|
||||||
|
|
||||||
SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx)
|
SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx)
|
||||||
: NotificationCtr(SKCtx.getNotificationCenter()),
|
: NotificationCtr(SKCtx.getNotificationCenter()),
|
||||||
CCCache(new SwiftCompletionCache) {
|
CCCache(new SwiftCompletionCache) {
|
||||||
@@ -270,7 +277,8 @@ SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx)
|
|||||||
SKCtx.getGlobalConfiguration(),
|
SKCtx.getGlobalConfiguration(),
|
||||||
Stats, RuntimeResourcePath);
|
Stats, RuntimeResourcePath);
|
||||||
|
|
||||||
CompletionInst = std::make_unique<CompletionInstance>();
|
CompletionInst = std::make_shared<CompletionInstance>();
|
||||||
|
configureCompletionInstance(CompletionInst, SKCtx.getGlobalConfiguration());
|
||||||
|
|
||||||
// By default, just use the in-memory cache.
|
// By default, just use the in-memory cache.
|
||||||
CCCache->inMemory = std::make_unique<ide::CodeCompletionCache>();
|
CCCache->inMemory = std::make_unique<ide::CodeCompletionCache>();
|
||||||
@@ -282,6 +290,11 @@ SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx)
|
|||||||
SwiftLangSupport::~SwiftLangSupport() {
|
SwiftLangSupport::~SwiftLangSupport() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SwiftLangSupport::globalConfigurationUpdated(
|
||||||
|
std::shared_ptr<GlobalConfig> Config) {
|
||||||
|
configureCompletionInstance(CompletionInst, Config);
|
||||||
|
}
|
||||||
|
|
||||||
UIdent SwiftLangSupport::getUIDForDecl(const Decl *D, bool IsRef) {
|
UIdent SwiftLangSupport::getUIDForDecl(const Decl *D, bool IsRef) {
|
||||||
return UIdentVisitor(IsRef).visit(const_cast<Decl*>(D));
|
return UIdentVisitor(IsRef).visit(const_cast<Decl*>(D));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -450,6 +450,8 @@ public:
|
|||||||
// LangSupport Interface
|
// LangSupport Interface
|
||||||
//==========================================================================//
|
//==========================================================================//
|
||||||
|
|
||||||
|
void globalConfigurationUpdated(std::shared_ptr<GlobalConfig> Config) override;
|
||||||
|
|
||||||
void indexSource(StringRef Filename, IndexingConsumer &Consumer,
|
void indexSource(StringRef Filename, IndexingConsumer &Consumer,
|
||||||
ArrayRef<const char *> Args) override;
|
ArrayRef<const char *> Args) override;
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,11 @@ def vfs_name : Separate<["-"], "vfs-name">,
|
|||||||
def optimize_for_ide : Joined<["-"], "for-ide=">,
|
def optimize_for_ide : Joined<["-"], "for-ide=">,
|
||||||
HelpText<"Value for the OptimizeForIde global configuration setting">;
|
HelpText<"Value for the OptimizeForIde global configuration setting">;
|
||||||
|
|
||||||
|
def completion_check_dependency_interval : Separate<["-"], "completion-check-dependency-interval">,
|
||||||
|
HelpText<"Inteval seconds for checking dependencies in fast completion">;
|
||||||
|
def completion_check_dependency_interval_EQ : Joined<["-"], "completion-check-dependency-interval=">,
|
||||||
|
Alias<completion_check_dependency_interval>;
|
||||||
|
|
||||||
def suppress_config_request : Flag<["-"], "suppress-config-request">,
|
def suppress_config_request : Flag<["-"], "suppress-config-request">,
|
||||||
HelpText<"Suppress the default global configuration request, that is otherwise sent before any other request (except for the global-config request itself)">;
|
HelpText<"Suppress the default global configuration request, that is otherwise sent before any other request (except for the global-config request itself)">;
|
||||||
|
|
||||||
|
|||||||
@@ -381,6 +381,19 @@ bool TestOptions::parseArgs(llvm::ArrayRef<const char *> Args) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OPT_completion_check_dependency_interval: {
|
||||||
|
int64_t Value;
|
||||||
|
if (StringRef(InputArg->getValue()).getAsInteger(10, Value)) {
|
||||||
|
llvm::errs() << "error: expected number for inteval\n";
|
||||||
|
return true;
|
||||||
|
} else if (Value < 0) {
|
||||||
|
llvm::errs() << "error: completion-check-dependency-interval must be > 0\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
CompletionCheckDependencyInterval = Value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case OPT_suppress_config_request:
|
case OPT_suppress_config_request:
|
||||||
SuppressDefaultConfigRequest = true;
|
SuppressDefaultConfigRequest = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ struct TestOptions {
|
|||||||
bool timeRequest = false;
|
bool timeRequest = false;
|
||||||
llvm::Optional<bool> OptimizeForIde;
|
llvm::Optional<bool> OptimizeForIde;
|
||||||
bool SuppressDefaultConfigRequest = false;
|
bool SuppressDefaultConfigRequest = false;
|
||||||
|
llvm::Optional<unsigned> CompletionCheckDependencyInterval;
|
||||||
unsigned repeatRequest = 1;
|
unsigned repeatRequest = 1;
|
||||||
struct VFSFile {
|
struct VFSFile {
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|||||||
@@ -548,7 +548,14 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
|
|||||||
case SourceKitRequest::GlobalConfiguration:
|
case SourceKitRequest::GlobalConfiguration:
|
||||||
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestGlobalConfiguration);
|
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestGlobalConfiguration);
|
||||||
if (Opts.OptimizeForIde.hasValue())
|
if (Opts.OptimizeForIde.hasValue())
|
||||||
sourcekitd_request_dictionary_set_int64(Req, KeyOptimizeForIDE, static_cast<int64_t>(Opts.OptimizeForIde.getValue()));
|
sourcekitd_request_dictionary_set_int64(
|
||||||
|
Req, KeyOptimizeForIDE,
|
||||||
|
static_cast<int64_t>(Opts.OptimizeForIde.getValue()));
|
||||||
|
if (Opts.CompletionCheckDependencyInterval.hasValue())
|
||||||
|
sourcekitd_request_dictionary_set_int64(
|
||||||
|
Req, KeyCompletionCheckDependencyInterval,
|
||||||
|
static_cast<int64_t>(
|
||||||
|
Opts.CompletionCheckDependencyInterval.getValue()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SourceKitRequest::ProtocolVersion:
|
case SourceKitRequest::ProtocolVersion:
|
||||||
|
|||||||
@@ -438,9 +438,21 @@ void handleRequestImpl(sourcekitd_object_t ReqObj, ResponseReceiver Rec) {
|
|||||||
if (!Req.getInt64(KeyOptimizeForIDE, EditorMode, true)) {
|
if (!Req.getInt64(KeyOptimizeForIDE, EditorMode, true)) {
|
||||||
OptimizeForIDE = EditorMode;
|
OptimizeForIDE = EditorMode;
|
||||||
}
|
}
|
||||||
|
Optional<unsigned> CompletionCheckDependencyInterval;
|
||||||
|
int64_t IntervalValue = 0;
|
||||||
|
if (!Req.getInt64(KeyCompletionCheckDependencyInterval,
|
||||||
|
IntervalValue, /*isOptional=*/true))
|
||||||
|
CompletionCheckDependencyInterval = IntervalValue;
|
||||||
|
|
||||||
|
GlobalConfig::Settings UpdatedConfig = Config->update(
|
||||||
|
OptimizeForIDE, CompletionCheckDependencyInterval);
|
||||||
|
|
||||||
|
getGlobalContext().getSwiftLangSupport().globalConfigurationUpdated(Config);
|
||||||
|
|
||||||
GlobalConfig::Settings UpdatedConfig = Config->update(OptimizeForIDE);
|
|
||||||
dict.set(KeyOptimizeForIDE, UpdatedConfig.OptimizeForIDE);
|
dict.set(KeyOptimizeForIDE, UpdatedConfig.OptimizeForIDE);
|
||||||
|
dict.set(KeyCompletionCheckDependencyInterval,
|
||||||
|
UpdatedConfig.CompletionCheckDependencyInterval);
|
||||||
|
|
||||||
return Rec(RB.createResponse());
|
return Rec(RB.createResponse());
|
||||||
}
|
}
|
||||||
if (ReqUID == RequestProtocolVersion) {
|
if (ReqUID == RequestProtocolVersion) {
|
||||||
|
|||||||
@@ -179,6 +179,8 @@ UID_KEYS = [
|
|||||||
KEY('OptimizeForIDE', 'key.optimize_for_ide'),
|
KEY('OptimizeForIDE', 'key.optimize_for_ide'),
|
||||||
KEY('RequiredBystanders', 'key.required_bystanders'),
|
KEY('RequiredBystanders', 'key.required_bystanders'),
|
||||||
KEY('ReusingASTContext', 'key.reusingastcontext'),
|
KEY('ReusingASTContext', 'key.reusingastcontext'),
|
||||||
|
KEY('CompletionCheckDependencyInterval',
|
||||||
|
'key.completion_check_dependency_interval'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user