Skip to content

[SourceKit/swift-ide-test] Consolidate duplicated logics between completion like requests #28322

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

Closed
Closed
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
4 changes: 4 additions & 0 deletions include/swift/Frontend/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,10 @@ class CompilerInstance {
/// Returns true if there was an error during setup.
bool setup(const CompilerInvocation &Invocation);

const CompilerInvocation &getInvocation() {
return Invocation;
}

private:
/// Set up the file system by loading and validating all VFS overlay YAML
/// files. If the process of validating VFS files failed, or the overlay
Expand Down
6 changes: 4 additions & 2 deletions tools/SourceKit/include/SourceKit/Core/LangSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -801,13 +801,15 @@ class LangSupport {
virtual void getExpressionContextInfo(llvm::MemoryBuffer *inputBuf,
unsigned Offset,
ArrayRef<const char *> Args,
TypeContextInfoConsumer &Consumer) = 0;
TypeContextInfoConsumer &Consumer,
Optional<VFSOptions> vfsOptions) = 0;

virtual void getConformingMethodList(llvm::MemoryBuffer *inputBuf,
unsigned Offset,
ArrayRef<const char *> Args,
ArrayRef<const char *> ExpectedTypes,
ConformingMethodListConsumer &Consumer) = 0;
ConformingMethodListConsumer &Consumer,
Optional<VFSOptions> vfsOptions) = 0;

virtual void getStatistics(StatisticsReceiver) = 0;
};
Expand Down
5 changes: 3 additions & 2 deletions tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class ImportDepth {

public:
ImportDepth() = default;
ImportDepth(ASTContext &context, CompilerInvocation &invocation);
ImportDepth(ASTContext &context, const CompilerInvocation &invocation);

Optional<uint8_t> lookup(StringRef module) {
auto I = depths.find(module);
Expand Down Expand Up @@ -320,7 +320,8 @@ CodeCompletionViewRef CodeCompletionOrganizer::takeResultsView() {
// ImportDepth
//===----------------------------------------------------------------------===//

ImportDepth::ImportDepth(ASTContext &context, CompilerInvocation &invocation) {
ImportDepth::ImportDepth(ASTContext &context,
const CompilerInvocation &invocation) {
llvm::DenseSet<ModuleDecl *> seen;
std::deque<std::pair<ModuleDecl *, uint8_t>> worklist;

Expand Down
2 changes: 1 addition & 1 deletion tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct Options {

struct SwiftCompletionInfo {
swift::ASTContext *swiftASTContext = nullptr;
swift::CompilerInvocation *invocation = nullptr;
const swift::CompilerInvocation *invocation = nullptr;
swift::ide::CodeCompletionContext *completionContext = nullptr;
};

Expand Down
82 changes: 23 additions & 59 deletions tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ struct SwiftCodeCompletionConsumer
: handleResultsImpl(handleResultsImpl) {}

void setContext(swift::ASTContext *context,
swift::CompilerInvocation *invocation,
const swift::CompilerInvocation *invocation,
swift::ide::CodeCompletionContext *completionContext) {
swiftContext.swiftASTContext = context;
swiftContext.invocation = invocation;
Expand Down Expand Up @@ -129,15 +129,12 @@ static bool swiftCodeCompleteImpl(
// Resolve symlinks for the input file; we resolve them for the input files
// in the arguments as well.
// FIXME: We need the Swift equivalent of Clang's FileEntry.
auto InputFile = llvm::MemoryBuffer::getMemBuffer(
UnresolvedInputFile->getBuffer(),
Lang.resolvePathSymlinks(UnresolvedInputFile->getBufferIdentifier()));

auto origBuffSize = InputFile->getBufferSize();
unsigned CodeCompletionOffset = Offset;
if (CodeCompletionOffset > origBuffSize) {
CodeCompletionOffset = origBuffSize;
}
auto bufferIdentifier =
Lang.resolvePathSymlinks(UnresolvedInputFile->getBufferIdentifier());

auto origOffset = Offset;
auto newBuffer = SwiftLangSupport::makeCodeCompletionMemoryBuffer(
UnresolvedInputFile, Offset, bufferIdentifier);

CompilerInstance CI;
// Display diagnostics to stderr.
Expand All @@ -149,69 +146,35 @@ static bool swiftCodeCompleteImpl(
if (TracedOp.enabled()) {
CI.addDiagnosticConsumer(&TraceDiags);
trace::SwiftInvocation SwiftArgs;
trace::initTraceInfo(SwiftArgs, InputFile->getBufferIdentifier(), Args);
trace::initTraceInfo(SwiftArgs, bufferIdentifier, Args);
TracedOp.setDiagnosticProvider(
[&TraceDiags](SmallVectorImpl<DiagnosticEntryInfo> &diags) {
TraceDiags.getAllDiagnostics(diags);
});
TracedOp.start(SwiftArgs,
{std::make_pair("OriginalOffset", std::to_string(Offset)),
std::make_pair("Offset",
std::to_string(CodeCompletionOffset))});
}

CompilerInvocation Invocation;
bool Failed = Lang.getASTManager()->initCompilerInvocation(
Invocation, Args, CI.getDiags(), InputFile->getBufferIdentifier(),
FileSystem, Error);
if (Failed) {
return false;
TracedOp.start(
SwiftArgs,
{std::make_pair("OriginalOffset", std::to_string(origOffset)),
std::make_pair("Offset", std::to_string(Offset))});
}
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
Error = "no input filenames specified";
return false;
}

const char *Position = InputFile->getBufferStart() + CodeCompletionOffset;
std::unique_ptr<llvm::WritableMemoryBuffer> NewBuffer =
llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
InputFile->getBufferSize() + 1,
InputFile->getBufferIdentifier());
char *NewBuf = NewBuffer->getBufferStart();
char *NewPos = std::copy(InputFile->getBufferStart(), Position, NewBuf);
*NewPos = '\0';
std::copy(Position, InputFile->getBufferEnd(), NewPos+1);

Invocation.setCodeCompletionPoint(NewBuffer.get(), CodeCompletionOffset);

auto swiftCache = Lang.getCodeCompletionCache(); // Pin the cache.
ide::CodeCompletionContext CompletionContext(swiftCache->getCache());

// Create a factory for code completion callbacks that will feed the
// Consumer.
std::unique_ptr<CodeCompletionCallbacksFactory> CompletionCallbacksFactory(
ide::makeCodeCompletionCallbacksFactory(CompletionContext,
SwiftConsumer));

Invocation.setCodeCompletionFactory(CompletionCallbacksFactory.get());

// FIXME: We need to be passing the buffers from the open documents.
// It is not a huge problem in practice because Xcode auto-saves constantly.
auto swiftCache = Lang.getCodeCompletionCache(); // Pin the cache.
ide::CodeCompletionContext CompletionContext(swiftCache->getCache());

if (FileSystem != llvm::vfs::getRealFileSystem()) {
CI.getSourceMgr().setFileSystem(FileSystem);
}
std::unique_ptr<CodeCompletionCallbacksFactory> callbacksFactory(
ide::makeCodeCompletionCallbacksFactory(CompletionContext, SwiftConsumer));

if (CI.setup(Invocation)) {
// FIXME: error?
return true;
if (!Lang.setupCompilerInstanceForCodeCompletion(CI, newBuffer.get(), Offset,
Args, callbacksFactory.get(),
FileSystem, Error)) {
return false;
}

CloseClangModuleFiles scopedCloseFiles(
*CI.getASTContext().getClangModuleLoader());
SwiftConsumer.setContext(&CI.getASTContext(), &Invocation,
SwiftConsumer.setContext(&CI.getASTContext(), &CI.getInvocation(),
&CompletionContext);
registerIDETypeCheckRequestFunctions(CI.getASTContext().evaluator);
CI.performParseAndResolveImportsOnly();
SwiftConsumer.clearContext();

Expand Down Expand Up @@ -1174,7 +1137,8 @@ static void transformAndForwardResults(
void SwiftLangSupport::codeCompleteOpen(
StringRef name, llvm::MemoryBuffer *inputBuf, unsigned offset,
OptionsDictionary *options, ArrayRef<FilterRule> rawFilterRules,
GroupedCodeCompletionConsumer &consumer, ArrayRef<const char *> args, Optional<VFSOptions> vfsOptions) {
GroupedCodeCompletionConsumer &consumer, ArrayRef<const char *> args,
Optional<VFSOptions> vfsOptions) {
StringRef filterText;
unsigned resultOffset = 0;
unsigned maxResults = 0;
Expand Down
43 changes: 20 additions & 23 deletions tools/SourceKit/lib/SwiftLang/SwiftConformingMethodList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ static bool swiftConformingMethodListImpl(
SwiftLangSupport &Lang, llvm::MemoryBuffer *UnresolvedInputFile,
unsigned Offset, ArrayRef<const char *> Args,
ArrayRef<const char *> ExpectedTypeNames,
ide::ConformingMethodListConsumer &Consumer, std::string &Error) {
ide::ConformingMethodListConsumer &Consumer,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
std::string &Error) {
auto bufferIdentifier =
Lang.resolvePathSymlinks(UnresolvedInputFile->getBufferIdentifier());

Expand Down Expand Up @@ -57,31 +59,18 @@ static bool swiftConformingMethodListImpl(
std::make_pair("Offset", std::to_string(Offset))});
}

CompilerInvocation Invocation;
bool Failed = Lang.getASTManager()->initCompilerInvocation(
Invocation, Args, CI.getDiags(), bufferIdentifier, Error);
if (Failed)
return false;
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
Error = "no input filenames specified";
return false;
}

Invocation.setCodeCompletionPoint(newBuffer.get(), Offset);

// Create a factory for code completion callbacks that will feed the
// Consumer.
std::unique_ptr<CodeCompletionCallbacksFactory> callbacksFactory(
ide::makeConformingMethodListCallbacksFactory(ExpectedTypeNames,
Consumer));

Invocation.setCodeCompletionFactory(callbacksFactory.get());

if (CI.setup(Invocation)) {
// FIXME: error?
return true;
if (!Lang.setupCompilerInstanceForCodeCompletion(CI, newBuffer.get(), Offset,
Args, callbacksFactory.get(),
FileSystem, Error)) {
return false;
}
registerIDERequestFunctions(CI.getASTContext().evaluator);

CI.performParseAndResolveImportsOnly();

return true;
Expand All @@ -90,7 +79,15 @@ static bool swiftConformingMethodListImpl(
void SwiftLangSupport::getConformingMethodList(
llvm::MemoryBuffer *UnresolvedInputFile, unsigned Offset,
ArrayRef<const char *> Args, ArrayRef<const char *> ExpectedTypeNames,
SourceKit::ConformingMethodListConsumer &SKConsumer) {
SourceKit::ConformingMethodListConsumer &SKConsumer,
Optional<VFSOptions> vfsOptions) {
std::string error;

// FIXME: the use of None as primary file is to match the fact we do not read
// the document contents using the editor documents infrastructure.
auto fileSystem = getFileSystem(vfsOptions, /*primaryFile=*/None, error);
if (!fileSystem)
return SKConsumer.failed(error);

class Consumer : public ide::ConformingMethodListConsumer {
SourceKit::ConformingMethodListConsumer &SKConsumer;
Expand Down Expand Up @@ -206,9 +203,9 @@ void SwiftLangSupport::getConformingMethodList(
}
} Consumer(SKConsumer);

std::string Error;
if (!swiftConformingMethodListImpl(*this, UnresolvedInputFile, Offset, Args,
ExpectedTypeNames, Consumer, Error)) {
SKConsumer.failed(Error);
ExpectedTypeNames, Consumer, fileSystem,
error)) {
SKConsumer.failed(error);
}
}
40 changes: 40 additions & 0 deletions tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "swift/AST/SILOptions.h"
#include "swift/AST/USRGeneration.h"
#include "swift/Config.h"
#include "swift/Frontend/Frontend.h"
#include "swift/IDE/CodeCompletion.h"
#include "swift/IDE/CodeCompletionCache.h"
#include "swift/IDE/SyntaxModel.h"
Expand Down Expand Up @@ -295,6 +296,45 @@ SwiftLangSupport::makeCodeCompletionMemoryBuffer(
return std::unique_ptr<llvm::MemoryBuffer>(newBuffer.release());
}

bool SwiftLangSupport::setupCompilerInstanceForCodeCompletion(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this move to lib/IDE so swift-ide-test can also use it and ensure that swift-ide-test performs code-completion the same way as sourcekitd?

swift::CompilerInstance &CI, llvm::MemoryBuffer *completionBuffer,
unsigned int Offset, ArrayRef<const char *> Args,
swift::CodeCompletionCallbacksFactory *callbacksFactory,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
std::string &Error) {
assert(FileSystem);

CompilerInvocation Invocation;
bool Failed = getASTManager()->initCompilerInvocation(
Invocation, Args, CI.getDiags(), completionBuffer->getBufferIdentifier(),
FileSystem, Error);
if (Failed)
return false;
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
Error = "no input filenames specified";
return false;
}

// Disable source location resolutions from .swiftsourceinfo file because
// they are somewhat heavy operations and are not needed for completions.
Invocation.getFrontendOptions().IgnoreSwiftSourceInfo = true;

Invocation.setCodeCompletionPoint(completionBuffer, Offset);
Invocation.setCodeCompletionFactory(callbacksFactory);

if (FileSystem != llvm::vfs::getRealFileSystem()) {
CI.getSourceMgr().setFileSystem(FileSystem);
}

if (CI.setup(Invocation)) {
Error = "failed to setup compiler instance";
return false;
}

registerIDERequestFunctions(CI.getASTContext().evaluator);
return true;
}

UIdent SwiftLangSupport::getUIDForDecl(const Decl *D, bool IsRef) {
return UIdentVisitor(IsRef).visit(const_cast<Decl*>(D));
}
Expand Down
14 changes: 12 additions & 2 deletions tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,14 @@ class SwiftLangSupport : public LangSupport {
unsigned &Offset,
const std::string bufferIdentifier);

bool setupCompilerInstanceForCodeCompletion(
swift::CompilerInstance &CI,
llvm::MemoryBuffer *completionBuffer, unsigned Offset,
ArrayRef<const char *> Args,
swift::CodeCompletionCallbacksFactory *callbacksFactory,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
std::string &Error);

static SourceKit::UIdent getUIDForDecl(const swift::Decl *D,
bool IsRef = false);
static SourceKit::UIdent getUIDForExtensionOfDecl(const swift::Decl *D);
Expand Down Expand Up @@ -585,12 +593,14 @@ class SwiftLangSupport : public LangSupport {

void getExpressionContextInfo(llvm::MemoryBuffer *inputBuf, unsigned Offset,
ArrayRef<const char *> Args,
TypeContextInfoConsumer &Consumer) override;
TypeContextInfoConsumer &Consumer,
Optional<VFSOptions> vfsOptions) override;

void getConformingMethodList(llvm::MemoryBuffer *inputBuf, unsigned Offset,
ArrayRef<const char *> Args,
ArrayRef<const char *> ExpectedTypes,
ConformingMethodListConsumer &Consumer) override;
ConformingMethodListConsumer &Consumer,
Optional<VFSOptions> vfsOptions) override;

void getStatistics(StatisticsReceiver) override;

Expand Down
Loading