@@ -73,6 +73,83 @@ class InfoBuilder {
73
73
return units;
74
74
}
75
75
76
+ /// Return details for a fix built from the given [edge] , or `null` if the
77
+ /// edge does not have an origin.
78
+ String _baseDescriptionForOrigin (AstNode node) {
79
+ if (node is DefaultFormalParameter ) {
80
+ Expression defaultValue = node.defaultValue;
81
+ if (defaultValue == null ) {
82
+ return "This parameter has an implicit default value of 'null'" ;
83
+ } else if (defaultValue is NullLiteral ) {
84
+ return "This parameter has an explicit default value of 'null'" ;
85
+ }
86
+ return "This parameter has a nullable default value" ;
87
+ } else if (node is FieldFormalParameter ) {
88
+ AstNode parent = node.parent;
89
+ if (parent is DefaultFormalParameter ) {
90
+ Expression defaultValue = parent.defaultValue;
91
+ if (defaultValue == null ) {
92
+ return "This field is initialized by an optional field formal "
93
+ "parameter that has an implicit default value of 'null'" ;
94
+ } else if (defaultValue is NullLiteral ) {
95
+ return "This field is initialized by an optional field formal "
96
+ "parameter that has an explicit default value of 'null'" ;
97
+ }
98
+ return "This field is initialized by an optional field formal "
99
+ "parameter that has a nullable default value" ;
100
+ }
101
+ return "This field is initialized by a field formal parameter and a "
102
+ "nullable value is passed as an argument" ;
103
+ }
104
+ AstNode parent = node.parent;
105
+ if (parent is ArgumentList ) {
106
+ if (node is NullLiteral ) {
107
+ return "An explicit 'null' is passed as an argument" ;
108
+ }
109
+ return "A nullable value is explicitly passed as an argument" ;
110
+ }
111
+
112
+ /// If the [node] is the return expression for a function body, return the
113
+ /// function body. Otherwise return `null` .
114
+ AstNode findFunctionBody () {
115
+ if (parent is ExpressionFunctionBody ) {
116
+ return parent;
117
+ } else if (parent is ReturnStatement &&
118
+ parent.parent? .parent is BlockFunctionBody ) {
119
+ return parent.parent.parent;
120
+ }
121
+ return null ;
122
+ }
123
+
124
+ AstNode functionBody = findFunctionBody ();
125
+ if (functionBody != null ) {
126
+ AstNode function = functionBody.parent;
127
+ if (function is MethodDeclaration ) {
128
+ if (function.isGetter) {
129
+ return "This getter returns a nullable value" ;
130
+ }
131
+ return "This method returns a nullable value" ;
132
+ }
133
+ return "This function returns a nullable value" ;
134
+ } else if (parent is VariableDeclaration ) {
135
+ AstNode grandparent = parent.parent? .parent;
136
+ if (grandparent is FieldDeclaration ) {
137
+ if (node is NullLiteral ) {
138
+ return "This field is initialized to null" ;
139
+ }
140
+ return "This field is initialized to a nullable value" ;
141
+ }
142
+ if (node is NullLiteral ) {
143
+ return "This variable is initialized to null" ;
144
+ }
145
+ return "This variable is initialized to a nullable value" ;
146
+ }
147
+ if (node is NullLiteral ) {
148
+ return "An explicit 'null' is assigned" ;
149
+ }
150
+ return "A nullable value is assigned" ;
151
+ }
152
+
76
153
/// Return details for a fix built from the given [edge] , or `null` if the
77
154
/// edge does not have an origin.
78
155
String _buildDescriptionForDestination (AstNode node) {
@@ -85,24 +162,12 @@ class InfoBuilder {
85
162
}
86
163
}
87
164
88
- /// Return details for a fix built from the given [edge] , or `null` if the
89
- /// edge does not have an origin.
90
- String _buildDescriptionForOrigin (AstNode node) {
91
- String /*!*/ description;
92
- if (node.parent is ArgumentList ) {
93
- if (node is NullLiteral ) {
94
- description = "An explicit 'null' is passed as an argument" ;
95
- } else {
96
- description = "A nullable value is explicitly passed as an argument" ;
97
- }
98
- } else {
99
- if (node is NullLiteral ) {
100
- description = "An explicit 'null' is assigned" ;
101
- } else {
102
- description = "A nullable value is assigned" ;
103
- }
104
- }
105
- if (_inTestCode (node)) {
165
+ /// Return a description of the given [origin] .
166
+ String _buildDescriptionForOrigin (AstNode origin) {
167
+ String description = _baseDescriptionForOrigin (origin);
168
+ if (_inTestCode (origin)) {
169
+ // TODO(brianwilkerson) Don't add this if the graph node with which the
170
+ // origin is associated is also in test code.
106
171
description += " in test code" ;
107
172
}
108
173
return description;
@@ -123,6 +188,9 @@ class InfoBuilder {
123
188
// the superclass.
124
189
details.add (RegionDetail (_buildDescriptionForOrigin (origin.node),
125
190
_targetForNode (origin.source.fullName, origin.node)));
191
+ } else {
192
+ details.add (
193
+ RegionDetail ('upstream edge with no origin ($edge )' , null ));
126
194
}
127
195
}
128
196
}
@@ -133,6 +201,8 @@ class InfoBuilder {
133
201
details.add (RegionDetail (
134
202
_buildDescriptionForDestination (nodeInfo.astNode),
135
203
_targetForNode (nodeInfo.filePath, nodeInfo.astNode)));
204
+ } else {
205
+ details.add (RegionDetail ('node with no info ($destination )' , null ));
136
206
}
137
207
} else {
138
208
throw UnimplementedError (
0 commit comments