Skip to content

Commit e13d412

Browse files
Merge pull request #10066 from adrian-prantl/145152120
[lldb] Fix the computation of the hidden/in_user_code flag
2 parents bd66d7d + 6aebdcf commit e13d412

File tree

2 files changed

+72
-6
lines changed

2 files changed

+72
-6
lines changed

lldb/source/Plugins/TypeSystem/Swift/StoringDiagnosticConsumer.h

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,16 +152,52 @@ class StoringDiagnosticConsumer : public swift::DiagnosticConsumer {
152152
// FXIME: This is a heuristic.
153153
uint16_t len = info.Ranges.size() ? info.Ranges.front().getByteLength() : 0;
154154
bool in_user_input = false;
155-
// FIXME: improve this!
156-
if (buffer_name == "<REPL>" || buffer_name == "<EXPR>" ||
157-
buffer_name == "repl.swift" ||
158-
buffer_name.starts_with("<user expression"))
159-
in_user_input = true;
155+
bool hidden = false;
156+
[&]() {
157+
if (buffer_name == "repl.swift") {
158+
in_user_input = true;
159+
return;
160+
}
161+
if (buffer_name != "<REPL>" && buffer_name != "<EXPR>" &&
162+
!buffer_name.starts_with("<user expression"))
163+
return;
164+
165+
unsigned buffer_id = source_mgr.findBufferContainingLoc(info.Loc);
166+
llvm::SourceMgr &src_mgr = source_mgr.getLLVMSourceMgr();
167+
auto *buffer = src_mgr.getMemoryBuffer(buffer_id);
168+
if (!buffer)
169+
return;
170+
171+
// Clang uses the much more elegant #line mechanism to find the
172+
// user code, but doing this here could interfere with
173+
// ExprOptions.PoundLineLine mechanism used Swift
174+
// Playgrounds. So instead we find the markers from both ends.
175+
StringRef buffer_data = buffer->getBuffer();
176+
size_t pos = buffer_data.find("__LLDB_USER_START__");
177+
if (pos == StringRef::npos)
178+
return;
179+
auto start_loc =
180+
llvm::SMLoc::getFromPointer(buffer->getBufferStart() + pos);
181+
unsigned start_line = src_mgr.FindLineNumber(start_loc, buffer_id);
182+
183+
pos = buffer_data.rfind("__LLDB_USER_END__");
184+
if (pos == StringRef::npos)
185+
return;
186+
auto end_loc =
187+
llvm::SMLoc::getFromPointer(buffer->getBufferStart() + pos);
188+
unsigned end_line = src_mgr.FindLineNumber(end_loc, buffer_id);
189+
190+
unsigned diag_line =
191+
source_mgr.getLineAndColumnInBuffer(info.Loc, buffer_id).first;
192+
193+
in_user_input = start_line < diag_line && diag_line < end_line;
194+
hidden = !in_user_input;
195+
}();
160196
DiagnosticDetail::SourceLocation loc = {FileSpec{buffer_name.str()},
161197
line_col.first,
162198
(uint16_t)line_col.second,
163199
len,
164-
!in_user_input,
200+
hidden,
165201
in_user_input};
166202
DiagnosticDetail detail = {loc, severity, raw_text, formatted_text};
167203
RawDiagnostic diagnostic(

lldb/test/API/lang/swift/expression/error_reporting/TestSwiftExpressionErrorReporting.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,35 @@ def test_missing_var(self):
1414
target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
1515
self, 'break here', lldb.SBFileSpec('main.swift'))
1616

17+
# This produces two errors:
18+
# error: <EXPR>:8:1: initializers may only be declared within a type
19+
# } catch (let __lldb_tmp_error) {
20+
# ^
21+
#
22+
# error: <EXPR>:6:5: expected '(' for initializer parameters
23+
# init
24+
# ^
25+
# The first one is outside of user code, the second one isn't.
26+
27+
options = lldb.SBExpressionOptions()
28+
value = self.frame().EvaluateExpression("init", options)
29+
data = value.GetError().GetErrorData()
30+
31+
version = data.GetValueForKey("version")
32+
self.assertEqual(version.GetIntegerValue(), 1)
33+
diags = data.GetValueForKey("errors").GetItemAtIndex(0)
34+
details = diags.GetValueForKey("details")
35+
err0 = details.GetItemAtIndex(0)
36+
self.assertIn("initializers", str(err0.GetValueForKey("message")))
37+
loc0 = err0.GetValueForKey("source_location")
38+
self.assertTrue(loc0.GetValueForKey("hidden").GetBooleanValue())
39+
self.assertFalse(loc0.GetValueForKey("in_user_input").GetBooleanValue())
40+
err1 = details.GetItemAtIndex(1)
41+
self.assertIn("expected '('", str(err1.GetValueForKey("message")))
42+
loc1 = err1.GetValueForKey("source_location")
43+
self.assertFalse(loc1.GetValueForKey("hidden").GetBooleanValue())
44+
self.assertTrue(loc1.GetValueForKey("in_user_input").GetBooleanValue())
45+
1746
options = lldb.SBExpressionOptions()
1847
value = self.frame().EvaluateExpression(
1948
"ceciNestPasUnVar", options)
@@ -58,3 +87,4 @@ def check(value):
5887
process.Continue()
5988
self.expect('expression -O -- number', error=True,
6089
substrs=['self', 'not', 'found'])
90+

0 commit comments

Comments
 (0)