mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[CodeCompletion] Lazily compute contextual diagnostics
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
|
||||
|
||||
@@ -341,6 +341,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
|
||||
@@ -361,13 +365,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) {
|
||||
DiagnosticMessage(DiagnosticMessage), FilterName(FilterName),
|
||||
NameForDiagnostics(NameForDiagnostics) {
|
||||
this->AssociatedKind.Opaque = AssociatedKind;
|
||||
assert((NotRecommended == ContextFreeNotRecommendedReason::None) ==
|
||||
(DiagnosticSeverity == CodeCompletionDiagnosticSeverity::None) &&
|
||||
@@ -491,6 +497,10 @@ public:
|
||||
|
||||
NullTerminatedStringRef getFilterName() const { return FilterName; }
|
||||
|
||||
NullTerminatedStringRef getNameForDiagnostics() const {
|
||||
return NameForDiagnostics;
|
||||
}
|
||||
|
||||
bool isOperator() const {
|
||||
if (getKind() == CodeCompletionResultKind::Declaration) {
|
||||
switch (getAssociatedDeclKind()) {
|
||||
@@ -528,11 +538,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.
|
||||
@@ -553,14 +558,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
|
||||
@@ -578,9 +579,7 @@ public:
|
||||
const ExpectedTypeContext *TypeContext,
|
||||
const DeclContext *DC,
|
||||
const USRBasedTypeContext *USRTypeContext,
|
||||
ContextualNotRecommendedReason NotRecommended,
|
||||
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
|
||||
NullTerminatedStringRef DiagnosticMessage);
|
||||
ContextualNotRecommendedReason NotRecommended);
|
||||
|
||||
const ContextFreeCodeCompletionResult &getContextFreeResult() const {
|
||||
return ContextFree;
|
||||
@@ -699,37 +698,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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 =
|
||||
8; // Store name for diagnostics
|
||||
|
||||
/// Deserializes CodeCompletionResults from \p in and stores them in \p V.
|
||||
/// \see writeCacheModule.
|
||||
@@ -239,6 +240,7 @@ static bool readCachedModule(llvm::MemoryBuffer *in,
|
||||
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 +260,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,
|
||||
briefDocComment, makeArrayRef(assocUSRs).copy(*V.Allocator),
|
||||
CodeCompletionResultType(resultTypes), notRecommended, diagSeverity,
|
||||
diagMessage, filterName);
|
||||
diagMessage, filterName, nameForDiagnostics);
|
||||
|
||||
V.Results.push_back(result);
|
||||
}
|
||||
@@ -426,6 +429,7 @@ static void writeCachedModule(llvm::raw_ostream &out,
|
||||
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) {
|
||||
|
||||
@@ -87,8 +87,7 @@ static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
|
||||
*contextFreeResult, SemanticContextKind::OtherModule,
|
||||
CodeCompletionFlair(),
|
||||
/*numBytesToErase=*/0, TypeContext, DC, &USRTypeContext,
|
||||
ContextualNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
|
||||
ContextualNotRecommendedReason::None);
|
||||
targetSink.Results.push_back(contextualResult);
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -34,12 +35,19 @@ 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,
|
||||
/*AssociatedUSRs=*/{}, ResultType, NotRecommended, DiagnosticSeverity,
|
||||
DiagnosticMessage,
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()));
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
|
||||
NameForDiagnostics);
|
||||
}
|
||||
|
||||
ContextFreeCodeCompletionResult *
|
||||
@@ -57,7 +65,8 @@ ContextFreeCodeCompletionResult::createKeywordResult(
|
||||
/*ModuleName=*/"", BriefDocComment,
|
||||
/*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"",
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()));
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
|
||||
/*NameForDiagnostics=*/"");
|
||||
}
|
||||
|
||||
ContextFreeCodeCompletionResult *
|
||||
@@ -75,7 +84,23 @@ ContextFreeCodeCompletionResult::createLiteralResult(
|
||||
/*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;
|
||||
NameOS << VD->getName().getString(Scratch);
|
||||
NameOS << "'";
|
||||
return NullTerminatedStringRef(NameOS.str(), Sink.getAllocator());
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
ContextFreeCodeCompletionResult *
|
||||
@@ -98,7 +123,8 @@ ContextFreeCodeCompletionResult::createDeclResult(
|
||||
CodeCompletionOperatorKind::None, getDeclIsSystem(AssociatedDecl),
|
||||
CompletionString, ModuleName, BriefDocComment, AssociatedUSRs, ResultType,
|
||||
NotRecommended, DiagnosticSeverity, DiagnosticMessage,
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()));
|
||||
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
|
||||
/*NameForDiagnostics=*/getDeclNameForDiagnostics(AssociatedDecl, Sink));
|
||||
}
|
||||
|
||||
CodeCompletionOperatorKind
|
||||
@@ -267,22 +293,19 @@ CodeCompletionResult::CodeCompletionResult(
|
||||
SemanticContextKind SemanticContext, CodeCompletionFlair Flair,
|
||||
uint8_t NumBytesToErase, const ExpectedTypeContext *TypeContext,
|
||||
const DeclContext *DC, const USRBasedTypeContext *USRTypeContext,
|
||||
ContextualNotRecommendedReason NotRecommended,
|
||||
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
|
||||
NullTerminatedStringRef DiagnosticMessage)
|
||||
ContextualNotRecommendedReason NotRecommended)
|
||||
: ContextFree(ContextFree), SemanticContext(SemanticContext),
|
||||
Flair(Flair.toRaw()), NotRecommended(NotRecommended),
|
||||
DiagnosticSeverity(DiagnosticSeverity),
|
||||
DiagnosticMessage(DiagnosticMessage), NumBytesToErase(NumBytesToErase),
|
||||
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 +313,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 {
|
||||
|
||||
@@ -164,35 +164,8 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
|
||||
*ContextFreeResult, SemanticContextKind::None, CodeCompletionFlair(),
|
||||
/*NumBytesToErase=*/0, /*TypeContext=*/nullptr,
|
||||
/*DC=*/nullptr, /*USRTypeContext=*/nullptr,
|
||||
ContextualNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, "");
|
||||
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 +175,7 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
|
||||
// for USRTypeContext.
|
||||
return new (Allocator) CodeCompletionResult(
|
||||
*ContextFreeResult, SemanticContext, Flair, NumBytesToErase,
|
||||
TypeContext, DC, /*USRTypeContext=*/nullptr, ContextualNotRecReason,
|
||||
ContextualDiagnosticSeverity, ContextualDiagnosticMessage);
|
||||
TypeContext, DC, /*USRTypeContext=*/nullptr, ContextualNotRecReason);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,8 +33,7 @@ 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
|
||||
}
|
||||
|
||||
@@ -142,8 +142,7 @@ bool SourceKit::CodeCompletion::addCustomCompletions(
|
||||
*contextFreeResult, SemanticContextKind::Local,
|
||||
CodeCompletionFlairBit::ExpressionSpecific,
|
||||
/*NumBytesToErase=*/0, /*TypeContext=*/nullptr, /*DC=*/nullptr,
|
||||
/*USRTypeContext=*/nullptr, ContextualNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
|
||||
/*USRTypeContext=*/nullptr, ContextualNotRecommendedReason::None);
|
||||
|
||||
CompletionBuilder builder(sink, *swiftResult);
|
||||
builder.setCustomKind(customCompletion.Kind);
|
||||
@@ -1173,8 +1172,8 @@ Completion *CompletionBuilder::finish() {
|
||||
contextFreeBase.getResultType(),
|
||||
contextFreeBase.getNotRecommendedReason(),
|
||||
contextFreeBase.getDiagnosticSeverity(),
|
||||
contextFreeBase.getDiagnosticMessage(),
|
||||
newFilterName);
|
||||
contextFreeBase.getDiagnosticMessage(), newFilterName,
|
||||
contextFreeBase.getNameForDiagnostics());
|
||||
newBase = base.withContextFreeResultSemanticContextAndFlair(
|
||||
*contextFreeResult, semanticContext, flair, sink.swiftSink);
|
||||
}
|
||||
|
||||
@@ -919,8 +919,7 @@ static void transformAndForwardResults(
|
||||
CodeCompletionFlairBit::ExpressionSpecific,
|
||||
exactMatch ? exactMatch->getNumBytesToErase() : 0,
|
||||
/*TypeContext=*/nullptr, /*DC=*/nullptr, /*USRTypeContext=*/nullptr,
|
||||
ContextualNotRecommendedReason::None,
|
||||
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
|
||||
ContextualNotRecommendedReason::None);
|
||||
|
||||
SwiftCompletionInfo info;
|
||||
std::vector<Completion *> extended = extendCompletions(
|
||||
|
||||
@@ -1082,11 +1082,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 &&
|
||||
@@ -1129,10 +1128,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;
|
||||
@@ -1148,7 +1150,8 @@ printCodeCompletionResultsImpl(ArrayRef<CodeCompletionResult *> Results,
|
||||
case CodeCompletionDiagnosticSeverity::None:
|
||||
llvm_unreachable("none");
|
||||
}
|
||||
OS << ":" << Result->getDiagnosticMessage();
|
||||
SmallString<256> Scratch;
|
||||
OS << ":" << DiagSeverityAndMessage.second;
|
||||
}
|
||||
|
||||
OS << "\n";
|
||||
@@ -1164,7 +1167,8 @@ static int printCodeCompletionResults(
|
||||
CancellableResult, [&](CodeCompleteResult &Result) {
|
||||
printCodeCompletionResultsImpl(
|
||||
Result.ResultSink.Results, llvm::outs(), IncludeKeywords,
|
||||
IncludeComments, IncludeSourceText, PrintAnnotatedDescription);
|
||||
IncludeComments, IncludeSourceText, PrintAnnotatedDescription,
|
||||
*Result.Info.swiftASTContext);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
@@ -1540,10 +1544,10 @@ 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.swiftASTContext);
|
||||
break;
|
||||
}
|
||||
case CancellableResultKind::Failure:
|
||||
@@ -4222,14 +4226,15 @@ 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, 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