Skip to content

Commit f1bd3cf

Browse files
authored
Context messages (#1770)
* Display diagnostic messages * Show links on issues if available, add hover CSS to issues * Add correction messages * Tweak layout of analysis errors + correction messages * oops'd the server urls * remove outdated parameter * Run dart format --fix * format protobuf file * fix link styles * Rename LineInfo -> Location * keep periods at the end of analyzer messages * change - line x to (line x)
1 parent 90c6691 commit f1bd3cf

16 files changed

Lines changed: 1681 additions & 486 deletions

lib/elements/analysis_results_controller.dart

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ class AnalysisResultsController {
2525
final DElement toggle;
2626
bool _flashHidden;
2727

28-
final StreamController<AnalysisIssue> _onClickController =
28+
final StreamController<Location> _onClickController =
2929
StreamController.broadcast();
3030

31-
Stream<AnalysisIssue> get onIssueClick => _onClickController.stream;
31+
Stream<Location> get onItemClicked => _onClickController.stream;
3232

3333
AnalysisResultsController(this.flash, this.message, this.toggle) {
3434
// Show issues by default, but hide the flash element (otherwise an empty
@@ -70,29 +70,80 @@ class AnalysisResultsController {
7070
message.text = '$amount ${amount == 1 ? 'issue' : 'issues'}';
7171

7272
flash.clearChildren();
73-
for (var elem in issues.map(_issueElement)) {
73+
for (var issue in issues) {
74+
var elem = _issueElement(issue);
7475
flash.add(elem);
76+
77+
for (var diagnostic in issue.diagnosticMessages) {
78+
var diagnosticElement = _diagnosticElement(diagnostic);
79+
flash.add(diagnosticElement);
80+
}
7581
}
7682
}
7783

7884
Element _issueElement(AnalysisIssue issue) {
7985
var message = issue.message;
80-
if (issue.message.endsWith('.')) {
81-
message = message.substring(0, message.length - 1);
82-
}
8386

84-
var elem = DivElement()..classes.add('issue');
87+
var elem = DivElement()..classes.addAll(['issue', 'clickable']);
8588

8689
elem.children.add(SpanElement()
8790
..text = issue.kind
8891
..classes.addAll(_classesForType[issue.kind]));
8992

93+
var columnElem = DivElement()..classes.add('issue-column');
94+
95+
var messageSpan = DivElement()
96+
..text = '$message (line ${issue.line})'
97+
..classes.add('message');
98+
columnElem.children.add(messageSpan);
99+
100+
// Add the correction, if any.
101+
if (issue.correction != null && issue.correction.isNotEmpty) {
102+
columnElem.children.add(DivElement()
103+
..text = issue.correction
104+
..classes.add('message'));
105+
}
106+
107+
// Add a link to the documentation
108+
if (issue.url != null && issue.url.isNotEmpty) {
109+
columnElem.children.add(AnchorElement()
110+
..href = issue.url
111+
..text = ' Open Documentation'
112+
..target = '_blank'
113+
..classes.add('issue-anchor'));
114+
}
115+
116+
elem.children.add(columnElem);
117+
118+
elem.onClick.listen((_) {
119+
_onClickController.add(Location(
120+
line: issue.line,
121+
charStart: issue.charStart,
122+
charLength: issue.charLength));
123+
});
124+
125+
return elem;
126+
}
127+
128+
Element _diagnosticElement(DiagnosticMessage diagnosticMessage) {
129+
var message = diagnosticMessage.message;
130+
if (message.endsWith('.')) {
131+
message = message.substring(0, message.length - 1);
132+
}
133+
134+
var elem = DivElement()..classes.addAll(['issue', 'clickable']);
135+
136+
elem.children.add(SpanElement()..classes.add('issue-indent'));
137+
90138
elem.children.add(SpanElement()
91-
..text = '$message - line ${issue.line}'
139+
..text = message
92140
..classes.add('message'));
93141

94142
elem.onClick.listen((_) {
95-
_onClickController.add(issue);
143+
_onClickController.add(Location(
144+
line: diagnosticMessage.line,
145+
charStart: diagnosticMessage.charStart,
146+
charLength: diagnosticMessage.charLength));
96147
});
97148

98149
return elem;
@@ -118,3 +169,16 @@ class AnalysisResultsController {
118169
toggle.text = _hideMsg;
119170
}
120171
}
172+
173+
/// A range of text in the file.
174+
class Location {
175+
final int line;
176+
final int charStart;
177+
final int charLength;
178+
179+
Location({
180+
this.line,
181+
this.charStart,
182+
this.charLength,
183+
});
184+
}

lib/embed.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,8 @@ class Embed {
400400
DElement(querySelector('#issues')),
401401
DElement(querySelector('#issues-message')),
402402
DElement(querySelector('#issues-toggle')))
403-
..onIssueClick.listen((issue) {
404-
_jumpTo(issue.line, issue.charStart, issue.charLength, focus: true);
403+
..onItemClicked.listen((item) {
404+
_jumpTo(item.line, item.charStart, item.charLength, focus: true);
405405
});
406406

407407
if (options.mode == EmbedMode.flutter || options.mode == EmbedMode.html) {

lib/playground.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -600,8 +600,8 @@ class Playground implements GistContainer, GistController {
600600
DElement(querySelector('#issues')),
601601
DElement(querySelector('#issues-message')),
602602
DElement(querySelector('#issues-toggle')))
603-
..onIssueClick.listen((issue) {
604-
_jumpTo(issue.line, issue.charStart, issue.charLength, focus: true);
603+
..onItemClicked.listen((item) {
604+
_jumpTo(item.line, item.charStart, item.charLength, focus: true);
605605
});
606606

607607
_finishedInit();

lib/scss/shared.scss

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
@import 'package:dart_pad/scss/colors';
44
@import 'package:dart_pad/scss/variables';
55

6+
a {
7+
text-decoration: none;
8+
cursor: pointer;
9+
font-family: Roboto, sans-serif;
10+
}
11+
612
// Flashes
713
#flash-container > div + div {
814
// Adds space between the flashes in the flash container, if more than one is displayed.
@@ -69,16 +75,23 @@
6975

7076
// Issues
7177
#issues {
72-
padding: 8px;
7378
overflow-y: auto;
7479
max-height: 50vh;
7580
}
7681

7782
#issues .issue {
7883
display: flex;
7984
flex-direction: row;
85+
align-items: start;
8086
line-height: 20px;
8187
border-radius: 3px;
88+
padding: 4px;
89+
margin: 0;
90+
}
91+
92+
93+
94+
.clickable {
8295
cursor: pointer;
8396
}
8497

@@ -91,10 +104,20 @@
91104
font-size: $embed-editor-font-size;
92105
display: inline-block;
93106
border-radius: 3px;
94-
padding: 2px 5px;
107+
padding: 0 5px 2px 5px;
108+
min-width: 62px;
109+
}
110+
111+
.issue-indent {
112+
border: 1px;
113+
padding: 2px 5px; // to match size of issuelabel
95114
min-width: 62px;
96115
}
97116

117+
.issue-anchor {
118+
margin: 0 4px;
119+
}
120+
98121
.issue .issuelabel.error {
99122
color: $issue-error-color;
100123
border: 1px solid $issue-error-color;

lib/services/common.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const nullSafetyServerUrl = 'https://nullsafety.api.dartpad.dev/';
1212

1313
// A URL to use while debugging.
1414
// final serverUrl = 'http://127.0.0.1:8082/';
15+
// const nullSafetyServerUrl = 'http://127.0.0.1:8082/';
1516

1617
const Duration serviceCallTimeout = Duration(seconds: 10);
1718
const Duration longServiceCallTimeout = Duration(seconds: 60);

0 commit comments

Comments
 (0)