Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: pkg/compiler/lib/src/patch_parser.dart

Issue 2732793002: Add NativeDataResolver (Closed)
Patch Set: Fix. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 /** 5 /**
6 * This library contains the infrastructure to parse and integrate patch files. 6 * This library contains the infrastructure to parse and integrate patch files.
7 * 7 *
8 * Three types of elements can be patched: [LibraryElement], [ClassElement], 8 * Three types of elements can be patched: [LibraryElement], [ClassElement],
9 * [FunctionElement]. Patches are introduced in patch libraries which are loaded 9 * [FunctionElement]. Patches are introduced in patch libraries which are loaded
10 * together with the corresponding origin library. Which libraries that are 10 * together with the corresponding origin library. Which libraries that are
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 * - Builders shift between declaration and implementation depending on usages. 109 * - Builders shift between declaration and implementation depending on usages.
110 * - Compile-time constants use constructor implementation exclusively. 110 * - Compile-time constants use constructor implementation exclusively.
111 * - Work on function parameters is performed on the declaration of the function 111 * - Work on function parameters is performed on the declaration of the function
112 * element. 112 * element.
113 */ 113 */
114 114
115 library dart2js.patchparser; 115 library dart2js.patchparser;
116 116
117 import 'dart:async'; 117 import 'dart:async';
118 118
119 import 'package:front_end/src/fasta/parser.dart'
120 show Listener, Parser, ParserError;
121 import 'package:front_end/src/fasta/scanner.dart' show Token;
122
119 import 'common/tasks.dart' show CompilerTask; 123 import 'common/tasks.dart' show CompilerTask;
120 import 'common.dart'; 124 import 'common.dart';
121 import 'compiler.dart' show Compiler; 125 import 'compiler.dart' show Compiler;
122 import 'constants/values.dart' show ConstantValue; 126 import 'constants/values.dart' show ConstantValue;
123 import 'elements/resolution_types.dart' show ResolutionDartType; 127 import 'elements/resolution_types.dart' show ResolutionDartType;
124 import 'elements/elements.dart'; 128 import 'elements/elements.dart';
125 import 'elements/modelx.dart' 129 import 'elements/modelx.dart'
126 show 130 show
127 BaseFunctionElementX, 131 BaseFunctionElementX,
128 ClassElementX, 132 ClassElementX,
129 GetterElementX, 133 GetterElementX,
130 LibraryElementX, 134 LibraryElementX,
131 MetadataAnnotationX, 135 MetadataAnnotationX,
132 SetterElementX; 136 SetterElementX;
133 import 'id_generator.dart'; 137 import 'id_generator.dart';
134 import 'js_backend/js_backend.dart' show JavaScriptBackend;
135 import 'library_loader.dart' show LibraryLoader; 138 import 'library_loader.dart' show LibraryLoader;
136 import 'parser/element_listener.dart' show ElementListener; 139 import 'parser/element_listener.dart' show ElementListener;
137 import 'package:front_end/src/fasta/parser.dart'
138 show Listener, Parser, ParserError;
139 import 'parser/member_listener.dart' show MemberListener; 140 import 'parser/member_listener.dart' show MemberListener;
140 import 'parser/partial_elements.dart' 141 import 'parser/partial_elements.dart'
141 show ClassElementParser, PartialClassElement; 142 show ClassElementParser, PartialClassElement;
143 import 'parser/diet_parser_task.dart' show PartialParser;
142 import 'script.dart'; 144 import 'script.dart';
143 import 'package:front_end/src/fasta/scanner.dart' show StringToken, Token;
144 import 'parser/diet_parser_task.dart' show PartialParser;
145 145
146 class PatchParserTask extends CompilerTask { 146 class PatchParserTask extends CompilerTask {
147 final String name = "Patching Parser"; 147 final String name = "Patching Parser";
148 final Compiler compiler; 148 final Compiler compiler;
149 DiagnosticReporter get reporter => compiler.reporter; 149 DiagnosticReporter get reporter => compiler.reporter;
150 150
151 PatchParserTask(Compiler compiler) 151 PatchParserTask(Compiler compiler)
152 : compiler = compiler, 152 : compiler = compiler,
153 super(compiler.measurer); 153 super(compiler.measurer);
154 154
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 } 326 }
327 patchClass(compiler, reporter, origin, patch); 327 patchClass(compiler, reporter, origin, patch);
328 } 328 }
329 329
330 void patchClass(Compiler compiler, DiagnosticReporter reporter, 330 void patchClass(Compiler compiler, DiagnosticReporter reporter,
331 ClassElementX origin, ClassElementX patch) { 331 ClassElementX origin, ClassElementX patch) {
332 if (origin.isPatched) { 332 if (origin.isPatched) {
333 reporter.internalError(origin, "Patching the same class more than once."); 333 reporter.internalError(origin, "Patching the same class more than once.");
334 } 334 }
335 origin.applyPatch(patch); 335 origin.applyPatch(patch);
336 checkNativeAnnotation(compiler, patch);
337 }
338
339 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its
340 /// native name from the annotation.
341 checkNativeAnnotation(Compiler compiler, ClassElement cls) {
342 EagerAnnotationHandler.checkAnnotation(
343 compiler, cls, const NativeAnnotationHandler());
344 }
345
346 checkJsInteropAnnotation(Compiler compiler, element) {
347 EagerAnnotationHandler.checkAnnotation(
348 compiler, element, const JsInteropAnnotationHandler());
349 } 336 }
350 337
351 /// Abstract interface for pre-resolution detection of metadata. 338 /// Abstract interface for pre-resolution detection of metadata.
352 /// 339 ///
353 /// The detection is handled in two steps: 340 /// The detection is handled in two steps:
354 /// - match the annotation syntactically and assume that the annotation is valid 341 /// - match the annotation syntactically and assume that the annotation is valid
355 /// if it looks correct, 342 /// if it looks correct,
356 /// - setup a deferred action to check that the annotation has a valid constant 343 /// - setup a deferred action to check that the annotation has a valid constant
357 /// value and report an internal error if not. 344 /// value and report an internal error if not.
358 abstract class EagerAnnotationHandler<T> { 345 abstract class EagerAnnotationHandler<T> {
346 const EagerAnnotationHandler();
347
359 /// Checks that [annotation] looks like a matching annotation and optionally 348 /// Checks that [annotation] looks like a matching annotation and optionally
360 /// applies actions on [element]. Returns a non-null annotation marker if the 349 /// applies actions on [element]. Returns a non-null annotation marker if the
361 /// annotation matched and should be validated. 350 /// annotation matched and should be validated.
362 T apply(Compiler compiler, Element element, MetadataAnnotation annotation); 351 T apply(Compiler compiler, Element element, MetadataAnnotation annotation);
363 352
364 /// Checks that the annotation value is valid. 353 /// Checks that the annotation value is valid.
365 void validate(Compiler compiler, Element element, 354 void validate(Compiler compiler, Element element,
366 MetadataAnnotation annotation, ConstantValue constant); 355 MetadataAnnotation annotation, ConstantValue constant);
367 356
368 /// Checks [element] for metadata matching the [handler]. Return a non-null 357 /// Checks [element] for metadata matching the [handler]. Return a non-null
369 /// annotation marker matching metadata was found. 358 /// annotation marker matching metadata was found.
370 static checkAnnotation( 359 static T checkAnnotation<T>(
371 Compiler compiler, Element element, EagerAnnotationHandler handler) { 360 Compiler compiler, Element element, EagerAnnotationHandler<T> handler) {
372 for (MetadataAnnotation annotation in element.implementation.metadata) { 361 for (MetadataAnnotation annotation in element.implementation.metadata) {
373 var result = handler.apply(compiler, element, annotation); 362 T result = handler.apply(compiler, element, annotation);
374 if (result != null) { 363 if (result != handler.defaultResult) {
375 // TODO(johnniwinther): Perform this check in 364 // TODO(johnniwinther): Perform this check in
376 // [Compiler.onLibrariesLoaded]. 365 // [Compiler.onLibrariesLoaded].
377 compiler.enqueuer.resolution.addDeferredAction(element, () { 366 compiler.enqueuer.resolution.addDeferredAction(element, () {
378 annotation.ensureResolved(compiler.resolution); 367 annotation.ensureResolved(compiler.resolution);
379 handler.validate(compiler, element, annotation, 368 handler.validate(compiler, element, annotation,
380 compiler.constants.getConstantValue(annotation.constant)); 369 compiler.constants.getConstantValue(annotation.constant));
381 }); 370 });
382 return result; 371 return result;
383 } 372 }
384 } 373 }
385 return null; 374 return handler.defaultResult;
386 }
387 }
388
389 /// Annotation handler for pre-resolution detection of `@Native(...)`
390 /// annotations.
391 class NativeAnnotationHandler implements EagerAnnotationHandler<String> {
392 const NativeAnnotationHandler();
393
394 String getNativeAnnotation(MetadataAnnotationX annotation) {
395 if (annotation.beginToken != null &&
396 annotation.beginToken.next.value == 'Native') {
397 // Skipping '@', 'Native', and '('.
398 Token argument = annotation.beginToken.next.next.next;
399 if (argument is StringToken) {
400 return argument.value;
401 }
402 }
403 return null;
404 } 375 }
405 376
406 String apply( 377 /// Result that signals the absence of annotations.
407 Compiler compiler, Element element, MetadataAnnotation annotation) { 378 T get defaultResult => null;
408 if (element.isClass) {
409 String native = getNativeAnnotation(annotation);
410 if (native != null) {
411 JavaScriptBackend backend = compiler.backend;
412 backend.nativeClassDataBuilder.setNativeClassTagInfo(element, native);
413 return native;
414 }
415 }
416 return null;
417 }
418
419 void validate(Compiler compiler, Element element,
420 MetadataAnnotation annotation, ConstantValue constant) {
421 ResolutionDartType annotationType =
422 constant.getType(compiler.commonElements);
423 if (annotationType.element !=
424 compiler.backend.helpers.nativeAnnotationClass) {
425 DiagnosticReporter reporter = compiler.reporter;
426 reporter.internalError(annotation, 'Invalid @Native(...) annotation.');
427 }
428 }
429 }
430
431 /// Annotation handler for pre-resolution detection of `@JS(...)`
432 /// annotations.
433 class JsInteropAnnotationHandler implements EagerAnnotationHandler<bool> {
434 const JsInteropAnnotationHandler();
435
436 bool hasJsNameAnnotation(MetadataAnnotationX annotation) =>
437 annotation.beginToken != null && annotation.beginToken.next.value == 'JS';
438
439 bool apply(
440 Compiler compiler, Element element, MetadataAnnotation annotation) {
441 bool hasJsInterop = hasJsNameAnnotation(annotation);
442 if (hasJsInterop) {
443 JavaScriptBackend backend = compiler.backend;
444 backend.nativeClassDataBuilder.markAsJsInterop(element);
445 }
446 // Due to semantics of apply in the baseclass we have to return null to
447 // indicate that no match was found.
448 return hasJsInterop ? true : null;
449 }
450
451 @override
452 void validate(Compiler compiler, Element element,
453 MetadataAnnotation annotation, ConstantValue constant) {
454 JavaScriptBackend backend = compiler.backend;
455 ResolutionDartType type = constant.getType(compiler.commonElements);
456 if (type.element != backend.helpers.jsAnnotationClass) {
457 compiler.reporter
458 .internalError(annotation, 'Invalid @JS(...) annotation.');
459 }
460 }
461 } 379 }
462 380
463 /// Annotation handler for pre-resolution detection of `@patch` annotations. 381 /// Annotation handler for pre-resolution detection of `@patch` annotations.
464 class PatchAnnotationHandler implements EagerAnnotationHandler<PatchVersion> { 382 class PatchAnnotationHandler extends EagerAnnotationHandler<PatchVersion> {
465 const PatchAnnotationHandler(); 383 const PatchAnnotationHandler();
466 384
467 PatchVersion getPatchVersion(MetadataAnnotationX annotation) { 385 PatchVersion getPatchVersion(MetadataAnnotationX annotation) {
468 if (annotation.beginToken != null) { 386 if (annotation.beginToken != null) {
469 if (annotation.beginToken.next.value == 'patch') { 387 if (annotation.beginToken.next.value == 'patch') {
470 return const PatchVersion(null); 388 return const PatchVersion(null);
471 } else if (annotation.beginToken.next.value == 'patch_full') { 389 } else if (annotation.beginToken.next.value == 'patch_full') {
472 return const PatchVersion('full'); 390 return const PatchVersion('full');
473 } else if (annotation.beginToken.next.value == 'patch_lazy') { 391 } else if (annotation.beginToken.next.value == 'patch_lazy') {
474 return const PatchVersion('lazy'); 392 return const PatchVersion('lazy');
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 525
608 class PatchVersion { 526 class PatchVersion {
609 final String tag; 527 final String tag;
610 528
611 const PatchVersion(this.tag); 529 const PatchVersion(this.tag);
612 530
613 bool isActive(String patchTag) => tag == null || tag == patchTag; 531 bool isActive(String patchTag) => tag == null || tag == patchTag;
614 532
615 String toString() => 'PatchVersion($tag)'; 533 String toString() => 'PatchVersion($tag)';
616 } 534 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698