OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.resolution_strategy; | 5 library dart2js.resolution_strategy; |
6 | 6 |
| 7 import 'package:front_end/src/fasta/scanner.dart' show Token; |
| 8 |
7 import '../common.dart'; | 9 import '../common.dart'; |
8 import '../common_elements.dart'; | 10 import '../common_elements.dart'; |
9 import '../common/backend_api.dart'; | 11 import '../common/backend_api.dart'; |
10 import '../common/names.dart'; | 12 import '../common/names.dart'; |
11 import '../common/resolution.dart'; | 13 import '../common/resolution.dart'; |
12 import '../common/tasks.dart'; | 14 import '../common/tasks.dart'; |
13 import '../common/work.dart'; | 15 import '../common/work.dart'; |
14 import '../compiler.dart'; | 16 import '../compiler.dart'; |
15 import '../constants/values.dart'; | 17 import '../constants/values.dart'; |
16 import '../elements/elements.dart'; | 18 import '../elements/elements.dart'; |
17 import '../elements/entities.dart'; | 19 import '../elements/entities.dart'; |
18 import '../elements/modelx.dart'; | 20 import '../elements/modelx.dart'; |
19 import '../elements/resolution_types.dart'; | 21 import '../elements/resolution_types.dart'; |
20 import '../elements/types.dart'; | 22 import '../elements/types.dart'; |
21 import '../environment.dart'; | 23 import '../environment.dart'; |
22 import '../enqueue.dart'; | 24 import '../enqueue.dart'; |
23 import '../frontend_strategy.dart'; | 25 import '../frontend_strategy.dart'; |
24 import '../js_backend/backend.dart'; | 26 import '../js_backend/backend.dart'; |
25 import '../js_backend/backend_usage.dart'; | 27 import '../js_backend/backend_usage.dart'; |
26 import '../js_backend/custom_elements_analysis.dart'; | 28 import '../js_backend/custom_elements_analysis.dart'; |
27 import '../js_backend/interceptor_data.dart'; | 29 import '../js_backend/interceptor_data.dart'; |
28 import '../js_backend/mirrors_analysis.dart'; | 30 import '../js_backend/mirrors_analysis.dart'; |
29 import '../js_backend/mirrors_data.dart'; | 31 import '../js_backend/mirrors_data.dart'; |
30 import '../js_backend/native_data.dart'; | 32 import '../js_backend/native_data.dart'; |
31 import '../js_backend/no_such_method_registry.dart'; | 33 import '../js_backend/no_such_method_registry.dart'; |
32 import '../library_loader.dart'; | 34 import '../library_loader.dart'; |
33 import '../native/resolver.dart'; | 35 import '../native/resolver.dart'; |
| 36 import '../tree/tree.dart' show Node; |
34 import '../serialization/task.dart'; | 37 import '../serialization/task.dart'; |
35 import '../patch_parser.dart'; | 38 import '../patch_parser.dart'; |
36 import '../resolved_uri_translator.dart'; | 39 import '../resolved_uri_translator.dart'; |
37 import '../universe/call_structure.dart'; | 40 import '../universe/call_structure.dart'; |
38 import '../universe/use.dart'; | 41 import '../universe/use.dart'; |
39 import '../universe/world_builder.dart'; | 42 import '../universe/world_builder.dart'; |
40 import '../universe/world_impact.dart'; | 43 import '../universe/world_impact.dart'; |
41 import 'no_such_method_resolver.dart'; | 44 import 'no_such_method_resolver.dart'; |
42 | 45 |
43 /// [FrontendStrategy] that loads '.dart' files and creates a resolved element | 46 /// [FrontendStrategy] that loads '.dart' files and creates a resolved element |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 _compiler.reporter.reportWarningMessage(errorElement, | 208 _compiler.reporter.reportWarningMessage(errorElement, |
206 errorElement.messageKind, errorElement.messageArguments); | 209 errorElement.messageKind, errorElement.messageArguments); |
207 } | 210 } |
208 MethodElement mainMethod; | 211 MethodElement mainMethod; |
209 if (mainFunction != null && !mainFunction.isMalformed) { | 212 if (mainFunction != null && !mainFunction.isMalformed) { |
210 mainFunction.computeType(_compiler.resolution); | 213 mainFunction.computeType(_compiler.resolution); |
211 mainMethod = mainFunction; | 214 mainMethod = mainFunction; |
212 } | 215 } |
213 return mainMethod; | 216 return mainMethod; |
214 } | 217 } |
| 218 |
| 219 SourceSpan spanFromToken(Element currentElement, Token token) => |
| 220 _spanFromTokens(currentElement, token, token); |
| 221 |
| 222 SourceSpan _spanFromTokens(Element currentElement, Token begin, Token end, |
| 223 [Uri uri]) { |
| 224 if (begin == null || end == null) { |
| 225 // TODO(ahe): We can almost always do better. Often it is only |
| 226 // end that is null. Otherwise, we probably know the current |
| 227 // URI. |
| 228 throw 'Cannot find tokens to produce error message.'; |
| 229 } |
| 230 if (uri == null && currentElement != null) { |
| 231 if (currentElement is! Element) { |
| 232 throw 'Can only find tokens from an Element.'; |
| 233 } |
| 234 Element element = currentElement; |
| 235 uri = element.compilationUnit.script.resourceUri; |
| 236 assert(invariant(currentElement, () { |
| 237 bool sameToken(Token token, Token sought) { |
| 238 if (token == sought) return true; |
| 239 if (token.stringValue == '>>') { |
| 240 // `>>` is converted to `>` in the parser when needed. |
| 241 return sought.stringValue == '>' && |
| 242 token.charOffset <= sought.charOffset && |
| 243 sought.charOffset < token.charEnd; |
| 244 } |
| 245 return false; |
| 246 } |
| 247 |
| 248 /// Check that [begin] and [end] can be found between [from] and [to]. |
| 249 validateToken(Token from, Token to) { |
| 250 if (from == null || to == null) return true; |
| 251 bool foundBegin = false; |
| 252 bool foundEnd = false; |
| 253 Token token = from; |
| 254 while (true) { |
| 255 if (sameToken(token, begin)) { |
| 256 foundBegin = true; |
| 257 } |
| 258 if (sameToken(token, end)) { |
| 259 foundEnd = true; |
| 260 } |
| 261 if (foundBegin && foundEnd) { |
| 262 return true; |
| 263 } |
| 264 if (token == to || token == token.next || token.next == null) { |
| 265 break; |
| 266 } |
| 267 token = token.next; |
| 268 } |
| 269 |
| 270 // Create a good message for when the tokens were not found. |
| 271 StringBuffer sb = new StringBuffer(); |
| 272 sb.write('Invalid current element: $element. '); |
| 273 sb.write('Looking for '); |
| 274 sb.write('[${begin} (${begin.hashCode}),'); |
| 275 sb.write('${end} (${end.hashCode})] in'); |
| 276 |
| 277 token = from; |
| 278 while (true) { |
| 279 sb.write('\n ${token} (${token.hashCode})'); |
| 280 if (token == to || token == token.next || token.next == null) { |
| 281 break; |
| 282 } |
| 283 token = token.next; |
| 284 } |
| 285 return sb.toString(); |
| 286 } |
| 287 |
| 288 if (element.enclosingClass != null && |
| 289 element.enclosingClass.isEnumClass) { |
| 290 // Enums ASTs are synthesized (and give messed up messages). |
| 291 return true; |
| 292 } |
| 293 |
| 294 if (element is AstElement) { |
| 295 AstElement astElement = element; |
| 296 if (astElement.hasNode) { |
| 297 Token from = astElement.node.getBeginToken(); |
| 298 Token to = astElement.node.getEndToken(); |
| 299 if (astElement.metadata.isNotEmpty) { |
| 300 if (!astElement.metadata.first.hasNode) { |
| 301 // We might try to report an error while parsing the metadata |
| 302 // itself. |
| 303 return true; |
| 304 } |
| 305 from = astElement.metadata.first.node.getBeginToken(); |
| 306 } |
| 307 return validateToken(from, to); |
| 308 } |
| 309 } |
| 310 return true; |
| 311 }, message: "Invalid current element: $element [$begin,$end].")); |
| 312 } |
| 313 return new SourceSpan.fromTokens(uri, begin, end); |
| 314 } |
| 315 |
| 316 SourceSpan _spanFromNode(Element currentElement, Node node) { |
| 317 return _spanFromTokens( |
| 318 currentElement, node.getBeginToken(), node.getPrefixEndToken()); |
| 319 } |
| 320 |
| 321 SourceSpan _spanFromElement(Element currentElement, Element element) { |
| 322 if (element != null && element.sourcePosition != null) { |
| 323 return element.sourcePosition; |
| 324 } |
| 325 while (element != null && element.isSynthesized) { |
| 326 element = element.enclosingElement; |
| 327 } |
| 328 if (element != null && |
| 329 element.sourcePosition == null && |
| 330 !element.isLibrary && |
| 331 !element.isCompilationUnit) { |
| 332 // Sometimes, the backend fakes up elements that have no |
| 333 // position. So we use the enclosing element instead. It is |
| 334 // not a good error location, but cancel really is "internal |
| 335 // error" or "not implemented yet", so the vicinity is good |
| 336 // enough for now. |
| 337 element = element.enclosingElement; |
| 338 // TODO(ahe): I plan to overhaul this infrastructure anyways. |
| 339 } |
| 340 if (element == null) { |
| 341 element = currentElement; |
| 342 } |
| 343 if (element == null) { |
| 344 return null; |
| 345 } |
| 346 |
| 347 if (element.sourcePosition != null) { |
| 348 return element.sourcePosition; |
| 349 } |
| 350 Token position = element.position; |
| 351 Uri uri = element.compilationUnit.script.resourceUri; |
| 352 return (position == null) |
| 353 ? new SourceSpan(uri, 0, 0) |
| 354 : _spanFromTokens(currentElement, position, position, uri); |
| 355 } |
| 356 |
| 357 SourceSpan spanFromSpannable(Spannable node, Entity currentElement) { |
| 358 if (node is Node) { |
| 359 return _spanFromNode(currentElement, node); |
| 360 } else if (node is Element) { |
| 361 return _spanFromElement(currentElement, node); |
| 362 } else if (node is MetadataAnnotation) { |
| 363 return node.sourcePosition; |
| 364 } |
| 365 return null; |
| 366 } |
215 } | 367 } |
216 | 368 |
217 /// An element environment base on a [Compiler]. | 369 /// An element environment base on a [Compiler]. |
218 class _CompilerElementEnvironment implements ElementEnvironment { | 370 class _CompilerElementEnvironment implements ElementEnvironment { |
219 final Compiler _compiler; | 371 final Compiler _compiler; |
220 | 372 |
221 _CompilerElementEnvironment(this._compiler); | 373 _CompilerElementEnvironment(this._compiler); |
222 | 374 |
223 LibraryProvider get _libraryProvider => _compiler.libraryLoader; | 375 LibraryProvider get _libraryProvider => _compiler.libraryLoader; |
224 Resolution get _resolution => _compiler.resolution; | 376 Resolution get _resolution => _compiler.resolution; |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 @override | 830 @override |
679 WorkItem createWorkItem(MemberElement element) { | 831 WorkItem createWorkItem(MemberElement element) { |
680 assert(invariant(element, element.isDeclaration)); | 832 assert(invariant(element, element.isDeclaration)); |
681 if (element.isMalformed) return null; | 833 if (element.isMalformed) return null; |
682 | 834 |
683 assert(invariant(element, element is AnalyzableElement, | 835 assert(invariant(element, element is AnalyzableElement, |
684 message: 'Element $element is not analyzable.')); | 836 message: 'Element $element is not analyzable.')); |
685 return _resolution.createWorkItem(element); | 837 return _resolution.createWorkItem(element); |
686 } | 838 } |
687 } | 839 } |
OLD | NEW |