blob: fd7576f8267635ca57f24d4d662fd51674f9763a [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.result;
import '../constants/expressions.dart';
import '../elements/resolution_types.dart';
import '../elements/elements.dart';
import '../tree/tree.dart';
import '../universe/call_structure.dart' show CallStructure;
enum ResultKind {
NONE,
ELEMENT,
TYPE,
ASSERT,
CONSTANT,
PREFIX,
}
/// The result of resolving a node.
abstract class ResolutionResult {
const ResolutionResult();
// TODO(johnniwinther): Remove this factory constructor when `null` is never
// passed as an element result.
factory ResolutionResult.forElement(Element element) {
return element != null ? new ElementResult(element) : const NoneResult();
}
ResultKind get kind;
Node get node => null;
Element get element => null;
ResolutionDartType get type => null;
ConstantExpression get constant => null;
bool get isConstant => false;
}
/// The prefix of top level or member access, like `prefix.member`,
/// `prefix.Class.member` or `Class.member`.
class PrefixResult extends ResolutionResult {
final PrefixElement prefix;
final ClassElement cls;
PrefixResult(this.prefix, this.cls);
Element get element => cls != null ? cls : prefix;
bool get isDeferred => prefix != null && prefix.isDeferred;
ResultKind get kind => ResultKind.PREFIX;
String toString() => 'PrefixResult($prefix,$cls)';
}
/// The result for the resolution of a node that points to an [Element].
class ElementResult extends ResolutionResult {
final Element element;
ResultKind get kind => ResultKind.ELEMENT;
ElementResult(this.element) {
assert(element != null);
}
String toString() => 'ElementResult($element)';
}
/// The result for the resolution of a node that points to an
/// [ResolutionDartType].
class TypeResult extends ResolutionResult {
final ResolutionDartType type;
TypeResult(this.type) {
assert(type != null);
}
ResultKind get kind => ResultKind.TYPE;
Element get element => type.element;
String toString() => 'TypeResult($type)';
}
/// The result for resolving a constant expression.
class ConstantResult extends ResolutionResult {
final Node node;
final ConstantExpression constant;
final Element element;
/// Creates a result for the [constant] expression. [node] is provided for
/// error reporting on the constant and [element] is provided if the
/// expression additionally serves an [Element] like [ElementResult].
ConstantResult(this.node, this.constant, {this.element});
bool get isConstant => true;
ResultKind get kind => ResultKind.CONSTANT;
String toString() => 'ConstantResult(${constant.toDartText()})';
}
class NoneResult extends ResolutionResult {
const NoneResult();
ResultKind get kind => ResultKind.NONE;
String toString() => 'NoneResult()';
}
/// The result of resolving a list of arguments.
class ArgumentsResult {
/// The call structure of the arguments.
final CallStructure callStructure;
/// The resolutions results for each argument.
final List<ResolutionResult> argumentResults;
/// `true` if the arguments are valid as arguments to a constructed constant
/// expression.
final bool isValidAsConstant;
ArgumentsResult(this.callStructure, this.argumentResults,
{this.isValidAsConstant});
/// Returns the list of [ConstantExpression]s for each of the arguments. If
/// [isValidAsConstant] is `false`, `null` is returned.
List<ConstantExpression> get constantArguments {
if (!isValidAsConstant) return null;
return argumentResults.map((ResolutionResult result) {
return result.constant;
}).toList();
}
}