@@ -8,21 +8,42 @@ import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_informat
8
8
import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart' ;
9
9
import 'package:analyzer/dart/analysis/results.dart' ;
10
10
import 'package:analyzer/dart/analysis/session.dart' ;
11
+ import 'package:analyzer/dart/ast/ast.dart' ;
11
12
import 'package:analyzer/src/generated/source.dart' ;
12
- import 'package:analyzer_plugin/protocol/protocol_common.dart' ;
13
+ import 'package:analyzer_plugin/protocol/protocol_common.dart'
14
+ show Location, SourceEdit, SourceFileEdit;
15
+ import 'package:nnbd_migration/instrumentation.dart' ;
16
+ import 'package:nnbd_migration/nnbd_migration.dart' ;
17
+
18
+ class FixInfo {
19
+ /// The fix being described.
20
+ SingleNullabilityFix fix;
21
+
22
+ /// The reasons why the fix was made.
23
+ List <FixReasonInfo > reasons;
24
+
25
+ /// Initialize information about a fix from the given map [entry] .
26
+ FixInfo (this .fix, this .reasons);
27
+ }
13
28
14
29
/// A builder used to build the migration information for a library.
15
30
class InfoBuilder {
16
- /// The analysis session used to get information about libraries.
17
- AnalysisServer server;
31
+ /// The instrumentation information gathered while the migration engine was
32
+ /// running.
33
+ final InstrumentationInformation info;
34
+
35
+ /// The listener used to gather the changes to be applied.
36
+ final DartFixListener listener;
18
37
19
38
/// Initialize a newly created builder.
20
- InfoBuilder (this .server);
39
+ InfoBuilder (this .info, this .listener);
40
+
41
+ /// The analysis server used to get information about libraries.
42
+ AnalysisServer get server => listener.server;
21
43
22
44
/// Return the migration information for all of the libraries that were
23
45
/// migrated.
24
- Future <List <LibraryInfo >> explainMigration (
25
- InstrumentationInformation info, DartFixListener listener) async {
46
+ Future <List <LibraryInfo >> explainMigration () async {
26
47
Map <Source , SourceInformation > sourceInfo = info.sourceInformation;
27
48
List <LibraryInfo > libraries = [];
28
49
for (Source source in sourceInfo.keys) {
@@ -38,6 +59,42 @@ class InfoBuilder {
38
59
return libraries;
39
60
}
40
61
62
+ /// Compute the details for the fix with the given [fixInfo] .
63
+ List <RegionDetail > _computeDetails (FixInfo fixInfo) {
64
+ List <RegionDetail > details = [];
65
+ for (FixReasonInfo reason in fixInfo.reasons) {
66
+ if (reason is NullabilityNodeInfo ) {
67
+ for (EdgeInfo edge in reason.upstreamEdges) {
68
+ EdgeOriginInfo origin = info.edgeOrigin[edge];
69
+ if (origin != null ) {
70
+ AstNode node = origin.node;
71
+ if (node.parent is ArgumentList ) {
72
+ if (node is NullLiteral ) {
73
+ details.add (RegionDetail (
74
+ 'null is explicitly passed as an argument.' ,
75
+ _targetFor (origin)));
76
+ } else {
77
+ details.add (RegionDetail (
78
+ 'A nullable value is explicitly passed as an argument.' ,
79
+ _targetFor (origin)));
80
+ }
81
+ } else {
82
+ details.add (RegionDetail (
83
+ 'A nullable value is assigned.' , _targetFor (origin)));
84
+ }
85
+ }
86
+ }
87
+ } else if (reason is EdgeInfo ) {
88
+ // TODO(brianwilkerson) Implement this after finding an example whose
89
+ // reason is an edge.
90
+ } else {
91
+ throw UnimplementedError (
92
+ 'Unexpected class of reason: ${reason .runtimeType }' );
93
+ }
94
+ }
95
+ return details;
96
+ }
97
+
41
98
/// Return the migration information for the given library.
42
99
LibraryInfo _explainLibrary (
43
100
ParsedLibraryResult result,
@@ -47,13 +104,14 @@ class InfoBuilder {
47
104
List <UnitInfo > units = [];
48
105
for (ParsedUnitResult unit in result.units) {
49
106
SourceFileEdit edit = listener.sourceChange.getFileEdit (unit.path);
50
- units.add (_explainUnit (unit, edit));
107
+ units.add (_explainUnit (sourceInfo, unit, edit));
51
108
}
52
109
return LibraryInfo (units);
53
110
}
54
111
55
112
/// Return the migration information for the given unit.
56
- UnitInfo _explainUnit (ParsedUnitResult result, SourceFileEdit fileEdit) {
113
+ UnitInfo _explainUnit (SourceInformation sourceInfo, ParsedUnitResult result,
114
+ SourceFileEdit fileEdit) {
57
115
List <RegionInfo > regions = [];
58
116
String content = result.content;
59
117
// [fileEdit] is null when a file has no edits.
@@ -83,14 +141,35 @@ class InfoBuilder {
83
141
int delta = deltas[index-- ];
84
142
// Insert the replacement text without deleting the replaced text.
85
143
content = content.replaceRange (end, end, replacement);
144
+ FixInfo fixInfo = _findFixInfo (sourceInfo, offset);
145
+ String explanation = '${fixInfo .fix .description .appliedMessage }.' ;
146
+ List <RegionDetail > details = _computeDetails (fixInfo);
86
147
if (length > 0 ) {
87
- // TODO(brianwilkerson) Create a sensible explanation.
88
- regions.add (RegionInfo (offset + delta, length, 'removed' ));
148
+ regions.add (RegionInfo (offset + delta, length, explanation, details));
89
149
}
90
- // TODO(brianwilkerson) Create a sensible explanation.
91
- regions. add ( RegionInfo (end + delta, replacement.length, 'added' ));
150
+ regions. add (
151
+ RegionInfo (end + delta, replacement.length, explanation, details ));
92
152
}
93
153
regions.sort ((first, second) => first.offset.compareTo (second.offset));
94
154
return UnitInfo (result.path, content, regions);
95
155
}
156
+
157
+ /// Return information about the fix that was applied at the given [offset] ,
158
+ /// or `null` if the information could not be found. The information is
159
+ /// extracted from the [sourceInfo] .
160
+ FixInfo _findFixInfo (SourceInformation sourceInfo, int offset) {
161
+ for (MapEntry <SingleNullabilityFix , List <FixReasonInfo >> entry
162
+ in sourceInfo.fixes.entries) {
163
+ Location location = entry.key.location;
164
+ if (location.offset == offset) {
165
+ return FixInfo (entry.key, entry.value);
166
+ }
167
+ }
168
+ return null ;
169
+ }
170
+
171
+ NavigationTarget _targetFor (EdgeOriginInfo origin) {
172
+ AstNode node = origin.node;
173
+ return NavigationTarget (origin.source.fullName, node.offset, node.length);
174
+ }
96
175
}
0 commit comments