[SourceKit] Add a global-configuration request to control SourceKit's behavior around .swiftsourceinfo files
SwiftSourceInfo files provide source location information for decls coming from loaded modules. For most IDE use cases it either has an undesirable impact on performance with no benefit (code completion), results in stale locations being used instead of more up-to-date indexer locations (cursor info), or has no observable effect (live diagnostics, which are filtered to just those with a location in the primary file). For non-IDE clients of SourceKit though, cursor info providing declaration locations for symbols from other modules is useful, so add a global configuration option (and a new request to set it) to control whether .swiftsourceinfo files are loaded or not based on use case (they are loaded by default).
This commit is contained in:
Родитель
12bda79e23
Коммит
b9d5672ca1
|
@ -764,18 +764,21 @@ void swift::ide::getLocationInfo(const ValueDecl *VD,
|
|||
auto ClangNode = VD->getClangNode();
|
||||
|
||||
if (VD->getLoc().isValid()) {
|
||||
unsigned NameLen;
|
||||
if (auto FD = dyn_cast<AbstractFunctionDecl>(VD)) {
|
||||
SourceRange R = FD->getSignatureSourceRange();
|
||||
if (R.isInvalid())
|
||||
return;
|
||||
NameLen = getCharLength(SM, R);
|
||||
} else {
|
||||
if (VD->hasName()) {
|
||||
NameLen = VD->getBaseName().userFacingName().size();
|
||||
} else {
|
||||
NameLen = getCharLength(SM, VD->getLoc());
|
||||
auto getSignatureRange = [&](const ValueDecl *VD) -> Optional<unsigned> {
|
||||
if (auto FD = dyn_cast<AbstractFunctionDecl>(VD)) {
|
||||
SourceRange R = FD->getSignatureSourceRange();
|
||||
if (R.isValid())
|
||||
return getCharLength(SM, R);
|
||||
}
|
||||
return None;
|
||||
};
|
||||
unsigned NameLen;
|
||||
if (auto SigLen = getSignatureRange(VD)) {
|
||||
NameLen = SigLen.getValue();
|
||||
} else if (VD->hasName()) {
|
||||
NameLen = VD->getBaseName().userFacingName().size();
|
||||
} else {
|
||||
NameLen = getCharLength(SM, VD->getLoc());
|
||||
}
|
||||
|
||||
unsigned DeclBufID = SM.findBufferContainingLoc(VD->getLoc());
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -enable-batch-mode -emit-module -emit-module-doc -emit-module-path %t/Foo.swiftmodule %S/Inputs/comments-batch/File1.swift %S/Inputs/comments-batch/File2.swift %S/Inputs/comments-batch/File3.swift %S/Inputs/comments-batch/File4.swift %S/Inputs/comments-batch/File5.swift -module-name Foo -emit-module-source-info-path %t/Foo.swiftsourceinfo -emit-module-doc-path %t/Foo.swiftdoc
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=Foo -source-filename %s -I %t | %FileCheck %s
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=Foo -enable-swiftsourceinfo -source-filename %s -I %t | %FileCheck %s
|
||||
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -wmo -emit-module -emit-module-doc -emit-module-path %t/Foo.swiftmodule %S/Inputs/comments-batch/File1.swift %S/Inputs/comments-batch/File2.swift %S/Inputs/comments-batch/File3.swift %S/Inputs/comments-batch/File4.swift %S/Inputs/comments-batch/File5.swift -module-name Foo -emit-module-source-info-path %t/Foo.swiftsourceinfo -emit-module-doc-path %t/Foo.swiftdoc
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=Foo -source-filename %s -I %t | %FileCheck %s
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=Foo -enable-swiftsourceinfo -source-filename %s -I %t | %FileCheck %s
|
||||
|
||||
// CHECK: Inputs/comments-batch/File1.swift:2:13: Func/FuncFromFile1 RawComment=[/// Comment in File1\n]
|
||||
// CHECK: Inputs/comments-batch/File2.swift:2:13: Func/FuncFromFile2 RawComment=[/// Comment in File2\n]
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
// RUN: %empty-directory(%t/comments.framework/Modules/comments.swiftmodule/Project)
|
||||
|
||||
// RUN: %target-swift-frontend -module-name comments -emit-module -emit-module-path %t/comments.framework/Modules/comments.swiftmodule/%target-swiftmodule-name -emit-module-doc-path %t/comments.framework/Modules/comments.swiftmodule/%target-swiftdoc-name -emit-module-source-info-path %t/comments.framework/Modules/comments.swiftmodule/Project/%target-swiftsourceinfo-name %s
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=comments -source-filename %s -F %t | %FileCheck %s
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=comments -enable-swiftsourceinfo -source-filename %s -F %t | %FileCheck %s
|
||||
|
||||
// RUN: cp -r %t/comments.framework/Modules/comments.swiftmodule %t/comments.swiftmodule
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=comments -source-filename %s -I %t | %FileCheck %s
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=comments -enable-swiftsourceinfo -source-filename %s -I %t | %FileCheck %s
|
||||
|
||||
/// first_decl_class_1 Aaa.
|
||||
public class first_decl_class_1 {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
//
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -enable-testing -module-name comments -emit-module -emit-module-path %t/comments.swiftmodule -emit-module-doc -emit-module-doc-path %t/comments.swiftdoc -emit-module-source-info-path %t/comments.swiftsourceinfo %s
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=comments -source-filename %s -I %t > %t.testing.txt
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=comments -enable-swiftsourceinfo -source-filename %s -I %t > %t.testing.txt
|
||||
// RUN: %FileCheck %s -check-prefix=SOURCE-LOC < %t.testing.txt
|
||||
|
||||
/// PublicClass Documentation
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// RUN: llvm-bcanalyzer %t/comments.swiftmodule | %FileCheck %s -check-prefix=BCANALYZER
|
||||
// RUN: llvm-bcanalyzer %t/comments.swiftdoc | %FileCheck %s -check-prefix=BCANALYZER
|
||||
// RUN: llvm-bcanalyzer %t/comments.swiftsourceinfo | %FileCheck %s -check-prefix=BCANALYZER
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=comments -source-filename %s -I %t | %FileCheck %s -check-prefix=FIRST
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=comments -enable-swiftsourceinfo -source-filename %s -I %t | %FileCheck %s -check-prefix=FIRST
|
||||
|
||||
// Test the case when we have a multiple files in a module.
|
||||
//
|
||||
|
@ -16,7 +16,7 @@
|
|||
// RUN: llvm-bcanalyzer %t/comments.swiftmodule | %FileCheck %s -check-prefix=BCANALYZER
|
||||
// RUN: llvm-bcanalyzer %t/comments.swiftdoc | %FileCheck %s -check-prefix=BCANALYZER
|
||||
// RUN: llvm-bcanalyzer %t/comments.swiftsourceinfo | %FileCheck %s -check-prefix=BCANALYZER
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=comments -source-filename %s -I %t > %t.printed.txt
|
||||
// RUN: %target-swift-ide-test -print-module-comments -module-to-print=comments -enable-swiftsourceinfo -source-filename %s -I %t > %t.printed.txt
|
||||
// RUN: %FileCheck %s -check-prefix=FIRST < %t.printed.txt
|
||||
// RUN: %FileCheck %s -check-prefix=SECOND < %t.printed.txt
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// ARG_PARSE_0: {
|
||||
// ARG_PARSE_0: key.notification: source.notification.compile-will-start
|
||||
// ARG_PARSE_0: key.compileid: [[CID1:".*"]]
|
||||
// ARG_PARSE_0: key.compilerargs-string: "{{.*}}.swift -no-such-arg -Xfrontend -ignore-module-source-info"
|
||||
// ARG_PARSE_0: key.compilerargs-string: "{{.*}}.swift -no-such-arg"
|
||||
// ARG_PARSE_0: }
|
||||
// ARG_PARSE_0: {
|
||||
// ARG_PARSE_0: key.notification: source.notification.compile-did-finish
|
||||
|
@ -24,7 +24,7 @@
|
|||
// ARG_PARSE_1: {
|
||||
// ARG_PARSE_1: key.notification: source.notification.compile-will-start
|
||||
// ARG_PARSE_1: key.compileid: [[CID1:".*"]]
|
||||
// ARG_PARSE_1: key.compilerargs-string: "{{.*}}.swift -no-such-arg -Xfrontend -ignore-module-source-info"
|
||||
// ARG_PARSE_1: key.compilerargs-string: "{{.*}}.swift -no-such-arg"
|
||||
// ARG_PARSE_1: }
|
||||
// ARG_PARSE_1: {
|
||||
// ARG_PARSE_1: key.notification: source.notification.compile-did-finish
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import Foo
|
||||
func bar() {
|
||||
foo()
|
||||
}
|
||||
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: echo "/// Some doc" >> %t/Foo.swift
|
||||
// RUN: echo "public func foo() { }" >> %t/Foo.swift
|
||||
// RUN: %target-swift-frontend -enable-batch-mode -emit-module -emit-module-doc -emit-module-path %t/Foo.swiftmodule %t/Foo.swift -module-name Foo -emit-module-source-info-path %t/Foo.swiftsourceinfo -emit-module-doc-path %t/Foo.swiftdoc
|
||||
//
|
||||
// Test setting optimize for ide to false
|
||||
// RUN: %sourcekitd-test -req=global-config -for-ide=0 == -req=cursor -pos=3:3 %s -- -I %t -target %target-triple %s | %FileCheck --check-prefixes=BOTH,WITH %s
|
||||
//
|
||||
// Test setting optimize for ide to true
|
||||
// RUN: %sourcekitd-test -req=global-config -for-ide=1 == -req=cursor -pos=3:3 %s -- -I %t -target %target-triple %s | %FileCheck --check-prefixes=BOTH,WITHOUT %s
|
||||
//
|
||||
// Test sourcekitd-test's default global configuration request (optimize for ide is true)
|
||||
// RUN: %sourcekitd-test -req=cursor -pos=3:3 %s -- -I %t -target %target-triple %s | %FileCheck --check-prefixes=BOTH,WITHOUT %s
|
||||
//
|
||||
// Test without sending any global configuration request to check the sevice's default settings (optimize for ide is false)
|
||||
// RUN: %sourcekitd-test -suppress-config-request -req=cursor -pos=3:3 %s -- -I %t -target %target-triple %s | %FileCheck --check-prefixes=BOTH,WITH %s
|
||||
|
||||
// WITH: source.lang.swift.ref.function.free ({{.*}}/Foo.swift:2:13-2:16)
|
||||
// WITHOUT: source.lang.swift.ref.function.free ()
|
||||
// BOTH: foo()
|
||||
// BOTH: s:3Foo3fooyyF
|
||||
// BOTH: () -> ()
|
||||
// BOTH: $syycD
|
||||
// BOTH: Foo
|
|
@ -2,7 +2,7 @@ func foo() {}
|
|||
|
||||
// RUN: %sourcekitd-test -req=syntax-map %s == -req=stats | %FileCheck %s -check-prefix=SYNTAX_1
|
||||
|
||||
// SYNTAX_1: 2 {{.*}} source.statistic.num-requests
|
||||
// SYNTAX_1: 3 {{.*}} source.statistic.num-requests
|
||||
// SYNTAX_1: 0 {{.*}} source.statistic.num-semantic-requests
|
||||
// SYNTAX_1: 0 {{.*}} source.statistic.num-ast-builds
|
||||
// SYNTAX_1: 1 {{.*}} source.statistic.num-open-documents
|
||||
|
@ -10,7 +10,7 @@ func foo() {}
|
|||
|
||||
// RUN: %sourcekitd-test -req=syntax-map %s == -req=close %s == -req=stats | %FileCheck %s -check-prefix=SYNTAX_2
|
||||
|
||||
// SYNTAX_2: 3 {{.*}} source.statistic.num-requests
|
||||
// SYNTAX_2: 4 {{.*}} source.statistic.num-requests
|
||||
// SYNTAX_2: 0 {{.*}} source.statistic.num-semantic-requests
|
||||
// SYNTAX_2: 0 {{.*}} source.statistic.num-ast-builds
|
||||
// SYNTAX_2: 0 {{.*}} source.statistic.num-open-documents
|
||||
|
@ -18,7 +18,7 @@ func foo() {}
|
|||
|
||||
// RUN: %sourcekitd-test -req=sema %s -- %s == -req=stats | %FileCheck %s -check-prefix=SEMA_1
|
||||
|
||||
// SEMA_1: 3 {{.*}} source.statistic.num-requests
|
||||
// SEMA_1: 4 {{.*}} source.statistic.num-requests
|
||||
// SEMA_1: 0 {{.*}} source.statistic.num-semantic-requests
|
||||
// SEMA_1: 1 {{.*}} source.statistic.num-ast-builds
|
||||
// SEMA_1: 1 {{.*}} source.statistic.num-asts-in-memory
|
||||
|
@ -28,7 +28,7 @@ func foo() {}
|
|||
|
||||
// RUN: %sourcekitd-test -req=sema %s -- %s == -req=edit -pos=1:1 -replace=" " %s == -req=stats | %FileCheck %s -check-prefix=SEMA_2
|
||||
|
||||
// SEMA_2: 5 {{.*}} source.statistic.num-requests
|
||||
// SEMA_2: 6 {{.*}} source.statistic.num-requests
|
||||
// SEMA_2: 0 {{.*}} source.statistic.num-semantic-requests
|
||||
// SEMA_2: 2 {{.*}} source.statistic.num-ast-builds
|
||||
// NOTE: we cannot match num-asts-in-memory, or num-ast-cache-hits reliably when
|
||||
|
@ -40,7 +40,7 @@ func foo() {}
|
|||
|
||||
// RUN: %sourcekitd-test -req=sema %s -- %s == -req=cursor -pos=1:6 %s -- %s == -req=stats | %FileCheck %s -check-prefix=SEMA_3
|
||||
|
||||
// SEMA_3: 4 {{.*}} source.statistic.num-requests
|
||||
// SEMA_3: 5 {{.*}} source.statistic.num-requests
|
||||
// SEMA_3: 1 {{.*}} source.statistic.num-semantic-requests
|
||||
// SEMA_3: 1 {{.*}} source.statistic.num-ast-builds
|
||||
// SEMA_3: 1 {{.*}} source.statistic.num-asts-in-memory
|
||||
|
@ -50,7 +50,7 @@ func foo() {}
|
|||
|
||||
// RUN: %sourcekitd-test -req=sema %s -- %s == -req=related-idents -pos=1:6 %s -- %s == -req=stats | %FileCheck %s -check-prefix=SEMA_4
|
||||
|
||||
// SEMA_4: 4 {{.*}} source.statistic.num-requests
|
||||
// SEMA_4: 5 {{.*}} source.statistic.num-requests
|
||||
// SEMA_4: 1 {{.*}} source.statistic.num-semantic-requests
|
||||
// SEMA_4: 1 {{.*}} source.statistic.num-ast-builds
|
||||
// SEMA_4: 1 {{.*}} source.statistic.num-asts-in-memory
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "SourceKit/Core/LLVM.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/Mutex.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
@ -27,10 +28,30 @@ namespace SourceKit {
|
|||
class LangSupport;
|
||||
class NotificationCenter;
|
||||
|
||||
class GlobalConfig {
|
||||
public:
|
||||
struct Settings {
|
||||
/// When true, the default compiler options and other configuration flags will be chosen to optimize for
|
||||
/// usage from an IDE.
|
||||
///
|
||||
/// At the time of writing this just means ignoring .swiftsourceinfo files.
|
||||
bool OptimizeForIDE = false;
|
||||
};
|
||||
|
||||
private:
|
||||
Settings State;
|
||||
mutable llvm::sys::Mutex Mtx;
|
||||
|
||||
public:
|
||||
Settings update(Optional<bool> OptimizeForIDE);
|
||||
bool shouldOptimizeForIDE() const;
|
||||
};
|
||||
|
||||
class Context {
|
||||
std::string RuntimeLibPath;
|
||||
std::unique_ptr<LangSupport> SwiftLang;
|
||||
std::shared_ptr<NotificationCenter> NotificationCtr;
|
||||
std::shared_ptr<GlobalConfig> Config;
|
||||
|
||||
public:
|
||||
Context(StringRef RuntimeLibPath,
|
||||
|
@ -44,6 +65,8 @@ public:
|
|||
LangSupport &getSwiftLangSupport() { return *SwiftLang; }
|
||||
|
||||
std::shared_ptr<NotificationCenter> getNotificationCenter() { return NotificationCtr; }
|
||||
|
||||
std::shared_ptr<GlobalConfig> getGlobalConfiguration() { return Config; }
|
||||
};
|
||||
|
||||
} // namespace SourceKit
|
||||
|
|
|
@ -16,11 +16,25 @@
|
|||
|
||||
using namespace SourceKit;
|
||||
|
||||
GlobalConfig::Settings
|
||||
GlobalConfig::update(Optional<bool> OptimizeForIDE) {
|
||||
llvm::sys::ScopedLock L(Mtx);
|
||||
if (OptimizeForIDE.hasValue())
|
||||
State.OptimizeForIDE = *OptimizeForIDE;
|
||||
return State;
|
||||
};
|
||||
|
||||
bool GlobalConfig::shouldOptimizeForIDE() const {
|
||||
llvm::sys::ScopedLock L(Mtx);
|
||||
return State.OptimizeForIDE;
|
||||
}
|
||||
|
||||
SourceKit::Context::Context(StringRef RuntimeLibPath,
|
||||
llvm::function_ref<std::unique_ptr<LangSupport>(Context &)>
|
||||
LangSupportFactoryFn,
|
||||
bool shouldDispatchNotificationsOnMain) : RuntimeLibPath(RuntimeLibPath),
|
||||
NotificationCtr(new NotificationCenter(shouldDispatchNotificationsOnMain)) {
|
||||
NotificationCtr(new NotificationCenter(shouldDispatchNotificationsOnMain)),
|
||||
Config(new GlobalConfig()) {
|
||||
// Should be called last after everything is initialized.
|
||||
SwiftLang = LangSupportFactoryFn(*this);
|
||||
}
|
||||
|
|
|
@ -371,11 +371,13 @@ struct CacheKeyHashInfo<ASTKey> {
|
|||
struct SwiftASTManager::Implementation {
|
||||
explicit Implementation(
|
||||
std::shared_ptr<SwiftEditorDocumentFileMap> EditorDocs,
|
||||
std::shared_ptr<GlobalConfig> Config,
|
||||
std::shared_ptr<SwiftStatistics> Stats, StringRef RuntimeResourcePath)
|
||||
: EditorDocs(EditorDocs), Stats(Stats),
|
||||
: EditorDocs(EditorDocs), Config(Config), Stats(Stats),
|
||||
RuntimeResourcePath(RuntimeResourcePath) {}
|
||||
|
||||
std::shared_ptr<SwiftEditorDocumentFileMap> EditorDocs;
|
||||
std::shared_ptr<GlobalConfig> Config;
|
||||
std::shared_ptr<SwiftStatistics> Stats;
|
||||
std::string RuntimeResourcePath;
|
||||
SourceManager SourceMgr;
|
||||
|
@ -401,8 +403,10 @@ struct SwiftASTManager::Implementation {
|
|||
|
||||
SwiftASTManager::SwiftASTManager(
|
||||
std::shared_ptr<SwiftEditorDocumentFileMap> EditorDocs,
|
||||
std::shared_ptr<GlobalConfig> Config,
|
||||
std::shared_ptr<SwiftStatistics> Stats, StringRef RuntimeResourcePath)
|
||||
: Impl(*new Implementation(EditorDocs, Stats, RuntimeResourcePath)) {}
|
||||
: Impl(*new Implementation(EditorDocs, Config, Stats,
|
||||
RuntimeResourcePath)) {}
|
||||
|
||||
SwiftASTManager::~SwiftASTManager() {
|
||||
delete &Impl;
|
||||
|
@ -535,6 +539,15 @@ bool SwiftASTManager::initCompilerInvocation(
|
|||
// We don't care about LLVMArgs
|
||||
FrontendOpts.LLVMArgs.clear();
|
||||
|
||||
// SwiftSourceInfo files provide source location information for decls coming
|
||||
// from loaded modules. For most IDE use cases it either has an undesirable
|
||||
// impact on performance with no benefit (code completion), results in stale
|
||||
// locations being used instead of more up-to-date indexer locations (cursor
|
||||
// info), or has no observable effect (diagnostics, which are filtered to just
|
||||
// those with a location in the primary file, and everything else).
|
||||
if (Impl.Config->shouldOptimizeForIDE())
|
||||
FrontendOpts.IgnoreSwiftSourceInfo = true;
|
||||
|
||||
// Disable expensive SIL options to reduce time spent in SILGen.
|
||||
disableExpensiveSILOptions(Invocation.getSILOptions());
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace SourceKit {
|
|||
class SwiftLangSupport;
|
||||
class SwiftInvocation;
|
||||
struct SwiftStatistics;
|
||||
class GlobalConfig;
|
||||
typedef RefPtr<SwiftInvocation> SwiftInvocationRef;
|
||||
class EditorDiagConsumer;
|
||||
|
||||
|
@ -89,6 +90,7 @@ typedef std::shared_ptr<SwiftASTConsumer> SwiftASTConsumerRef;
|
|||
class SwiftASTManager : public std::enable_shared_from_this<SwiftASTManager> {
|
||||
public:
|
||||
explicit SwiftASTManager(std::shared_ptr<SwiftEditorDocumentFileMap>,
|
||||
std::shared_ptr<GlobalConfig> Config,
|
||||
std::shared_ptr<SwiftStatistics> Stats,
|
||||
StringRef RuntimeResourcePath);
|
||||
~SwiftASTManager();
|
||||
|
|
|
@ -172,8 +172,8 @@ static bool swiftCodeCompleteImpl(
|
|||
return false;
|
||||
}
|
||||
|
||||
// Disable source location resolutions from .swiftsourceinfo file because
|
||||
// they are somewhat heavy operations and are not needed for completions.
|
||||
// Always disable source location resolutions from .swiftsourceinfo file
|
||||
// because they're somewhat heavy operations and aren't needed for completion.
|
||||
Invocation.getFrontendOptions().IgnoreSwiftSourceInfo = true;
|
||||
|
||||
const char *Position = InputFile->getBufferStart() + CodeCompletionOffset;
|
||||
|
|
|
@ -67,8 +67,8 @@ static bool swiftConformingMethodListImpl(
|
|||
return false;
|
||||
}
|
||||
|
||||
// Disable source location resolutions from .swiftsourceinfo file because
|
||||
// they are somewhat heavy operations and are not needed for completions.
|
||||
// Always disable source location resolutions from .swiftsourceinfo file
|
||||
// because they're somewhat heavy operations and aren't needed for completion.
|
||||
Invocation.getFrontendOptions().IgnoreSwiftSourceInfo = true;
|
||||
|
||||
Invocation.setCodeCompletionPoint(newBuffer.get(), Offset);
|
||||
|
|
|
@ -263,8 +263,9 @@ SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx)
|
|||
|
||||
Stats = std::make_shared<SwiftStatistics>();
|
||||
EditorDocuments = std::make_shared<SwiftEditorDocumentFileMap>();
|
||||
ASTMgr = std::make_shared<SwiftASTManager>(EditorDocuments, Stats,
|
||||
RuntimeResourcePath);
|
||||
ASTMgr = std::make_shared<SwiftASTManager>(EditorDocuments,
|
||||
SKCtx.getGlobalConfiguration(),
|
||||
Stats, RuntimeResourcePath);
|
||||
// By default, just use the in-memory cache.
|
||||
CCCache->inMemory = llvm::make_unique<ide::CodeCompletionCache>();
|
||||
|
||||
|
|
|
@ -67,8 +67,8 @@ static bool swiftTypeContextInfoImpl(SwiftLangSupport &Lang,
|
|||
return false;
|
||||
}
|
||||
|
||||
// Disable source location resolutions from .swiftsourceinfo file because
|
||||
// they are somewhat heavy operations and are not needed for completions.
|
||||
// Always disable source location resolutions from .swiftsourceinfo file
|
||||
// because they're somewhat heavy operations and aren't needed for completion.
|
||||
Invocation.getFrontendOptions().IgnoreSwiftSourceInfo = true;
|
||||
|
||||
Invocation.setCodeCompletionPoint(newBuffer.get(), Offset);
|
||||
|
|
|
@ -140,6 +140,12 @@ def vfs_files : CommaJoined<["-"], "vfs-files=">,
|
|||
def vfs_name : Separate<["-"], "vfs-name">,
|
||||
HelpText<"Specify a virtual filesystem name">;
|
||||
|
||||
def optimize_for_ide : Joined<["-"], "for-ide=">,
|
||||
HelpText<"Value for the OptimizeForIde global configuration setting">;
|
||||
|
||||
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)">;
|
||||
|
||||
def help : Flag<["-", "--"], "help">,
|
||||
HelpText<"Display available options">;
|
||||
|
||||
|
|
|
@ -154,6 +154,7 @@ bool TestOptions::parseArgs(llvm::ArrayRef<const char *> Args) {
|
|||
.Case("stats", SourceKitRequest::Statistics)
|
||||
.Case("track-compiles", SourceKitRequest::EnableCompileNotifications)
|
||||
.Case("collect-type", SourceKitRequest::CollectExpresstionType)
|
||||
.Case("global-config", SourceKitRequest::GlobalConfiguration)
|
||||
.Default(SourceKitRequest::None);
|
||||
|
||||
if (Request == SourceKitRequest::None) {
|
||||
|
@ -370,6 +371,20 @@ bool TestOptions::parseArgs(llvm::ArrayRef<const char *> Args) {
|
|||
VFSName = InputArg->getValue();
|
||||
break;
|
||||
|
||||
case OPT_optimize_for_ide: {
|
||||
bool Value;
|
||||
if (StringRef(InputArg->getValue()).getAsInteger(10, Value)) {
|
||||
llvm::errs() << "error: expected 0 or 1 for 'for-ide'\n";
|
||||
return true;
|
||||
}
|
||||
OptimizeForIde = Value;
|
||||
break;
|
||||
}
|
||||
|
||||
case OPT_suppress_config_request:
|
||||
SuppressDefaultConfigRequest = true;
|
||||
break;
|
||||
|
||||
case OPT_UNKNOWN:
|
||||
llvm::errs() << "error: unknown argument: "
|
||||
<< InputArg->getAsString(ParsedArgs) << '\n'
|
||||
|
|
|
@ -64,6 +64,7 @@ enum class SourceKitRequest {
|
|||
SyntaxTree,
|
||||
EnableCompileNotifications,
|
||||
CollectExpresstionType,
|
||||
GlobalConfiguration,
|
||||
#define SEMANTIC_REFACTORING(KIND, NAME, ID) KIND,
|
||||
#include "swift/IDE/RefactoringKinds.def"
|
||||
};
|
||||
|
@ -110,6 +111,8 @@ struct TestOptions {
|
|||
bool CollectActionables = false;
|
||||
bool isAsyncRequest = false;
|
||||
bool timeRequest = false;
|
||||
llvm::Optional<bool> OptimizeForIde;
|
||||
bool SuppressDefaultConfigRequest = false;
|
||||
unsigned repeatRequest = 1;
|
||||
struct VFSFile {
|
||||
std::string path;
|
||||
|
|
|
@ -53,7 +53,9 @@ int STDOUT_FILENO = _fileno(stdout);
|
|||
}
|
||||
#endif
|
||||
|
||||
static int handleTestInvocation(ArrayRef<const char *> Args, TestOptions &InitOpts);
|
||||
static bool sendGlobalConfigRequest();
|
||||
static int handleTestInvocation(ArrayRef<const char *> Args, TestOptions &InitOpts,
|
||||
bool IsFirstInvocation);
|
||||
static bool handleResponse(sourcekitd_response_t Resp, const TestOptions &Opts,
|
||||
const std::string &SourceFile,
|
||||
std::unique_ptr<llvm::MemoryBuffer> SourceBuf,
|
||||
|
@ -238,6 +240,7 @@ static void skt_main(skt_args *args) {
|
|||
// invocations.
|
||||
TestOptions InitOpts;
|
||||
auto Args = llvm::makeArrayRef(argv+1, argc-1);
|
||||
bool firstInvocation = true;
|
||||
while (1) {
|
||||
unsigned i = 0;
|
||||
for (auto Arg: Args) {
|
||||
|
@ -247,15 +250,17 @@ static void skt_main(skt_args *args) {
|
|||
}
|
||||
if (i == Args.size())
|
||||
break;
|
||||
if (int ret = handleTestInvocation(Args.slice(0, i), InitOpts)) {
|
||||
if (int ret = handleTestInvocation(Args.slice(0, i), InitOpts,
|
||||
firstInvocation)) {
|
||||
sourcekitd_shutdown();
|
||||
args->ret = ret;
|
||||
return;
|
||||
}
|
||||
Args = Args.slice(i + 1);
|
||||
firstInvocation = false;
|
||||
}
|
||||
|
||||
if (int ret = handleTestInvocation(Args, InitOpts)) {
|
||||
if (int ret = handleTestInvocation(Args, InitOpts, firstInvocation)) {
|
||||
sourcekitd_shutdown();
|
||||
args->ret = ret;
|
||||
return;
|
||||
|
@ -385,7 +390,7 @@ static int handleJsonRequestPath(StringRef QueryPath, const TestOptions &Opts) {
|
|||
static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts);
|
||||
|
||||
static int handleTestInvocation(ArrayRef<const char *> Args,
|
||||
TestOptions &InitOpts) {
|
||||
TestOptions &InitOpts, bool firstInvocation) {
|
||||
|
||||
unsigned Optargc = 0;
|
||||
for (auto Arg: Args) {
|
||||
|
@ -401,6 +406,16 @@ static int handleTestInvocation(ArrayRef<const char *> Args,
|
|||
if (Optargc < Args.size())
|
||||
Opts.CompilerArgs = Args.slice(Optargc+1);
|
||||
|
||||
if (firstInvocation && Opts.Request != SourceKitRequest::GlobalConfiguration &&
|
||||
!Opts.SuppressDefaultConfigRequest) {
|
||||
// We don't fail if this request fails for now so that sourcekitd-test is
|
||||
// still usable with older versions of sourcekitd that don't have the
|
||||
// global-configuration request.
|
||||
if (sendGlobalConfigRequest()) {
|
||||
llvm::outs() << "warning: global configuration request failed\n";
|
||||
}
|
||||
}
|
||||
|
||||
assert(Opts.repeatRequest >= 1);
|
||||
for (unsigned i = 0; i < Opts.repeatRequest; ++i) {
|
||||
if (int ret = handleTestInvocation(Opts, InitOpts)) {
|
||||
|
@ -435,6 +450,28 @@ static int setExpectedTypes(const sourcekitd_test::TestOptions &Opts,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool sendGlobalConfigRequest() {
|
||||
TestOptions Opts;
|
||||
sourcekitd_object_t Req = sourcekitd_request_dictionary_create(nullptr,
|
||||
nullptr, 0);
|
||||
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestGlobalConfiguration);
|
||||
|
||||
// For test invocations we default to setting OptimizeForIDE to true. This
|
||||
// matches the use case of the most popular clients of sourcekitd (editors)
|
||||
// and also disables loading locations from .swiftsourceinfo files. This is
|
||||
// desirable for testing because the .swiftsourceinfo for the stdlib is
|
||||
// available when sourcekitd is tested, and can make some stdlib-dependent
|
||||
// sourcekitd tests unstable due to changing source locations from the stdlib
|
||||
// module.
|
||||
sourcekitd_request_dictionary_set_int64(Req, KeyOptimizeForIDE, static_cast<int64_t>(true));
|
||||
sourcekitd_response_t Resp = sendRequestSync(Req, Opts);
|
||||
bool IsError = sourcekitd_response_is_error(Resp);
|
||||
if (IsError)
|
||||
sourcekitd_response_description_dump(Resp);
|
||||
sourcekitd_request_release(Req);
|
||||
return IsError;
|
||||
}
|
||||
|
||||
static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
|
||||
if (!Opts.JsonRequestPath.empty())
|
||||
return handleJsonRequestPath(Opts.JsonRequestPath, Opts);
|
||||
|
@ -481,7 +518,6 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
|
|||
sourcekitd_object_t Req = sourcekitd_request_dictionary_create(nullptr,
|
||||
nullptr, 0);
|
||||
ActiveRequest = Opts.Request;
|
||||
bool ShouldIgnoreSourceInfo = true;
|
||||
switch (Opts.Request) {
|
||||
case SourceKitRequest::None:
|
||||
llvm::errs() << "request is not set\n";
|
||||
|
@ -490,6 +526,12 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
|
|||
// with a zero (successful) exit code.
|
||||
return 1;
|
||||
|
||||
case SourceKitRequest::GlobalConfiguration:
|
||||
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestGlobalConfiguration);
|
||||
if (Opts.OptimizeForIde.hasValue())
|
||||
sourcekitd_request_dictionary_set_int64(Req, KeyOptimizeForIDE, static_cast<int64_t>(Opts.OptimizeForIde.getValue()));
|
||||
break;
|
||||
|
||||
case SourceKitRequest::ProtocolVersion:
|
||||
sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestProtocolVersion);
|
||||
break;
|
||||
|
@ -841,7 +883,6 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
|
|||
sourcekitd_request_dictionary_set_int64(Req, KeyUsingSwiftArgs, true);
|
||||
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
|
||||
RequestEditorOpenHeaderInterface);
|
||||
ShouldIgnoreSourceInfo = false;
|
||||
}
|
||||
|
||||
sourcekitd_request_dictionary_set_string(Req, KeyName, getInterfaceGenDocumentName().c_str());
|
||||
|
@ -935,17 +976,6 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
|
|||
sourcekitd_object_t Args = sourcekitd_request_array_create(nullptr, 0);
|
||||
for (auto Arg : Opts.CompilerArgs)
|
||||
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, Arg);
|
||||
if (ShouldIgnoreSourceInfo) {
|
||||
// Ignore .swiftsourceinfo file when testing sourcekitd.
|
||||
// .swiftsourceinfo for stdlib will be available when sourcekitd is tested,
|
||||
// which may make some stdlib-depending sourcekitd tests volatile.
|
||||
// We cannot append the flags when the compiler arguments are for clang
|
||||
// invocation.
|
||||
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND,
|
||||
"-Xfrontend");
|
||||
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND,
|
||||
"-ignore-module-source-info");
|
||||
}
|
||||
sourcekitd_request_dictionary_set_value(Req, KeyCompilerArgs, Args);
|
||||
sourcekitd_request_release(Args);
|
||||
}
|
||||
|
@ -1092,6 +1122,7 @@ static bool handleResponse(sourcekitd_response_t Resp, const TestOptions &Opts,
|
|||
printMangleResults(sourcekitd_response_get_value(Resp), outs());
|
||||
break;
|
||||
|
||||
case SourceKitRequest::GlobalConfiguration:
|
||||
case SourceKitRequest::ProtocolVersion:
|
||||
case SourceKitRequest::CompilerVersion:
|
||||
case SourceKitRequest::Close:
|
||||
|
|
|
@ -425,6 +425,21 @@ void handleRequestImpl(sourcekitd_object_t ReqObj, ResponseReceiver Rec) {
|
|||
if (!ReqUID)
|
||||
return Rec(createErrorRequestInvalid("missing 'key.request' with UID value"));
|
||||
|
||||
if (ReqUID == RequestGlobalConfiguration) {
|
||||
auto Config = getGlobalContext().getGlobalConfiguration();
|
||||
ResponseBuilder RB;
|
||||
auto dict = RB.getDictionary();
|
||||
|
||||
Optional<bool> OptimizeForIDE;
|
||||
int64_t EditorMode = true;
|
||||
if (!Req.getInt64(KeyOptimizeForIDE, EditorMode, true)) {
|
||||
OptimizeForIDE = EditorMode;
|
||||
}
|
||||
|
||||
GlobalConfig::Settings UpdatedConfig = Config->update(OptimizeForIDE);
|
||||
dict.set(KeyOptimizeForIDE, UpdatedConfig.OptimizeForIDE);
|
||||
return Rec(RB.createResponse());
|
||||
}
|
||||
if (ReqUID == RequestProtocolVersion) {
|
||||
ResponseBuilder RB;
|
||||
auto dict = RB.getDictionary();
|
||||
|
@ -1002,7 +1017,8 @@ static void handleSemanticRequest(
|
|||
Req.getInt64(KeyRetrieveRefactorActions, Actionables, /*isOptional=*/true);
|
||||
return Lang.getCursorInfo(
|
||||
*SourceFile, Offset, Length, Actionables, CancelOnSubsequentRequest,
|
||||
Args, std::move(vfsOptions), [Rec](const RequestResult<CursorInfoData> &Result) {
|
||||
Args, std::move(vfsOptions),
|
||||
[Rec](const RequestResult<CursorInfoData> &Result) {
|
||||
reportCursorInfo(Result, Rec);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -694,6 +694,13 @@ GraphVisPath("output-request-graphviz",
|
|||
static llvm::cl::opt<bool>
|
||||
CanonicalizeType("canonicalize-type", llvm::cl::Hidden,
|
||||
llvm::cl::cat(Category), llvm::cl::init(false));
|
||||
|
||||
static llvm::cl::opt<bool>
|
||||
EnableSwiftSourceInfo("enable-swiftsourceinfo",
|
||||
llvm::cl::desc("Whether to consume .swiftsourceinfo files"),
|
||||
llvm::cl::cat(Category),
|
||||
llvm::cl::init(false));
|
||||
|
||||
} // namespace options
|
||||
|
||||
static std::unique_ptr<llvm::MemoryBuffer>
|
||||
|
@ -3325,6 +3332,12 @@ int main(int argc, char *argv[]) {
|
|||
InitInvok.getLangOptions().EnableObjCInterop =
|
||||
llvm::Triple(options::Triple).isOSDarwin();
|
||||
}
|
||||
|
||||
// We disable source location resolutions from .swiftsourceinfo files by
|
||||
// default to match sourcekitd-test's and ide clients' expected behavior
|
||||
// (passing optimize-for-ide in the global configuration request).
|
||||
if (!options::EnableSwiftSourceInfo)
|
||||
InitInvok.getFrontendOptions().IgnoreSwiftSourceInfo = true;
|
||||
if (!options::Triple.empty())
|
||||
InitInvok.setTargetTriple(options::Triple);
|
||||
if (!options::SwiftVersion.empty()) {
|
||||
|
|
|
@ -174,6 +174,7 @@ UID_KEYS = [
|
|||
KEY('VFSName', 'key.vfs.name'),
|
||||
KEY('VFSOptions', 'key.vfs.options'),
|
||||
KEY('Files', 'key.files'),
|
||||
KEY('OptimizeForIDE', 'key.optimize_for_ide'),
|
||||
]
|
||||
|
||||
|
||||
|
@ -231,6 +232,7 @@ UID_REQUESTS = [
|
|||
'source.request.enable-compile-notifications'),
|
||||
REQUEST('TestNotification', 'source.request.test_notification'),
|
||||
REQUEST('CollectExpressionType', 'source.request.expression.type'),
|
||||
REQUEST('GlobalConfiguration', 'source.request.configuration.global')
|
||||
]
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче