Skip to content

feat!: allow analyzer 7.0.0 and update dart_style to ^3.0.0 #970

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion pkgs/intl_translation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
## 0.21.0-wip
* BREAKING CHANGE: Update `dart_style` to `^3.0.0`
* Allow analyzer `>=6.3.0 <8.0.0`

## 0.20.1
* Add topics to `pubspec.yaml`
* Update to `dart_style `2.3.7`. `bin/make_examples_const.dart` and
* Update to `dart_style` `2.3.7`. `bin/make_examples_const.dart` and
`rewrite_intl_messages.dart` will now look for a surrounding
`.dart_tool/package_config.json` file to infer the language version of the
files updated by the script.
Expand Down
73 changes: 73 additions & 0 deletions pkgs/intl_translation/lib/src/messages/constant_evaluator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (c) 2025, 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 'package:analyzer/dart/ast/ast.dart';

/// Needed to wrap `null` as a valid constant value
class Constant<T extends Object?> {
final T value;

Constant(this.value);

static Constant<T>? nullable<T extends Object>(T? o) =>
o == null ? null : Constant(o);
}

Constant? evaluate(Expression expression) {
return switch (expression) {
AdjacentStrings() => Constant.nullable(evaluateConstString(expression)),
SimpleStringLiteral() => Constant(expression.value),
IntegerLiteral() => Constant(expression.value),
DoubleLiteral() => Constant(expression.value),
BooleanLiteral() => Constant(expression.value),
NullLiteral() => Constant(null),
SetOrMapLiteral() => evaluateConstStringMap(expression),
_ => null,
};
}

String? evaluateConstString(Expression expression) => switch (expression) {
SimpleStringLiteral() => expression.value,
AdjacentStrings() => _checkChildren(expression.strings)?.join(),
_ => null,
};

Iterable<String>? _checkChildren(Iterable<StringLiteral> strings) {
final constExpressions = strings.map(
(string) => evaluateConstString(string),
);
return constExpressions.any(
(string) => string == null,
)
? null
: constExpressions.whereType();
}

Constant<Map>? evaluateConstStringMap(SetOrMapLiteral map) {
if (!map.isConst) {
return null;
}
if (map.elements.any(
(element) => element is! MapLiteralEntry,
)) {
return null;
}
final evaluatedEntries = map.elements.whereType<MapLiteralEntry>().map(
(literalEntry) =>
(evaluate(literalEntry.key), evaluate(literalEntry.value)),
);
if (evaluatedEntries
.any((element) => element.$1 == null || element.$2 == null)) {
return null;
}
var extractedValues = evaluatedEntries.map(
(literalEntry) => MapEntry(literalEntry.$1!.value, literalEntry.$2!.value),
);
if (extractedValues.any((element) => element.key is! String)) {
return null;
}
return Constant(Map<String, dynamic>.fromEntries(extractedValues.map(
(e) => MapEntry(e.key as String, e.value),
)));
}
2 changes: 1 addition & 1 deletion pkgs/intl_translation/lib/src/messages/main_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class MainMessage extends ComplexMessage {
/// Verify that this looks like a correct Intl.message invocation.
static void checkValidity(
MethodInvocation node,
List arguments,
List<Expression> arguments,
String? outerName,
List<FormalParameter> outerArgs, {
bool nameAndArgsGenerated = false,
Expand Down
36 changes: 7 additions & 29 deletions pkgs/intl_translation/lib/src/messages/message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@ library intl_message;
import 'dart:convert';

import 'package:analyzer/dart/ast/ast.dart';
// ignore: implementation_imports
import 'package:analyzer/src/dart/ast/constant_evaluator.dart';

import 'complex_message.dart';
import 'composite_message.dart';
import 'constant_evaluator.dart';
import 'literal_string_message.dart';
import 'message_extraction_exception.dart';
import 'variable_substitution_message.dart';
Expand Down Expand Up @@ -75,26 +74,6 @@ abstract class Message {
/// The name of the top-level [MainMessage].
String get name => parent == null ? '<unnamed>' : parent!.name;

static final _evaluator = ConstantEvaluator();

static String? _evaluateAsString(expression) {
var result = expression.accept(_evaluator);
if (result == ConstantEvaluator.NOT_A_CONSTANT || result is! String) {
return null;
} else {
return result;
}
}

static Map? _evaluateAsMap(Expression expression) {
var result = expression.accept(_evaluator);
if (result == ConstantEvaluator.NOT_A_CONSTANT || result is! Map) {
return null;
} else {
return result;
}
}

/// Verify that the args argument matches the method parameters and
/// isn't, e.g. passing string names instead of the argument values.
static bool checkArgs(NamedExpression? args, List<String> parameterNames) {
Expand Down Expand Up @@ -141,7 +120,7 @@ abstract class Message {
/// for messages with parameters.
static void checkValidity(
MethodInvocation node,
List arguments,
List<Expression> arguments,
String? outerName,
List<FormalParameter> outerArgs, {
bool nameAndArgsGenerated = false,
Expand All @@ -165,7 +144,7 @@ abstract class Message {
' e.g. args: $parameterNames');
}

var nameNamedExps = arguments
final nameNamedExps = arguments
.whereType<NamedExpression>()
.where((arg) => arg.name.label.name == 'name')
.map((e) => e.expression);
Expand All @@ -177,7 +156,7 @@ abstract class Message {
if (nameNamedExps.isEmpty) {
if (!hasParameters) {
// No name supplied, no parameters. Use the message as the name.
var name = _evaluateAsString(arguments[0]);
var name = evaluateConstString(arguments[0]);
messageName = name;
outerName = name;
} else {
Expand All @@ -195,7 +174,7 @@ abstract class Message {
}
} else {
// Name argument is supplied, use it.
var name = _evaluateAsString(nameNamedExps.first);
var name = evaluateConstString(nameNamedExps.first);
messageName = name;
givenName = name;
}
Expand Down Expand Up @@ -227,7 +206,7 @@ abstract class Message {
.map((each) => each.expression)
.toList();
for (var arg in values) {
if (_evaluateAsString(arg) == null) {
if (evaluateConstString(arg) == null) {
throw MessageExtractionException(
'Intl.message arguments must be string literals: $arg');
}
Expand All @@ -245,8 +224,7 @@ abstract class Message {
if (examples.isNotEmpty) {
var example = examples.first;
if (example is SetOrMapLiteral) {
var map = _evaluateAsMap(example);
if (map == null) {
if (evaluateConstStringMap(example) == null) {
throw MessageExtractionException(
'Examples must be a const Map literal.');
} else if (example.constKeyword == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
// ignore: implementation_imports
import 'package:analyzer/src/dart/ast/constant_evaluator.dart';

import '../extract_messages.dart';
import '../src/messages/constant_evaluator.dart';
import '../src/messages/main_message.dart';
import '../src/messages/message.dart';
import '../src/messages/message_extraction_exception.dart';
Expand Down Expand Up @@ -288,10 +287,8 @@ class MessageFindingVisitor extends GeneralizingAstVisitor {
for (var namedExpr in arguments.whereType<NamedExpression>()) {
var name = namedExpr.name.label.name;
var exp = namedExpr.expression;
var basicValue = exp.accept(ConstantEvaluator());
var value = basicValue == ConstantEvaluator.NOT_A_CONSTANT
? exp.toString()
: basicValue;
var constant = evaluate(exp);
var value = constant == null ? exp.toString() : constant.value;
setAttribute(message, name, value);
}
// We only rewrite messages with parameters, otherwise we use the literal
Expand Down
6 changes: 3 additions & 3 deletions pkgs/intl_translation/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: intl_translation
version: 0.20.1
version: 0.21.0-wip
description: >-
Contains code to deal with internationalized/localized messages,
date and number formatting and parsing, bi-directional text, and
Expand All @@ -15,9 +15,9 @@ environment:
sdk: ^3.0.0

dependencies:
analyzer: ^6.3.0
analyzer: ">=6.3.0 <8.0.0"
args: ^2.0.0
dart_style: ^2.0.0
dart_style: ^3.0.0
intl: '>=0.19.0 <0.21.0'
package_config: ^2.1.0
path: ^1.0.0
Expand Down
Loading
Loading