From bdacb7d0349e751617930bfb9eb3fbd7f70c8a0a Mon Sep 17 00:00:00 2001 From: Johnni Winther Date: Fri, 1 Nov 2024 09:26:44 +0000 Subject: [PATCH] [_fe_analyzer_shared] Add evaluateExpression This adds a helper method that evaluates an [Expression] based on the semantics that can be deduced from the syntax. Change-Id: I1b54ee03c1380d337969671133179aa557702a9b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392440 Reviewed-by: Konstantin Shcheglov Commit-Queue: Johnni Winther --- .../analysis_options_no_lints.yaml | 1 + .../lib/src/metadata/evaluate.dart | 600 ++++++++++++++++++ .../lib/src/testing/metadata_helper.dart | 19 +- .../evaluate_data/adjacent_strings.dart | 24 + .../test/metadata/evaluate_data/binary.dart | 129 ++++ .../metadata/evaluate_data/conditional.dart | 25 + .../evaluate_data/constructor_invocation.dart | 32 + .../test/metadata/evaluate_data/equality.dart | 58 ++ .../metadata/evaluate_data/identical.dart | 19 + .../test/metadata/evaluate_data/if_null.dart | 63 ++ .../test/metadata/evaluate_data/is_as.dart | 19 + .../metadata/evaluate_data/list_literal.dart | 221 +++++++ .../test/metadata/evaluate_data/logical.dart | 81 +++ .../metadata/evaluate_data/marker.options | 3 + .../metadata/evaluate_data/null_check.dart | 27 + .../metadata/evaluate_data/parenthesized.dart | 13 + .../metadata/evaluate_data/property_get.dart | 37 ++ .../evaluate_data/record_literal.dart | 27 + .../evaluate_data/set_or_map_literal.dart | 389 ++++++++++++ .../evaluate_data/string_interpolation.dart | 58 ++ .../test/metadata/evaluate_data/unary.dart | 47 ++ .../test/id_tests/metadata_evaluate_test.dart | 74 +++ .../test/id_tests/metadata_evaluate_test.dart | 75 +++ 23 files changed, 2040 insertions(+), 1 deletion(-) create mode 100644 pkg/_fe_analyzer_shared/lib/src/metadata/evaluate.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/adjacent_strings.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/binary.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/conditional.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/constructor_invocation.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/equality.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/identical.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/if_null.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/is_as.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/list_literal.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/logical.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/marker.options create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/null_check.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/parenthesized.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/property_get.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/record_literal.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/set_or_map_literal.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/string_interpolation.dart create mode 100644 pkg/_fe_analyzer_shared/test/metadata/evaluate_data/unary.dart create mode 100644 pkg/analyzer/test/id_tests/metadata_evaluate_test.dart create mode 100644 pkg/front_end/test/id_tests/metadata_evaluate_test.dart diff --git a/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml index dd47ce52df37..c39ff3c5487c 100644 --- a/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml +++ b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml @@ -21,3 +21,4 @@ analyzer: - test/inference/inferred_variable_types/data/** - test/inheritance/data/** - test/metadata/data/** + - test/metadata/evaluate_data/** diff --git a/pkg/_fe_analyzer_shared/lib/src/metadata/evaluate.dart b/pkg/_fe_analyzer_shared/lib/src/metadata/evaluate.dart new file mode 100644 index 000000000000..050c7be85af3 --- /dev/null +++ b/pkg/_fe_analyzer_shared/lib/src/metadata/evaluate.dart @@ -0,0 +1,600 @@ +// Copyright (c) 2024, 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. + +import 'ast.dart'; + +/// Evaluates an [expression] based on the semantics that can be deduced from +/// the syntax. +Expression evaluateExpression(Expression expression) { + return new Evaluator().evaluate(expression); +} + +class Evaluator { + Expression evaluate(Expression expression) { + return _visitExpression(expression); + } + + Expression _visitExpression(Expression expression) { + switch (expression) { + case StaticGet(): + // TODO(johnniwinther): Support inlining constant values. + return expression; + case InvalidExpression(): + case FunctionTearOff(): + case ConstructorTearOff(): + case IntegerLiteral(): + case DoubleLiteral(): + case BooleanLiteral(): + case NullLiteral(): + case SymbolLiteral(): + return expression; + case ConstructorInvocation(): + return new ConstructorInvocation(expression.type, + expression.constructor, _visitArguments(expression.arguments)); + case StringLiteral(): + return _visitStringLiteral(expression); + case AdjacentStringLiterals(): + return _visitAdjacentStringLiterals(expression); + case ImplicitInvocation(): + return new ImplicitInvocation(_visitExpression(expression.receiver), + expression.typeArguments, _visitArguments(expression.arguments)); + case StaticInvocation(): + return new StaticInvocation(expression.function, + expression.typeArguments, _visitArguments(expression.arguments)); + case Instantiation(): + return new Instantiation( + _visitExpression(expression.receiver), expression.typeArguments); + case MethodInvocation(): + return new MethodInvocation( + _visitExpression(expression.receiver), + expression.name, + expression.typeArguments, + _visitArguments(expression.arguments)); + case PropertyGet(): + Expression receiver = _visitExpression(expression.receiver); + if (expression.name == 'length') { + if (receiver case StringLiteral(parts: [StringPart(:String text)])) { + return new IntegerLiteral.fromValue(text.length); + } + } + return new PropertyGet(receiver, expression.name); + case NullAwarePropertyGet(): + Expression receiver = _visitExpression(expression.receiver); + return switch (_isNull(receiver)) { + NullValue.isNull => new NullLiteral(), + NullValue.isNonNull => + _visitExpression(new PropertyGet(receiver, expression.name)), + NullValue.unknown => + new NullAwarePropertyGet(receiver, expression.name), + }; + case TypeLiteral(): + return expression; + case ParenthesizedExpression(): + return _visitExpression(expression.expression); + case ConditionalExpression(): + Expression condition = _visitExpression(expression.condition); + return switch (condition) { + BooleanLiteral(value: true) => _visitExpression(expression.then), + BooleanLiteral(value: false) => + _visitExpression(expression.otherwise), + _ => new ConditionalExpression( + condition, + _visitExpression(expression.then), + _visitExpression(expression.otherwise)), + }; + case ListLiteral(): + return new ListLiteral( + expression.typeArguments, _visitElements(expression.elements)); + case SetOrMapLiteral(): + return new SetOrMapLiteral( + expression.typeArguments, _visitElements(expression.elements)); + case RecordLiteral(): + return new RecordLiteral(_visitRecordFields(expression.fields)); + case IfNull(): + Expression left = _visitExpression(expression.left); + return switch (_isNull(left)) { + NullValue.isNull => _visitExpression(expression.right), + NullValue.isNonNull => left, + NullValue.unknown => + new IfNull(left, _visitExpression(expression.right)), + }; + case LogicalExpression(): + return _visitLogicalExpression(expression); + case EqualityExpression(): + return _visitEqualityExpression(expression); + case BinaryExpression(): + return _visitBinaryExpression(expression); + case UnaryExpression(): + return _visitUnaryExpression(expression); + case IsTest(): + return new IsTest( + _visitExpression(expression.expression), expression.type, + isNot: expression.isNot); + case AsExpression(): + return new AsExpression( + _visitExpression(expression.expression), expression.type); + case NullCheck(): + Expression operand = _visitExpression(expression.expression); + return switch (_isNull(operand)) { + // This is known to fail but we have no way to represent failure. + NullValue.isNull => new NullCheck(operand), + NullValue.isNonNull => operand, + NullValue.unknown => new NullCheck(operand) + }; + + case UnresolvedExpression(): + return expression; + } + } + + Expression _visitStringLiteral(StringLiteral expression) { + if (expression.parts.length == 1 && expression.parts.single is StringPart) { + return expression; + } + List evaluatedParts = []; + StringBuffer? stringBuffer; + + void flush() { + if (stringBuffer != null) { + String text = stringBuffer.toString(); + if (text.isNotEmpty) { + evaluatedParts.add(new StringPart(stringBuffer.toString())); + } + stringBuffer = null; + } + } + + for (StringLiteralPart part in expression.parts) { + for (StringLiteralPart evaluatedPart in _visitStringLiteralPart(part)) { + switch (evaluatedPart) { + case StringPart(): + (stringBuffer ??= new StringBuffer()).write(evaluatedPart.text); + case InterpolationPart(): + flush(); + evaluatedParts.add(evaluatedPart); + } + } + } + flush(); + + if (evaluatedParts.isEmpty) { + evaluatedParts.add(new StringPart(stringBuffer.toString())); + } + return new StringLiteral(evaluatedParts); + } + + Expression _visitAdjacentStringLiterals(AdjacentStringLiterals expression) { + List evaluatedParts = []; + List? stringLiteralParts; + + void flush() { + if (stringLiteralParts != null) { + StringLiteral stringLiteral = new StringLiteral(stringLiteralParts); + evaluatedParts.add(_visitExpression(stringLiteral)); + } + } + + for (Expression part in expression.expressions) { + Expression evaluatedPart = _visitExpression(part); + switch (evaluatedPart) { + case StringLiteral(:List parts): + (stringLiteralParts ??= []).addAll(parts); + default: + flush(); + evaluatedParts.add(evaluatedPart); + } + } + + flush(); + if (evaluatedParts.length == 1) { + return evaluatedParts.single; + } + return new AdjacentStringLiterals(evaluatedParts); + } + + Expression _visitLogicalExpression(LogicalExpression expression) { + Expression left = _visitExpression(expression.left); + return switch (left) { + BooleanLiteral(value: true) => switch (expression.operator) { + LogicalOperator.and => _visitExpression(expression.right), + LogicalOperator.or => left, + }, + BooleanLiteral(value: false) => switch (expression.operator) { + LogicalOperator.and => left, + LogicalOperator.or => _visitExpression(expression.right), + }, + _ => new LogicalExpression( + left, expression.operator, _visitExpression(expression.right)), + }; + } + + Expression _visitEqualityExpression(EqualityExpression expression) { + Expression leftExpression = _visitExpression(expression.left); + Expression rightExpression = _visitExpression(expression.right); + switch ((leftExpression, rightExpression)) { + case ( + NullLiteral(), + NullLiteral(), + ): + return new BooleanLiteral(!expression.isNotEquals); + case (IntegerLiteral(value: int left), IntegerLiteral(value: int right)): + return new BooleanLiteral( + expression.isNotEquals ? left != right : left == right); + default: + // TODO(johnniwinther): Support all cases. + return new EqualityExpression(leftExpression, rightExpression, + isNotEquals: expression.isNotEquals); + } + } + + Expression? _visitBinaryIntExpression( + int left, BinaryOperator operator, int right) { + switch (operator) { + case BinaryOperator.lessThan: + return new BooleanLiteral(left < right); + case BinaryOperator.lessThanOrEqual: + return new BooleanLiteral(left <= right); + case BinaryOperator.greaterThan: + return new BooleanLiteral(left > right); + case BinaryOperator.greaterThanOrEqual: + return new BooleanLiteral(left >= right); + case BinaryOperator.bitwiseOr: + return new IntegerLiteral.fromValue(left | right); + case BinaryOperator.bitwiseXor: + return new IntegerLiteral.fromValue(left ^ right); + case BinaryOperator.bitwiseAnd: + return new IntegerLiteral.fromValue(left & right); + case BinaryOperator.shiftLeft: + return new IntegerLiteral.fromValue(left << right); + case BinaryOperator.unsignedShiftRight: + return new IntegerLiteral.fromValue(left >> right); + case BinaryOperator.signedShiftRight: + return new IntegerLiteral.fromValue(left >>> right); + case BinaryOperator.plus: + return new IntegerLiteral.fromValue(left + right); + case BinaryOperator.minus: + return new IntegerLiteral.fromValue(left - right); + case BinaryOperator.times: + return new IntegerLiteral.fromValue(left * right); + case BinaryOperator.divide: + if (right != 0) { + double value = left / right; + return new DoubleLiteral('$value', value); + } + case BinaryOperator.modulo: + if (right != 0) { + return new IntegerLiteral.fromValue(left % right); + } + case BinaryOperator.integerDivide: + if (right != 0) { + return new IntegerLiteral.fromValue(left ~/ right); + } + } + return null; + } + + Expression _visitBinaryExpression(BinaryExpression expression) { + Expression leftExpression = _visitExpression(expression.left); + Expression rightExpression = _visitExpression(expression.right); + + switch ((leftExpression, rightExpression)) { + case (IntegerLiteral(value: int left), IntegerLiteral(value: int right)): + return _visitBinaryIntExpression(left, expression.operator, right) ?? + new BinaryExpression( + leftExpression, expression.operator, rightExpression); + default: + // TODO(johnniwinther): Support more cases. + return new BinaryExpression( + leftExpression, expression.operator, rightExpression); + } + } + + Expression _visitUnaryExpression(UnaryExpression expression) { + Expression operand = _visitExpression(expression.expression); + switch ((expression.operator, operand)) { + case (UnaryOperator.minus, IntegerLiteral(:int value)): + return new IntegerLiteral.fromValue(-value); + case (UnaryOperator.bang, BooleanLiteral(:bool value)): + return new BooleanLiteral(!value); + case (UnaryOperator.tilde, IntegerLiteral(:int value)): + return new IntegerLiteral.fromValue(~value); + default: + // TODO(johnniwinther): Support more cases. + return new UnaryExpression(expression.operator, operand); + } + } + + List _visitStringLiteralPart(StringLiteralPart part) { + switch (part) { + case StringPart(): + return [part]; + case InterpolationPart(): + Expression expression = _visitExpression(part.expression); + return switch (expression) { + StringLiteral() => expression.parts, + NullLiteral() => [new StringPart('null')], + BooleanLiteral(:bool value) => [new StringPart('$value')], + IntegerLiteral(:int value) => [new StringPart('$value')], + DoubleLiteral(:double value) => [new StringPart('$value')], + _ => [new InterpolationPart(expression)], + }; + } + } + + List _visitArguments(List arguments) { + List list = []; + for (Argument argument in arguments) { + switch (argument) { + case PositionalArgument(): + list.add( + new PositionalArgument(_visitExpression(argument.expression))); + case NamedArgument(): + list.add(new NamedArgument( + argument.name, _visitExpression(argument.expression))); + } + } + return list; + } + + List _visitRecordFields(List fields) { + List list = []; + for (RecordField field in fields) { + switch (field) { + case RecordNamedField(): + list.add(new RecordNamedField( + field.name, _visitExpression(field.expression))); + case RecordPositionalField(): + list.add( + new RecordPositionalField(_visitExpression(field.expression))); + } + } + return list; + } + + List _visitElements(List elements) { + List list = []; + for (Element element in elements) { + switch (element) { + case ExpressionElement(): + Expression expression = _visitExpression(element.expression); + bool isNullAware = element.isNullAware; + if (isNullAware) { + switch (_isNull(expression)) { + case NullValue.isNull: + // Skip element. + continue; + case NullValue.isNonNull: + isNullAware = false; + case NullValue.unknown: + } + } + list.add(new ExpressionElement(expression, isNullAware: isNullAware)); + case MapEntryElement(): + Expression key = _visitExpression(element.key); + Expression value = _visitExpression(element.value); + bool isNullAwareKey = element.isNullAwareKey; + bool isNullAwareValue = element.isNullAwareValue; + if (isNullAwareKey) { + switch (_isNull(key)) { + case NullValue.isNull: + // Skip entry. + continue; + case NullValue.isNonNull: + isNullAwareKey = false; + case NullValue.unknown: + } + } + if (isNullAwareValue) { + switch (_isNull(value)) { + case NullValue.isNull: + // Skip entry. + continue; + case NullValue.isNonNull: + isNullAwareValue = false; + case NullValue.unknown: + } + } + list.add(new MapEntryElement(key, value, + isNullAwareKey: isNullAwareKey, + isNullAwareValue: isNullAwareValue)); + case SpreadElement(): + Expression expression = _visitExpression(element.expression); + bool isNullAware = element.isNullAware; + if (isNullAware) { + switch (_isNull(expression)) { + case NullValue.isNull: + // Skip element. + continue; + case NullValue.isNonNull: + isNullAware = false; + case NullValue.unknown: + } + } + if (isNullAware) { + list.add(new SpreadElement(expression, isNullAware: true)); + } else { + switch (expression) { + case ListLiteral(): + list.addAll(_visitElements(expression.elements)); + case SetOrMapLiteral(): + list.addAll(_visitElements(expression.elements)); + default: + list.add(new SpreadElement(expression, isNullAware: false)); + } + } + case IfElement(): + Expression condition = _visitExpression(element.condition); + switch (condition) { + case BooleanLiteral(value: true): + list.addAll(_visitElements([element.then])); + case BooleanLiteral(value: false): + if (element.otherwise != null) { + list.addAll(_visitElements([element.otherwise!])); + } + default: + Element? then = _visitElement(element.then); + Element? otherwise = element.otherwise != null + ? _visitElement(element.otherwise!) + : null; + if (then != null) { + list.add(new IfElement(condition, then, otherwise)); + } else if (otherwise != null) { + list.add(new IfElement( + new UnaryExpression(UnaryOperator.bang, condition), + otherwise)); + } else { + // Skip element. + continue; + } + } + } + } + return list; + } + + Element? _visitElement(Element element) { + switch (element) { + case ExpressionElement(): + Expression expression = _visitExpression(element.expression); + bool isNullAware = element.isNullAware; + if (isNullAware) { + switch (_isNull(expression)) { + case NullValue.isNull: + // Skip element. + return null; + case NullValue.isNonNull: + isNullAware = false; + case NullValue.unknown: + } + } + return new ExpressionElement(expression, + isNullAware: element.isNullAware); + case MapEntryElement(): + Expression key = _visitExpression(element.key); + Expression value = _visitExpression(element.value); + bool isNullAwareKey = element.isNullAwareKey; + bool isNullAwareValue = element.isNullAwareValue; + if (isNullAwareKey) { + switch (_isNull(key)) { + case NullValue.isNull: + // Skip entry. + return null; + case NullValue.isNonNull: + isNullAwareKey = false; + case NullValue.unknown: + } + } + if (isNullAwareValue) { + switch (_isNull(value)) { + case NullValue.isNull: + // Skip entry. + return null; + case NullValue.isNonNull: + isNullAwareValue = false; + case NullValue.unknown: + } + } + return new MapEntryElement(key, value, + isNullAwareKey: isNullAwareKey, isNullAwareValue: isNullAwareValue); + case SpreadElement(): + Expression expression = _visitExpression(element.expression); + bool isNullAware = element.isNullAware; + if (isNullAware) { + switch (_isNull(expression)) { + case NullValue.isNull: + // Skip element. + return null; + case NullValue.isNonNull: + isNullAware = false; + case NullValue.unknown: + } + } + if (isNullAware) { + return new SpreadElement(expression, isNullAware: true); + } else { + switch (expression) { + case ListLiteral(elements: []): + case SetOrMapLiteral(elements: []): + // Empty spread. + return null; + default: + return new SpreadElement(expression, isNullAware: false); + } + } + case IfElement(): + Expression condition = _visitExpression(element.condition); + switch (condition) { + case BooleanLiteral(value: true): + return _visitElement(element.then); + case BooleanLiteral(value: false): + if (element.otherwise != null) { + return _visitElement(element.otherwise!); + } else { + return null; + } + default: + Element? then = _visitElement(element.then); + Element? otherwise = element.otherwise != null + ? _visitElement(element.otherwise!) + : null; + if (then != null) { + return new IfElement(condition, then, otherwise); + } else if (otherwise != null) { + return new IfElement( + new UnaryExpression(UnaryOperator.bang, condition), + otherwise); + } else { + // Skip element. + return null; + } + } + } + } + + NullValue _isNull(Expression expression) { + return switch (expression) { + NullLiteral() => NullValue.isNull, + BooleanLiteral() => NullValue.isNonNull, + IntegerLiteral() => NullValue.isNonNull, + DoubleLiteral() => NullValue.isNonNull, + StringLiteral() => NullValue.isNonNull, + SymbolLiteral() => NullValue.isNonNull, + AdjacentStringLiterals() => NullValue.isNonNull, + EqualityExpression() => NullValue.isNonNull, + FunctionTearOff() => NullValue.isNonNull, + IsTest() => NullValue.isNonNull, + ListLiteral() => NullValue.isNonNull, + SetOrMapLiteral() => NullValue.isNonNull, + LogicalExpression() => NullValue.isNonNull, + ConstructorTearOff() => NullValue.isNonNull, + ConstructorInvocation() => NullValue.isNonNull, + Instantiation() => NullValue.isNonNull, + TypeLiteral() => NullValue.isNonNull, + RecordLiteral() => NullValue.isNonNull, + NullCheck() => NullValue.isNonNull, + + // TODO(johnniwinther): Should the subexpressions be visited? + ParenthesizedExpression() => NullValue.unknown, + ConditionalExpression() => NullValue.unknown, + IfNull() => NullValue.unknown, + BinaryExpression() => NullValue.unknown, + UnaryExpression() => NullValue.unknown, + PropertyGet() => NullValue.unknown, + NullAwarePropertyGet() => NullValue.unknown, + StaticGet() => NullValue.unknown, + StaticInvocation() => NullValue.unknown, + InvalidExpression() => NullValue.unknown, + ImplicitInvocation() => NullValue.unknown, + MethodInvocation() => NullValue.unknown, + AsExpression() => NullValue.unknown, + UnresolvedExpression() => NullValue.unknown, + }; + } +} + +enum NullValue { + isNull, + isNonNull, + unknown, +} diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/metadata_helper.dart b/pkg/_fe_analyzer_shared/lib/src/testing/metadata_helper.dart index 950429a9a677..ebbf160ffd7a 100644 --- a/pkg/_fe_analyzer_shared/lib/src/testing/metadata_helper.dart +++ b/pkg/_fe_analyzer_shared/lib/src/testing/metadata_helper.dart @@ -4,6 +4,8 @@ import 'package:_fe_analyzer_shared/src/metadata/ast.dart'; +import '../metadata/evaluate.dart'; + /// Returns the arguments expression, if [expression] is of the form /// `Helper(foo)`, and [expression] otherwise. /// @@ -23,6 +25,19 @@ Expression unwrap(Expression expression) { return expression; } +/// Creates a list containing structured and readable textual representation of +/// the [resolved] expression and the result of evaluating [resolved]. +List evaluationToText(Expression resolved) { + List list = []; + + Expression unwrappedResolved = unwrap(resolved); + list.add('resolved=${expressionToText(unwrappedResolved)}'); + list.add( + 'evaluate=${expressionToText(evaluateExpression(unwrappedResolved))}'); + + return list; +} + /// Creates a list containing structured and readable textual representation of /// the [unresolved] and [resolved] expressions. List expressionsToText( @@ -35,7 +50,8 @@ List expressionsToText( // its resolved equivalent. Expression lateResolved = unresolved.resolve() ?? unresolved; - String earlyResolvedText = expressionToText(unwrap(resolved)); + Expression unwrappedResolved = unwrap(resolved); + String earlyResolvedText = expressionToText(unwrappedResolved); String lateResolvedText = expressionToText(unwrap(lateResolved)); // These should always be the same. If not we include both to @@ -46,6 +62,7 @@ List expressionsToText( list.add('early-resolved=${earlyResolvedText}'); list.add('late-resolved=${lateResolvedText}'); } + return list; } diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/adjacent_strings.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/adjacent_strings.dart new file mode 100644 index 000000000000..bf31f0949da8 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/adjacent_strings.dart @@ -0,0 +1,24 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +@Helper("a" "b") +/*member: adjacentStrings1: +resolved=AdjacentStringLiterals( + StringLiteral('a') + StringLiteral('b')) +evaluate=StringLiteral('ab')*/ +void adjacentStrings1() {} + +@Helper("a" "b" "c") +/*member: adjacentStrings2: +resolved=AdjacentStringLiterals( + StringLiteral('a') + StringLiteral('b') + StringLiteral('c')) +evaluate=StringLiteral('abc')*/ +void adjacentStrings2() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/binary.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/binary.dart new file mode 100644 index 000000000000..6e5d48b5e8af --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/binary.dart @@ -0,0 +1,129 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +const int constInt = 42; + +@Helper(1 < 2) +/*member: binary1: +resolved=BinaryExpression(IntegerLiteral(1) < IntegerLiteral(2)) +evaluate=BooleanLiteral(true)*/ +void binary1() {} + +@Helper(1 <= 2) +/*member: binary2: +resolved=BinaryExpression(IntegerLiteral(1) <= IntegerLiteral(2)) +evaluate=BooleanLiteral(true)*/ +void binary2() {} + +@Helper(1 > 2) +/*member: binary3: +resolved=BinaryExpression(IntegerLiteral(1) > IntegerLiteral(2)) +evaluate=BooleanLiteral(false)*/ +void binary3() {} + +@Helper(1 >= 2) +/*member: binary4: +resolved=BinaryExpression(IntegerLiteral(1) >= IntegerLiteral(2)) +evaluate=BooleanLiteral(false)*/ +void binary4() {} + +@Helper(1 | 2) +/*member: binary5: +resolved=BinaryExpression(IntegerLiteral(1) | IntegerLiteral(2)) +evaluate=IntegerLiteral(value=3)*/ +void binary5() {} + +@Helper(1 ^ 2) +/*member: binary6: +resolved=BinaryExpression(IntegerLiteral(1) ^ IntegerLiteral(2)) +evaluate=IntegerLiteral(value=3)*/ +void binary6() {} + +@Helper(1 & 2) +/*member: binary7: +resolved=BinaryExpression(IntegerLiteral(1) & IntegerLiteral(2)) +evaluate=IntegerLiteral(value=0)*/ +void binary7() {} + +@Helper(1 >> 2) +/*member: binary8: +resolved=BinaryExpression(IntegerLiteral(1) >> IntegerLiteral(2)) +evaluate=IntegerLiteral(value=0)*/ +void binary8() {} + +@Helper(1 >>> 2) +/*member: binary9: +resolved=BinaryExpression(IntegerLiteral(1) >>> IntegerLiteral(2)) +evaluate=IntegerLiteral(value=0)*/ +void binary9() {} + +@Helper(1 << 2) +/*member: binary10: +resolved=BinaryExpression(IntegerLiteral(1) << IntegerLiteral(2)) +evaluate=IntegerLiteral(value=4)*/ +void binary10() {} + +@Helper(1 + 2) +/*member: binary11: +resolved=BinaryExpression(IntegerLiteral(1) + IntegerLiteral(2)) +evaluate=IntegerLiteral(value=3)*/ +void binary11() {} + +@Helper(1 - 2) +/*member: binary12: +resolved=BinaryExpression(IntegerLiteral(1) - IntegerLiteral(2)) +evaluate=IntegerLiteral(value=-1)*/ +void binary12() {} + +@Helper(1 * 2) +/*member: binary13: +resolved=BinaryExpression(IntegerLiteral(1) * IntegerLiteral(2)) +evaluate=IntegerLiteral(value=2)*/ +void binary13() {} + +@Helper(1 / 2) +/*member: binary14: +resolved=BinaryExpression(IntegerLiteral(1) / IntegerLiteral(2)) +evaluate=DoubleLiteral(0.5)*/ +void binary14() {} + +@Helper(1 / 0) +/*member: binary15: +resolved=BinaryExpression(IntegerLiteral(1) / IntegerLiteral(0)) +evaluate=BinaryExpression(IntegerLiteral(1) / IntegerLiteral(0))*/ +void binary15() {} + +@Helper(1 ~/ 2) +/*member: binary16: +resolved=BinaryExpression(IntegerLiteral(1) ~/ IntegerLiteral(2)) +evaluate=IntegerLiteral(value=0)*/ +void binary16() {} + +@Helper(1 ~/ 0) +/*member: binary17: +resolved=BinaryExpression(IntegerLiteral(1) ~/ IntegerLiteral(0)) +evaluate=BinaryExpression(IntegerLiteral(1) ~/ IntegerLiteral(0))*/ +void binary17() {} + +@Helper(1 % 2) +/*member: binary18: +resolved=BinaryExpression(IntegerLiteral(1) % IntegerLiteral(2)) +evaluate=IntegerLiteral(value=1)*/ +void binary18() {} + +@Helper(1 / 0) +/*member: binary19: +resolved=BinaryExpression(IntegerLiteral(1) / IntegerLiteral(0)) +evaluate=BinaryExpression(IntegerLiteral(1) / IntegerLiteral(0))*/ +void binary19() {} + +@Helper(1 + constInt) +/*member: binary20: +resolved=BinaryExpression(IntegerLiteral(1) + StaticGet(constInt)) +evaluate=BinaryExpression(IntegerLiteral(1) + StaticGet(constInt))*/ +void binary20() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/conditional.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/conditional.dart new file mode 100644 index 000000000000..b300c4bd9904 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/conditional.dart @@ -0,0 +1,25 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +@Helper(true ? 0 : 1) +/*member: conditional1: +resolved=ConditionalExpression( + BooleanLiteral(true) + ? IntegerLiteral(0) + : IntegerLiteral(1)) +evaluate=IntegerLiteral(0)*/ +void conditional1() {} + +@Helper(false ? 0 : 1) +/*member: conditional2: +resolved=ConditionalExpression( + BooleanLiteral(false) + ? IntegerLiteral(0) + : IntegerLiteral(1)) +evaluate=IntegerLiteral(1)*/ +void conditional2() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/constructor_invocation.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/constructor_invocation.dart new file mode 100644 index 000000000000..ad07d7c97b0d --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/constructor_invocation.dart @@ -0,0 +1,32 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +class Class { + const Class([a]); + const Class.named({a}); +} + +@Class("a" "b") +/*member: constructorInvocation1: +resolved=ConstructorInvocation( + Class.new(AdjacentStringLiterals( + StringLiteral('a') + StringLiteral('b')))) +evaluate=ConstructorInvocation( + Class.new(StringLiteral('ab')))*/ +void constructorInvocation1() {} + +@Class.named(a: "a" "b") +/*member: constructorInvocation2: +resolved=ConstructorInvocation( + Class.named(a: AdjacentStringLiterals( + StringLiteral('a') + StringLiteral('b')))) +evaluate=ConstructorInvocation( + Class.named(a: StringLiteral('ab')))*/ +void constructorInvocation2() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/equality.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/equality.dart new file mode 100644 index 000000000000..a319c6222f15 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/equality.dart @@ -0,0 +1,58 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +const int constInt = 42; + +@Helper(null == null) +/*member: equalityExpression1: +resolved=EqualityExpression(NullLiteral() == NullLiteral()) +evaluate=BooleanLiteral(true)*/ +void equalityExpression1() {} + +@Helper(null != null) +/*member: equalityExpression2: +resolved=EqualityExpression(NullLiteral() != NullLiteral()) +evaluate=BooleanLiteral(false)*/ +void equalityExpression2() {} + +@Helper(0 == 0) +/*member: equalityExpression3: +resolved=EqualityExpression(IntegerLiteral(0) == IntegerLiteral(0)) +evaluate=BooleanLiteral(true)*/ +void equalityExpression3() {} + +@Helper(0 != 0) +/*member: equalityExpression4: +resolved=EqualityExpression(IntegerLiteral(0) != IntegerLiteral(0)) +evaluate=BooleanLiteral(false)*/ +void equalityExpression4() {} + +@Helper(0 == 1) +/*member: equalityExpression5: +resolved=EqualityExpression(IntegerLiteral(0) == IntegerLiteral(1)) +evaluate=BooleanLiteral(false)*/ +void equalityExpression5() {} + +@Helper(0 != 1) +/*member: equalityExpression6: +resolved=EqualityExpression(IntegerLiteral(0) != IntegerLiteral(1)) +evaluate=BooleanLiteral(true)*/ +void equalityExpression6() {} + +@Helper(constInt == 1) +/*member: equalityExpression7: +resolved=EqualityExpression(StaticGet(constInt) == IntegerLiteral(1)) +evaluate=EqualityExpression(StaticGet(constInt) == IntegerLiteral(1))*/ +void equalityExpression7() {} + +@Helper(constInt != 1) +/*member: equalityExpression8: +resolved=EqualityExpression(StaticGet(constInt) != IntegerLiteral(1)) +evaluate=EqualityExpression(StaticGet(constInt) != IntegerLiteral(1))*/ +void equalityExpression8() {} + diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/identical.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/identical.dart new file mode 100644 index 000000000000..de619c8e3c1a --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/identical.dart @@ -0,0 +1,19 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +@Helper(identical(true, false)) +/*member: identicalCall1: +resolved=StaticInvocation( + identical( + BooleanLiteral(true), + BooleanLiteral(false))) +evaluate=StaticInvocation( + identical( + BooleanLiteral(true), + BooleanLiteral(false)))*/ +void identicalCall1() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/if_null.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/if_null.dart new file mode 100644 index 000000000000..1ca9ccc841b2 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/if_null.dart @@ -0,0 +1,63 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +const int? constNullableInt = 42; + +@Helper(0 ?? 1) +/*member: ifNull1: +resolved=IfNull( + IntegerLiteral(0) + ?? + IntegerLiteral(1) +) +evaluate=IntegerLiteral(0)*/ +void ifNull1() {} + +@Helper(null ?? 1) +/*member: ifNull2: +resolved=IfNull( + NullLiteral() + ?? + IntegerLiteral(1) +) +evaluate=IntegerLiteral(1)*/ +void ifNull2() {} + +@Helper(1 ?? null) +/*member: ifNull3: +resolved=IfNull( + IntegerLiteral(1) + ?? + NullLiteral() +) +evaluate=IntegerLiteral(1)*/ +void ifNull3() {} + +@Helper(null ?? null) +/*member: ifNull4: +resolved=IfNull( + NullLiteral() + ?? + NullLiteral() +) +evaluate=NullLiteral()*/ +void ifNull4() {} + +@Helper(constNullableInt ?? 0) +/*member: ifNull5: +resolved=IfNull( + StaticGet(constNullableInt) + ?? + IntegerLiteral(0) +) +evaluate=IfNull( + StaticGet(constNullableInt) + ?? + IntegerLiteral(0) +)*/ +void ifNull5() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/is_as.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/is_as.dart new file mode 100644 index 000000000000..1e4ead0509ed --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/is_as.dart @@ -0,0 +1,19 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +@Helper((1 + 2) as int) +/*member: as1: +resolved=AsExpression(ParenthesizedExpression(BinaryExpression(IntegerLiteral(1) + IntegerLiteral(2))) as int) +evaluate=AsExpression(IntegerLiteral(value=3) as int)*/ +void as1() {} + +@Helper((1 + 2) is int) +/*member: is1: +resolved=IsTest(ParenthesizedExpression(BinaryExpression(IntegerLiteral(1) + IntegerLiteral(2))) is int) +evaluate=IsTest(IntegerLiteral(value=3) is int)*/ +void is1() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/list_literal.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/list_literal.dart new file mode 100644 index 000000000000..4c3994391679 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/list_literal.dart @@ -0,0 +1,221 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +const bool constBool = true; + +const int constInt = 42; + +const List constList = [2, 3]; + +@Helper([0]) +/*member: listLiteral1: +resolved=ListLiteral([ExpressionElement(IntegerLiteral(0))]) +evaluate=ListLiteral([ExpressionElement(IntegerLiteral(0))])*/ +void listLiteral1() {} + +@Helper([?0]) +/*member: listLiteral2: +resolved=ListLiteral([ExpressionElement(?IntegerLiteral(0))]) +evaluate=ListLiteral([ExpressionElement(IntegerLiteral(0))])*/ +void listLiteral2() {} + +@Helper([?null]) +/*member: listLiteral3: +resolved=ListLiteral([ExpressionElement(?NullLiteral())]) +evaluate=ListLiteral([])*/ +void listLiteral3() {} + +@Helper([?constInt]) +/*member: listLiteral4: +resolved=ListLiteral([ExpressionElement(?StaticGet(constInt))]) +evaluate=ListLiteral([ExpressionElement(?StaticGet(constInt))])*/ +void listLiteral4() {} + +@Helper([if (true) 1]) +/*member: listLiteral5: +resolved=ListLiteral([IfElement( + BooleanLiteral(true), + ExpressionElement(IntegerLiteral(1)))]) +evaluate=ListLiteral([ExpressionElement(IntegerLiteral(1))])*/ +void listLiteral5() {} + +@Helper([if (false) 1]) +/*member: listLiteral6: +resolved=ListLiteral([IfElement( + BooleanLiteral(false), + ExpressionElement(IntegerLiteral(1)))]) +evaluate=ListLiteral([])*/ +void listLiteral6() {} + +@Helper([if (constBool) 1]) +/*member: listLiteral7: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)))]) +evaluate=ListLiteral([IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)))])*/ +void listLiteral7() {} + +@Helper([if (true) 1 else 2]) +/*member: listLiteral8: +resolved=ListLiteral([IfElement( + BooleanLiteral(true), + ExpressionElement(IntegerLiteral(1)), + ExpressionElement(IntegerLiteral(2)))]) +evaluate=ListLiteral([ExpressionElement(IntegerLiteral(1))])*/ +void listLiteral8() {} + +@Helper([if (false) 1 else 2]) +/*member: listLiteral9: +resolved=ListLiteral([IfElement( + BooleanLiteral(false), + ExpressionElement(IntegerLiteral(1)), + ExpressionElement(IntegerLiteral(2)))]) +evaluate=ListLiteral([ExpressionElement(IntegerLiteral(2))])*/ +void listLiteral9() {} + +@Helper([if (constBool) 1 else 2]) +/*member: listLiteral10: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)), + ExpressionElement(IntegerLiteral(2)))]) +evaluate=ListLiteral([IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)), + ExpressionElement(IntegerLiteral(2)))])*/ +void listLiteral10() {} + +@Helper([...[0, 1]]) +/*member: listLiteral11: +resolved=ListLiteral([SpreadElement(...ListLiteral([ + ExpressionElement(IntegerLiteral(0)), + ExpressionElement(IntegerLiteral(1))]))]) +evaluate=ListLiteral([ + ExpressionElement(IntegerLiteral(0)), + ExpressionElement(IntegerLiteral(1))])*/ +void listLiteral11() {} + +@Helper([...constList]) +/*member: listLiteral12: +resolved=ListLiteral([SpreadElement(...StaticGet(constList))]) +evaluate=ListLiteral([SpreadElement(...StaticGet(constList))])*/ +void listLiteral12() {} + +@Helper([...?[0, 1]]) +/*member: listLiteral13: +resolved=ListLiteral([SpreadElement(?...ListLiteral([ + ExpressionElement(IntegerLiteral(0)), + ExpressionElement(IntegerLiteral(1))]))]) +evaluate=ListLiteral([ + ExpressionElement(IntegerLiteral(0)), + ExpressionElement(IntegerLiteral(1))])*/ +void listLiteral13() {} + +@Helper([...?constList]) +/*member: listLiteral14: +resolved=ListLiteral([SpreadElement(?...StaticGet(constList))]) +evaluate=ListLiteral([SpreadElement(?...StaticGet(constList))])*/ +void listLiteral14() {} + +@Helper([...?null]) +/*member: listLiteral15: +resolved=ListLiteral([SpreadElement(?...NullLiteral())]) +evaluate=ListLiteral([])*/ +void listLiteral15() {} + +@Helper([if (constBool) ?null]) +/*member: listLiteral16: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + ExpressionElement(?NullLiteral()))]) +evaluate=ListLiteral([])*/ +void listLiteral16() {} + +@Helper([if (constBool) ?null else 2]) +/*member: listLiteral17: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + ExpressionElement(?NullLiteral()), + ExpressionElement(IntegerLiteral(2)))]) +evaluate=ListLiteral([IfElement( + UnaryExpression(!StaticGet(constBool)), + ExpressionElement(IntegerLiteral(2)))])*/ +void listLiteral17() {} + +@Helper([if (constBool) 1 else ?null]) +/*member: listLiteral18: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)), + ExpressionElement(?NullLiteral()))]) +evaluate=ListLiteral([IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)))])*/ +void listLiteral18() {} + +@Helper([if (constBool) ?null else ?null]) +/*member: listLiteral19: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + ExpressionElement(?NullLiteral()), + ExpressionElement(?NullLiteral()))]) +evaluate=ListLiteral([])*/ +void listLiteral19() {} + +@Helper([if (constBool) ...[]]) +/*member: listLiteral20: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + SpreadElement(...ListLiteral([])))]) +evaluate=ListLiteral([])*/ +void listLiteral20() {} + +@Helper([if (constBool) ...{}]) +/*member: listLiteral21: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + SpreadElement(...SetOrMapLiteral({})))]) +evaluate=ListLiteral([])*/ +void listLiteral21() {} + +@Helper([if (constBool) ...?[]]) +/*member: listLiteral22: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + SpreadElement(?...ListLiteral([])))]) +evaluate=ListLiteral([])*/ +void listLiteral22() {} + +@Helper([if (constBool) ...?{}]) +/*member: listLiteral23: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + SpreadElement(?...SetOrMapLiteral({})))]) +evaluate=ListLiteral([])*/ +void listLiteral23() {} + +@Helper([if (constBool) ...?null]) +/*member: listLiteral24: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + SpreadElement(?...NullLiteral()))]) +evaluate=ListLiteral([])*/ +void listLiteral24() {} + +@Helper([if (constBool) if (constBool) ?null else ?null]) +/*member: listLiteral25: +resolved=ListLiteral([IfElement( + StaticGet(constBool), + IfElement( + StaticGet(constBool), + ExpressionElement(?NullLiteral()), + ExpressionElement(?NullLiteral())))]) +evaluate=ListLiteral([])*/ +void listLiteral25() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/logical.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/logical.dart new file mode 100644 index 000000000000..a6045001d26a --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/logical.dart @@ -0,0 +1,81 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +const bool constBool = true; + +@Helper(true && true) +/*member: logicalExpression1: +resolved=LogicalExpression(BooleanLiteral(true) && BooleanLiteral(true)) +evaluate=BooleanLiteral(true)*/ +void logicalExpression1() {} + +@Helper(true && false) +/*member: logicalExpression2: +resolved=LogicalExpression(BooleanLiteral(true) && BooleanLiteral(false)) +evaluate=BooleanLiteral(false)*/ +void logicalExpression2() {} + +@Helper(false && true) +/*member: logicalExpression3: +resolved=LogicalExpression(BooleanLiteral(false) && BooleanLiteral(true)) +evaluate=BooleanLiteral(false)*/ +void logicalExpression3() {} + +@Helper(false && false) +/*member: logicalExpression4: +resolved=LogicalExpression(BooleanLiteral(false) && BooleanLiteral(false)) +evaluate=BooleanLiteral(false)*/ +void logicalExpression4() {} + +@Helper(true || true) +/*member: logicalExpression5: +resolved=LogicalExpression(BooleanLiteral(true) || BooleanLiteral(true)) +evaluate=BooleanLiteral(true)*/ +void logicalExpression5() {} + +@Helper(true || false) +/*member: logicalExpression6: +resolved=LogicalExpression(BooleanLiteral(true) || BooleanLiteral(false)) +evaluate=BooleanLiteral(true)*/ +void logicalExpression6() {} + +@Helper(false || true) +/*member: logicalExpression7: +resolved=LogicalExpression(BooleanLiteral(false) || BooleanLiteral(true)) +evaluate=BooleanLiteral(true)*/ +void logicalExpression7() {} + +@Helper(false || false) +/*member: logicalExpression8: +resolved=LogicalExpression(BooleanLiteral(false) || BooleanLiteral(false)) +evaluate=BooleanLiteral(false)*/ +void logicalExpression8() {} + +@Helper(constBool && true) +/*member: logicalExpression9: +resolved=LogicalExpression(StaticGet(constBool) && BooleanLiteral(true)) +evaluate=LogicalExpression(StaticGet(constBool) && BooleanLiteral(true))*/ +void logicalExpression9() {} + +@Helper(constBool && false) +/*member: logicalExpression10: +resolved=LogicalExpression(StaticGet(constBool) && BooleanLiteral(false)) +evaluate=LogicalExpression(StaticGet(constBool) && BooleanLiteral(false))*/ +void logicalExpression10() {} + +@Helper(constBool || true) +/*member: logicalExpression11: +resolved=LogicalExpression(StaticGet(constBool) || BooleanLiteral(true)) +evaluate=LogicalExpression(StaticGet(constBool) || BooleanLiteral(true))*/ +void logicalExpression11() {} + +@Helper(constBool || false) +/*member: logicalExpression12: +resolved=LogicalExpression(StaticGet(constBool) || BooleanLiteral(false)) +evaluate=LogicalExpression(StaticGet(constBool) || BooleanLiteral(false))*/ +void logicalExpression12() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/marker.options b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/marker.options new file mode 100644 index 000000000000..d7c479d80af9 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/marker.options @@ -0,0 +1,3 @@ +cfe=pkg/front_end/test/id_tests/metadata_evaluate_test.dart +analyzer=pkg/analyzer/test/id_tests/metadata_evaluate_test.dart + diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/null_check.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/null_check.dart new file mode 100644 index 000000000000..d8b06a031985 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/null_check.dart @@ -0,0 +1,27 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +const int constInt = 42; + +@Helper(0!) +/*member: nullCheck1: +resolved=NullCheck(IntegerLiteral(0)) +evaluate=IntegerLiteral(0)*/ +void nullCheck1() {} + +@Helper(null!) +/*member: nullCheck2: +resolved=NullCheck(NullLiteral()) +evaluate=NullCheck(NullLiteral())*/ +void nullCheck2() {} + +@Helper(constInt!) +/*member: nullCheck3: +resolved=NullCheck(StaticGet(constInt)) +evaluate=NullCheck(StaticGet(constInt))*/ +void nullCheck3() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/parenthesized.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/parenthesized.dart new file mode 100644 index 000000000000..6626b2801960 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/parenthesized.dart @@ -0,0 +1,13 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +@Helper((1)) +/*member: parenthesized1: +resolved=ParenthesizedExpression(IntegerLiteral(1)) +evaluate=IntegerLiteral(1)*/ +void parenthesized1() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/property_get.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/property_get.dart new file mode 100644 index 000000000000..6f63b027b2c9 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/property_get.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +@Helper("foo".length) +/*member: propertyGet1: +resolved=PropertyGet(StringLiteral('foo').length) +evaluate=IntegerLiteral(value=3)*/ +void propertyGet1() {} + +@Helper("foo"?.length) +/*member: propertyGet2: +resolved=NullAwarePropertyGet(StringLiteral('foo')?.length) +evaluate=IntegerLiteral(value=3)*/ +void propertyGet2() {} + +@Helper((true ? "foo" : null)?.length) +/*member: propertyGet3: +resolved=NullAwarePropertyGet(ParenthesizedExpression(ConditionalExpression( + BooleanLiteral(true) + ? StringLiteral('foo') + : NullLiteral()))?.length) +evaluate=IntegerLiteral(value=3)*/ +void propertyGet3() {} + +@Helper((false ? "foo" : null)?.length) +/*member: propertyGet4: +resolved=NullAwarePropertyGet(ParenthesizedExpression(ConditionalExpression( + BooleanLiteral(false) + ? StringLiteral('foo') + : NullLiteral()))?.length) +evaluate=NullLiteral()*/ +void propertyGet4() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/record_literal.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/record_literal.dart new file mode 100644 index 000000000000..2c0cfdae35f4 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/record_literal.dart @@ -0,0 +1,27 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +@Helper(("a" "b", c: "c" "d")) +/*member: recordLiteral1: +resolved=RecordLiteral(AdjacentStringLiterals( + StringLiteral('a') + StringLiteral('b')), c: AdjacentStringLiterals( + StringLiteral('c') + StringLiteral('d'))) +evaluate=RecordLiteral(StringLiteral('ab'), c: StringLiteral('cd'))*/ +void recordLiteral1() {} + +@Helper(("a" "b", c: (d: "c" "d"))) +/*member: recordLiteral2: +resolved=RecordLiteral(AdjacentStringLiterals( + StringLiteral('a') + StringLiteral('b')), c: RecordLiteral(d: AdjacentStringLiterals( + StringLiteral('c') + StringLiteral('d')))) +evaluate=RecordLiteral(StringLiteral('ab'), c: RecordLiteral(d: StringLiteral('cd')))*/ + void recordLiteral2() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/set_or_map_literal.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/set_or_map_literal.dart new file mode 100644 index 000000000000..34efa4b2b4b4 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/set_or_map_literal.dart @@ -0,0 +1,389 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +const bool constBool = true; + +const int constInt = 42; + +const List constList = [2, 3]; + +@Helper({0}) +/*member: setOrMapLiteral1: +resolved=SetOrMapLiteral({ExpressionElement(IntegerLiteral(0))}) +evaluate=SetOrMapLiteral({ExpressionElement(IntegerLiteral(0))})*/ +void setOrMapLiteral1() {} + +@Helper({?0}) +/*member: setOrMapLiteral2: +resolved=SetOrMapLiteral({ExpressionElement(?IntegerLiteral(0))}) +evaluate=SetOrMapLiteral({ExpressionElement(IntegerLiteral(0))})*/ +void setOrMapLiteral2() {} + +@Helper({?null}) +/*member: setOrMapLiteral3: +resolved=SetOrMapLiteral({ExpressionElement(?NullLiteral())}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral3() {} + +@Helper({?constInt}) +/*member: setOrMapLiteral4: +resolved=SetOrMapLiteral({ExpressionElement(?StaticGet(constInt))}) +evaluate=SetOrMapLiteral({ExpressionElement(?StaticGet(constInt))})*/ +void setOrMapLiteral4() {} + +@Helper({if (true) 1}) +/*member: setOrMapLiteral5: +resolved=SetOrMapLiteral({IfElement( + BooleanLiteral(true), + ExpressionElement(IntegerLiteral(1)))}) +evaluate=SetOrMapLiteral({ExpressionElement(IntegerLiteral(1))})*/ +void setOrMapLiteral5() {} + +@Helper({if (false) 1}) +/*member: setOrMapLiteral6: +resolved=SetOrMapLiteral({IfElement( + BooleanLiteral(false), + ExpressionElement(IntegerLiteral(1)))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral6() {} + +@Helper({if (constBool) 1}) +/*member: setOrMapLiteral7: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)))}) +evaluate=SetOrMapLiteral({IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)))})*/ +void setOrMapLiteral7() {} + +@Helper({if (true) 1 else 2}) +/*member: setOrMapLiteral8: +resolved=SetOrMapLiteral({IfElement( + BooleanLiteral(true), + ExpressionElement(IntegerLiteral(1)), + ExpressionElement(IntegerLiteral(2)))}) +evaluate=SetOrMapLiteral({ExpressionElement(IntegerLiteral(1))})*/ +void setOrMapLiteral8() {} + +@Helper({if (false) 1 else 2}) +/*member: setOrMapLiteral9: +resolved=SetOrMapLiteral({IfElement( + BooleanLiteral(false), + ExpressionElement(IntegerLiteral(1)), + ExpressionElement(IntegerLiteral(2)))}) +evaluate=SetOrMapLiteral({ExpressionElement(IntegerLiteral(2))})*/ +void setOrMapLiteral9() {} + +@Helper({if (constBool) 1 else 2}) +/*member: setOrMapLiteral10: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)), + ExpressionElement(IntegerLiteral(2)))}) +evaluate=SetOrMapLiteral({IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)), + ExpressionElement(IntegerLiteral(2)))})*/ +void setOrMapLiteral10() {} + +@Helper({...{0, 1}}) +/*member: setOrMapLiteral11: +resolved=SetOrMapLiteral({SpreadElement(...SetOrMapLiteral({ + ExpressionElement(IntegerLiteral(0)), + ExpressionElement(IntegerLiteral(1))}))}) +evaluate=SetOrMapLiteral({ + ExpressionElement(IntegerLiteral(0)), + ExpressionElement(IntegerLiteral(1))})*/ +void setOrMapLiteral11() {} + +@Helper({...constList}) +/*member: setOrMapLiteral12: +resolved=SetOrMapLiteral({SpreadElement(...StaticGet(constList))}) +evaluate=SetOrMapLiteral({SpreadElement(...StaticGet(constList))})*/ +void setOrMapLiteral12() {} + +@Helper({...?{0, 1}}) +/*member: setOrMapLiteral13: +resolved=SetOrMapLiteral({SpreadElement(?...SetOrMapLiteral({ + ExpressionElement(IntegerLiteral(0)), + ExpressionElement(IntegerLiteral(1))}))}) +evaluate=SetOrMapLiteral({ + ExpressionElement(IntegerLiteral(0)), + ExpressionElement(IntegerLiteral(1))})*/ +void setOrMapLiteral13() {} + +@Helper({...?constList}) +/*member: setOrMapLiteral14: +resolved=SetOrMapLiteral({SpreadElement(?...StaticGet(constList))}) +evaluate=SetOrMapLiteral({SpreadElement(?...StaticGet(constList))})*/ +void setOrMapLiteral14() {} + +@Helper({...?null}) +/*member: setOrMapLiteral15: +resolved=SetOrMapLiteral({SpreadElement(?...NullLiteral())}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral15() {} + +@Helper({if (constBool) ?null}) +/*member: setOrMapLiteral16: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + ExpressionElement(?NullLiteral()))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral16() {} + +@Helper({if (constBool) ?null else 2}) +/*member: setOrMapLiteral17: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + ExpressionElement(?NullLiteral()), + ExpressionElement(IntegerLiteral(2)))}) +evaluate=SetOrMapLiteral({IfElement( + UnaryExpression(!StaticGet(constBool)), + ExpressionElement(IntegerLiteral(2)))})*/ +void setOrMapLiteral17() {} + +@Helper({if (constBool) 1 else ?null}) +/*member: setOrMapLiteral18: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)), + ExpressionElement(?NullLiteral()))}) +evaluate=SetOrMapLiteral({IfElement( + StaticGet(constBool), + ExpressionElement(IntegerLiteral(1)))})*/ +void setOrMapLiteral18() {} + +@Helper({if (constBool) ?null else ?null}) +/*member: setOrMapLiteral19: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + ExpressionElement(?NullLiteral()), + ExpressionElement(?NullLiteral()))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral19() {} + +@Helper({if (constBool) ...[]}) +/*member: setOrMapLiteral20: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + SpreadElement(...ListLiteral([])))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral20() {} + +@Helper({if (constBool) ...[]}) +/*member: setOrMapLiteral21: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + SpreadElement(...ListLiteral([])))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral21() {} + +@Helper({if (constBool) ...?{}}) +/*member: setOrMapLiteral22: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + SpreadElement(?...SetOrMapLiteral({})))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral22() {} + +@Helper({if (constBool) ...?{}}) +/*member: setOrMapLiteral23: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + SpreadElement(?...SetOrMapLiteral({})))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral23() {} + +@Helper({if (constBool) ...?null}) +/*member: setOrMapLiteral24: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + SpreadElement(?...NullLiteral()))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral24() {} + +@Helper({if (constBool) if (constBool) ?null else ?null}) +/*member: setOrMapLiteral25: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + IfElement( + StaticGet(constBool), + ExpressionElement(?NullLiteral()), + ExpressionElement(?NullLiteral())))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral25() {} + +@Helper({0: 1}) +/*member: setOrMapLiteral26: +resolved=SetOrMapLiteral({MapEntryElement(IntegerLiteral(0):IntegerLiteral(1))}) +evaluate=SetOrMapLiteral({MapEntryElement(IntegerLiteral(0):IntegerLiteral(1))})*/ +void setOrMapLiteral26() {} + +@Helper({?0: 1}) +/*member: setOrMapLiteral27: +resolved=SetOrMapLiteral({MapEntryElement(?IntegerLiteral(0):IntegerLiteral(1))}) +evaluate=SetOrMapLiteral({MapEntryElement(IntegerLiteral(0):IntegerLiteral(1))})*/ +void setOrMapLiteral27() {} + +@Helper({0: ?1}) +/*member: setOrMapLiteral28: +resolved=SetOrMapLiteral({MapEntryElement(IntegerLiteral(0):?IntegerLiteral(1))}) +evaluate=SetOrMapLiteral({MapEntryElement(IntegerLiteral(0):IntegerLiteral(1))})*/ +void setOrMapLiteral28() {} + +@Helper({?0: ?1}) +/*member: setOrMapLiteral29: +resolved=SetOrMapLiteral({MapEntryElement(?IntegerLiteral(0):?IntegerLiteral(1))}) +evaluate=SetOrMapLiteral({MapEntryElement(IntegerLiteral(0):IntegerLiteral(1))})*/ +void setOrMapLiteral29() {} + +@Helper({?null: 1}) +/*member: setOrMapLiteral30: +resolved=SetOrMapLiteral({MapEntryElement(?NullLiteral():IntegerLiteral(1))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral30() {} + +@Helper({0: ?null}) +/*member: setOrMapLiteral31: +resolved=SetOrMapLiteral({MapEntryElement(IntegerLiteral(0):?NullLiteral())}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral31() {} + +@Helper({?null: ?null}) +/*member: setOrMapLiteral32: +resolved=SetOrMapLiteral({MapEntryElement(?NullLiteral():?NullLiteral())}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral32() {} + +@Helper({?constInt: 1}) +/*member: setOrMapLiteral33: +resolved=SetOrMapLiteral({MapEntryElement(?StaticGet(constInt):IntegerLiteral(1))}) +evaluate=SetOrMapLiteral({MapEntryElement(?StaticGet(constInt):IntegerLiteral(1))})*/ +void setOrMapLiteral33() {} + +@Helper({0: ?constInt}) +/*member: setOrMapLiteral34: +resolved=SetOrMapLiteral({MapEntryElement(IntegerLiteral(0):?StaticGet(constInt))}) +evaluate=SetOrMapLiteral({MapEntryElement(IntegerLiteral(0):?StaticGet(constInt))})*/ +void setOrMapLiteral34() {} + +@Helper({?constInt: ?constInt}) +/*member: setOrMapLiteral35: +resolved=SetOrMapLiteral({MapEntryElement(?StaticGet(constInt):?StaticGet(constInt))}) +evaluate=SetOrMapLiteral({MapEntryElement(?StaticGet(constInt):?StaticGet(constInt))})*/ +void setOrMapLiteral35() {} + +@Helper({if (constBool) ?null: 1}) +/*member: setOrMapLiteral36: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(?NullLiteral():IntegerLiteral(1)))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral36() {} + +@Helper({if (constBool) 0: ?null}) +/*member: setOrMapLiteral37: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(IntegerLiteral(0):?NullLiteral()))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral37() {} + +@Helper({if (constBool) ?null: ?null}) +/*member: setOrMapLiteral38: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(?NullLiteral():?NullLiteral()))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral38() {} + +@Helper({if (constBool) ?null: 1 else 2: 3}) +/*member: setOrMapLiteral39: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(?NullLiteral():IntegerLiteral(1)), + MapEntryElement(IntegerLiteral(2):IntegerLiteral(3)))}) +evaluate=SetOrMapLiteral({IfElement( + UnaryExpression(!StaticGet(constBool)), + MapEntryElement(IntegerLiteral(2):IntegerLiteral(3)))})*/ +void setOrMapLiteral39() {} + +@Helper({if (constBool) 0: ?null else 2: 3}) +/*member: setOrMapLiteral40: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(IntegerLiteral(0):?NullLiteral()), + MapEntryElement(IntegerLiteral(2):IntegerLiteral(3)))}) +evaluate=SetOrMapLiteral({IfElement( + UnaryExpression(!StaticGet(constBool)), + MapEntryElement(IntegerLiteral(2):IntegerLiteral(3)))})*/ +void setOrMapLiteral40() {} + +@Helper({if (constBool) ?null: ?null else 2: 3}) +/*member: setOrMapLiteral41: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(?NullLiteral():?NullLiteral()), + MapEntryElement(IntegerLiteral(2):IntegerLiteral(3)))}) +evaluate=SetOrMapLiteral({IfElement( + UnaryExpression(!StaticGet(constBool)), + MapEntryElement(IntegerLiteral(2):IntegerLiteral(3)))})*/ +void setOrMapLiteral41() {} + +@Helper({if (constBool) 1: 2 else ?null: 3}) +/*member: setOrMapLiteral42: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(IntegerLiteral(1):IntegerLiteral(2)), + MapEntryElement(?NullLiteral():IntegerLiteral(3)))}) +evaluate=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(IntegerLiteral(1):IntegerLiteral(2)))})*/ +void setOrMapLiteral42() {} + +@Helper({if (constBool) 1: 2 else 3: ?null}) +/*member: setOrMapLiteral43: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(IntegerLiteral(1):IntegerLiteral(2)), + MapEntryElement(IntegerLiteral(3):?NullLiteral()))}) +evaluate=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(IntegerLiteral(1):IntegerLiteral(2)))})*/ +void setOrMapLiteral43() {} + +@Helper({if (constBool) 1: 2 else ?null: ?null}) +/*member: setOrMapLiteral44: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(IntegerLiteral(1):IntegerLiteral(2)), + MapEntryElement(?NullLiteral():?NullLiteral()))}) +evaluate=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(IntegerLiteral(1):IntegerLiteral(2)))})*/ +void setOrMapLiteral44() {} + +@Helper({if (constBool) ?null: 1 else ?null: 2}) +/*member: setOrMapLiteral45: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(?NullLiteral():IntegerLiteral(1)), + MapEntryElement(?NullLiteral():IntegerLiteral(2)))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral45() {} + +@Helper({if (constBool) 1: ?null else 2: ?null}) +/*member: setOrMapLiteral46: +resolved=SetOrMapLiteral({IfElement( + StaticGet(constBool), + MapEntryElement(IntegerLiteral(1):?NullLiteral()), + MapEntryElement(IntegerLiteral(2):?NullLiteral()))}) +evaluate=SetOrMapLiteral({})*/ +void setOrMapLiteral46() {} diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/string_interpolation.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/string_interpolation.dart new file mode 100644 index 000000000000..aeb1e8fd8526 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/string_interpolation.dart @@ -0,0 +1,58 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +const bool constBool = true; + +@Helper("a ${"b"} c") +/*member: stringInterpolation1: +resolved=StringLiteral('a ${StringLiteral('b')} c') +evaluate=StringLiteral('a b c')*/ +void stringInterpolation1() {} + +@Helper("a ${null} c") +/*member: stringInterpolation2: +resolved=StringLiteral('a ${NullLiteral()} c') +evaluate=StringLiteral('a null c')*/ +void stringInterpolation2() {} + +@Helper("a ${true} c") +/*member: stringInterpolation3: +resolved=StringLiteral('a ${BooleanLiteral(true)} c') +evaluate=StringLiteral('a true c')*/ +void stringInterpolation3() {} + +@Helper("a ${false} c") +/*member: stringInterpolation4: +resolved=StringLiteral('a ${BooleanLiteral(false)} c') +evaluate=StringLiteral('a false c')*/ +void stringInterpolation4() {} + +@Helper("a ${0} c") +/*member: stringInterpolation5: +resolved=StringLiteral('a ${IntegerLiteral(0)} c') +evaluate=StringLiteral('a 0 c')*/ +void stringInterpolation5() {} + +@Helper("a ${0.5} c") +/*member: stringInterpolation6: +resolved=StringLiteral('a ${DoubleLiteral(0.5)} c') +evaluate=StringLiteral('a 0.5 c')*/ +void stringInterpolation6() {} + +@Helper("a ${"b ${"c"} d"} e") +/*member: stringInterpolation7: +resolved=StringLiteral('a ${StringLiteral('b ${StringLiteral('c')} d')} e') +evaluate=StringLiteral('a b c d e')*/ +void stringInterpolation7() {} + +@Helper("a ${" b ${constBool}"} c") +/*member: stringInterpolation8: +resolved=StringLiteral('a ${StringLiteral(' b ${StaticGet(constBool)}')} c') +evaluate=StringLiteral('a b ${StaticGet(constBool)} c')*/ +void stringInterpolation8() {} + diff --git a/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/unary.dart b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/unary.dart new file mode 100644 index 000000000000..096d24af44a0 --- /dev/null +++ b/pkg/_fe_analyzer_shared/test/metadata/evaluate_data/unary.dart @@ -0,0 +1,47 @@ +// Copyright (c) 2024, 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. + +class Helper { + const Helper(a); +} + +const bool constBool = true; + +const int constInt = 42; + +@Helper(!false) +/*member: unary1: +resolved=UnaryExpression(!BooleanLiteral(false)) +evaluate=BooleanLiteral(true)*/ +void unary1() {} + +@Helper(!true) +/*member: unary2: +resolved=UnaryExpression(!BooleanLiteral(true)) +evaluate=BooleanLiteral(false)*/ +void unary2() {} + +@Helper(-1) +/*member: unary3: +resolved=UnaryExpression(-IntegerLiteral(1)) +evaluate=IntegerLiteral(value=-1)*/ +void unary3() {} + +@Helper(~2) +/*member: unary4: +resolved=UnaryExpression(~IntegerLiteral(2)) +evaluate=IntegerLiteral(value=-3)*/ +void unary4() {} + +@Helper(!constBool) +/*member: unary5: +resolved=UnaryExpression(!StaticGet(constBool)) +evaluate=UnaryExpression(!StaticGet(constBool))*/ +void unary5() {} + +@Helper(-constInt) +/*member: unary6: +resolved=UnaryExpression(-StaticGet(constInt)) +evaluate=UnaryExpression(-StaticGet(constInt))*/ +void unary6() {} diff --git a/pkg/analyzer/test/id_tests/metadata_evaluate_test.dart b/pkg/analyzer/test/id_tests/metadata_evaluate_test.dart new file mode 100644 index 000000000000..6b8f4a54b6b6 --- /dev/null +++ b/pkg/analyzer/test/id_tests/metadata_evaluate_test.dart @@ -0,0 +1,74 @@ +// Copyright (c) 2024, 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. + +import 'dart:io'; + +import 'package:_fe_analyzer_shared/src/testing/id.dart'; +import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'; +import 'package:_fe_analyzer_shared/src/testing/metadata_helper.dart'; +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/src/dart/analysis/testing_data.dart'; +import 'package:analyzer/src/dart/element/element.dart'; +import 'package:analyzer/src/dart/element/inheritance_manager3.dart'; +import 'package:analyzer/src/summary2/macro_metadata.dart'; +import 'package:analyzer/src/util/ast_data_extractor.dart'; + +import '../util/id_testing_helper.dart'; + +main(List args) async { + Directory dataDir = Directory.fromUri(Platform.script + .resolve('../../../_fe_analyzer_shared/test/metadata/evaluate_data')); + return runTests( + dataDir, + args: args, + createUriForFileName: createUriForFileName, + onFailure: onFailure, + runTest: runTestFor(const _MetadataDataComputer(), [analyzerDefaultConfig]), + preserveWhitespaceInAnnotations: true, + ); +} + +class _MetadataDataComputer extends DataComputer { + const _MetadataDataComputer(); + + @override + DataInterpreter get dataValidator => const StringDataInterpreter(); + + @override + bool get supportsErrors => true; + + @override + void computeUnitData(TestingData testingData, CompilationUnit unit, + Map> actualMap) { + _MetadataDataExtractor(unit.declaredElement!.source.uri, actualMap) + .run(unit); + } +} + +class _MetadataDataExtractor extends AstDataExtractor { + final inheritance = InheritanceManager3(); + + _MetadataDataExtractor(super.uri, super.actualMap); + + @override + String? computeNodeValue(Id id, AstNode node) { + if (node is Declaration) { + Element? element = node.declaredElement; + if (element != null) { + List list = []; + for (ElementAnnotation annotation in element.metadata) { + if (annotation is ElementAnnotationImpl) { + var resolved = parseAnnotation(annotation); + list.addAll(evaluationToText(resolved)); + } + } + if (list.isNotEmpty) { + return '\n${list.join('\n')}'; + } + } + } + return null; + } +} diff --git a/pkg/front_end/test/id_tests/metadata_evaluate_test.dart b/pkg/front_end/test/id_tests/metadata_evaluate_test.dart new file mode 100644 index 000000000000..13ae56b0cdd1 --- /dev/null +++ b/pkg/front_end/test/id_tests/metadata_evaluate_test.dart @@ -0,0 +1,75 @@ +// Copyright (c) 2024, 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. + +import 'dart:io' show Directory, Platform; + +import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id; +import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'; +import 'package:_fe_analyzer_shared/src/testing/metadata_helper.dart'; +import 'package:_fe_analyzer_shared/src/metadata/ast.dart' as shared; +import 'package:front_end/src/base/common.dart'; +import 'package:front_end/src/builder/member_builder.dart'; +import 'package:front_end/src/source/source_member_builder.dart'; +import 'package:front_end/src/testing/id_testing_helper.dart'; +import 'package:front_end/src/testing/id_testing_utils.dart'; +import 'package:kernel/ast.dart'; +import 'package:front_end/src/builder/metadata_builder.dart'; + +Future main(List args) async { + retainDataForTesting = true; + computeSharedExpressionForTesting = true; + + Directory dataDir = new Directory.fromUri(Platform.script + .resolve('../../../_fe_analyzer_shared/test/metadata/evaluate_data')); + await runTests(dataDir, + args: args, + createUriForFileName: createUriForFileName, + onFailure: onFailure, + runTest: runTestFor(const MetadataDataComputer(), [defaultCfeConfig]), + preserveWhitespaceInAnnotations: true); +} + +class MetadataDataComputer extends CfeDataComputer { + const MetadataDataComputer(); + + @override + DataInterpreter get dataValidator => const StringDataInterpreter(); + + @override + bool get supportsErrors => true; + + /// Function that computes a data mapping for [member]. + /// + /// Fills [actualMap] with the data. + @override + void computeMemberData(CfeTestResultData testResultData, Member member, + Map> actualMap, + {bool? verbose}) { + member.accept( + new MetadataDataExtractor(testResultData.compilerResult, actualMap)); + } +} + +class MetadataDataExtractor extends CfeDataExtractor { + MetadataDataExtractor(InternalCompilerResult compilerResult, + Map> actualMap) + : super(compilerResult, actualMap); + + @override + String? computeMemberValue(Id id, Member member) { + MemberBuilder? memberBuilder = lookupMemberBuilder(compilerResult, member); + if (memberBuilder is SourceMemberBuilder) { + Iterable? metadata = memberBuilder.metadataForTesting; + if (metadata != null) { + List list = []; + for (MetadataBuilder metadataBuilder in metadata) { + shared.Expression resolved = metadataBuilder.expression!; + list.addAll(evaluationToText(resolved)); + } + return '\n${list.join('\n')}'; + } + } + return null; + } +}