blob: 53d3c69b7cf3d3fb9d729f5b228d368fd2740db2 [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 '../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;
CommonResolverVisitor(this.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(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),
super(resolution);
AsyncMarker get currentAsyncMarker => AsyncMarker.SYNC;
/// Add [element] to the current scope and check for duplicate definitions.
void addToScope(Element element) {
Element existing = scope.add(element);
if (existing != element) {
reportDuplicateDefinition(element.name, element, existing);
}
}
void checkLocalDefinitionName(Node node, Element element) {
if (currentAsyncMarker != AsyncMarker.SYNC) {
if (element.name == 'yield' ||
element.name == 'async' ||
element.name == 'await') {
reporter.reportErrorMessage(
node,
MessageKind.ASYNC_KEYWORD_AS_IDENTIFIER,
{'keyword': element.name, '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) {
reporter.reportError(
reporter.createMessage(
definition, MessageKind.DUPLICATE_DEFINITION, {'name': name}),
<DiagnosticMessage>[
reporter.createMessage(
existing, MessageKind.EXISTING_DEFINITION, {'name': name}),
]);
}
}