mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
240 lines
9.9 KiB
C++
240 lines
9.9 KiB
C++
//===--- IDEInspectionInstance.h ------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_IDE_IDEINSPECTIONINSTANCE_H
|
|
#define SWIFT_IDE_IDEINSPECTIONINSTANCE_H
|
|
|
|
#include "swift/Frontend/Frontend.h"
|
|
#include "swift/IDE/CancellableResult.h"
|
|
#include "swift/IDE/CodeCompletionContext.h"
|
|
#include "swift/IDE/CodeCompletionResult.h"
|
|
#include "swift/IDE/CodeCompletionResultSink.h"
|
|
#include "swift/IDE/ConformingMethodList.h"
|
|
#include "swift/IDE/CursorInfo.h"
|
|
#include "swift/IDE/ImportDepth.h"
|
|
#include "swift/IDE/SignatureHelp.h"
|
|
#include "swift/IDE/SwiftCompletionInfo.h"
|
|
#include "swift/IDE/TypeContextInfo.h"
|
|
#include "llvm/ADT/Hashing.h"
|
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/Chrono.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Support/VirtualFileSystem.h"
|
|
|
|
namespace swift {
|
|
|
|
class CompilerInstance;
|
|
class CompilerInvocation;
|
|
class DiagnosticConsumer;
|
|
class PluginRegistry;
|
|
|
|
namespace ide {
|
|
|
|
/// Copy a memory buffer inserting '\0' at the position of \c origBuf.
|
|
std::unique_ptr<llvm::MemoryBuffer>
|
|
makeCodeCompletionMemoryBuffer(const llvm::MemoryBuffer *origBuf,
|
|
unsigned &Offset,
|
|
llvm::StringRef bufferIdentifier);
|
|
|
|
/// The result returned via the callback from the perform*Operation methods.
|
|
struct IDEInspectionInstanceResult {
|
|
/// The compiler instance that is prepared for the second pass.
|
|
std::shared_ptr<CompilerInstance> CI;
|
|
/// Whether an AST was reused.
|
|
bool DidReuseAST;
|
|
/// Whether the IDEInspectionInstance target could be found in the source
|
|
/// file. If this is \c false, the user will most likely want to return
|
|
/// empty results.
|
|
bool DidFindIDEInspectionTarget;
|
|
};
|
|
|
|
/// The results returned from \c IDEInspectionInstance::codeComplete.
|
|
struct CodeCompleteResult {
|
|
CodeCompletionResultSink &ResultSink;
|
|
SwiftCompletionInfo &Info;
|
|
ImportDepth ImportDep;
|
|
};
|
|
|
|
/// The results returned from \c IDEInspectionInstance::typeContextInfo.
|
|
struct TypeContextInfoResult {
|
|
/// The actual results. If empty, no results were found.
|
|
ArrayRef<TypeContextInfoItem> Results;
|
|
/// Whether an AST was reused to produce the results.
|
|
bool DidReuseAST;
|
|
};
|
|
|
|
/// The results returned from \c IDEInspectionInstance::conformingMethodList.
|
|
struct ConformingMethodListResults {
|
|
/// The actual results. If \c nullptr, no results were found.
|
|
const ConformingMethodListResult *Result;
|
|
/// Whether an AST was reused to produce the results.
|
|
bool DidReuseAST;
|
|
};
|
|
|
|
/// The results returned from \c IDEInspectionInstance::signatures.
|
|
struct SignatureHelpResults {
|
|
/// The actual results. If \c nullptr, no results were found.
|
|
const SignatureHelpResult *Result;
|
|
/// Whether an AST was reused to produce the results.
|
|
bool DidReuseAST;
|
|
};
|
|
|
|
/// The results returned from \c IDEInspectionInstance::cursorInfo.
|
|
struct CursorInfoResults {
|
|
/// The actual results.
|
|
std::vector<ResolvedCursorInfoPtr> ResolvedCursorInfos;
|
|
/// Whether an AST was reused to produce the results.
|
|
bool DidReuseAST;
|
|
};
|
|
|
|
/// Manages \c CompilerInstance for completion like operations.
|
|
class IDEInspectionInstance {
|
|
struct Options {
|
|
unsigned MaxASTReuseCount = 100;
|
|
unsigned DependencyCheckIntervalSecond = 5;
|
|
} Opts;
|
|
|
|
std::mutex mtx;
|
|
|
|
std::shared_ptr<PluginRegistry> Plugins;
|
|
|
|
std::shared_ptr<CompilerInstance> CachedCI;
|
|
llvm::hash_code CachedArgHash;
|
|
llvm::sys::TimePoint<> DependencyCheckedTimestamp;
|
|
llvm::StringMap<llvm::hash_code> InMemoryDependencyHash;
|
|
unsigned CachedReuseCount = 0;
|
|
std::atomic<bool> CachedCIShouldBeInvalidated;
|
|
|
|
void cacheCompilerInstance(std::shared_ptr<CompilerInstance> CI,
|
|
llvm::hash_code ArgsHash);
|
|
|
|
bool shouldCheckDependencies() const;
|
|
|
|
/// Calls \p Callback with cached \c CompilerInstance if it's usable for the
|
|
/// specified completion request.
|
|
/// Returns \c true if performing the cached operation was possible. Returns
|
|
/// \c false if the compiler argument has changed, primary file is not the
|
|
/// same, the \c Offset is not in function bodies, or the interface hash of
|
|
/// the file has changed.
|
|
/// \p Callback will be called if and only if this function returns \c true.
|
|
bool performCachedOperationIfPossible(
|
|
llvm::hash_code ArgsHash,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
|
const SearchPathOptions &SearchPathOpts,
|
|
llvm::MemoryBuffer *ideInspectionTargetBuffer, unsigned int Offset,
|
|
DiagnosticConsumer *DiagC,
|
|
std::shared_ptr<std::atomic<bool>> CancellationFlag,
|
|
llvm::function_ref<void(CancellableResult<IDEInspectionInstanceResult>)>
|
|
Callback);
|
|
|
|
/// Calls \p Callback with new \c CompilerInstance for the completion
|
|
/// request. The \c CompilerInstace passed to the callback already performed
|
|
/// the first pass.
|
|
/// Returns \c false if it fails to setup the \c CompilerInstance.
|
|
void performNewOperation(
|
|
std::optional<llvm::hash_code> ArgsHash,
|
|
swift::CompilerInvocation &Invocation,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
|
llvm::MemoryBuffer *ideInspectionTargetBuffer, unsigned int Offset,
|
|
DiagnosticConsumer *DiagC,
|
|
std::shared_ptr<std::atomic<bool>> CancellationFlag,
|
|
llvm::function_ref<void(CancellableResult<IDEInspectionInstanceResult>)>
|
|
Callback);
|
|
|
|
/// 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.
|
|
/// The \c CompilerInstance may be reused from the previous completions,
|
|
/// and may be cached for the next completion.
|
|
/// In case of failure or cancellation, the callback receives the
|
|
/// corresponding failed or cancelled result.
|
|
///
|
|
/// If \p CancellationFlag is not \c nullptr, code completion can be cancelled
|
|
/// by setting the flag to \c true.
|
|
/// IMPORTANT: If \p CancellationFlag is not \c nullptr, then completion might
|
|
/// be cancelled in the secon pass that's invoked inside \p Callback.
|
|
/// Therefore, \p Callback MUST check whether completion was cancelled before
|
|
/// interpreting the results, since invalid results may be returned in case
|
|
/// of cancellation.
|
|
///
|
|
/// NOTE: \p Args is only used for checking the equaity of the invocation.
|
|
/// Since this function assumes that it is already normalized, exact the same
|
|
/// arguments including their order is considered as the same invocation.
|
|
void performOperation(
|
|
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
|
llvm::MemoryBuffer *ideInspectionTargetBuffer, unsigned int Offset,
|
|
DiagnosticConsumer *DiagC,
|
|
std::shared_ptr<std::atomic<bool>> CancellationFlag,
|
|
llvm::function_ref<void(CancellableResult<IDEInspectionInstanceResult>)>
|
|
Callback);
|
|
|
|
public:
|
|
IDEInspectionInstance(std::shared_ptr<PluginRegistry> Plugins = nullptr)
|
|
: Plugins(Plugins), CachedCIShouldBeInvalidated(false) {}
|
|
|
|
// Mark the cached compiler instance "should be invalidated". In the next
|
|
// completion, new compiler instance will be used. (Thread safe.)
|
|
void markCachedCompilerInstanceShouldBeInvalidated();
|
|
|
|
// Update options with \c NewOpts. (Thread safe.)
|
|
void setOptions(Options NewOpts);
|
|
|
|
void codeComplete(
|
|
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
|
llvm::MemoryBuffer *ideInspectionTargetBuffer, unsigned int Offset,
|
|
DiagnosticConsumer *DiagC, ide::CodeCompletionContext &CompletionContext,
|
|
std::shared_ptr<std::atomic<bool>> CancellationFlag,
|
|
llvm::function_ref<void(CancellableResult<CodeCompleteResult>)> Callback);
|
|
|
|
void typeContextInfo(
|
|
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
|
llvm::MemoryBuffer *ideInspectionTargetBuffer, unsigned int Offset,
|
|
DiagnosticConsumer *DiagC,
|
|
std::shared_ptr<std::atomic<bool>> CancellationFlag,
|
|
llvm::function_ref<void(CancellableResult<TypeContextInfoResult>)>
|
|
Callback);
|
|
|
|
void conformingMethodList(
|
|
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
|
llvm::MemoryBuffer *ideInspectionTargetBuffer, unsigned int Offset,
|
|
DiagnosticConsumer *DiagC, ArrayRef<const char *> ExpectedTypeNames,
|
|
std::shared_ptr<std::atomic<bool>> CancellationFlag,
|
|
llvm::function_ref<void(CancellableResult<ConformingMethodListResults>)>
|
|
Callback);
|
|
|
|
void signatureHelp(
|
|
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
|
llvm::MemoryBuffer *ideInspectionTargetBuffer, unsigned int Offset,
|
|
DiagnosticConsumer *DiagC,
|
|
std::shared_ptr<std::atomic<bool>> CancellationFlag,
|
|
llvm::function_ref<void(CancellableResult<SignatureHelpResults>)>
|
|
Callback);
|
|
|
|
void cursorInfo(
|
|
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
|
|
llvm::MemoryBuffer *ideInspectionTargetBuffer, unsigned int Offset,
|
|
DiagnosticConsumer *DiagC,
|
|
std::shared_ptr<std::atomic<bool>> CancellationFlag,
|
|
llvm::function_ref<void(CancellableResult<CursorInfoResults>)> Callback);
|
|
};
|
|
|
|
} // namespace ide
|
|
} // namespace swift
|
|
|
|
#endif // SWIFT_IDE_IDEINSPECTIONINSTANCE_H
|