Support for RecordState in DartObjectPrinter.

Change-Id: I44481daa436916841620491529178036fc46456a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/260003
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
Konstantin Shcheglov 2022-09-20 16:05:05 +00:00 committed by Commit Bot
parent 84b71e55d4
commit 139344eb28
3 changed files with 151 additions and 66 deletions

View file

@ -158,18 +158,18 @@ class DartObjectImpl implements DartObject {
final DartType type;
/// The state of the object.
final InstanceState _state;
final InstanceState state;
@override
final VariableElement? variable;
/// Initialize a newly created object to have the given [type] and [_state].
DartObjectImpl(this._typeSystem, this.type, this._state, {this.variable});
/// Initialize a newly created object to have the given [type] and [state].
DartObjectImpl(this._typeSystem, this.type, this.state, {this.variable});
/// Creates a duplicate instance of [other], tied to [variable].
factory DartObjectImpl.forVariable(
DartObjectImpl other, VariableElement variable) {
return DartObjectImpl(other._typeSystem, other.type, other._state,
return DartObjectImpl(other._typeSystem, other.type, other.state,
variable: variable);
}
@ -190,42 +190,42 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(typeSystem, type, GenericState.UNKNOWN_VALUE);
}
Map<String, DartObjectImpl>? get fields => _state.fields;
Map<String, DartObjectImpl>? get fields => state.fields;
@override
int get hashCode => Object.hash(type, _state);
int get hashCode => Object.hash(type, state);
@override
bool get hasKnownValue => !_state.isUnknown;
bool get hasKnownValue => !state.isUnknown;
/// Return `true` if this object represents an object whose type is 'bool'.
bool get isBool => _state.isBool;
bool get isBool => state.isBool;
/// Return `true` if this object represents an object whose type is either
/// 'bool', 'num', 'String', or 'Null'.
bool get isBoolNumStringOrNull => _state.isBoolNumStringOrNull;
bool get isBoolNumStringOrNull => state.isBoolNumStringOrNull;
/// Return `true` if this object represents an object whose type is 'int'.
bool get isInt => _state.isInt;
bool get isInt => state.isInt;
@override
bool get isNull => _state is NullState;
bool get isNull => state is NullState;
/// Return `true` if this object represents an unknown value.
bool get isUnknown => _state.isUnknown;
bool get isUnknown => state.isUnknown;
/// Return `true` if this object represents an instance of a user-defined
/// class.
bool get isUserDefinedObject => _state is GenericState;
bool get isUserDefinedObject => state is GenericState;
@visibleForTesting
List<DartType>? get typeArguments => (_state as FunctionState)._typeArguments;
List<DartType>? get typeArguments => (state as FunctionState)._typeArguments;
@override
bool operator ==(Object other) {
if (other is DartObjectImpl) {
return _typeSystem.runtimeTypesEqual(type, other.type) &&
_state == other._state;
state == other.state;
}
return false;
}
@ -236,7 +236,7 @@ class DartObjectImpl implements DartObject {
/// Throws an [EvaluationException] if the operator is not appropriate for an
/// object of this kind.
DartObjectImpl add(TypeSystemImpl typeSystem, DartObjectImpl rightOperand) {
InstanceState result = _state.add(rightOperand._state);
InstanceState result = state.add(rightOperand.state);
if (result is IntState) {
return DartObjectImpl(
typeSystem,
@ -268,7 +268,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.intType,
_state.bitNot(),
state.bitNot(),
);
}
@ -276,7 +276,7 @@ class DartObjectImpl implements DartObject {
DartObjectImpl castToType(
TypeSystemImpl typeSystem, DartObjectImpl castType) {
_assertType(castType);
var resultType = (castType._state as TypeState)._type;
var resultType = (castType.state as TypeState)._type;
// If we don't know the type, we cannot prove that the cast will fail.
if (resultType == null) {
@ -306,7 +306,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.stringType,
_state.concatenate(rightOperand._state),
state.concatenate(rightOperand.state),
);
}
@ -319,7 +319,7 @@ class DartObjectImpl implements DartObject {
if (identical(type, boolType)) {
return this;
}
return DartObjectImpl(typeSystem, boolType, _state.convertToBool());
return DartObjectImpl(typeSystem, boolType, state.convertToBool());
}
/// Return the result of invoking the '/' operator on this object with the
@ -329,7 +329,7 @@ class DartObjectImpl implements DartObject {
/// an object of this kind.
DartObjectImpl divide(
TypeSystemImpl typeSystem, DartObjectImpl rightOperand) {
InstanceState result = _state.divide(rightOperand._state);
InstanceState result = state.divide(rightOperand.state);
if (result is IntState) {
return DartObjectImpl(
typeSystem,
@ -358,13 +358,13 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.logicalAnd(rightOperand._state),
state.logicalAnd(rightOperand.state),
);
} else if (isInt && rightOperand.isInt) {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.intType,
_state.bitAnd(rightOperand._state),
state.bitAnd(rightOperand.state),
);
}
throw EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT);
@ -381,13 +381,13 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.logicalOr(rightOperand._state),
state.logicalOr(rightOperand.state),
);
} else if (isInt && rightOperand.isInt) {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.intType,
_state.bitOr(rightOperand._state),
state.bitOr(rightOperand.state),
);
}
throw EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT);
@ -404,13 +404,13 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.logicalXor(rightOperand._state),
state.logicalXor(rightOperand.state),
);
} else if (isInt && rightOperand.isInt) {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.intType,
_state.bitXor(rightOperand._state),
state.bitXor(rightOperand.state),
);
}
throw EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT);
@ -436,7 +436,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.equalEqual(typeSystem, rightOperand._state),
state.equalEqual(typeSystem, rightOperand.state),
);
}
throw EvaluationException(
@ -445,7 +445,7 @@ class DartObjectImpl implements DartObject {
@override
DartObject? getField(String name) {
InstanceState state = _state;
final state = this.state;
if (state is GenericState) {
return state.fields[name];
} else if (state is RecordState) {
@ -457,7 +457,7 @@ class DartObjectImpl implements DartObject {
/// Gets the constructor that was called to create this value, if this is a
/// const constructor invocation. Otherwise returns null.
ConstructorInvocation? getInvocation() {
InstanceState state = _state;
final state = this.state;
if (state is GenericState) {
return state.invocation;
}
@ -474,7 +474,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.greaterThan(rightOperand._state),
state.greaterThan(rightOperand.state),
);
}
@ -488,7 +488,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.greaterThanOrEqual(rightOperand._state),
state.greaterThanOrEqual(rightOperand.state),
);
}
@ -496,7 +496,7 @@ class DartObjectImpl implements DartObject {
/// [testedType].
DartObjectImpl hasType(TypeSystemImpl typeSystem, DartObjectImpl testedType) {
_assertType(testedType);
var typeType = (testedType._state as TypeState)._type;
var typeType = (testedType.state as TypeState)._type;
BoolState state;
if (typeType == null) {
state = BoolState.TRUE_STATE;
@ -516,7 +516,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.intType,
_state.integerDivide(rightOperand._state),
state.integerDivide(rightOperand.state),
);
}
@ -561,7 +561,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.isIdentical(typeSystem, rightOperand._state),
state.isIdentical(typeSystem, rightOperand.state),
);
}
@ -575,7 +575,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.lazyAnd(() => rightOperandComputer()?._state),
state.lazyAnd(() => rightOperandComputer()?.state),
);
}
@ -599,7 +599,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.lazyEqualEqual(typeSystem, rightOperand._state),
state.lazyEqualEqual(typeSystem, rightOperand.state),
);
}
throw EvaluationException(
@ -616,7 +616,7 @@ class DartObjectImpl implements DartObject {
DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.lazyOr(() => rightOperandComputer()?._state),
state.lazyOr(() => rightOperandComputer()?.state),
);
/// Return the result of invoking the '&lt;' operator on this object with the
@ -629,7 +629,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.lessThan(rightOperand._state),
state.lessThan(rightOperand.state),
);
}
@ -643,7 +643,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.lessThanOrEqual(rightOperand._state),
state.lessThanOrEqual(rightOperand.state),
);
}
@ -655,7 +655,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.boolType,
_state.logicalNot(),
state.logicalNot(),
);
}
@ -669,7 +669,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.intType,
_state.logicalShiftRight(rightOperand._state),
state.logicalShiftRight(rightOperand.state),
);
}
@ -679,7 +679,7 @@ class DartObjectImpl implements DartObject {
/// Throws an [EvaluationException] if the operator is not appropriate for an
/// object of this kind.
DartObjectImpl minus(TypeSystemImpl typeSystem, DartObjectImpl rightOperand) {
InstanceState result = _state.minus(rightOperand._state);
InstanceState result = state.minus(rightOperand.state);
if (result is IntState) {
return DartObjectImpl(
typeSystem,
@ -702,7 +702,7 @@ class DartObjectImpl implements DartObject {
/// Throws an [EvaluationException] if the operator is not appropriate for an
/// object of this kind.
DartObjectImpl negated(TypeSystemImpl typeSystem) {
InstanceState result = _state.negated();
InstanceState result = state.negated();
if (result is IntState) {
return DartObjectImpl(
typeSystem,
@ -739,7 +739,7 @@ class DartObjectImpl implements DartObject {
if (identical(type, stringType)) {
return this;
}
return DartObjectImpl(typeSystem, stringType, _state.convertToString());
return DartObjectImpl(typeSystem, stringType, state.convertToString());
}
/// Return the result of invoking the '%' operator on this object with the
@ -749,7 +749,7 @@ class DartObjectImpl implements DartObject {
/// object of this kind.
DartObjectImpl remainder(
TypeSystemImpl typeSystem, DartObjectImpl rightOperand) {
InstanceState result = _state.remainder(rightOperand._state);
InstanceState result = state.remainder(rightOperand.state);
if (result is IntState) {
return DartObjectImpl(
typeSystem,
@ -777,7 +777,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.intType,
_state.shiftLeft(rightOperand._state),
state.shiftLeft(rightOperand.state),
);
}
@ -791,7 +791,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.intType,
_state.shiftRight(rightOperand._state),
state.shiftRight(rightOperand.state),
);
}
@ -803,7 +803,7 @@ class DartObjectImpl implements DartObject {
return DartObjectImpl(
typeSystem,
typeSystem.typeProvider.intType,
_state.stringLength(),
state.stringLength(),
);
}
@ -813,7 +813,7 @@ class DartObjectImpl implements DartObject {
/// Throws an [EvaluationException] if the operator is not appropriate for an
/// object of this kind.
DartObjectImpl times(TypeSystemImpl typeSystem, DartObjectImpl rightOperand) {
InstanceState result = _state.times(rightOperand._state);
InstanceState result = state.times(rightOperand.state);
if (result is IntState) {
return DartObjectImpl(
typeSystem,
@ -833,7 +833,7 @@ class DartObjectImpl implements DartObject {
@override
bool? toBoolValue() {
InstanceState state = _state;
final state = this.state;
if (state is BoolState) {
return state.value;
}
@ -842,7 +842,7 @@ class DartObjectImpl implements DartObject {
@override
double? toDoubleValue() {
InstanceState state = _state;
final state = this.state;
if (state is DoubleState) {
return state.value;
}
@ -851,13 +851,13 @@ class DartObjectImpl implements DartObject {
@override
ExecutableElement? toFunctionValue() {
InstanceState state = _state;
final state = this.state;
return state is FunctionState ? state._element : null;
}
@override
int? toIntValue() {
InstanceState state = _state;
final state = this.state;
if (state is IntState) {
return state.value;
}
@ -866,7 +866,7 @@ class DartObjectImpl implements DartObject {
@override
List<DartObject>? toListValue() {
InstanceState state = _state;
final state = this.state;
if (state is ListState) {
return state._elements;
}
@ -875,7 +875,7 @@ class DartObjectImpl implements DartObject {
@override
Map<DartObjectImpl, DartObjectImpl>? toMapValue() {
InstanceState state = _state;
final state = this.state;
if (state is MapState) {
return state._entries;
}
@ -884,7 +884,7 @@ class DartObjectImpl implements DartObject {
@override
Set<DartObject>? toSetValue() {
InstanceState state = _state;
final state = this.state;
if (state is SetState) {
return state._elements;
}
@ -893,12 +893,12 @@ class DartObjectImpl implements DartObject {
@override
String toString() {
return "${type.getDisplayString(withNullability: false)} ($_state)";
return "${type.getDisplayString(withNullability: false)} ($state)";
}
@override
String? toStringValue() {
InstanceState state = _state;
final state = this.state;
if (state is StringState) {
return state.value;
}
@ -907,7 +907,7 @@ class DartObjectImpl implements DartObject {
@override
String? toSymbolValue() {
InstanceState state = _state;
final state = this.state;
if (state is SymbolState) {
return state.value;
}
@ -916,7 +916,7 @@ class DartObjectImpl implements DartObject {
@override
DartType? toTypeValue() {
InstanceState state = _state;
final state = this.state;
if (state is TypeState) {
return state._type;
}
@ -931,7 +931,7 @@ class DartObjectImpl implements DartObject {
FunctionType type,
List<DartType> typeArguments,
) {
var functionState = _state as FunctionState;
var functionState = state as FunctionState;
return DartObjectImpl(
typeSystem,
type,
@ -948,7 +948,7 @@ class DartObjectImpl implements DartObject {
required int index,
required String name,
}) {
var fields = _state.fields!;
var fields = state.fields!;
fields['index'] = DartObjectImpl(
_typeSystem,
_typeSystem.typeProvider.intType,
@ -964,7 +964,7 @@ class DartObjectImpl implements DartObject {
/// Throw an exception if the given [object]'s state does not represent a Type
/// value.
void _assertType(DartObjectImpl object) {
if (object._state is! TypeState) {
if (object.state is! TypeState) {
throw EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_TYPE);
}
}
@ -2559,7 +2559,7 @@ class RecordState extends InstanceState {
for (var i = 0; i < positionalCount; i++) {
var result = positionalFields[i]
.equalEqual(typeSystem, otherPositionalFields[i])
._state;
.state;
if (result is! BoolState) {
return BoolState.FALSE_STATE;
} else if (result != BoolState.TRUE_STATE) {
@ -2571,7 +2571,7 @@ class RecordState extends InstanceState {
if (otherValue == null) {
return BoolState.FALSE_STATE;
}
var result = entry.value.equalEqual(typeSystem, otherValue)._state;
var result = entry.value.equalEqual(typeSystem, otherValue).state;
if (result is! BoolState) {
return BoolState.FALSE_STATE;
} else if (result != BoolState.TRUE_STATE) {

View file

@ -600,6 +600,54 @@ E<String>
expect(value, null);
}
test_record_mixed() async {
await assertNoErrorsInCode(r'''
const x = (0, f1: 10, f2: 2.3);
''');
final value = _topVarConstValue('x');
assertDartObjectText(value, r'''
Record
positionalFields
$0: int 0
namedFields
f1: int 10
f2: double 2.3
variable: self::@variable::x
''');
}
test_record_named() async {
await assertNoErrorsInCode(r'''
const x = (f1: 10, f2: -3);
''');
final value = _topVarConstValue('x');
assertDartObjectText(value, r'''
Record
namedFields
f1: int 10
f2: int -3
variable: self::@variable::x
''');
}
test_record_positional() async {
await assertNoErrorsInCode(r'''
const x = (20, 0, 7);
''');
final value = _topVarConstValue('x');
assertDartObjectText(value, r'''
Record
positionalFields
$0: int 20
$1: int 0
$2: int 7
variable: self::@variable::x
''');
}
@failingTest
test_simpleIdentifier_invalid() async {
var result = await _getExpressionValue("?");
@ -981,6 +1029,10 @@ $context
var element = findElement.topVar(name) as ConstTopLevelVariableElementImpl;
return element.evaluationResult!;
}
DartObjectImpl _topVarConstValue(String name) {
return _topVarConstResult(name).value!;
}
}
class _UnitElementResult {

View file

@ -23,6 +23,7 @@ class DartObjectPrinter {
void write(DartObjectImpl? object) {
if (object != null) {
final type = object.type;
final state = object.state;
if (object.isUnknown) {
sink.write(
type.getDisplayString(
@ -71,6 +72,8 @@ class DartObjectPrinter {
}
}
});
} else if (state is RecordState) {
_writeRecord(state);
} else {
throw UnimplementedError();
}
@ -114,6 +117,36 @@ class DartObjectPrinter {
sink.writeln(line);
}
void _writeRecord(RecordState state) {
sink.writeln('Record');
_withIndent(() {
final positionalFields = state.positionalFields;
if (positionalFields.isNotEmpty) {
_writelnWithIndent('positionalFields');
_withIndent(() {
positionalFields.forEachIndexed((index, field) {
sink.write(indent);
sink.write('\$$index: ');
write(field);
});
});
}
final namedFields = state.namedFields;
if (namedFields.isNotEmpty) {
_writelnWithIndent('namedFields');
_withIndent(() {
final entries = namedFields.entries.sortedBy((entry) => entry.key);
for (final entry in entries) {
sink.write(indent);
sink.write('${entry.key}: ');
write(entry.value);
}
});
}
});
}
void _writeVariable(DartObjectImpl object) {
final variable = object.variable;
if (variable is VariableElementImpl) {