blob: eb4121a5d99edb5807e6d08bcb73c3d150e79e0c [file] [log] [blame]
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library dart2js.resolution.common;
import '../common.dart';
import '../common/resolution.dart' show Resolution;
import '../elements/elements.dart';
import '../enqueue.dart' show DeferredAction;
import '../tree/tree.dart';
import 'registry.dart' show ResolutionRegistry;
import 'scope.dart' show Scope;
import 'type_resolver.dart' show TypeResolver;
class CommonResolverVisitor<R> extends Visitor<R> {
final Resolution resolution;
DiagnosticReporter get reporter => resolution.reporter;
R visitNode(Node node) {
return reporter.internalError(
node, 'internal error: Unhandled node: ${node.getObjectDescription()}');
R visitEmptyStatement(Node node) => null;
/** Convenience method for visiting nodes that may be null. */
R visit(Node node) => (node == null) ? null : node.accept(this);
void addDeferredAction(Element element, void action()) {
resolution.enqueuer.addDeferredAction(new DeferredAction(element, action));
* Common supertype for resolver visitors that record resolutions in a
* [ResolutionRegistry].
abstract class MappingVisitor<T> extends CommonResolverVisitor<T> {
final ResolutionRegistry registry;
final TypeResolver typeResolver;
/// The current enclosing element for the visited AST nodes.
Element get enclosingElement;
/// The current scope of the visitor.
Scope get scope;
MappingVisitor(Resolution resolution, this.registry)
: typeResolver = new TypeResolver(resolution),
AsyncMarker get currentAsyncMarker => AsyncMarker.SYNC;
/// Add [element] to the current scope and check for duplicate definitions.
void addToScope(Element element) {
if (element is FormalElement && element.isUnnamed) {
// No duplicate names possible.
Element existing = scope.add(element);
if (existing != element) {
reportDuplicateDefinition(, element, existing);
void checkLocalDefinitionName(Node node, Element element) {
if (currentAsyncMarker != AsyncMarker.SYNC) {
if ( == 'yield' || == 'async' || == 'await') {
{'keyword':, 'modifier': currentAsyncMarker});
/// Register [node] as the definition of [element].
void defineLocalVariable(Node node, LocalVariableElement element) {
if (element == null) {
throw reporter.internalError(node, 'element is null');
checkLocalDefinitionName(node, element);
registry.defineElement(node, element);
void reportDuplicateDefinition(
String name, Spannable definition, Spannable existing) {
definition, MessageKind.DUPLICATE_DEFINITION, {'name': name}),
existing, MessageKind.EXISTING_DEFINITION, {'name': name}),