Skip to content

Commit 5c217bd

Browse files
committed
Add source buffers pretty-printed for diagnostics to serialized diagnostics
When emitting a diagnostic that references a declaration that does not itself have a source location (e.g., because it was synthesized or deserialized), the diagnostics engine pretty-prints the declaration into a buffer so it can provide caret diagnostics pointing to that declaration. Start marking those buffers as "generated source buffers", so that we emit their contents into serialized diagnostics files. This will allow tools that make use of serialized diagnostics to also show caret information.
1 parent 973b0ce commit 5c217bd

File tree

5 files changed

+43
-1
lines changed

5 files changed

+43
-1
lines changed

include/swift/Basic/SourceManager.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ class GeneratedSourceInfo {
3636

3737
/// A new function body that is replacing an existing function body.
3838
ReplacedFunctionBody,
39+
40+
/// Pretty-printed declarations that have no source location.
41+
PrettyPrinted,
3942
} kind;
4043

4144
/// The buffer ID for the enclosing buffer, in which originalSourceRange

lib/AST/DiagnosticEngine.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,7 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic) {
11421142
SmallVector<std::pair<const Decl *, uint64_t>, 8> entries;
11431143
llvm::SmallString<128> buffer;
11441144
llvm::SmallString<128> bufferName;
1145+
const Decl *ppDecl = decl;
11451146
{
11461147
// The access level of the buffer we want to print. Declarations below
11471148
// this access level will be omitted from the buffer; declarations
@@ -1152,7 +1153,6 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic) {
11521153

11531154
// Figure out which declaration to print. It's the top-most
11541155
// declaration (not a module).
1155-
const Decl *ppDecl = decl;
11561156
auto dc = decl->getDeclContext();
11571157

11581158
// FIXME: Horrible, horrible hackaround. We're not getting a
@@ -1237,6 +1237,21 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic) {
12371237
auto bufferID = SourceMgr.addMemBufferCopy(buffer, bufferName);
12381238
auto memBufferStartLoc = SourceMgr.getLocForBufferStart(bufferID);
12391239

1240+
SourceMgr.setGeneratedSourceInfo(
1241+
bufferID,
1242+
GeneratedSourceInfo{
1243+
GeneratedSourceInfo::PrettyPrinted,
1244+
bufferID,
1245+
SourceRange(),
1246+
SourceRange(
1247+
memBufferStartLoc,
1248+
memBufferStartLoc.getAdvancedLoc(buffer.size())
1249+
),
1250+
ASTNode(const_cast<Decl *>(ppDecl)).getOpaqueValue(),
1251+
nullptr
1252+
}
1253+
);
1254+
12401255
// Go through all of the pretty-printed entries and record their
12411256
// locations.
12421257
for (auto entry : entries) {
@@ -1318,12 +1333,18 @@ std::vector<Diagnostic> DiagnosticEngine::getGeneratedSourceBufferNotes(
13181333
break;
13191334
}
13201335

1336+
case GeneratedSourceInfo::PrettyPrinted:
1337+
break;
1338+
13211339
case GeneratedSourceInfo::ReplacedFunctionBody:
13221340
return childNotes;
13231341
}
13241342

13251343
// Walk up the stack.
13261344
currentLoc = expansionNode.getStartLoc();
1345+
if (currentLoc.isInvalid())
1346+
return childNotes;
1347+
13271348
currentBufferID = SourceMgr.findBufferContainingLoc(currentLoc);
13281349
} while (true);
13291350
}

lib/Basic/SourceLoc.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ void SourceManager::setGeneratedSourceInfo(
260260

261261
switch (info.kind) {
262262
case GeneratedSourceInfo::MacroExpansion:
263+
case GeneratedSourceInfo::PrettyPrinted:
263264
break;
264265

265266
case GeneratedSourceInfo::ReplacedFunctionBody:

test/ImportResolution/import-specific-fixits.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ import struct ambiguous.funcOrVar // expected-error{{ambiguous name 'funcOrVar'
5555
// CHECK-NEXT: Number FIXITs = 0
5656
// CHECK-NEXT: note: found this candidate
5757
// CHECK-NEXT: Number FIXITs = 0
58+
// CHECK-NEXT: CONTENTS OF FILE ambiguous_right.funcOrVar:
59+
// CHECK: public var funcOrVar: Int
60+
// CHECK: END CONTENTS OF FILE
5861
// CHECK-NEXT: note: found this candidate
5962

6063
import func ambiguous.someVar // expected-error{{ambiguous name 'someVar' in module 'ambiguous'}}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: rm -f %t.*
2+
3+
// Test swift executable
4+
// RUN: %target-swift-frontend -typecheck -serialize-diagnostics-path %t.dia %s -verify
5+
// RUN: c-index-test -read-diagnostics %t.dia > %t.deserialized_diagnostics.txt 2>&1
6+
// RUN: %FileCheck --input-file=%t.deserialized_diagnostics.txt %s
7+
8+
var x = String.init // expected-error{{ambiguous use of 'init'}}
9+
// CHECK: {{.*[/\\]}}serialized-diagnostics-prettyprint.swift:[[@LINE-1]]:9: error: ambiguous use of 'init'
10+
11+
// CHECK: Swift.String:2:23: note: found this candidate
12+
// CHECK: CONTENTS OF FILE Swift.String:
13+
// CHECK: extension String {
14+
// CHECK: public init(_ content: Substring.UnicodeScalarView)

0 commit comments

Comments
 (0)