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

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

Issue 1318043005: Support user generated custom native JS classes. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: ptal Created 5 years, 2 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 import 'diagnostics/messages.dart' show 126 import 'diagnostics/messages.dart' show
127 MessageKind; 127 MessageKind;
128 import 'elements/elements.dart'; 128 import 'elements/elements.dart';
129 import 'elements/modelx.dart' show 129 import 'elements/modelx.dart' show
130 BaseFunctionElementX, 130 BaseFunctionElementX,
131 ClassElementX, 131 ClassElementX,
132 GetterElementX, 132 GetterElementX,
133 LibraryElementX, 133 LibraryElementX,
134 MetadataAnnotationX, 134 MetadataAnnotationX,
135 SetterElementX; 135 SetterElementX;
136 import 'js_backend/js_backend.dart' show
137 JavaScriptBackend;
136 import 'library_loader.dart' show 138 import 'library_loader.dart' show
137 LibraryLoader; 139 LibraryLoader;
138 import 'parser/listener.dart' show 140 import 'parser/listener.dart' show
139 Listener, 141 Listener,
140 ParserError; 142 ParserError;
141 import 'parser/element_listener.dart' show 143 import 'parser/element_listener.dart' show
142 ElementListener; 144 ElementListener;
143 import 'parser/member_listener.dart' show 145 import 'parser/member_listener.dart' show
144 MemberListener; 146 MemberListener;
145 import 'parser/partial_elements.dart' show 147 import 'parser/partial_elements.dart' show
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 } 299 }
298 300
299 void patchElement(Compiler compiler, 301 void patchElement(Compiler compiler,
300 Element origin, 302 Element origin,
301 Element patch) { 303 Element patch) {
302 if (origin == null) { 304 if (origin == null) {
303 compiler.reportError( 305 compiler.reportError(
304 patch, MessageKind.PATCH_NON_EXISTING, {'name': patch.name}); 306 patch, MessageKind.PATCH_NON_EXISTING, {'name': patch.name});
305 return; 307 return;
306 } 308 }
309
307 if (!(origin.isClass || 310 if (!(origin.isClass ||
308 origin.isConstructor || 311 origin.isConstructor ||
309 origin.isFunction || 312 origin.isFunction ||
310 origin.isAbstractField)) { 313 origin.isAbstractField)) {
311 // TODO(ahe): Remove this error when the parser rejects all bad modifiers. 314 // TODO(ahe): Remove this error when the parser rejects all bad modifiers.
312 compiler.reportError(origin, MessageKind.PATCH_NONPATCHABLE); 315 compiler.reportError(origin, MessageKind.PATCH_NONPATCHABLE);
313 return; 316 return;
314 } 317 }
315 if (patch.isClass) { 318 if (patch.isClass) {
316 tryPatchClass(compiler, origin, patch); 319 tryPatchClass(compiler, origin, patch);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 checkNativeAnnotation(compiler, patch); 355 checkNativeAnnotation(compiler, patch);
353 } 356 }
354 357
355 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its 358 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its
356 /// native name from the annotation. 359 /// native name from the annotation.
357 checkNativeAnnotation(Compiler compiler, ClassElement cls) { 360 checkNativeAnnotation(Compiler compiler, ClassElement cls) {
358 EagerAnnotationHandler.checkAnnotation(compiler, cls, 361 EagerAnnotationHandler.checkAnnotation(compiler, cls,
359 const NativeAnnotationHandler()); 362 const NativeAnnotationHandler());
360 } 363 }
361 364
365 checkJsInteropAnnotation(Compiler compiler, element) {
366 EagerAnnotationHandler.checkAnnotation(compiler, element,
367 const JsInteropAnnotationHandler());
368 }
369
370
362 /// Abstract interface for pre-resolution detection of metadata. 371 /// Abstract interface for pre-resolution detection of metadata.
363 /// 372 ///
364 /// The detection is handled in two steps: 373 /// The detection is handled in two steps:
365 /// - match the annotation syntactically and assume that the annotation is valid 374 /// - match the annotation syntactically and assume that the annotation is valid
366 /// if it looks correct, 375 /// if it looks correct,
367 /// - setup a deferred action to check that the annotation has a valid constant 376 /// - setup a deferred action to check that the annotation has a valid constant
368 /// value and report an internal error if not. 377 /// value and report an internal error if not.
369 abstract class EagerAnnotationHandler<T> { 378 abstract class EagerAnnotationHandler<T> {
370 /// Checks that [annotation] looks like a matching annotation and optionally 379 /// Checks that [annotation] looks like a matching annotation and optionally
371 /// applies actions on [element]. Returns a non-null annotation marker if the 380 /// applies actions on [element]. Returns a non-null annotation marker if the
(...skipping 15 matching lines...) Expand all
387 Element element, 396 Element element,
388 EagerAnnotationHandler handler) { 397 EagerAnnotationHandler handler) {
389 for (Link<MetadataAnnotation> link = element.metadata; 398 for (Link<MetadataAnnotation> link = element.metadata;
390 !link.isEmpty; 399 !link.isEmpty;
391 link = link.tail) { 400 link = link.tail) {
392 MetadataAnnotation annotation = link.head; 401 MetadataAnnotation annotation = link.head;
393 var result = handler.apply(compiler, element, annotation); 402 var result = handler.apply(compiler, element, annotation);
394 if (result != null) { 403 if (result != null) {
395 // TODO(johnniwinther): Perform this check in 404 // TODO(johnniwinther): Perform this check in
396 // [Compiler.onLibrariesLoaded]. 405 // [Compiler.onLibrariesLoaded].
397 compiler.enqueuer.resolution.addDeferredAction(element, () { 406 // TODO(jacobr): annotation resolution needs to be refactored.
407 actionCallback() {
398 annotation.ensureResolved(compiler); 408 annotation.ensureResolved(compiler);
399 handler.validate( 409 handler.validate(
400 compiler, element, annotation, 410 compiler, element, annotation,
401 compiler.constants.getConstantValue(annotation.constant)); 411 compiler.constants.getConstantValue(annotation.constant));
402 }); 412 }
413 if (compiler.enqueuer.resolution.queueIsClosed) {
414 actionCallback();
415 } else {
416 compiler.enqueuer.resolution.addDeferredAction(element,
417 actionCallback);
418 }
403 return result; 419 return result;
404 } 420 }
405 } 421 }
406 return null; 422 return null;
407 } 423 }
408 } 424 }
409 425
410 /// Annotation handler for pre-resolution detection of `@Native(...)` 426 /// Annotation handler for pre-resolution detection of `@Native(...)`
411 /// annotations. 427 /// annotations.
412 class NativeAnnotationHandler implements EagerAnnotationHandler<String> { 428 class NativeAnnotationHandler implements EagerAnnotationHandler<String> {
(...skipping 29 matching lines...) Expand all
442 Element element, 458 Element element,
443 MetadataAnnotation annotation, 459 MetadataAnnotation annotation,
444 ConstantValue constant) { 460 ConstantValue constant) {
445 if (constant.getType(compiler.coreTypes).element != 461 if (constant.getType(compiler.coreTypes).element !=
446 compiler.nativeAnnotationClass) { 462 compiler.nativeAnnotationClass) {
447 compiler.internalError(annotation, 'Invalid @Native(...) annotation.'); 463 compiler.internalError(annotation, 'Invalid @Native(...) annotation.');
448 } 464 }
449 } 465 }
450 } 466 }
451 467
468 /// Annotation handler for pre-resolution detection of `@Js(...)`
469 /// annotations.
470 class JsInteropAnnotationHandler implements EagerAnnotationHandler<String> {
471 const JsInteropAnnotationHandler();
472
473 // TODO(jacobr): this method is pure technical debt.
474 String dietResolveStringToken(StringToken token) {
475 String value = token.value;
476 if ((value.startsWith('"') && value.endsWith('"')) ||
477 value.startsWith("'") && value.endsWith("'")) {
478 return value.substring(1, value.length - 1);
479 } else {
480 throw 'Invalid @Js(...) annotation. Unexpected name: $value';
481 }
482 }
483
484 String getJsNameAnnotation(MetadataAnnotation annotation) {
485 if (annotation.beginToken != null &&
486 annotation.beginToken.next.value == 'Js') {
487 // Skipping '@', 'Js', and '('.
488 Token argument = annotation.beginToken.next.next.next;
489 return (argument is StringToken) ? dietResolveStringToken(argument) : '';
490 }
491
492 return null;
493 }
494
495 String apply(Compiler compiler,
496 Element element,
497 MetadataAnnotation annotation) {
498 String jsName = getJsNameAnnotation(annotation);
499 if (jsName != null) {
500 element.setJsInterop(jsName);
501 element.declaration.setJsInterop(jsName);
502 }
503 return jsName;
504 }
505
506 @override
507 void validate(Compiler compiler,
508 Element element,
509 MetadataAnnotation annotation,
510 ConstantValue constant) {
511 JavaScriptBackend backend = compiler.backend;
512 if (constant.getType(compiler.coreTypes).element !=
513 backend.jsAnnotationClass) {
514 compiler.internalError(annotation, 'Invalid @Js(...) annotation.');
515 }
516 }
517 }
518
452 /// Annotation handler for pre-resolution detection of `@patch` annotations. 519 /// Annotation handler for pre-resolution detection of `@patch` annotations.
453 class PatchAnnotationHandler implements EagerAnnotationHandler<PatchVersion> { 520 class PatchAnnotationHandler implements EagerAnnotationHandler<PatchVersion> {
454 const PatchAnnotationHandler(); 521 const PatchAnnotationHandler();
455 522
456 PatchVersion getPatchVersion(MetadataAnnotation annotation) { 523 PatchVersion getPatchVersion(MetadataAnnotation annotation) {
457 if (annotation.beginToken != null) { 524 if (annotation.beginToken != null) {
458 if (annotation.beginToken.next.value == 'patch') { 525 if (annotation.beginToken.next.value == 'patch') {
459 return const PatchVersion(null); 526 return const PatchVersion(null);
460 } else if (annotation.beginToken.next.value == 'patch_full') { 527 } else if (annotation.beginToken.next.value == 'patch_full') {
461 return const PatchVersion('full'); 528 return const PatchVersion('full');
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 658
592 class PatchVersion { 659 class PatchVersion {
593 final String tag; 660 final String tag;
594 661
595 const PatchVersion(this.tag); 662 const PatchVersion(this.tag);
596 663
597 bool isActive(String patchTag) => tag == null || tag == patchTag; 664 bool isActive(String patchTag) => tag == null || tag == patchTag;
598 665
599 String toString() => 'PatchVersion($tag)'; 666 String toString() => 'PatchVersion($tag)';
600 } 667 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698