From 139344eb28c1fb19eb9c5fbc3db690b18bc0f1a6 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Tue, 20 Sep 2022 16:05:05 +0000 Subject: [PATCH] Support for RecordState in DartObjectPrinter. Change-Id: I44481daa436916841620491529178036fc46456a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/260003 Reviewed-by: Brian Wilkerson Commit-Queue: Konstantin Shcheglov Reviewed-by: Samuel Rawlins --- pkg/analyzer/lib/src/dart/constant/value.dart | 132 +++++++++--------- .../test/generated/constant_test.dart | 52 +++++++ .../dart/resolution/dart_object_printer.dart | 33 +++++ 3 files changed, 151 insertions(+), 66 deletions(-) diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart index 5a9b012866b..2ae32bc14a5 100644 --- a/pkg/analyzer/lib/src/dart/constant/value.dart +++ b/pkg/analyzer/lib/src/dart/constant/value.dart @@ -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? get fields => _state.fields; + Map? 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? get typeArguments => (_state as FunctionState)._typeArguments; + List? 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 '<' 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? 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? 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? 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 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) { diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart index 40c90d51aae..ac0159b58d7 100644 --- a/pkg/analyzer/test/generated/constant_test.dart +++ b/pkg/analyzer/test/generated/constant_test.dart @@ -600,6 +600,54 @@ E 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 { diff --git a/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart b/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart index 40861f1d8ce..1cd5b3cff26 100644 --- a/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart +++ b/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart @@ -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) {