mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #58999 from ahoppen/pr/cache-function-asyncness
[CodeCompletion] Cache 'async'-ness of free functions
This commit is contained in:
@@ -17,21 +17,21 @@
|
||||
|
||||
ERROR(ide_async_in_nonasync_context, none,
|
||||
"async %0 used in a context that does not support concurrency",
|
||||
(DeclName))
|
||||
(StringRef))
|
||||
|
||||
// NOTE: This is WARNING because this is emitted for cross actor references with
|
||||
// non-'Sendable' types. That is optionally ('-warn-concurrency') warning in
|
||||
// Swift 5.5.
|
||||
WARNING(ide_cross_actor_reference_swift5, none,
|
||||
"actor-isolated %0 should only be referenced from inside the actor",
|
||||
(DeclName))
|
||||
(StringRef))
|
||||
|
||||
WARNING(ide_redundant_import, none,
|
||||
"module %0 is already imported", (DeclName))
|
||||
"module %0 is already imported", (StringRef))
|
||||
|
||||
// FIXME: Inform which other 'import' this module came from.
|
||||
NOTE(ide_redundant_import_indirect, none,
|
||||
"module %0 is already imported via another module import", (DeclName))
|
||||
"module %0 is already imported via another module import", (StringRef))
|
||||
|
||||
WARNING(ide_availability_softdeprecated, Deprecation,
|
||||
"%select{getter for |setter for |}0%1 will be deprecated"
|
||||
@@ -46,6 +46,10 @@ WARNING(ide_availability_softdeprecated_rename, Deprecation,
|
||||
": renamed to '%6'",
|
||||
(unsigned, DeclName, bool, StringRef, bool, llvm::VersionTuple, StringRef))
|
||||
|
||||
WARNING(ide_recursive_accessor_reference,none,
|
||||
"attempting to %select{access|modify}1 %0 within its own "
|
||||
"%select{getter|setter}1", (StringRef, bool))
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define UNDEFINE_DIAGNOSTIC_MACROS
|
||||
|
||||
@@ -30,7 +30,8 @@ public:
|
||||
handleResultsAndModules(CodeCompletionContext &context,
|
||||
ArrayRef<RequestedCachedModule> requestedModules,
|
||||
const ExpectedTypeContext *TypeContext,
|
||||
const DeclContext *DC) = 0;
|
||||
const DeclContext *DC,
|
||||
bool CanCurrDeclContextHandleAsync) = 0;
|
||||
};
|
||||
|
||||
/// A simplified code completion consumer interface that clients can use to get
|
||||
@@ -42,7 +43,8 @@ struct SimpleCachingCodeCompletionConsumer : public CodeCompletionConsumer {
|
||||
void handleResultsAndModules(CodeCompletionContext &context,
|
||||
ArrayRef<RequestedCachedModule> requestedModules,
|
||||
const ExpectedTypeContext *TypeContext,
|
||||
const DeclContext *DCForModules) override;
|
||||
const DeclContext *DCForModules,
|
||||
bool CanCurrDeclContextHandleAsync) override;
|
||||
|
||||
/// Clients should override this method to receive \p Results.
|
||||
virtual void handleResults(CodeCompletionContext &context) = 0;
|
||||
|
||||
@@ -329,6 +329,7 @@ class ContextFreeCodeCompletionResult {
|
||||
static_assert(int(CodeCompletionOperatorKind::MAX_VALUE) < 1 << 6, "");
|
||||
|
||||
bool IsSystem : 1;
|
||||
bool IsAsync : 1;
|
||||
CodeCompletionString *CompletionString;
|
||||
NullTerminatedStringRef ModuleName;
|
||||
NullTerminatedStringRef BriefDocComment;
|
||||
@@ -344,6 +345,10 @@ class ContextFreeCodeCompletionResult {
|
||||
NullTerminatedStringRef DiagnosticMessage;
|
||||
NullTerminatedStringRef FilterName;
|
||||
|
||||
/// If the result represents a \c ValueDecl the name by which this decl should
|
||||
/// be refered to in diagnostics.
|
||||
NullTerminatedStringRef NameForDiagnostics;
|
||||
|
||||
public:
|
||||
/// Memberwise initializer. \p AssociatedKInd is opaque and will be
|
||||
/// interpreted based on \p Kind. If \p KnownOperatorKind is \c None and the
|
||||
@@ -355,7 +360,7 @@ public:
|
||||
/// \c CodeCompletionResultSink as the result itself.
|
||||
ContextFreeCodeCompletionResult(
|
||||
CodeCompletionResultKind Kind, uint8_t AssociatedKind,
|
||||
CodeCompletionOperatorKind KnownOperatorKind, bool IsSystem,
|
||||
CodeCompletionOperatorKind KnownOperatorKind, bool IsSystem, bool IsAsync,
|
||||
CodeCompletionString *CompletionString,
|
||||
NullTerminatedStringRef ModuleName,
|
||||
NullTerminatedStringRef BriefDocComment,
|
||||
@@ -364,13 +369,15 @@ public:
|
||||
ContextFreeNotRecommendedReason NotRecommended,
|
||||
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
|
||||
NullTerminatedStringRef DiagnosticMessage,
|
||||
NullTerminatedStringRef FilterName)
|
||||
NullTerminatedStringRef FilterName,
|
||||
NullTerminatedStringRef NameForDiagnostics)
|
||||
: Kind(Kind), KnownOperatorKind(KnownOperatorKind), IsSystem(IsSystem),
|
||||
CompletionString(CompletionString), ModuleName(ModuleName),
|
||||
BriefDocComment(BriefDocComment), AssociatedUSRs(AssociatedUSRs),
|
||||
ResultType(ResultType), NotRecommended(NotRecommended),
|
||||
DiagnosticSeverity(DiagnosticSeverity),
|
||||
DiagnosticMessage(DiagnosticMessage), FilterName(FilterName) {
|
||||
IsAsync(IsAsync), CompletionString(CompletionString),
|
||||
ModuleName(ModuleName), BriefDocComment(BriefDocComment),
|
||||
AssociatedUSRs(AssociatedUSRs), ResultType(ResultType),
|
||||
NotRecommended(NotRecommended), DiagnosticSeverity(DiagnosticSeverity),
|
||||
DiagnosticMessage(DiagnosticMessage), FilterName(FilterName),
|
||||
NameForDiagnostics(NameForDiagnostics) {
|
||||
this->AssociatedKind.Opaque = AssociatedKind;
|
||||
assert((NotRecommended == ContextFreeNotRecommendedReason::None) ==
|
||||
(DiagnosticSeverity == CodeCompletionDiagnosticSeverity::None) &&
|
||||
@@ -396,7 +403,7 @@ public:
|
||||
static ContextFreeCodeCompletionResult *createPatternOrBuiltInOperatorResult(
|
||||
CodeCompletionResultSink &Sink, CodeCompletionResultKind Kind,
|
||||
CodeCompletionString *CompletionString,
|
||||
CodeCompletionOperatorKind KnownOperatorKind,
|
||||
CodeCompletionOperatorKind KnownOperatorKind, bool IsAsync,
|
||||
NullTerminatedStringRef BriefDocComment,
|
||||
CodeCompletionResultType ResultType,
|
||||
ContextFreeNotRecommendedReason NotRecommended,
|
||||
@@ -431,9 +438,11 @@ public:
|
||||
/// \note The caller must ensure that the \p CompletionString and all
|
||||
/// \c StringRefs outlive this result, typically by storing them in the same
|
||||
/// \c CodeCompletionResultSink as the result itself.
|
||||
static ContextFreeCodeCompletionResult *createDeclResult(
|
||||
CodeCompletionResultSink &Sink, CodeCompletionString *CompletionString,
|
||||
const Decl *AssociatedDecl, NullTerminatedStringRef ModuleName,
|
||||
static ContextFreeCodeCompletionResult *
|
||||
createDeclResult(CodeCompletionResultSink &Sink,
|
||||
CodeCompletionString *CompletionString,
|
||||
const Decl *AssociatedDecl, bool IsAsync,
|
||||
NullTerminatedStringRef ModuleName,
|
||||
NullTerminatedStringRef BriefDocComment,
|
||||
ArrayRef<NullTerminatedStringRef> AssociatedUSRs,
|
||||
CodeCompletionResultType ResultType,
|
||||
@@ -469,6 +478,8 @@ public:
|
||||
|
||||
bool isSystem() const { return IsSystem; };
|
||||
|
||||
bool isAsync() const { return IsAsync; };
|
||||
|
||||
CodeCompletionString *getCompletionString() const { return CompletionString; }
|
||||
|
||||
NullTerminatedStringRef getModuleName() const { return ModuleName; }
|
||||
@@ -494,6 +505,10 @@ public:
|
||||
|
||||
NullTerminatedStringRef getFilterName() const { return FilterName; }
|
||||
|
||||
NullTerminatedStringRef getNameForDiagnostics() const {
|
||||
return NameForDiagnostics;
|
||||
}
|
||||
|
||||
bool isOperator() const {
|
||||
if (getKind() == CodeCompletionResultKind::Declaration) {
|
||||
switch (getAssociatedDeclKind()) {
|
||||
@@ -531,11 +546,6 @@ class CodeCompletionResult {
|
||||
ContextualNotRecommendedReason NotRecommended : 4;
|
||||
static_assert(int(ContextualNotRecommendedReason::MAX_VALUE) < 1 << 4, "");
|
||||
|
||||
CodeCompletionDiagnosticSeverity DiagnosticSeverity : 3;
|
||||
static_assert(int(CodeCompletionDiagnosticSeverity::MAX_VALUE) < 1 << 3, "");
|
||||
|
||||
NullTerminatedStringRef DiagnosticMessage;
|
||||
|
||||
/// The number of bytes to the left of the code completion point that
|
||||
/// should be erased first if this completion string is inserted in the
|
||||
/// editor buffer.
|
||||
@@ -556,14 +566,10 @@ private:
|
||||
SemanticContextKind SemanticContext,
|
||||
CodeCompletionFlair Flair, uint8_t NumBytesToErase,
|
||||
CodeCompletionResultTypeRelation TypeDistance,
|
||||
ContextualNotRecommendedReason NotRecommended,
|
||||
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
|
||||
NullTerminatedStringRef DiagnosticMessage)
|
||||
ContextualNotRecommendedReason NotRecommended)
|
||||
: ContextFree(ContextFree), SemanticContext(SemanticContext),
|
||||
Flair(Flair.toRaw()), NotRecommended(NotRecommended),
|
||||
DiagnosticSeverity(DiagnosticSeverity),
|
||||
DiagnosticMessage(DiagnosticMessage), NumBytesToErase(NumBytesToErase),
|
||||
TypeDistance(TypeDistance) {}
|
||||
NumBytesToErase(NumBytesToErase), TypeDistance(TypeDistance) {}
|
||||
|
||||
public:
|
||||
/// Enrich a \c ContextFreeCodeCompletionResult with the following contextual
|
||||
@@ -581,9 +587,8 @@ public:
|
||||
const ExpectedTypeContext *TypeContext,
|
||||
const DeclContext *DC,
|
||||
const USRBasedTypeContext *USRTypeContext,
|
||||
ContextualNotRecommendedReason NotRecommended,
|
||||
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
|
||||
NullTerminatedStringRef DiagnosticMessage);
|
||||
bool CanCurrDeclContextHandleAsync,
|
||||
ContextualNotRecommendedReason NotRecommended);
|
||||
|
||||
const ContextFreeCodeCompletionResult &getContextFreeResult() const {
|
||||
return ContextFree;
|
||||
@@ -702,37 +707,23 @@ public:
|
||||
return getContextFreeResult().getAssociatedUSRs();
|
||||
}
|
||||
|
||||
/// Get the contextual diagnostic severity. This disregards context-free
|
||||
/// diagnostics.
|
||||
CodeCompletionDiagnosticSeverity getContextualDiagnosticSeverity() const {
|
||||
return DiagnosticSeverity;
|
||||
}
|
||||
/// Get the contextual diagnostic severity and message. This disregards
|
||||
/// context-free diagnostics.
|
||||
std::pair<CodeCompletionDiagnosticSeverity, NullTerminatedStringRef>
|
||||
getContextualDiagnosticSeverityAndMessage(SmallVectorImpl<char> &Scratch,
|
||||
const ASTContext &Ctx) const;
|
||||
|
||||
/// Get the contextual diagnostic message. This disregards context-free
|
||||
/// diagnostics.
|
||||
NullTerminatedStringRef getContextualDiagnosticMessage() const {
|
||||
return DiagnosticMessage;
|
||||
}
|
||||
|
||||
/// Return the contextual diagnostic severity if there was a contextual
|
||||
/// diagnostic. If there is no contextual diagnostic, return the context-free
|
||||
/// diagnostic severity.
|
||||
CodeCompletionDiagnosticSeverity getDiagnosticSeverity() const {
|
||||
/// Return the contextual diagnostic severity and message if there was a
|
||||
/// contextual diagnostic. If there is no contextual diagnostic, return the
|
||||
/// context-free diagnostic severity and message.
|
||||
std::pair<CodeCompletionDiagnosticSeverity, NullTerminatedStringRef>
|
||||
getDiagnosticSeverityAndMessage(SmallVectorImpl<char> &Scratch,
|
||||
const ASTContext &Ctx) const {
|
||||
if (NotRecommended != ContextualNotRecommendedReason::None) {
|
||||
return DiagnosticSeverity;
|
||||
return getContextualDiagnosticSeverityAndMessage(Scratch, Ctx);
|
||||
} else {
|
||||
return getContextFreeResult().getDiagnosticSeverity();
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the contextual diagnostic message if there was a contextual
|
||||
/// diagnostic. If there is no contextual diagnostic, return the context-free
|
||||
/// diagnostic message.
|
||||
NullTerminatedStringRef getDiagnosticMessage() const {
|
||||
if (NotRecommended != ContextualNotRecommendedReason::None) {
|
||||
return DiagnosticMessage;
|
||||
} else {
|
||||
return getContextFreeResult().getDiagnosticMessage();
|
||||
return std::make_pair(getContextFreeResult().getDiagnosticSeverity(),
|
||||
getContextFreeResult().getDiagnosticMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ makeCodeCompletionMemoryBuffer(const llvm::MemoryBuffer *origBuf,
|
||||
/// The result returned via the callback from the perform*Operation methods.
|
||||
struct CompletionInstanceResult {
|
||||
/// The compiler instance that is prepared for the second pass.
|
||||
CompilerInstance &CI;
|
||||
std::shared_ptr<CompilerInstance> CI;
|
||||
/// Whether an AST was reused.
|
||||
bool DidReuseAST;
|
||||
/// Whether the CompletionInstance found a code completion token in the source
|
||||
@@ -87,14 +87,14 @@ class CompletionInstance {
|
||||
|
||||
std::mutex mtx;
|
||||
|
||||
std::unique_ptr<CompilerInstance> CachedCI;
|
||||
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::unique_ptr<CompilerInstance> CI,
|
||||
void cacheCompilerInstance(std::shared_ptr<CompilerInstance> CI,
|
||||
llvm::hash_code ArgsHash);
|
||||
|
||||
bool shouldCheckDependencies() const;
|
||||
|
||||
@@ -254,6 +254,10 @@ public:
|
||||
|
||||
void setIdealExpectedType(Type Ty) { expectedTypeContext.setIdealType(Ty); }
|
||||
|
||||
bool canCurrDeclContextHandleAsync() const {
|
||||
return CanCurrDeclContextHandleAsync;
|
||||
}
|
||||
|
||||
void setCanCurrDeclContextHandleAsync(bool CanCurrDeclContextHandleAsync) {
|
||||
this->CanCurrDeclContextHandleAsync = CanCurrDeclContextHandleAsync;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@ namespace swift {
|
||||
namespace ide {
|
||||
|
||||
struct SwiftCompletionInfo {
|
||||
swift::ASTContext *swiftASTContext = nullptr;
|
||||
const swift::CompilerInvocation *invocation = nullptr;
|
||||
std::shared_ptr<CompilerInstance> compilerInstance = nullptr;
|
||||
CodeCompletionContext *completionContext = nullptr;
|
||||
};
|
||||
|
||||
|
||||
@@ -1369,7 +1369,8 @@ void swift::ide::deliverCompletionResults(
|
||||
/*Sink=*/nullptr);
|
||||
|
||||
Consumer.handleResultsAndModules(CompletionContext, RequestedModules,
|
||||
Lookup.getExpectedTypeContext(), DC);
|
||||
Lookup.getExpectedTypeContext(), DC,
|
||||
Lookup.canCurrDeclContextHandleAsync());
|
||||
}
|
||||
|
||||
bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
|
||||
|
||||
@@ -103,7 +103,8 @@ CodeCompletionCache::~CodeCompletionCache() {}
|
||||
///
|
||||
/// This should be incremented any time we commit a change to the format of the
|
||||
/// cached results. This isn't expected to change very often.
|
||||
static constexpr uint32_t onDiskCompletionCacheVersion = 7; // Store whether a type can be used as attribute
|
||||
static constexpr uint32_t onDiskCompletionCacheVersion =
|
||||
9; // Store whether a decl is async
|
||||
|
||||
/// Deserializes CodeCompletionResults from \p in and stores them in \p V.
|
||||
/// \see writeCacheModule.
|
||||
@@ -234,11 +235,13 @@ static bool readCachedModule(llvm::MemoryBuffer *in,
|
||||
auto diagSeverity =
|
||||
static_cast<CodeCompletionDiagnosticSeverity>(*cursor++);
|
||||
auto isSystem = static_cast<bool>(*cursor++);
|
||||
auto isAsync = static_cast<bool>(*cursor++);
|
||||
auto chunkIndex = read32le(cursor);
|
||||
auto moduleIndex = read32le(cursor);
|
||||
auto briefDocIndex = read32le(cursor);
|
||||
auto diagMessageIndex = read32le(cursor);
|
||||
auto filterNameIndex = read32le(cursor);
|
||||
auto nameForDiagnosticsIndex = read32le(cursor);
|
||||
|
||||
auto assocUSRCount = read32le(cursor);
|
||||
SmallVector<NullTerminatedStringRef, 4> assocUSRs;
|
||||
@@ -258,13 +261,14 @@ static bool readCachedModule(llvm::MemoryBuffer *in,
|
||||
auto briefDocComment = getString(briefDocIndex);
|
||||
auto diagMessage = getString(diagMessageIndex);
|
||||
auto filterName = getString(filterNameIndex);
|
||||
auto nameForDiagnostics = getString(nameForDiagnosticsIndex);
|
||||
|
||||
ContextFreeCodeCompletionResult *result =
|
||||
new (*V.Allocator) ContextFreeCodeCompletionResult(
|
||||
kind, associatedKind, opKind, isSystem, string, moduleName,
|
||||
kind, associatedKind, opKind, isSystem, isAsync, string, moduleName,
|
||||
briefDocComment, makeArrayRef(assocUSRs).copy(*V.Allocator),
|
||||
CodeCompletionResultType(resultTypes), notRecommended, diagSeverity,
|
||||
diagMessage, filterName);
|
||||
diagMessage, filterName, nameForDiagnostics);
|
||||
|
||||
V.Results.push_back(result);
|
||||
}
|
||||
@@ -420,12 +424,14 @@ static void writeCachedModule(llvm::raw_ostream &out,
|
||||
LE.write(static_cast<uint8_t>(R->getNotRecommendedReason()));
|
||||
LE.write(static_cast<uint8_t>(R->getDiagnosticSeverity()));
|
||||
LE.write(static_cast<uint8_t>(R->isSystem()));
|
||||
LE.write(static_cast<uint8_t>(R->isAsync()));
|
||||
LE.write(
|
||||
static_cast<uint32_t>(addCompletionString(R->getCompletionString())));
|
||||
LE.write(addString(R->getModuleName())); // index into strings
|
||||
LE.write(addString(R->getBriefDocComment())); // index into strings
|
||||
LE.write(addString(R->getDiagnosticMessage())); // index into strings
|
||||
LE.write(addString(R->getFilterName())); // index into strings
|
||||
LE.write(addString(R->getNameForDiagnostics())); // index into strings
|
||||
|
||||
LE.write(static_cast<uint32_t>(R->getAssociatedUSRs().size()));
|
||||
for (unsigned i = 0; i < R->getAssociatedUSRs().size(); ++i) {
|
||||
|
||||
@@ -19,7 +19,8 @@ using namespace swift::ide;
|
||||
static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
|
||||
CodeCompletionResultSink &targetSink, CodeCompletionCache::Value &source,
|
||||
bool onlyTypes, bool onlyPrecedenceGroups,
|
||||
const ExpectedTypeContext *TypeContext, const DeclContext *DC) {
|
||||
const ExpectedTypeContext *TypeContext, const DeclContext *DC,
|
||||
bool CanCurrDeclContextHandleAsync) {
|
||||
|
||||
// We will be adding foreign results (from another sink) into TargetSink.
|
||||
// TargetSink should have an owning pointer to the allocator that keeps the
|
||||
@@ -87,8 +88,7 @@ static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
|
||||
*contextFreeResult, SemanticContextKind::OtherModule,
|
||||
CodeCompletionFlair(),
|
||||
/*numBytesToErase=*/0, TypeContext, DC, &USRTypeContext,
|
||||
ContextualNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
|
||||
CanCurrDeclContextHandleAsync, ContextualNotRecommendedReason::None);
|
||||
targetSink.Results.push_back(contextualResult);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,8 @@ static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
|
||||
void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
|
||||
CodeCompletionContext &context,
|
||||
ArrayRef<RequestedCachedModule> requestedModules,
|
||||
const ExpectedTypeContext *TypeContext, const DeclContext *DC) {
|
||||
const ExpectedTypeContext *TypeContext, const DeclContext *DC,
|
||||
bool CanCurrDeclContextHandleAsync) {
|
||||
|
||||
// Use the current SourceFile as the DeclContext so that we can use it to
|
||||
// perform qualified lookup, and to get the correct visibility for
|
||||
@@ -144,9 +145,9 @@ void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
|
||||
context.Cache.set(R.Key, *V);
|
||||
}
|
||||
assert(V.hasValue());
|
||||
auto newItems =
|
||||
copyCodeCompletionResults(context.getResultSink(), **V, R.OnlyTypes,
|
||||
R.OnlyPrecedenceGroups, TypeContext, DC);
|
||||
auto newItems = copyCodeCompletionResults(
|
||||
context.getResultSink(), **V, R.OnlyTypes, R.OnlyPrecedenceGroups,
|
||||
TypeContext, DC, CanCurrDeclContextHandleAsync);
|
||||
postProcessCompletionResults(newItems, context.CodeCompletionKind, DC,
|
||||
&context.getResultSink());
|
||||
}
|
||||
|
||||
@@ -42,11 +42,12 @@ CodeCompletionDiagnosticSeverity getSeverity(DiagnosticKind DiagKind) {
|
||||
}
|
||||
|
||||
class CodeCompletionDiagnostics {
|
||||
ASTContext &Ctx;
|
||||
const ASTContext &Ctx;
|
||||
DiagnosticEngine &Engine;
|
||||
|
||||
public:
|
||||
CodeCompletionDiagnostics(ASTContext &Ctx) : Ctx(Ctx), Engine(Ctx.Diags) {}
|
||||
CodeCompletionDiagnostics(const ASTContext &Ctx)
|
||||
: Ctx(Ctx), Engine(Ctx.Diags) {}
|
||||
|
||||
template <typename... ArgTypes>
|
||||
bool
|
||||
@@ -159,27 +160,29 @@ bool swift::ide::getContextFreeCompletionDiagnostics(
|
||||
}
|
||||
|
||||
bool swift::ide::getContextualCompletionDiagnostics(
|
||||
ContextualNotRecommendedReason Reason, const ValueDecl *D,
|
||||
CodeCompletionDiagnosticSeverity &Severity, llvm::raw_ostream &Out) {
|
||||
CodeCompletionDiagnostics Diag(D->getASTContext());
|
||||
ContextualNotRecommendedReason Reason, StringRef NameForDiagnostics,
|
||||
CodeCompletionDiagnosticSeverity &Severity, llvm::raw_ostream &Out,
|
||||
const ASTContext &Ctx) {
|
||||
CodeCompletionDiagnostics Diag(Ctx);
|
||||
switch (Reason) {
|
||||
case ContextualNotRecommendedReason::InvalidAsyncContext:
|
||||
// FIXME: Could we use 'diag::async_in_nonasync_function'?
|
||||
return Diag.getDiagnostics(
|
||||
Severity, Out, diag::ide_async_in_nonasync_context, D->getName());
|
||||
Severity, Out, diag::ide_async_in_nonasync_context, NameForDiagnostics);
|
||||
case ContextualNotRecommendedReason::CrossActorReference:
|
||||
return Diag.getDiagnostics(
|
||||
Severity, Out, diag::ide_cross_actor_reference_swift5, D->getName());
|
||||
return Diag.getDiagnostics(Severity, Out,
|
||||
diag::ide_cross_actor_reference_swift5,
|
||||
NameForDiagnostics);
|
||||
case ContextualNotRecommendedReason::RedundantImport:
|
||||
return Diag.getDiagnostics(Severity, Out, diag::ide_redundant_import,
|
||||
D->getName());
|
||||
NameForDiagnostics);
|
||||
case ContextualNotRecommendedReason::RedundantImportIndirect:
|
||||
return Diag.getDiagnostics(
|
||||
Severity, Out, diag::ide_redundant_import_indirect, D->getName());
|
||||
Severity, Out, diag::ide_redundant_import_indirect, NameForDiagnostics);
|
||||
case ContextualNotRecommendedReason::VariableUsedInOwnDefinition:
|
||||
return Diag.getDiagnostics(
|
||||
Severity, Out, diag::recursive_accessor_reference,
|
||||
D->getName().getBaseIdentifier(), /*"getter"*/ 0);
|
||||
return Diag.getDiagnostics(Severity, Out,
|
||||
diag::ide_recursive_accessor_reference,
|
||||
NameForDiagnostics, /*"getter"*/ 0);
|
||||
case ContextualNotRecommendedReason::None:
|
||||
llvm_unreachable("invalid not recommended reason");
|
||||
}
|
||||
|
||||
@@ -29,13 +29,17 @@ bool getContextFreeCompletionDiagnostics(
|
||||
ContextFreeNotRecommendedReason reason, const ValueDecl *D,
|
||||
CodeCompletionDiagnosticSeverity &severity, llvm::raw_ostream &Out);
|
||||
|
||||
/// Populate \p severity and \p Out with the contextual diagnostics for \p D.
|
||||
/// Populate \p severity and \p Out with the contextual for \p reason.
|
||||
/// \p NameForDiagnostic is the name of the decl that produced this diagnostic.
|
||||
/// \p Ctx is a context that's purely used to have a reference to a diagnostic
|
||||
/// engine.
|
||||
/// See \c NotRecommendedReason for an explaination of context-free vs.
|
||||
/// contextual diagnostics.
|
||||
/// Returns \c true if it fails to generate the diagnostics.
|
||||
bool getContextualCompletionDiagnostics(
|
||||
ContextualNotRecommendedReason reason, const ValueDecl *D,
|
||||
CodeCompletionDiagnosticSeverity &severity, llvm::raw_ostream &Out);
|
||||
ContextualNotRecommendedReason Reason, StringRef NameForDiagnostics,
|
||||
CodeCompletionDiagnosticSeverity &Severity, llvm::raw_ostream &Out,
|
||||
const ASTContext &Ctx);
|
||||
|
||||
} // namespace ide
|
||||
} // namespace swift
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/IDE/CodeCompletionResult.h"
|
||||
#include "CodeCompletionDiagnostics.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/IDE/CodeCompletionResultPrinter.h"
|
||||
@@ -25,7 +26,7 @@ ContextFreeCodeCompletionResult *
|
||||
ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult(
|
||||
CodeCompletionResultSink &Sink, CodeCompletionResultKind Kind,
|
||||
CodeCompletionString *CompletionString,
|
||||
CodeCompletionOperatorKind KnownOperatorKind,
|
||||
CodeCompletionOperatorKind KnownOperatorKind, bool IsAsync,
|
||||
NullTerminatedStringRef BriefDocComment,
|
||||
CodeCompletionResultType ResultType,
|
||||
ContextFreeNotRecommendedReason NotRecommended,
|
||||
@@ -34,12 +35,20 @@ ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult(
|
||||
if (Sink.shouldProduceContextFreeResults()) {
|
||||
ResultType = ResultType.usrBasedType(Sink.getUSRTypeArena());
|
||||
}
|
||||
NullTerminatedStringRef NameForDiagnostics;
|
||||
if (KnownOperatorKind == CodeCompletionOperatorKind::None) {
|
||||
NameForDiagnostics = "function";
|
||||
} else {
|
||||
NameForDiagnostics = "operator";
|
||||
}
|
||||
return new (Sink.getAllocator()) ContextFreeCodeCompletionResult(
|
||||
Kind, /*AssociatedKind=*/0, KnownOperatorKind,
|
||||
/*IsSystem=*/false, CompletionString, /*ModuleName=*/"", BriefDocComment,
|
||||
/*IsSystem=*/false, IsAsync, CompletionString,
|
||||
/*ModuleName=*/"", BriefDocComment,
|
||||
/*AssociatedUSRs=*/{}, ResultType, NotRecommended, DiagnosticSeverity,
|
||||
DiagnosticMessage,
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()));
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
|
||||
NameForDiagnostics);
|
||||
}
|
||||
|
||||
ContextFreeCodeCompletionResult *
|
||||
@@ -53,11 +62,13 @@ ContextFreeCodeCompletionResult::createKeywordResult(
|
||||
}
|
||||
return new (Sink.getAllocator()) ContextFreeCodeCompletionResult(
|
||||
CodeCompletionResultKind::Keyword, static_cast<uint8_t>(Kind),
|
||||
CodeCompletionOperatorKind::None, /*IsSystem=*/false, CompletionString,
|
||||
CodeCompletionOperatorKind::None, /*IsSystem=*/false, /*IsAsync=*/false,
|
||||
CompletionString,
|
||||
/*ModuleName=*/"", BriefDocComment,
|
||||
/*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"",
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()));
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
|
||||
/*NameForDiagnostics=*/"");
|
||||
}
|
||||
|
||||
ContextFreeCodeCompletionResult *
|
||||
@@ -71,18 +82,35 @@ ContextFreeCodeCompletionResult::createLiteralResult(
|
||||
return new (Sink.getAllocator()) ContextFreeCodeCompletionResult(
|
||||
CodeCompletionResultKind::Literal, static_cast<uint8_t>(LiteralKind),
|
||||
CodeCompletionOperatorKind::None,
|
||||
/*IsSystem=*/false, CompletionString, /*ModuleName=*/"",
|
||||
/*IsSystem=*/false, /*IsAsync=*/false, CompletionString,
|
||||
/*ModuleName=*/"",
|
||||
/*BriefDocComment=*/"",
|
||||
/*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"",
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()));
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
|
||||
/*NameForDiagnostics=*/"");
|
||||
}
|
||||
|
||||
static NullTerminatedStringRef
|
||||
getDeclNameForDiagnostics(const Decl *D, CodeCompletionResultSink &Sink) {
|
||||
if (auto VD = dyn_cast<ValueDecl>(D)) {
|
||||
llvm::SmallString<64> Name;
|
||||
llvm::raw_svector_ostream NameOS(Name);
|
||||
NameOS << "'";
|
||||
llvm::SmallString<64> Scratch;
|
||||
VD->getName().printPretty(NameOS);
|
||||
NameOS << "'";
|
||||
return NullTerminatedStringRef(NameOS.str(), Sink.getAllocator());
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
ContextFreeCodeCompletionResult *
|
||||
ContextFreeCodeCompletionResult::createDeclResult(
|
||||
CodeCompletionResultSink &Sink, CodeCompletionString *CompletionString,
|
||||
const Decl *AssociatedDecl, NullTerminatedStringRef ModuleName,
|
||||
NullTerminatedStringRef BriefDocComment,
|
||||
const Decl *AssociatedDecl, bool IsAsync,
|
||||
NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment,
|
||||
ArrayRef<NullTerminatedStringRef> AssociatedUSRs,
|
||||
CodeCompletionResultType ResultType,
|
||||
ContextFreeNotRecommendedReason NotRecommended,
|
||||
@@ -96,9 +124,10 @@ ContextFreeCodeCompletionResult::createDeclResult(
|
||||
CodeCompletionResultKind::Declaration,
|
||||
static_cast<uint8_t>(getCodeCompletionDeclKind(AssociatedDecl)),
|
||||
CodeCompletionOperatorKind::None, getDeclIsSystem(AssociatedDecl),
|
||||
CompletionString, ModuleName, BriefDocComment, AssociatedUSRs, ResultType,
|
||||
NotRecommended, DiagnosticSeverity, DiagnosticMessage,
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()));
|
||||
IsAsync, CompletionString, ModuleName, BriefDocComment, AssociatedUSRs,
|
||||
ResultType, NotRecommended, DiagnosticSeverity, DiagnosticMessage,
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
|
||||
/*NameForDiagnostics=*/getDeclNameForDiagnostics(AssociatedDecl, Sink));
|
||||
}
|
||||
|
||||
CodeCompletionOperatorKind
|
||||
@@ -262,27 +291,40 @@ bool ContextFreeCodeCompletionResult::getDeclIsSystem(const Decl *D) {
|
||||
|
||||
// MARK: - CodeCompletionResult
|
||||
|
||||
static ContextualNotRecommendedReason
|
||||
getNotRecommenedReason(const ContextFreeCodeCompletionResult &ContextFree,
|
||||
bool CanCurrDeclContextHandleAsync,
|
||||
ContextualNotRecommendedReason ExplicitReason) {
|
||||
if (ExplicitReason != ContextualNotRecommendedReason::None) {
|
||||
return ExplicitReason;
|
||||
}
|
||||
if (ContextFree.isAsync() && !CanCurrDeclContextHandleAsync) {
|
||||
return ContextualNotRecommendedReason::InvalidAsyncContext;
|
||||
}
|
||||
return ContextualNotRecommendedReason::None;
|
||||
}
|
||||
|
||||
CodeCompletionResult::CodeCompletionResult(
|
||||
const ContextFreeCodeCompletionResult &ContextFree,
|
||||
SemanticContextKind SemanticContext, CodeCompletionFlair Flair,
|
||||
uint8_t NumBytesToErase, const ExpectedTypeContext *TypeContext,
|
||||
const DeclContext *DC, const USRBasedTypeContext *USRTypeContext,
|
||||
ContextualNotRecommendedReason NotRecommended,
|
||||
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
|
||||
NullTerminatedStringRef DiagnosticMessage)
|
||||
bool CanCurrDeclContextHandleAsync,
|
||||
ContextualNotRecommendedReason NotRecommended)
|
||||
: ContextFree(ContextFree), SemanticContext(SemanticContext),
|
||||
Flair(Flair.toRaw()), NotRecommended(NotRecommended),
|
||||
DiagnosticSeverity(DiagnosticSeverity),
|
||||
DiagnosticMessage(DiagnosticMessage), NumBytesToErase(NumBytesToErase),
|
||||
Flair(Flair.toRaw()),
|
||||
NotRecommended(getNotRecommenedReason(
|
||||
ContextFree, CanCurrDeclContextHandleAsync, NotRecommended)),
|
||||
NumBytesToErase(NumBytesToErase),
|
||||
TypeDistance(ContextFree.getResultType().calculateTypeRelation(
|
||||
TypeContext, DC, USRTypeContext)) {}
|
||||
|
||||
CodeCompletionResult *
|
||||
CodeCompletionResult::withFlair(CodeCompletionFlair NewFlair,
|
||||
CodeCompletionResultSink &Sink) const {
|
||||
return new (*Sink.Allocator) CodeCompletionResult(
|
||||
ContextFree, SemanticContext, NewFlair, NumBytesToErase, TypeDistance,
|
||||
NotRecommended, DiagnosticSeverity, DiagnosticMessage);
|
||||
return new (*Sink.Allocator)
|
||||
CodeCompletionResult(ContextFree, SemanticContext, NewFlair,
|
||||
NumBytesToErase, TypeDistance, NotRecommended);
|
||||
}
|
||||
|
||||
CodeCompletionResult *
|
||||
@@ -290,9 +332,21 @@ CodeCompletionResult::withContextFreeResultSemanticContextAndFlair(
|
||||
const ContextFreeCodeCompletionResult &NewContextFree,
|
||||
SemanticContextKind NewSemanticContext, CodeCompletionFlair NewFlair,
|
||||
CodeCompletionResultSink &Sink) const {
|
||||
return new (*Sink.Allocator) CodeCompletionResult(
|
||||
NewContextFree, NewSemanticContext, NewFlair, NumBytesToErase,
|
||||
TypeDistance, NotRecommended, DiagnosticSeverity, DiagnosticMessage);
|
||||
return new (*Sink.Allocator)
|
||||
CodeCompletionResult(NewContextFree, NewSemanticContext, NewFlair,
|
||||
NumBytesToErase, TypeDistance, NotRecommended);
|
||||
}
|
||||
|
||||
std::pair<CodeCompletionDiagnosticSeverity, NullTerminatedStringRef>
|
||||
CodeCompletionResult::getContextualDiagnosticSeverityAndMessage(
|
||||
SmallVectorImpl<char> &Scratch, const ASTContext &Ctx) const {
|
||||
llvm::raw_svector_ostream Out(Scratch);
|
||||
CodeCompletionDiagnosticSeverity Severity;
|
||||
getContextualCompletionDiagnostics(
|
||||
NotRecommended, ContextFree.getNameForDiagnostics(), Severity, Out, Ctx);
|
||||
Out << '\0';
|
||||
NullTerminatedStringRef Message(Out.str().data(), Out.str().size() - 1);
|
||||
return std::make_pair(Severity, Message);
|
||||
}
|
||||
|
||||
void CodeCompletionResult::printPrefix(raw_ostream &OS) const {
|
||||
|
||||
@@ -128,7 +128,7 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
|
||||
}
|
||||
|
||||
ContextFreeResult = ContextFreeCodeCompletionResult::createDeclResult(
|
||||
Sink, CCS, AssociatedDecl, ModuleName,
|
||||
Sink, CCS, AssociatedDecl, IsAsync, ModuleName,
|
||||
NullTerminatedStringRef(BriefDocComment, Allocator),
|
||||
copyAssociatedUSRs(Allocator, AssociatedDecl), ResultType,
|
||||
ContextFreeNotRecReason, ContextFreeDiagnosticSeverity,
|
||||
@@ -145,7 +145,7 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
|
||||
case CodeCompletionResultKind::Pattern:
|
||||
ContextFreeResult =
|
||||
ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult(
|
||||
Sink, Kind, CCS, CodeCompletionOperatorKind::None,
|
||||
Sink, Kind, CCS, CodeCompletionOperatorKind::None, IsAsync,
|
||||
NullTerminatedStringRef(BriefDocComment, Allocator), ResultType,
|
||||
ContextFreeNotRecReason, ContextFreeDiagnosticSeverity,
|
||||
ContextFreeDiagnosticMessage);
|
||||
@@ -164,35 +164,9 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
|
||||
*ContextFreeResult, SemanticContextKind::None, CodeCompletionFlair(),
|
||||
/*NumBytesToErase=*/0, /*TypeContext=*/nullptr,
|
||||
/*DC=*/nullptr, /*USRTypeContext=*/nullptr,
|
||||
ContextualNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, "");
|
||||
/*CanCurrDeclContextHandleAsync=*/false,
|
||||
ContextualNotRecommendedReason::None);
|
||||
} else {
|
||||
CodeCompletionDiagnosticSeverity ContextualDiagnosticSeverity =
|
||||
CodeCompletionDiagnosticSeverity::None;
|
||||
NullTerminatedStringRef ContextualDiagnosticMessage;
|
||||
if (ContextualNotRecReason != ContextualNotRecommendedReason::None) {
|
||||
// FIXME: We should generate the message lazily.
|
||||
//
|
||||
// NOTE(rdar://95306033): dyn_cast_or_null because 'nullptr' happens in
|
||||
// cases like:
|
||||
//
|
||||
// func test(fn: () async -> Void) { fn(#HERE#) }
|
||||
//
|
||||
// In this case, it's 'InvalidAsyncContext' but there's no associated decl
|
||||
// because the callee is a random expression.
|
||||
// FIXME: Emit a diagnostic even without an associated decl.
|
||||
if (const auto *VD = dyn_cast_or_null<ValueDecl>(AssociatedDecl)) {
|
||||
CodeCompletionDiagnosticSeverity severity;
|
||||
SmallString<256> message;
|
||||
llvm::raw_svector_ostream messageOS(message);
|
||||
if (!getContextualCompletionDiagnostics(ContextualNotRecReason, VD,
|
||||
severity, messageOS)) {
|
||||
ContextualDiagnosticSeverity = severity;
|
||||
ContextualDiagnosticMessage =
|
||||
NullTerminatedStringRef(message, Allocator);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(
|
||||
ContextFreeResult != nullptr &&
|
||||
"ContextFreeResult should have been constructed by the switch above");
|
||||
@@ -202,8 +176,8 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
|
||||
// for USRTypeContext.
|
||||
return new (Allocator) CodeCompletionResult(
|
||||
*ContextFreeResult, SemanticContext, Flair, NumBytesToErase,
|
||||
TypeContext, DC, /*USRTypeContext=*/nullptr, ContextualNotRecReason,
|
||||
ContextualDiagnosticSeverity, ContextualDiagnosticMessage);
|
||||
TypeContext, DC, /*USRTypeContext=*/nullptr,
|
||||
CanCurrDeclContextHandleAsync, ContextualNotRecReason);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ class CodeCompletionResultBuilder {
|
||||
CodeCompletionFlair Flair;
|
||||
unsigned NumBytesToErase = 0;
|
||||
const Decl *AssociatedDecl = nullptr;
|
||||
bool IsAsync = false;
|
||||
Optional<CodeCompletionLiteralKind> LiteralKind;
|
||||
CodeCompletionKeywordKind KeywordKind = CodeCompletionKeywordKind::None;
|
||||
unsigned CurrentNestingLevel = 0;
|
||||
@@ -63,6 +64,7 @@ class CodeCompletionResultBuilder {
|
||||
/// type relation to \c ResultType.
|
||||
const ExpectedTypeContext *TypeContext = nullptr;
|
||||
const DeclContext *DC = nullptr;
|
||||
bool CanCurrDeclContextHandleAsync = false;
|
||||
|
||||
void addChunkWithText(CodeCompletionString::Chunk::ChunkKind Kind,
|
||||
StringRef Text);
|
||||
@@ -113,6 +115,8 @@ public:
|
||||
|
||||
void setAssociatedDecl(const Decl *D);
|
||||
|
||||
void setIsAsync(bool IsAsync) { this->IsAsync = IsAsync; }
|
||||
|
||||
void setLiteralKind(CodeCompletionLiteralKind kind) { LiteralKind = kind; }
|
||||
void setKeywordKind(CodeCompletionKeywordKind kind) { KeywordKind = kind; }
|
||||
void setContextFreeNotRecommended(ContextFreeNotRecommendedReason Reason) {
|
||||
@@ -149,6 +153,10 @@ public:
|
||||
this->DC = DC;
|
||||
}
|
||||
|
||||
void setCanCurrDeclContextHandleAsync(bool CanCurrDeclContextHandleAsync) {
|
||||
this->CanCurrDeclContextHandleAsync = CanCurrDeclContextHandleAsync;
|
||||
}
|
||||
|
||||
void withNestedGroup(CodeCompletionString::Chunk::ChunkKind Kind,
|
||||
llvm::function_ref<void()> body);
|
||||
|
||||
|
||||
@@ -197,15 +197,14 @@ bool CompletionInstance::performCachedOperationIfPossible(
|
||||
if (CachedArgHash != ArgsHash)
|
||||
return false;
|
||||
|
||||
auto &CI = *CachedCI;
|
||||
auto *oldSF = CI.getCodeCompletionFile();
|
||||
auto *oldSF = CachedCI->getCodeCompletionFile();
|
||||
assert(oldSF->getBufferID());
|
||||
|
||||
auto *oldState = oldSF->getDelayedParserState();
|
||||
assert(oldState->hasCodeCompletionDelayedDeclState());
|
||||
auto &oldInfo = oldState->getCodeCompletionDelayedDeclState();
|
||||
|
||||
auto &SM = CI.getSourceMgr();
|
||||
auto &SM = CachedCI->getSourceMgr();
|
||||
auto bufferName = completionBuffer->getBufferIdentifier();
|
||||
if (SM.getIdentifierForBuffer(*oldSF->getBufferID()) != bufferName)
|
||||
return false;
|
||||
@@ -222,7 +221,7 @@ bool CompletionInstance::performCachedOperationIfPossible(
|
||||
}
|
||||
|
||||
if (areAnyDependentFilesInvalidated(
|
||||
CI, *FileSystem, *oldSF->getBufferID(),
|
||||
*CachedCI, *FileSystem, *oldSF->getBufferID(),
|
||||
DependencyCheckedTimestamp, InMemoryDependencyHash))
|
||||
return false;
|
||||
DependencyCheckedTimestamp = std::chrono::system_clock::now();
|
||||
@@ -233,10 +232,10 @@ bool CompletionInstance::performCachedOperationIfPossible(
|
||||
auto tmpBufferID = tmpSM.addMemBufferCopy(completionBuffer);
|
||||
tmpSM.setCodeCompletionPoint(tmpBufferID, Offset);
|
||||
|
||||
LangOptions langOpts = CI.getASTContext().LangOpts;
|
||||
TypeCheckerOptions typeckOpts = CI.getASTContext().TypeCheckerOpts;
|
||||
SILOptions silOpts = CI.getASTContext().SILOpts;
|
||||
SearchPathOptions searchPathOpts = CI.getASTContext().SearchPathOpts;
|
||||
LangOptions langOpts = CachedCI->getASTContext().LangOpts;
|
||||
TypeCheckerOptions typeckOpts = CachedCI->getASTContext().TypeCheckerOpts;
|
||||
SILOptions silOpts = CachedCI->getASTContext().SILOpts;
|
||||
SearchPathOptions searchPathOpts = CachedCI->getASTContext().SearchPathOpts;
|
||||
DiagnosticEngine tmpDiags(tmpSM);
|
||||
ClangImporterOptions clangOpts;
|
||||
symbolgraphgen::SymbolGraphOptions symbolOpts;
|
||||
@@ -382,7 +381,7 @@ bool CompletionInstance::performCachedOperationIfPossible(
|
||||
newM->addFile(*newSF);
|
||||
|
||||
// Tell the compiler instance we've replaced the main module.
|
||||
CI.setMainModule(newM);
|
||||
CachedCI->setMainModule(newM);
|
||||
|
||||
// Re-process the whole file (parsing will be lazily triggered). Still
|
||||
// re-use imported modules.
|
||||
@@ -407,22 +406,22 @@ bool CompletionInstance::performCachedOperationIfPossible(
|
||||
|
||||
// The diagnostic engine is keeping track of state which might modify
|
||||
// parsing and type checking behaviour. Clear the flags.
|
||||
CI.getDiags().resetHadAnyError();
|
||||
CI.getASTContext().CancellationFlag = CancellationFlag;
|
||||
CachedCI->getDiags().resetHadAnyError();
|
||||
CachedCI->getASTContext().CancellationFlag = CancellationFlag;
|
||||
|
||||
if (DiagC)
|
||||
CI.addDiagnosticConsumer(DiagC);
|
||||
CachedCI->addDiagnosticConsumer(DiagC);
|
||||
|
||||
if (CancellationFlag && CancellationFlag->load(std::memory_order_relaxed)) {
|
||||
Callback(CancellableResult<CompletionInstanceResult>::cancelled());
|
||||
} else {
|
||||
Callback(CancellableResult<CompletionInstanceResult>::success(
|
||||
{CI, /*reusingASTContext=*/true,
|
||||
{CachedCI, /*reusingASTContext=*/true,
|
||||
/*DidFindCodeCompletionToken=*/true}));
|
||||
}
|
||||
|
||||
if (DiagC)
|
||||
CI.removeDiagnosticConsumer(DiagC);
|
||||
CachedCI->removeDiagnosticConsumer(DiagC);
|
||||
}
|
||||
|
||||
CachedReuseCount += 1;
|
||||
@@ -443,7 +442,7 @@ void CompletionInstance::performNewOperation(
|
||||
// If ArgsHash is None we shouldn't cache the compiler instance.
|
||||
bool ShouldCacheCompilerInstance = ArgsHash.hasValue();
|
||||
|
||||
auto TheInstance = std::make_unique<CompilerInstance>();
|
||||
auto CI = std::make_shared<CompilerInstance>();
|
||||
|
||||
// Track non-system dependencies in fast-completion mode to invalidate the
|
||||
// compiler instance if any dependent files are modified.
|
||||
@@ -451,37 +450,36 @@ void CompletionInstance::performNewOperation(
|
||||
IntermoduleDepTrackingMode::ExcludeSystem;
|
||||
|
||||
{
|
||||
auto &CI = *TheInstance;
|
||||
if (DiagC)
|
||||
CI.addDiagnosticConsumer(DiagC);
|
||||
CI->addDiagnosticConsumer(DiagC);
|
||||
|
||||
SWIFT_DEFER {
|
||||
if (DiagC)
|
||||
CI.removeDiagnosticConsumer(DiagC);
|
||||
CI->removeDiagnosticConsumer(DiagC);
|
||||
};
|
||||
|
||||
if (FileSystem != llvm::vfs::getRealFileSystem())
|
||||
CI.getSourceMgr().setFileSystem(FileSystem);
|
||||
CI->getSourceMgr().setFileSystem(FileSystem);
|
||||
|
||||
Invocation.setCodeCompletionPoint(completionBuffer, Offset);
|
||||
|
||||
std::string InstanceSetupError;
|
||||
if (CI.setup(Invocation, InstanceSetupError)) {
|
||||
if (CI->setup(Invocation, InstanceSetupError)) {
|
||||
Callback(CancellableResult<CompletionInstanceResult>::failure(
|
||||
InstanceSetupError));
|
||||
return;
|
||||
}
|
||||
CI.getASTContext().CancellationFlag = CancellationFlag;
|
||||
registerIDERequestFunctions(CI.getASTContext().evaluator);
|
||||
CI->getASTContext().CancellationFlag = CancellationFlag;
|
||||
registerIDERequestFunctions(CI->getASTContext().evaluator);
|
||||
|
||||
CI.performParseAndResolveImportsOnly();
|
||||
CI->performParseAndResolveImportsOnly();
|
||||
|
||||
bool DidFindCodeCompletionToken = CI.getCodeCompletionFile()
|
||||
bool DidFindCodeCompletionToken = CI->getCodeCompletionFile()
|
||||
->getDelayedParserState()
|
||||
->hasCodeCompletionDelayedDeclState();
|
||||
ShouldCacheCompilerInstance &= DidFindCodeCompletionToken;
|
||||
|
||||
auto CancellationFlag = CI.getASTContext().CancellationFlag;
|
||||
auto CancellationFlag = CI->getASTContext().CancellationFlag;
|
||||
if (CancellationFlag && CancellationFlag->load(std::memory_order_relaxed)) {
|
||||
Callback(CancellableResult<CompletionInstanceResult>::cancelled());
|
||||
// The completion instance may be in an invalid state when it's been
|
||||
@@ -502,11 +500,11 @@ void CompletionInstance::performNewOperation(
|
||||
// because performCachedOperationIfPossible wouldn't have an old code
|
||||
// completion state to compare the new one to.
|
||||
if (ShouldCacheCompilerInstance)
|
||||
cacheCompilerInstance(std::move(TheInstance), *ArgsHash);
|
||||
cacheCompilerInstance(std::move(CI), *ArgsHash);
|
||||
}
|
||||
|
||||
void CompletionInstance::cacheCompilerInstance(
|
||||
std::unique_ptr<CompilerInstance> CI, llvm::hash_code ArgsHash) {
|
||||
std::shared_ptr<CompilerInstance> CI, llvm::hash_code ArgsHash) {
|
||||
CachedCI = std::move(CI);
|
||||
CachedArgHash = ArgsHash;
|
||||
auto now = std::chrono::system_clock::now();
|
||||
@@ -602,11 +600,9 @@ void swift::ide::CompletionInstance::codeComplete(
|
||||
: ImportDep(ImportDep), CancellationFlag(CancellationFlag),
|
||||
Callback(Callback) {}
|
||||
|
||||
void setContext(swift::ASTContext *context,
|
||||
const swift::CompilerInvocation *invocation,
|
||||
void setContext(std::shared_ptr<CompilerInstance> compilerInstance,
|
||||
swift::ide::CodeCompletionContext *completionContext) {
|
||||
SwiftContext.swiftASTContext = context;
|
||||
SwiftContext.invocation = invocation;
|
||||
SwiftContext.compilerInstance = std::move(compilerInstance);
|
||||
SwiftContext.completionContext = completionContext;
|
||||
}
|
||||
void clearContext() { SwiftContext = SwiftCompletionInfo(); }
|
||||
@@ -617,7 +613,7 @@ void swift::ide::CompletionInstance::codeComplete(
|
||||
CancellationFlag->load(std::memory_order_relaxed)) {
|
||||
Callback(ResultType::cancelled());
|
||||
} else {
|
||||
assert(SwiftContext.swiftASTContext);
|
||||
assert(SwiftContext.compilerInstance);
|
||||
Callback(ResultType::success({context.getResultSink(), SwiftContext, ImportDep}));
|
||||
}
|
||||
}
|
||||
@@ -631,9 +627,9 @@ void swift::ide::CompletionInstance::codeComplete(
|
||||
[&CompletionContext, &CancellationFlag](auto &Result,
|
||||
auto DeliverTransformed) {
|
||||
CompletionContext.ReusingASTContext = Result.DidReuseAST;
|
||||
CompilerInstance &CI = Result.CI;
|
||||
ImportDepth ImportDep{CI.getASTContext(),
|
||||
CI.getInvocation().getFrontendOptions()};
|
||||
std::shared_ptr<CompilerInstance> CI = Result.CI;
|
||||
ImportDepth ImportDep{CI->getASTContext(),
|
||||
CI->getInvocation().getFrontendOptions()};
|
||||
ConsumerToCallbackAdapter Consumer(ImportDep, CancellationFlag,
|
||||
DeliverTransformed);
|
||||
|
||||
@@ -642,17 +638,14 @@ void swift::ide::CompletionInstance::codeComplete(
|
||||
Consumer));
|
||||
|
||||
if (!Result.DidFindCodeCompletionToken) {
|
||||
SwiftCompletionInfo Info{&CI.getASTContext(),
|
||||
&CI.getInvocation(),
|
||||
&CompletionContext};
|
||||
SwiftCompletionInfo Info{CI, &CompletionContext};
|
||||
CodeCompletionResultSink ResultSink;
|
||||
DeliverTransformed(ResultType::success({ResultSink, Info, ImportDep}));
|
||||
return;
|
||||
}
|
||||
|
||||
Consumer.setContext(&CI.getASTContext(), &CI.getInvocation(),
|
||||
&CompletionContext);
|
||||
performCodeCompletionSecondPass(*CI.getCodeCompletionFile(),
|
||||
Consumer.setContext(CI, &CompletionContext);
|
||||
performCodeCompletionSecondPass(*CI->getCodeCompletionFile(),
|
||||
*callbacksFactory);
|
||||
Consumer.clearContext();
|
||||
if (!Consumer.HandleResultsCalled) {
|
||||
@@ -660,9 +653,7 @@ void swift::ide::CompletionInstance::codeComplete(
|
||||
// pass, we didn't receive any results. To make sure Callback
|
||||
// gets called exactly once, call it manually with no results
|
||||
// here.
|
||||
SwiftCompletionInfo Info{&CI.getASTContext(),
|
||||
&CI.getInvocation(),
|
||||
&CompletionContext};
|
||||
SwiftCompletionInfo Info{CI, &CompletionContext};
|
||||
CodeCompletionResultSink ResultSink;
|
||||
DeliverTransformed(ResultType::success({ResultSink, Info, ImportDep}));
|
||||
}
|
||||
@@ -724,7 +715,7 @@ void swift::ide::CompletionInstance::typeContextInfo(
|
||||
}
|
||||
|
||||
performCodeCompletionSecondPass(
|
||||
*Result.CI.getCodeCompletionFile(), *callbacksFactory);
|
||||
*Result.CI->getCodeCompletionFile(), *callbacksFactory);
|
||||
if (!Consumer.HandleResultsCalled) {
|
||||
// If we didn't receive a handleResult call from the second
|
||||
// pass, we didn't receive any results. To make sure Callback
|
||||
@@ -792,7 +783,7 @@ void swift::ide::CompletionInstance::conformingMethodList(
|
||||
}
|
||||
|
||||
performCodeCompletionSecondPass(
|
||||
*Result.CI.getCodeCompletionFile(), *callbacksFactory);
|
||||
*Result.CI->getCodeCompletionFile(), *callbacksFactory);
|
||||
if (!Consumer.HandleResultsCalled) {
|
||||
// If we didn't receive a handleResult call from the second
|
||||
// pass, we didn't receive any results. To make sure Callback
|
||||
|
||||
@@ -824,14 +824,15 @@ void CompletionLookup::addVarDeclRef(const VarDecl *VD,
|
||||
}
|
||||
bool implicitlyAsync = false;
|
||||
analyzeActorIsolation(VD, VarType, implicitlyAsync, NotRecommended);
|
||||
if (!isForCaching() && !NotRecommended && implicitlyAsync &&
|
||||
!CanCurrDeclContextHandleAsync) {
|
||||
NotRecommended = ContextualNotRecommendedReason::InvalidAsyncContext;
|
||||
bool explicitlyAsync = false;
|
||||
if (auto accessor = VD->getEffectfulGetAccessor()) {
|
||||
explicitlyAsync = accessor->hasAsync();
|
||||
}
|
||||
|
||||
CodeCompletionResultBuilder Builder(
|
||||
Sink, CodeCompletionResultKind::Declaration,
|
||||
getSemanticContext(VD, Reason, dynamicLookupInfo));
|
||||
Builder.setIsAsync(explicitlyAsync || implicitlyAsync);
|
||||
Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
|
||||
Builder.setAssociatedDecl(VD);
|
||||
addLeadingDot(Builder);
|
||||
addValueBaseName(Builder, Name);
|
||||
@@ -1228,11 +1229,8 @@ void CompletionLookup::addFunctionCallPattern(
|
||||
else
|
||||
addTypeAnnotation(Builder, AFT->getResult(), genericSig);
|
||||
|
||||
if (!isForCaching() && AFT->hasExtInfo() && AFT->isAsync() &&
|
||||
!CanCurrDeclContextHandleAsync) {
|
||||
Builder.setContextualNotRecommended(
|
||||
ContextualNotRecommendedReason::InvalidAsyncContext);
|
||||
}
|
||||
Builder.setIsAsync(AFT->hasExtInfo() && AFT->isAsync());
|
||||
Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
|
||||
};
|
||||
|
||||
if (!AFD || !AFD->getInterfaceType()->is<AnyFunctionType>()) {
|
||||
@@ -1346,19 +1344,14 @@ void CompletionLookup::addMethodCall(const FuncDecl *FD,
|
||||
bool implictlyAsync = false;
|
||||
analyzeActorIsolation(FD, AFT, implictlyAsync, NotRecommended);
|
||||
|
||||
if (!isForCaching() && !NotRecommended &&
|
||||
!IsImplicitlyCurriedInstanceMethod &&
|
||||
((AFT && AFT->isAsync()) || implictlyAsync) &&
|
||||
!CanCurrDeclContextHandleAsync) {
|
||||
NotRecommended = ContextualNotRecommendedReason::InvalidAsyncContext;
|
||||
}
|
||||
|
||||
// Add the method, possibly including any default arguments.
|
||||
auto addMethodImpl = [&](bool includeDefaultArgs = true,
|
||||
bool trivialTrailingClosure = false) {
|
||||
CodeCompletionResultBuilder Builder(
|
||||
Sink, CodeCompletionResultKind::Declaration,
|
||||
getSemanticContext(FD, Reason, dynamicLookupInfo));
|
||||
Builder.setIsAsync(implictlyAsync || (AFT->hasExtInfo() && AFT->isAsync()));
|
||||
Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
|
||||
Builder.setAssociatedDecl(FD);
|
||||
|
||||
if (IsSuperRefExpr && CurrentMethod &&
|
||||
@@ -1547,11 +1540,9 @@ void CompletionLookup::addConstructorCall(const ConstructorDecl *CD,
|
||||
addTypeAnnotation(Builder, *Result, CD->getGenericSignatureOfContext());
|
||||
}
|
||||
|
||||
if (!isForCaching() && ConstructorType->isAsync() &&
|
||||
!CanCurrDeclContextHandleAsync) {
|
||||
Builder.setContextualNotRecommended(
|
||||
ContextualNotRecommendedReason::InvalidAsyncContext);
|
||||
}
|
||||
Builder.setIsAsync(ConstructorType->hasExtInfo() &&
|
||||
ConstructorType->isAsync());
|
||||
Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
|
||||
};
|
||||
|
||||
if (ConstructorType && shouldAddItemWithoutDefaultArgs(CD))
|
||||
@@ -1610,14 +1601,11 @@ void CompletionLookup::addSubscriptCall(const SubscriptDecl *SD,
|
||||
bool implictlyAsync = false;
|
||||
analyzeActorIsolation(SD, subscriptType, implictlyAsync, NotRecommended);
|
||||
|
||||
if (!isForCaching() && !NotRecommended && implictlyAsync &&
|
||||
!CanCurrDeclContextHandleAsync) {
|
||||
NotRecommended = ContextualNotRecommendedReason::InvalidAsyncContext;
|
||||
}
|
||||
|
||||
CodeCompletionResultBuilder Builder(
|
||||
Sink, CodeCompletionResultKind::Declaration,
|
||||
getSemanticContext(SD, Reason, dynamicLookupInfo));
|
||||
Builder.setIsAsync(implictlyAsync);
|
||||
Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
|
||||
Builder.setAssociatedDecl(SD);
|
||||
|
||||
if (NotRecommended)
|
||||
|
||||
@@ -20,12 +20,8 @@ import MyModule
|
||||
|
||||
func testSync() -> Int{
|
||||
#^GLOBAL_IN_SYNC^#
|
||||
// FIXME: 'globalAsyncFunc()' *should* be "NotRecommended" because it's 'async'
|
||||
// The curently behavior is due to completion cache. We should remember
|
||||
// 'async'-ness in the cache. (rdar://78317170)
|
||||
|
||||
// GLOBAL_IN_SYNC: Begin completions
|
||||
// GLOBAL_IN_SYNC-DAG: Decl[FreeFunction]/OtherModule[MyModule]/TypeRelation[Convertible]: globalAsyncFunc()[' async'][#Int#];
|
||||
// GLOBAL_IN_SYNC-DAG: Decl[FreeFunction]/OtherModule[MyModule]/NotRecommended/TypeRelation[Convertible]: globalAsyncFunc()[' async'][#Int#];
|
||||
// GLOBAL_IN_SYNC-DAG: Decl[FreeFunction]/OtherModule[MyModule]/NotRecommended: deprecatedFunc()[#Void#];
|
||||
// GLOBAL_IN_SYNC-DAG: Decl[Actor]/OtherModule[MyModule]: MyActor[#MyActor#];
|
||||
// GLOBAL_IN_SYNC: End completions
|
||||
|
||||
@@ -33,8 +33,31 @@ func testActor(obj: MyActor) async {
|
||||
|
||||
func testClosure(obj: (Int) async -> Void) {
|
||||
obj(#^CLOSURE_CALL^#)
|
||||
// FIXME: Emit diagnostics
|
||||
// CLOSURE_CALL: Begin completions
|
||||
// CLOSURE_CALL-DAG: Pattern/CurrModule/Flair[ArgLabels]/NotRecommended: ['(']{#Int#}[')'][' async'][#Void#]; name={{$}}
|
||||
// CLOSURE_CALL-DAG: Pattern/CurrModule/Flair[ArgLabels]/NotRecommended: ['(']{#Int#}[')'][' async'][#Void#]; name=; diagnostics=error:async function used in a context that does not support concurrency
|
||||
// CLOSURE_CALL: End completions
|
||||
}
|
||||
|
||||
func test() {
|
||||
struct Foo {
|
||||
var value: String? {
|
||||
get async { nil }
|
||||
}
|
||||
}
|
||||
|
||||
var globalValue: String? {
|
||||
get async { nil }
|
||||
}
|
||||
|
||||
let foo = Foo()
|
||||
foo.#^EXPLICITLY_ASYNC_PROPERTY^#
|
||||
// EXPLICITLY_ASYNC_PROPERTY: Begin completions
|
||||
// EXPLICITLY_ASYNC_PROPERTY-DAG: Decl[InstanceVar]/CurrNominal/NotRecommended: value[#String?#][' async']; name=value; diagnostics=error:async 'value' used in a context that does not support concurrency
|
||||
// EXPLICITLY_ASYNC_PROPERTY: End completions
|
||||
|
||||
#^EXPLICIT_GLOBAL_VAR^#
|
||||
// EXPLICIT_GLOBAL_VAR: Begin completions
|
||||
// EXPLICIT_GLOBAL_VAR-DAG: Decl[LocalVar]/Local/NotRecommended: globalValue[#String?#][' async']; name=globalValue; diagnostics=error:async 'globalValue' used in a context that does not support concurrency
|
||||
// EXPLICIT_GLOBAL_VAR: End completions
|
||||
|
||||
}
|
||||
|
||||
@@ -76,10 +76,11 @@ std::vector<Completion *> SourceKit::CodeCompletion::extendCompletions(
|
||||
const Options &options, Completion *prefix, bool clearFlair) {
|
||||
|
||||
ImportDepth depth;
|
||||
if (info.swiftASTContext) {
|
||||
if (info.compilerInstance) {
|
||||
// Build import depth map.
|
||||
depth = ImportDepth(*info.swiftASTContext,
|
||||
info.invocation->getFrontendOptions());
|
||||
depth = ImportDepth(
|
||||
info.compilerInstance->getASTContext(),
|
||||
info.compilerInstance->getInvocation().getFrontendOptions());
|
||||
}
|
||||
|
||||
if (info.completionContext)
|
||||
@@ -134,16 +135,16 @@ bool SourceKit::CodeCompletion::addCustomCompletions(
|
||||
auto *contextFreeResult =
|
||||
ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult(
|
||||
sink.swiftSink, CodeCompletionResultKind::Pattern, completionString,
|
||||
CodeCompletionOperatorKind::None, /*BriefDocComment=*/"",
|
||||
CodeCompletionResultType::unknown(),
|
||||
CodeCompletionOperatorKind::None, /*IsAsync=*/false,
|
||||
/*BriefDocComment=*/"", CodeCompletionResultType::unknown(),
|
||||
ContextFreeNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
|
||||
auto *swiftResult = new (sink.allocator) CodeCompletion::SwiftResult(
|
||||
*contextFreeResult, SemanticContextKind::Local,
|
||||
CodeCompletionFlairBit::ExpressionSpecific,
|
||||
/*NumBytesToErase=*/0, /*TypeContext=*/nullptr, /*DC=*/nullptr,
|
||||
/*USRTypeContext=*/nullptr, ContextualNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
|
||||
/*USRTypeContext=*/nullptr, /*CanCurrDeclContextHandleAsync=*/false,
|
||||
ContextualNotRecommendedReason::None);
|
||||
|
||||
CompletionBuilder builder(sink, *swiftResult);
|
||||
builder.setCustomKind(customCompletion.Kind);
|
||||
@@ -1166,15 +1167,15 @@ Completion *CompletionBuilder::finish() {
|
||||
new (sink.allocator) ContextFreeCodeCompletionResult(
|
||||
contextFreeBase.getKind(),
|
||||
contextFreeBase.getOpaqueAssociatedKind(), opKind,
|
||||
contextFreeBase.isSystem(), newCompletionString,
|
||||
contextFreeBase.getModuleName(),
|
||||
contextFreeBase.isSystem(), contextFreeBase.isAsync(),
|
||||
newCompletionString, contextFreeBase.getModuleName(),
|
||||
contextFreeBase.getBriefDocComment(),
|
||||
contextFreeBase.getAssociatedUSRs(),
|
||||
contextFreeBase.getResultType(),
|
||||
contextFreeBase.getNotRecommendedReason(),
|
||||
contextFreeBase.getDiagnosticSeverity(),
|
||||
contextFreeBase.getDiagnosticMessage(),
|
||||
newFilterName);
|
||||
contextFreeBase.getDiagnosticMessage(), newFilterName,
|
||||
contextFreeBase.getNameForDiagnostics());
|
||||
newBase = base.withContextFreeResultSemanticContextAndFlair(
|
||||
*contextFreeResult, semanticContext, flair, sink.swiftSink);
|
||||
}
|
||||
|
||||
@@ -910,6 +910,7 @@ static void transformAndForwardResults(
|
||||
ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult(
|
||||
innerSink.swiftSink, CodeCompletionResultKind::BuiltinOperator,
|
||||
completionString, CodeCompletionOperatorKind::None,
|
||||
/*IsAsync=*/false,
|
||||
/*BriefDocComment=*/"", CodeCompletionResultType::notApplicable(),
|
||||
ContextFreeNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None,
|
||||
@@ -919,8 +920,8 @@ static void transformAndForwardResults(
|
||||
CodeCompletionFlairBit::ExpressionSpecific,
|
||||
exactMatch ? exactMatch->getNumBytesToErase() : 0,
|
||||
/*TypeContext=*/nullptr, /*DC=*/nullptr, /*USRTypeContext=*/nullptr,
|
||||
ContextualNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
|
||||
/*CanCurrDeclContextHandleAsync=*/false,
|
||||
ContextualNotRecommendedReason::None);
|
||||
|
||||
SwiftCompletionInfo info;
|
||||
std::vector<Completion *> extended = extendCompletions(
|
||||
|
||||
@@ -1087,11 +1087,10 @@ doConformingMethodList(const CompilerInvocation &InitInvok,
|
||||
});
|
||||
}
|
||||
|
||||
static void
|
||||
printCodeCompletionResultsImpl(ArrayRef<CodeCompletionResult *> Results,
|
||||
llvm::raw_ostream &OS, bool IncludeKeywords,
|
||||
bool IncludeComments, bool IncludeSourceText,
|
||||
bool PrintAnnotatedDescription) {
|
||||
static void printCodeCompletionResultsImpl(
|
||||
ArrayRef<CodeCompletionResult *> Results, llvm::raw_ostream &OS,
|
||||
bool IncludeKeywords, bool IncludeComments, bool IncludeSourceText,
|
||||
bool PrintAnnotatedDescription, const ASTContext &Ctx) {
|
||||
unsigned NumResults = 0;
|
||||
for (auto Result : Results) {
|
||||
if (!IncludeKeywords &&
|
||||
@@ -1134,10 +1133,13 @@ printCodeCompletionResultsImpl(ArrayRef<CodeCompletionResult *> Results,
|
||||
OS << "; comment=" << comment;
|
||||
}
|
||||
|
||||
if (Result->getDiagnosticSeverity() !=
|
||||
SmallString<256> Scratch;
|
||||
auto DiagSeverityAndMessage =
|
||||
Result->getDiagnosticSeverityAndMessage(Scratch, Ctx);
|
||||
if (DiagSeverityAndMessage.first !=
|
||||
CodeCompletionDiagnosticSeverity::None) {
|
||||
OS << "; diagnostics=" << comment;
|
||||
switch (Result->getDiagnosticSeverity()) {
|
||||
switch (DiagSeverityAndMessage.first) {
|
||||
case CodeCompletionDiagnosticSeverity::Error:
|
||||
OS << "error";
|
||||
break;
|
||||
@@ -1153,7 +1155,8 @@ printCodeCompletionResultsImpl(ArrayRef<CodeCompletionResult *> Results,
|
||||
case CodeCompletionDiagnosticSeverity::None:
|
||||
llvm_unreachable("none");
|
||||
}
|
||||
OS << ":" << Result->getDiagnosticMessage();
|
||||
SmallString<256> Scratch;
|
||||
OS << ":" << DiagSeverityAndMessage.second;
|
||||
}
|
||||
|
||||
OS << "\n";
|
||||
@@ -1169,7 +1172,8 @@ static int printCodeCompletionResults(
|
||||
CancellableResult, [&](CodeCompleteResult &Result) {
|
||||
printCodeCompletionResultsImpl(
|
||||
Result.ResultSink.Results, llvm::outs(), IncludeKeywords,
|
||||
IncludeComments, IncludeSourceText, PrintAnnotatedDescription);
|
||||
IncludeComments, IncludeSourceText, PrintAnnotatedDescription,
|
||||
Result.Info.compilerInstance->getASTContext());
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
@@ -1545,10 +1549,11 @@ static int doBatchCodeCompletion(const CompilerInvocation &InitInvok,
|
||||
case CancellableResultKind::Success: {
|
||||
wasASTContextReused =
|
||||
Result->Info.completionContext->ReusingASTContext;
|
||||
printCodeCompletionResultsImpl(Result->ResultSink.Results, OS,
|
||||
IncludeKeywords, IncludeComments,
|
||||
IncludeSourceText,
|
||||
CodeCompletionAnnotateResults);
|
||||
printCodeCompletionResultsImpl(
|
||||
Result->ResultSink.Results, OS, IncludeKeywords,
|
||||
IncludeComments, IncludeSourceText,
|
||||
CodeCompletionAnnotateResults,
|
||||
Result->Info.compilerInstance->getASTContext());
|
||||
break;
|
||||
}
|
||||
case CancellableResultKind::Failure:
|
||||
@@ -4227,14 +4232,16 @@ int main(int argc, char *argv[]) {
|
||||
*contextFreeResult, SemanticContextKind::OtherModule,
|
||||
CodeCompletionFlair(),
|
||||
/*numBytesToErase=*/0, /*TypeContext=*/nullptr, /*DC=*/nullptr,
|
||||
/*USRTypeContext=*/nullptr, ContextualNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
|
||||
/*USRTypeContext=*/nullptr, /*CanCurrDeclContextHandleAsync=*/false,
|
||||
ContextualNotRecommendedReason::None);
|
||||
contextualResults.push_back(contextualResult);
|
||||
}
|
||||
auto CompInstance = std::make_unique<CompilerInstance>();
|
||||
printCodeCompletionResultsImpl(
|
||||
contextualResults, llvm::outs(), options::CodeCompletionKeywords,
|
||||
options::CodeCompletionComments, options::CodeCompletionSourceText,
|
||||
options::CodeCompletionAnnotateResults);
|
||||
options::CodeCompletionAnnotateResults,
|
||||
CompInstance->getASTContext());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user