[CodeCompletion] Lazily compute contextual diagnostics

This commit is contained in:
Alex Hoppen
2022-07-21 14:19:48 +02:00
parent 341bc34fe8
commit 9fc850abed
12 changed files with 145 additions and 137 deletions

View File

@@ -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

View File

@@ -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());
}
}

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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");
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -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);
}
}

View File

@@ -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
}

View File

@@ -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);
}

View File

@@ -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(

View File

@@ -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;