Skip to content

Commit ed1db1b

Browse files
committed
[CodeCompletion] Explain why results aren't recommended
* Implement 'getDiagnosticSeverity()' and 'getDiagnosticMessage()' on 'CodeCompletionResult' * Differentiate 'RedundantImportIndirect' from 'RedundantImport' * Make non-Sendable check respects '-warn-concurrency' rdar://76129658
1 parent f8751d4 commit ed1db1b

18 files changed

+528
-59
lines changed

include/swift/AST/DiagnosticEngine.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,8 @@ namespace swift {
11161116
void emitTentativeDiagnostics();
11171117

11181118
public:
1119+
DiagnosticKind declaredDiagnosticKindFor(const DiagID id);
1120+
11191121
llvm::StringRef diagnosticStringFor(const DiagID id,
11201122
bool printDiagnosticNames);
11211123

@@ -1313,6 +1315,26 @@ namespace swift {
13131315
builder();
13141316
}
13151317

1318+
/// Temporary on-stack storage and unescaping for encoded diagnostic
1319+
/// messages.
1320+
class EncodedDiagnosticMessage {
1321+
llvm::SmallString<128> Buf;
1322+
1323+
public:
1324+
/// \param S A string with an encoded message
1325+
EncodedDiagnosticMessage(StringRef S);
1326+
1327+
/// The unescaped message to display to the user.
1328+
const StringRef Message;
1329+
};
1330+
1331+
/// Returns a value that can be used to select between accessor kinds in
1332+
/// diagnostics.
1333+
///
1334+
/// This is correlated with diag::availability_deprecated and others.
1335+
std::pair<unsigned, DeclName>
1336+
getAccessorKindAndNameForDiagnostics(const ValueDecl *D);
1337+
13161338
} // end namespace swift
13171339

13181340
#endif

include/swift/AST/DiagnosticsAll.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define DIAG_NO_UNDEF
2121

2222
#include "DiagnosticsCommon.def"
23+
#include "DiagnosticsIDE.def"
2324
#include "DiagnosticsParse.def"
2425
#include "DiagnosticsSema.def"
2526
#include "DiagnosticsClangImporter.def"

include/swift/AST/DiagnosticsIDE.def

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===--- DiagnosticsIDE.def - Diagnostics Text ------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#define DEFINE_DIAGNOSTIC_MACROS
14+
#include "DefineDiagnosticMacros.h"
15+
16+
//===----------------------------------------------------------------------===//
17+
18+
ERROR(ide_async_in_nonasync_context, none,
19+
"async %0 used in a context that does not support concurrency",
20+
(DeclName))
21+
22+
// NOTE: This is WARNING because this is emitted for cross actor references with
23+
// non-'Sendable' types. That is optionally ('-warn-concurrency') warning in
24+
// Swift 5.5.
25+
WARNING(ide_cross_actor_reference_swift5, none,
26+
"actor-isolated %0 should only be referenced from inside the actor",
27+
(DeclName))
28+
29+
WARNING(ide_redundant_import, none,
30+
"module %0 is already imported", (DeclName))
31+
32+
// FIXME: Inform which other 'import' this module came from.
33+
NOTE(ide_redundant_import_indirect, none,
34+
"module %0 is already imported via another module import", (DeclName))
35+
36+
//===----------------------------------------------------------------------===//
37+
38+
#define UNDEFINE_DIAGNOSTIC_MACROS
39+
#include "DefineDiagnosticMacros.h"

include/swift/AST/DiagnosticsIDE.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===--- DiagnosticsIDE.h - Diagnostic Definitions --------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
/// \file
14+
/// This file defines diagnostics used only in IDE.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef SWIFT_DIAGNOSTICSIDE_H
19+
#define SWIFT_DIAGNOSTICSIDE_H
20+
21+
#include "swift/AST/DiagnosticsCommon.h"
22+
23+
namespace swift {
24+
namespace diag {
25+
// Declare common diagnostics objects with their appropriate types.
26+
#define DIAG(KIND,ID,Options,Text,Signature) \
27+
extern detail::DiagWithArguments<void Signature>::type ID;
28+
#include "DiagnosticsIDE.def"
29+
}
30+
}
31+
32+
#endif

include/swift/IDE/CodeCompletion.h

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,14 @@ enum class CompletionKind {
568568
TypeAttrBeginning,
569569
};
570570

571+
enum class CodeCompletionDiagnosticSeverity: uint8_t {
572+
None,
573+
Error,
574+
Warning,
575+
Remark,
576+
Note,
577+
};
578+
571579
/// A single code completion result.
572580
class CodeCompletionResult {
573581
friend class CodeCompletionResultBuilder;
@@ -607,6 +615,7 @@ class CodeCompletionResult {
607615
enum class NotRecommendedReason {
608616
None = 0,
609617
RedundantImport,
618+
RedundantImportIndirect,
610619
Deprecated,
611620
InvalidAsyncContext,
612621
CrossActorReference,
@@ -638,6 +647,8 @@ class CodeCompletionResult {
638647
ArrayRef<StringRef> AssociatedUSRs;
639648
ArrayRef<std::pair<StringRef, StringRef>> DocWords;
640649
unsigned TypeDistance : 3;
650+
unsigned DiagnosticSeverity: 3;
651+
StringRef DiagnosticMessage;
641652

642653
public:
643654
/// Constructs a \c Pattern, \c Keyword or \c BuiltinOperator result.
@@ -664,6 +675,7 @@ class CodeCompletionResult {
664675
getOperatorKind() != CodeCompletionOperatorKind::None);
665676
AssociatedKind = 0;
666677
IsSystem = 0;
678+
DiagnosticSeverity = 0;
667679
}
668680

669681
/// Constructs a \c Keyword result.
@@ -684,6 +696,7 @@ class CodeCompletionResult {
684696
assert(CompletionString);
685697
AssociatedKind = static_cast<unsigned>(Kind);
686698
IsSystem = 0;
699+
DiagnosticSeverity = 0;
687700
}
688701

689702
/// Constructs a \c Literal result.
@@ -701,6 +714,7 @@ class CodeCompletionResult {
701714
TypeDistance(TypeDistance) {
702715
AssociatedKind = static_cast<unsigned>(LiteralKind);
703716
IsSystem = 0;
717+
DiagnosticSeverity = 0;
704718
assert(CompletionString);
705719
}
706720

@@ -728,6 +742,7 @@ class CodeCompletionResult {
728742
assert(AssociatedDecl && "should have a decl");
729743
AssociatedKind = unsigned(getCodeCompletionDeclKind(AssociatedDecl));
730744
IsSystem = getDeclIsSystem(AssociatedDecl);
745+
DiagnosticSeverity = 0;
731746
assert(CompletionString);
732747
if (isOperator())
733748
KnownOperatorKind =
@@ -743,20 +758,22 @@ class CodeCompletionResult {
743758
CodeCompletionDeclKind DeclKind, bool IsSystem,
744759
StringRef ModuleName, StringRef SourceFilePath,
745760
CodeCompletionResult::NotRecommendedReason NotRecReason,
746-
StringRef BriefDocComment,
761+
CodeCompletionDiagnosticSeverity diagSeverity,
762+
StringRef DiagnosticMessage, StringRef BriefDocComment,
747763
ArrayRef<StringRef> AssociatedUSRs,
748764
ArrayRef<std::pair<StringRef, StringRef>> DocWords,
749765
ExpectedTypeRelation TypeDistance,
750766
CodeCompletionOperatorKind KnownOperatorKind)
751767
: Kind(ResultKind::Declaration),
752768
KnownOperatorKind(unsigned(KnownOperatorKind)),
753-
SemanticContext(unsigned(SemanticContext)),
754-
Flair(unsigned(Flair.toRaw())), NotRecommended(unsigned(NotRecReason)),
755-
IsSystem(IsSystem), NumBytesToErase(NumBytesToErase),
756-
CompletionString(CompletionString), ModuleName(ModuleName),
757-
SourceFilePath(SourceFilePath), BriefDocComment(BriefDocComment),
758-
AssociatedUSRs(AssociatedUSRs), DocWords(DocWords),
759-
TypeDistance(TypeDistance) {
769+
SemanticContext(unsigned(SemanticContext)), Flair(unsigned(Flair.toRaw())),
770+
NotRecommended(unsigned(NotRecReason)), IsSystem(IsSystem),
771+
NumBytesToErase(NumBytesToErase), CompletionString(CompletionString),
772+
ModuleName(ModuleName), SourceFilePath(SourceFilePath),
773+
BriefDocComment(BriefDocComment), AssociatedUSRs(AssociatedUSRs),
774+
DocWords(DocWords), TypeDistance(TypeDistance),
775+
DiagnosticSeverity(unsigned(diagSeverity)),
776+
DiagnosticMessage(DiagnosticMessage) {
760777
AssociatedKind = static_cast<unsigned>(DeclKind);
761778
assert(CompletionString);
762779
assert(!isOperator() ||
@@ -859,6 +876,19 @@ class CodeCompletionResult {
859876
SourceFilePath = value;
860877
}
861878

879+
void setDiagnostics(CodeCompletionDiagnosticSeverity severity, StringRef message) {
880+
DiagnosticSeverity = static_cast<unsigned>(severity);
881+
DiagnosticMessage = message;
882+
}
883+
884+
CodeCompletionDiagnosticSeverity getDiagnosticSeverity() const {
885+
return static_cast<CodeCompletionDiagnosticSeverity>(DiagnosticSeverity);
886+
}
887+
888+
StringRef getDiagnosticMessage() const {
889+
return DiagnosticMessage;
890+
}
891+
862892
/// Returns the source file path where the associated decl was declared.
863893
/// Returns an empty string if the information is not available.
864894
StringRef getSourceFilePath() const {

include/swift/Parse/Lexer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ class Lexer {
448448
/// the byte content.
449449
///
450450
/// If a copy needs to be made, it will be allocated out of the provided
451-
/// \p Buffer.
451+
/// \p Buffer. If \p IndentToStrip is '~0U', the indent is auto-detected.
452452
static StringRef getEncodedStringSegment(StringRef Str,
453453
SmallVectorImpl<char> &Buffer,
454454
bool IsFirstSegment = false,

lib/AST/DiagnosticEngine.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,10 @@ void DiagnosticEngine::emitDiagnostic(const Diagnostic &diagnostic) {
12441244
emitDiagnostic(childNote);
12451245
}
12461246

1247+
DiagnosticKind DiagnosticEngine::declaredDiagnosticKindFor(const DiagID id) {
1248+
return storedDiagnosticInfos[(unsigned)id].kind;
1249+
}
1250+
12471251
llvm::StringRef
12481252
DiagnosticEngine::diagnosticStringFor(const DiagID id,
12491253
bool printDiagnosticNames) {
@@ -1322,3 +1326,24 @@ void DiagnosticEngine::onTentativeDiagnosticFlush(Diagnostic &diagnostic) {
13221326
argument = DiagnosticArgument(StringRef(I->getKeyData()));
13231327
}
13241328
}
1329+
1330+
EncodedDiagnosticMessage::EncodedDiagnosticMessage(StringRef S)
1331+
: Message(Lexer::getEncodedStringSegment(S, Buf, /*IsFirstSegment=*/true,
1332+
/*IsLastSegment=*/true,
1333+
/*IndentToStrip=*/~0U)) {}
1334+
1335+
std::pair<unsigned, DeclName>
1336+
swift::getAccessorKindAndNameForDiagnostics(const ValueDecl *D) {
1337+
// This should always be one more than the last AccessorKind supported in
1338+
// the diagnostics. If you need to change it, change the assertion below as
1339+
// well.
1340+
static const unsigned NOT_ACCESSOR_INDEX = 2;
1341+
1342+
if (auto *accessor = dyn_cast<AccessorDecl>(D)) {
1343+
DeclName Name = accessor->getStorage()->getName();
1344+
assert(accessor->isGetterOrSetter());
1345+
return {static_cast<unsigned>(accessor->getAccessorKind()), Name};
1346+
}
1347+
1348+
return {NOT_ACCESSOR_INDEX, D->getName()};
1349+
}

lib/IDE/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
add_swift_host_library(swiftIDE STATIC
33
CodeCompletion.cpp
44
CodeCompletionCache.cpp
5+
CodeCompletionDiagnostics.cpp
56
CodeCompletionResultPrinter.cpp
67
CommentConversion.cpp
78
CompletionInstance.cpp

0 commit comments

Comments
 (0)