Skip to content

Commit 969f0f4

Browse files
committed
[sourcekitd] Capture diagnostics with invalid locations for compile notifications
Stop filtering out diagnostics with invalid locations in the editor diagnostic consumer, and instead capture them separately so that we can include them in did-compile notifications. rdar://39225000
1 parent cc51a87 commit 969f0f4

File tree

3 files changed

+68
-29
lines changed

3 files changed

+68
-29
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 & 29 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,14 +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-
clearLastDiag();
86-
return;
87-
}
8889
bool IsNote = (Kind == DiagnosticKind::Note);
8990

9091
if (IsNote && !haveLastDiag())
@@ -107,9 +108,12 @@ void EditorDiagConsumer::handleDiagnostic(
107108
}
108109
SKInfo.Description = Text.str();
109110

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

112-
if (!isInputBufferID(BufferID)) {
116+
if (BufferIDOpt && !isInputBufferID(*BufferIDOpt)) {
113117
if (Info.ID == diag::error_from_clang.ID ||
114118
Info.ID == diag::warning_from_clang.ID ||
115119
Info.ID == diag::note_from_clang.ID ||
@@ -125,7 +129,7 @@ void EditorDiagConsumer::handleDiagnostic(
125129
// buffer identifier and append it to the diagnostic message.
126130
auto &LastDiag = getLastDiag();
127131
SKInfo.Description += " (";
128-
SKInfo.Description += SM.getIdentifierForBuffer(BufferID);
132+
SKInfo.Description += SM.getIdentifierForBuffer(*BufferIDOpt);
129133
SKInfo.Description += ")";
130134
SKInfo.Offset = LastDiag.Offset;
131135
SKInfo.Line = LastDiag.Line;
@@ -136,35 +140,39 @@ void EditorDiagConsumer::handleDiagnostic(
136140
}
137141
}
138142

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

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

151-
for (auto F : Info.FixIts) {
152-
if (F.getRange().isInvalid() ||
153-
SM.findBufferContainingLoc(F.getRange().getStart()) != BufferID)
154-
continue;
155-
unsigned Offset = SM.getLocOffsetInBuffer(F.getRange().getStart(),
156-
BufferID);
157-
unsigned Length = F.getRange().getByteLength();
158-
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>";
159169
}
160170

161171
if (IsNote) {
162172
getLastDiag().Notes.push_back(std::move(SKInfo));
163173
return;
164174
}
165175

166-
DiagnosticsTy &Diagnostics = BufferDiagnostics[BufferID];
167-
168176
switch (Kind) {
169177
case DiagnosticKind::Error:
170178
SKInfo.Severity = DiagnosticSeverityKind::Error;
@@ -177,6 +185,15 @@ void EditorDiagConsumer::handleDiagnostic(
177185
llvm_unreachable("already covered");
178186
}
179187

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+
180197
if (Diagnostics.empty() || Diagnostics.back().Offset <= SKInfo.Offset) {
181198
Diagnostics.push_back(std::move(SKInfo));
182199
LastDiagBufferID = BufferID;

tools/SourceKit/lib/SwiftLang/SwiftEditorDiagConsumer.h

Lines changed: 1 addition & 0 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;

0 commit comments

Comments
 (0)