Skip to content

Commit e5d913b

Browse files
authored
Merge pull request #15782 from benlangmuir/invalid-diag-loc-note
[sourcekitd] Capture diagnostics with invalid locations for compile notifications
2 parents c35d508 + 969f0f4 commit e5d913b

File tree

3 files changed

+68
-34
lines changed

3 files changed

+68
-34
lines changed

test/SourceKit/CompileNotifications/diagnostics.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,28 @@
3939
// CLANG_IMPORTER-NEXT: key.severity: source.diagnostic.severity.error,
4040
// CLANG_IMPORTER-NEXT: key.description: {{.*}}not found
4141

42+
// RUN: %sourcekitd-test -req=track-compiles == -req=sema %s -- %s -Xcc -ivfsoverlay -Xcc /doesnotexist | %FileCheck %s -check-prefix=CLANG_IMPORTER_UNKNOWN
43+
// CLANG_IMPORTER_UNKNOWN: key.notification: source.notification.compile-did-finish,
44+
// CLANG_IMPORTER_UNKNOWN-NEXT: key.diagnostics: [
45+
// CLANG_IMPORTER_UNKNOWN-NEXT: {
46+
// CLANG_IMPORTER_UNKNOWN-NEXT: key.filepath: "<unknown>"
47+
// CLANG_IMPORTER_UNKNOWN-NEXT: key.severity: source.diagnostic.severity.error,
48+
// CLANG_IMPORTER_UNKNOWN-NEXT: key.offset: 0
49+
// CLANG_IMPORTER_UNKNOWN-NEXT: key.description: "virtual filesystem{{.*}}not found
50+
4251
// Note: we're missing the "compiler is in code completion mode" diagnostic,
4352
// which is probably just as well.
4453
// RUN: %sourcekitd-test -req=track-compiles == -req=complete -offset=0 %s -- %s | %FileCheck %s -check-prefix=NODIAGS
4554
// RUN: %sourcekitd-test -req=track-compiles == -req=complete -pos=2:1 %S/Inputs/sema-error.swift -- %S/Inputs/sema-error.swift | %FileCheck %s -check-prefix=SEMA
55+
56+
// FIXME: invalid arguments cause us to early-exit and not send the notifications
57+
// RUN_DISABLED: %sourcekitd-test -req=track-compiles == -req=sema %s -- %s -invalid-arg | %FileCheck %s -check-prefix=INVALID_ARG
58+
59+
// RUN: %sourcekitd-test -req=track-compiles == -req=sema %s -- %s -Xcc -invalid-arg | %FileCheck %s -check-prefix=INVALID_ARG_CLANG
60+
// INVALID_ARG_CLANG: key.notification: source.notification.compile-did-finish,
61+
// INVALID_ARG_CLANG-NEXT: key.diagnostics: [
62+
// INVALID_ARG_CLANG-NEXT: {
63+
// INVALID_ARG_CLANG-NEXT: key.filepath: "<unknown>"
64+
// INVALID_ARG_CLANG-NEXT: key.severity: source.diagnostic.severity.warning,
65+
// INVALID_ARG_CLANG-NEXT: key.offset: 0
66+
// INVALID_ARG_CLANG-NEXT: key.description: "argument unused

tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "swift/AST/ASTWalker.h"
2626
#include "swift/AST/DiagnosticsClangImporter.h"
2727
#include "swift/AST/DiagnosticsParse.h"
28+
#include "swift/AST/DiagnosticsFrontend.h"
2829
#include "swift/Basic/SourceManager.h"
2930
#include "swift/Demangling/ManglingUtils.h"
3031
#include "swift/Frontend/Frontend.h"
@@ -59,6 +60,9 @@ static std::vector<unsigned> getSortedBufferIDs(
5960

6061
void EditorDiagConsumer::getAllDiagnostics(
6162
SmallVectorImpl<DiagnosticEntryInfo> &Result) {
63+
64+
Result.append(InvalidLocDiagnostics.begin(), InvalidLocDiagnostics.end());
65+
6266
// Note: we cannot reuse InputBufIds because there may be diagnostics outside
6367
// the inputs. Instead, sort the extant buffers.
6468
auto bufferIDs = getSortedBufferIDs(BufferDiagnostics);
@@ -77,16 +81,11 @@ void EditorDiagConsumer::handleDiagnostic(
7781
HadAnyError = true;
7882
}
7983

80-
// Filter out lexer errors for placeholders.
81-
if (Info.ID == diag::lex_editor_placeholder.ID)
84+
// Filter out benign diagnostics for editing.
85+
if (Info.ID == diag::lex_editor_placeholder.ID ||
86+
Info.ID == diag::error_doing_code_completion.ID)
8287
return;
8388

84-
if (Loc.isInvalid()) {
85-
if (Kind == DiagnosticKind::Error)
86-
HadInvalidLocError = true;
87-
clearLastDiag();
88-
return;
89-
}
9089
bool IsNote = (Kind == DiagnosticKind::Note);
9190

9291
if (IsNote && !haveLastDiag())
@@ -109,9 +108,12 @@ void EditorDiagConsumer::handleDiagnostic(
109108
}
110109
SKInfo.Description = Text.str();
111110

112-
unsigned BufferID = SM.findBufferContainingLoc(Loc);
111+
Optional<unsigned> BufferIDOpt;
112+
if (Loc.isValid()) {
113+
BufferIDOpt = SM.findBufferContainingLoc(Loc);
114+
}
113115

114-
if (!isInputBufferID(BufferID)) {
116+
if (BufferIDOpt && !isInputBufferID(*BufferIDOpt)) {
115117
if (Info.ID == diag::error_from_clang.ID ||
116118
Info.ID == diag::warning_from_clang.ID ||
117119
Info.ID == diag::note_from_clang.ID ||
@@ -127,7 +129,7 @@ void EditorDiagConsumer::handleDiagnostic(
127129
// buffer identifier and append it to the diagnostic message.
128130
auto &LastDiag = getLastDiag();
129131
SKInfo.Description += " (";
130-
SKInfo.Description += SM.getIdentifierForBuffer(BufferID);
132+
SKInfo.Description += SM.getIdentifierForBuffer(*BufferIDOpt);
131133
SKInfo.Description += ")";
132134
SKInfo.Offset = LastDiag.Offset;
133135
SKInfo.Line = LastDiag.Line;
@@ -138,35 +140,39 @@ void EditorDiagConsumer::handleDiagnostic(
138140
}
139141
}
140142

141-
SKInfo.Offset = SM.getLocOffsetInBuffer(Loc, BufferID);
142-
std::tie(SKInfo.Line, SKInfo.Column) = SM.getLineAndColumn(Loc, BufferID);
143-
SKInfo.Filename = SM.getIdentifierForBuffer(BufferID);
143+
if (BufferIDOpt.hasValue()) {
144+
unsigned BufferID = *BufferIDOpt;
144145

145-
for (auto R : Info.Ranges) {
146-
if (R.isInvalid() || SM.findBufferContainingLoc(R.getStart()) != BufferID)
147-
continue;
148-
unsigned Offset = SM.getLocOffsetInBuffer(R.getStart(), BufferID);
149-
unsigned Length = R.getByteLength();
150-
SKInfo.Ranges.push_back({ Offset, Length });
151-
}
146+
SKInfo.Offset = SM.getLocOffsetInBuffer(Loc, BufferID);
147+
std::tie(SKInfo.Line, SKInfo.Column) = SM.getLineAndColumn(Loc, BufferID);
148+
SKInfo.Filename = SM.getIdentifierForBuffer(BufferID);
152149

153-
for (auto F : Info.FixIts) {
154-
if (F.getRange().isInvalid() ||
155-
SM.findBufferContainingLoc(F.getRange().getStart()) != BufferID)
156-
continue;
157-
unsigned Offset = SM.getLocOffsetInBuffer(F.getRange().getStart(),
158-
BufferID);
159-
unsigned Length = F.getRange().getByteLength();
160-
SKInfo.Fixits.push_back({ Offset, Length, F.getText() });
150+
for (auto R : Info.Ranges) {
151+
if (R.isInvalid() || SM.findBufferContainingLoc(R.getStart()) != BufferID)
152+
continue;
153+
unsigned Offset = SM.getLocOffsetInBuffer(R.getStart(), BufferID);
154+
unsigned Length = R.getByteLength();
155+
SKInfo.Ranges.push_back({Offset, Length});
156+
}
157+
158+
for (auto F : Info.FixIts) {
159+
if (F.getRange().isInvalid() ||
160+
SM.findBufferContainingLoc(F.getRange().getStart()) != BufferID)
161+
continue;
162+
unsigned Offset =
163+
SM.getLocOffsetInBuffer(F.getRange().getStart(), BufferID);
164+
unsigned Length = F.getRange().getByteLength();
165+
SKInfo.Fixits.push_back({Offset, Length, F.getText()});
166+
}
167+
} else {
168+
SKInfo.Filename = "<unknown>";
161169
}
162170

163171
if (IsNote) {
164172
getLastDiag().Notes.push_back(std::move(SKInfo));
165173
return;
166174
}
167175

168-
DiagnosticsTy &Diagnostics = BufferDiagnostics[BufferID];
169-
170176
switch (Kind) {
171177
case DiagnosticKind::Error:
172178
SKInfo.Severity = DiagnosticSeverityKind::Error;
@@ -179,6 +185,15 @@ void EditorDiagConsumer::handleDiagnostic(
179185
llvm_unreachable("already covered");
180186
}
181187

188+
if (!BufferIDOpt) {
189+
InvalidLocDiagnostics.push_back(std::move(SKInfo));
190+
clearLastDiag();
191+
return;
192+
}
193+
194+
unsigned BufferID = *BufferIDOpt;
195+
DiagnosticsTy &Diagnostics = BufferDiagnostics[BufferID];
196+
182197
if (Diagnostics.empty() || Diagnostics.back().Offset <= SKInfo.Offset) {
183198
Diagnostics.push_back(std::move(SKInfo));
184199
LastDiagBufferID = BufferID;

tools/SourceKit/lib/SwiftLang/SwiftEditorDiagConsumer.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class EditorDiagConsumer : public swift::DiagnosticConsumer {
2424
/// Maps from a BufferID to the diagnostics that were emitted inside that
2525
/// buffer.
2626
llvm::DenseMap<unsigned, DiagnosticsTy> BufferDiagnostics;
27+
DiagnosticsTy InvalidLocDiagnostics;
2728

2829
SmallVector<unsigned, 8> InputBufIDs;
2930
int LastDiagBufferID = -1;
@@ -40,7 +41,6 @@ class EditorDiagConsumer : public swift::DiagnosticConsumer {
4041
return BufferDiagnostics[LastDiagBufferID][LastDiagIndex];
4142
}
4243

43-
bool HadInvalidLocError = false;
4444
bool HadAnyError = false;
4545

4646
public:
@@ -64,8 +64,6 @@ class EditorDiagConsumer : public swift::DiagnosticConsumer {
6464

6565
void getAllDiagnostics(SmallVectorImpl<DiagnosticEntryInfo> &Result);
6666

67-
bool hadErrorWithInvalidLoc() const { return HadInvalidLocError; }
68-
6967
bool hadAnyError() const { return HadAnyError; }
7068

7169
void handleDiagnostic(swift::SourceManager &SM, swift::SourceLoc Loc,

0 commit comments

Comments
 (0)