mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

This auto-formats all *.dart files in the repository outside of the `engine` subdirectory and enforces that these files stay formatted with a presubmit check. **Reviewers:** Please carefully review all the commits except for the one titled "formatted". The "formatted" commit was auto-generated by running `dev/tools/format.sh -a -f`. The other commits were hand-crafted to prepare the repo for the formatting change. I recommend reviewing the commits one-by-one via the "Commits" tab and avoiding Github's "Files changed" tab as it will likely slow down your browser because of the size of this PR. --------- Co-authored-by: Kate Lovett <katelovett@google.com> Co-authored-by: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com>
782 lines
25 KiB
Dart
782 lines
25 KiB
Dart
// Copyright 2014 The Flutter Authors. 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:flutter_tools/src/localizations/gen_l10n_types.dart';
|
|
import 'package:flutter_tools/src/localizations/message_parser.dart';
|
|
import '../src/common.dart';
|
|
|
|
void main() {
|
|
// Going to test that operator== is overloaded properly since the rest
|
|
// of the test depends on it.
|
|
testWithoutContext('node equality', () {
|
|
final Node actual = Node(
|
|
ST.placeholderExpr,
|
|
0,
|
|
expectedSymbolCount: 3,
|
|
children: <Node>[Node.openBrace(0), Node.string(1, 'var'), Node.closeBrace(4)],
|
|
);
|
|
|
|
final Node expected = Node(
|
|
ST.placeholderExpr,
|
|
0,
|
|
expectedSymbolCount: 3,
|
|
children: <Node>[Node.openBrace(0), Node.string(1, 'var'), Node.closeBrace(4)],
|
|
);
|
|
expect(actual, equals(expected));
|
|
|
|
final Node wrongType = Node(
|
|
ST.pluralExpr,
|
|
0,
|
|
expectedSymbolCount: 3,
|
|
children: <Node>[Node.openBrace(0), Node.string(1, 'var'), Node.closeBrace(4)],
|
|
);
|
|
expect(actual, isNot(equals(wrongType)));
|
|
|
|
final Node wrongPosition = Node(
|
|
ST.placeholderExpr,
|
|
1,
|
|
expectedSymbolCount: 3,
|
|
children: <Node>[Node.openBrace(0), Node.string(1, 'var'), Node.closeBrace(4)],
|
|
);
|
|
expect(actual, isNot(equals(wrongPosition)));
|
|
|
|
final Node wrongChildrenCount = Node(
|
|
ST.placeholderExpr,
|
|
0,
|
|
expectedSymbolCount: 3,
|
|
children: <Node>[Node.string(1, 'var'), Node.closeBrace(4)],
|
|
);
|
|
expect(actual, isNot(equals(wrongChildrenCount)));
|
|
|
|
final Node wrongChild = Node(
|
|
ST.placeholderExpr,
|
|
0,
|
|
expectedSymbolCount: 3,
|
|
children: <Node>[Node.closeBrace(0), Node.string(1, 'var'), Node.closeBrace(4)],
|
|
);
|
|
expect(actual, isNot(equals(wrongChild)));
|
|
});
|
|
|
|
testWithoutContext('lexer basic', () {
|
|
final List<Node> tokens1 = Parser('helloWorld', 'app_en.arb', 'Hello {name}').lexIntoTokens();
|
|
expect(
|
|
tokens1,
|
|
equals(<Node>[
|
|
Node.string(0, 'Hello '),
|
|
Node.openBrace(6),
|
|
Node.identifier(7, 'name'),
|
|
Node.closeBrace(11),
|
|
]),
|
|
);
|
|
|
|
final List<Node> tokens2 =
|
|
Parser(
|
|
'plural',
|
|
'app_en.arb',
|
|
'There are {count} {count, plural, =1{cat} other{cats}}',
|
|
).lexIntoTokens();
|
|
expect(
|
|
tokens2,
|
|
equals(<Node>[
|
|
Node.string(0, 'There are '),
|
|
Node.openBrace(10),
|
|
Node.identifier(11, 'count'),
|
|
Node.closeBrace(16),
|
|
Node.string(17, ' '),
|
|
Node.openBrace(18),
|
|
Node.identifier(19, 'count'),
|
|
Node.comma(24),
|
|
Node.pluralKeyword(26),
|
|
Node.comma(32),
|
|
Node.equalSign(34),
|
|
Node.number(35, '1'),
|
|
Node.openBrace(36),
|
|
Node.string(37, 'cat'),
|
|
Node.closeBrace(40),
|
|
Node.otherKeyword(42),
|
|
Node.openBrace(47),
|
|
Node.string(48, 'cats'),
|
|
Node.closeBrace(52),
|
|
Node.closeBrace(53),
|
|
]),
|
|
);
|
|
|
|
final List<Node> tokens3 =
|
|
Parser(
|
|
'gender',
|
|
'app_en.arb',
|
|
'{gender, select, male{he} female{she} other{they}}',
|
|
).lexIntoTokens();
|
|
expect(
|
|
tokens3,
|
|
equals(<Node>[
|
|
Node.openBrace(0),
|
|
Node.identifier(1, 'gender'),
|
|
Node.comma(7),
|
|
Node.selectKeyword(9),
|
|
Node.comma(15),
|
|
Node.identifier(17, 'male'),
|
|
Node.openBrace(21),
|
|
Node.string(22, 'he'),
|
|
Node.closeBrace(24),
|
|
Node.identifier(26, 'female'),
|
|
Node.openBrace(32),
|
|
Node.string(33, 'she'),
|
|
Node.closeBrace(36),
|
|
Node.otherKeyword(38),
|
|
Node.openBrace(43),
|
|
Node.string(44, 'they'),
|
|
Node.closeBrace(48),
|
|
Node.closeBrace(49),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('lexer recursive', () {
|
|
final List<Node> tokens =
|
|
Parser(
|
|
'plural',
|
|
'app_en.arb',
|
|
'{count, plural, =1{{gender, select, male{he} female{she}}} other{they}}',
|
|
).lexIntoTokens();
|
|
expect(
|
|
tokens,
|
|
equals(<Node>[
|
|
Node.openBrace(0),
|
|
Node.identifier(1, 'count'),
|
|
Node.comma(6),
|
|
Node.pluralKeyword(8),
|
|
Node.comma(14),
|
|
Node.equalSign(16),
|
|
Node.number(17, '1'),
|
|
Node.openBrace(18),
|
|
Node.openBrace(19),
|
|
Node.identifier(20, 'gender'),
|
|
Node.comma(26),
|
|
Node.selectKeyword(28),
|
|
Node.comma(34),
|
|
Node.identifier(36, 'male'),
|
|
Node.openBrace(40),
|
|
Node.string(41, 'he'),
|
|
Node.closeBrace(43),
|
|
Node.identifier(45, 'female'),
|
|
Node.openBrace(51),
|
|
Node.string(52, 'she'),
|
|
Node.closeBrace(55),
|
|
Node.closeBrace(56),
|
|
Node.closeBrace(57),
|
|
Node.otherKeyword(59),
|
|
Node.openBrace(64),
|
|
Node.string(65, 'they'),
|
|
Node.closeBrace(69),
|
|
Node.closeBrace(70),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('lexer escaping', () {
|
|
final List<Node> tokens1 =
|
|
Parser('escaping', 'app_en.arb', "''", useEscaping: true).lexIntoTokens();
|
|
expect(tokens1, equals(<Node>[Node.string(0, "'")]));
|
|
|
|
final List<Node> tokens2 =
|
|
Parser(
|
|
'escaping',
|
|
'app_en.arb',
|
|
"'hello world { name }'",
|
|
useEscaping: true,
|
|
).lexIntoTokens();
|
|
expect(tokens2, equals(<Node>[Node.string(0, 'hello world { name }')]));
|
|
|
|
final List<Node> tokens3 =
|
|
Parser(
|
|
'escaping',
|
|
'app_en.arb',
|
|
"'{ escaped string }' { not escaped }",
|
|
useEscaping: true,
|
|
).lexIntoTokens();
|
|
expect(
|
|
tokens3,
|
|
equals(<Node>[
|
|
Node.string(0, '{ escaped string }'),
|
|
Node.string(20, ' '),
|
|
Node.openBrace(21),
|
|
Node.identifier(23, 'not'),
|
|
Node.identifier(27, 'escaped'),
|
|
Node.closeBrace(35),
|
|
]),
|
|
);
|
|
|
|
final List<Node> tokens4 =
|
|
Parser('escaping', 'app_en.arb', "Flutter''s amazing!", useEscaping: true).lexIntoTokens();
|
|
expect(
|
|
tokens4,
|
|
equals(<Node>[Node.string(0, 'Flutter'), Node.string(7, "'"), Node.string(9, 's amazing!')]),
|
|
);
|
|
|
|
final List<Node> tokens5 =
|
|
Parser(
|
|
'escaping',
|
|
'app_en.arb',
|
|
"'Flutter''s amazing!'",
|
|
useEscaping: true,
|
|
).lexIntoTokens();
|
|
expect(
|
|
tokens5,
|
|
equals(<Node>[
|
|
Node(ST.string, 0, value: 'Flutter'),
|
|
Node(ST.string, 9, value: "'s amazing!"),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('lexer identifier names can be "select" or "plural"', () {
|
|
final List<Node> tokens =
|
|
Parser(
|
|
'keywords',
|
|
'app_en.arb',
|
|
'{ select } { plural, select, singular{test} other{hmm} }',
|
|
).lexIntoTokens();
|
|
expect(tokens[1].value, equals('select'));
|
|
expect(tokens[1].type, equals(ST.identifier));
|
|
expect(tokens[5].value, equals('plural'));
|
|
expect(tokens[5].type, equals(ST.identifier));
|
|
});
|
|
|
|
testWithoutContext('lexer identifier names can contain underscores', () {
|
|
final List<Node> tokens =
|
|
Parser(
|
|
'keywords',
|
|
'app_en.arb',
|
|
'{ test_placeholder } { test_select, select, singular{test} other{hmm} }',
|
|
).lexIntoTokens();
|
|
expect(tokens[1].value, equals('test_placeholder'));
|
|
expect(tokens[1].type, equals(ST.identifier));
|
|
expect(tokens[5].value, equals('test_select'));
|
|
expect(tokens[5].type, equals(ST.identifier));
|
|
});
|
|
|
|
testWithoutContext('lexer identifier names can contain the strings select or plural', () {
|
|
final List<Node> tokens =
|
|
Parser(
|
|
'keywords',
|
|
'app_en.arb',
|
|
'{ selectTest } { pluralTest, select, singular{test} other{hmm} }',
|
|
).lexIntoTokens();
|
|
expect(tokens[1].value, equals('selectTest'));
|
|
expect(tokens[1].type, equals(ST.identifier));
|
|
expect(tokens[5].value, equals('pluralTest'));
|
|
expect(tokens[5].type, equals(ST.identifier));
|
|
});
|
|
|
|
testWithoutContext('lexer: lexically correct but syntactically incorrect', () {
|
|
final List<Node> tokens =
|
|
Parser(
|
|
'syntax',
|
|
'app_en.arb',
|
|
'string { identifier { string { identifier } } }',
|
|
).lexIntoTokens();
|
|
expect(
|
|
tokens,
|
|
equals(<Node>[
|
|
Node.string(0, 'string '),
|
|
Node.openBrace(7),
|
|
Node.identifier(9, 'identifier'),
|
|
Node.openBrace(20),
|
|
Node.string(21, ' string '),
|
|
Node.openBrace(29),
|
|
Node.identifier(31, 'identifier'),
|
|
Node.closeBrace(42),
|
|
Node.string(43, ' '),
|
|
Node.closeBrace(44),
|
|
Node.closeBrace(46),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('lexer unmatched single quote', () {
|
|
const String message = "here''s an unmatched single quote: '";
|
|
const String expectedError = '''
|
|
[app_en.arb:escaping] ICU Lexing Error: Unmatched single quotes.
|
|
here''s an unmatched single quote: '
|
|
^''';
|
|
expect(
|
|
() => Parser('escaping', 'app_en.arb', message, useEscaping: true).lexIntoTokens(),
|
|
throwsA(
|
|
isA<L10nException>().having(
|
|
(L10nException e) => e.message,
|
|
'message',
|
|
contains(expectedError),
|
|
),
|
|
),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('lexer unexpected character', () {
|
|
const String message = '{ * }';
|
|
const String expectedError = '''
|
|
[app_en.arb:lex] ICU Lexing Error: Unexpected character.
|
|
{ * }
|
|
^''';
|
|
expect(
|
|
() => Parser('lex', 'app_en.arb', message).lexIntoTokens(),
|
|
throwsA(
|
|
isA<L10nException>().having(
|
|
(L10nException e) => e.message,
|
|
'message',
|
|
contains(expectedError),
|
|
),
|
|
),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('relaxed lexer', () {
|
|
final List<Node> tokens1 =
|
|
Parser('string', 'app_en.arb', '{ }', placeholders: <String>[]).lexIntoTokens();
|
|
expect(
|
|
tokens1,
|
|
equals(<Node>[
|
|
Node(ST.string, 0, value: '{'),
|
|
Node(ST.string, 1, value: ' '),
|
|
Node(ST.string, 2, value: '}'),
|
|
]),
|
|
);
|
|
|
|
final List<Node> tokens2 =
|
|
Parser(
|
|
'string',
|
|
'app_en.arb',
|
|
'{ notAPlaceholder }',
|
|
placeholders: <String>['isAPlaceholder'],
|
|
).lexIntoTokens();
|
|
expect(
|
|
tokens2,
|
|
equals(<Node>[
|
|
Node(ST.string, 0, value: '{'),
|
|
Node(ST.string, 1, value: ' notAPlaceholder '),
|
|
Node(ST.string, 18, value: '}'),
|
|
]),
|
|
);
|
|
|
|
final List<Node> tokens3 =
|
|
Parser(
|
|
'string',
|
|
'app_en.arb',
|
|
'{ isAPlaceholder }',
|
|
placeholders: <String>['isAPlaceholder'],
|
|
).lexIntoTokens();
|
|
expect(
|
|
tokens3,
|
|
equals(<Node>[
|
|
Node(ST.openBrace, 0, value: '{'),
|
|
Node(ST.identifier, 2, value: 'isAPlaceholder'),
|
|
Node(ST.closeBrace, 17, value: '}'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('relaxed lexer complex', () {
|
|
const String message =
|
|
'{ notPlaceholder } {count,plural, =0{Hello} =1{Hello World} =2{Hello two worlds} few{Hello {count} worlds} many{Hello all {count} worlds} other{Hello other {count} worlds}}';
|
|
final List<Node> tokens =
|
|
Parser('string', 'app_en.arb', message, placeholders: <String>['count']).lexIntoTokens();
|
|
expect(tokens[0].type, equals(ST.string));
|
|
});
|
|
|
|
testWithoutContext('parser basic', () {
|
|
expect(
|
|
Parser('helloWorld', 'app_en.arb', 'Hello {name}').parse(),
|
|
equals(
|
|
Node(
|
|
ST.message,
|
|
0,
|
|
children: <Node>[
|
|
Node(ST.string, 0, value: 'Hello '),
|
|
Node(
|
|
ST.placeholderExpr,
|
|
6,
|
|
children: <Node>[
|
|
Node(ST.openBrace, 6, value: '{'),
|
|
Node(ST.identifier, 7, value: 'name'),
|
|
Node(ST.closeBrace, 11, value: '}'),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
Parser('argumentTest', 'app_en.arb', 'Today is {date, date, ::yMMd}').parse(),
|
|
equals(
|
|
Node(
|
|
ST.message,
|
|
0,
|
|
children: <Node>[
|
|
Node(ST.string, 0, value: 'Today is '),
|
|
Node(
|
|
ST.argumentExpr,
|
|
9,
|
|
children: <Node>[
|
|
Node(ST.openBrace, 9, value: '{'),
|
|
Node(ST.identifier, 10, value: 'date'),
|
|
Node(ST.comma, 14, value: ','),
|
|
Node(ST.argType, 16, children: <Node>[Node(ST.date, 16, value: 'date')]),
|
|
Node(ST.comma, 20, value: ','),
|
|
Node(ST.colon, 22, value: ':'),
|
|
Node(ST.colon, 23, value: ':'),
|
|
Node(ST.identifier, 24, value: 'yMMd'),
|
|
Node(ST.closeBrace, 28, value: '}'),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
Parser(
|
|
'plural',
|
|
'app_en.arb',
|
|
'There are {count} {count, plural, =1{cat} other{cats}}',
|
|
).parse(),
|
|
equals(
|
|
Node(
|
|
ST.message,
|
|
0,
|
|
children: <Node>[
|
|
Node(ST.string, 0, value: 'There are '),
|
|
Node(
|
|
ST.placeholderExpr,
|
|
10,
|
|
children: <Node>[
|
|
Node(ST.openBrace, 10, value: '{'),
|
|
Node(ST.identifier, 11, value: 'count'),
|
|
Node(ST.closeBrace, 16, value: '}'),
|
|
],
|
|
),
|
|
Node(ST.string, 17, value: ' '),
|
|
Node(
|
|
ST.pluralExpr,
|
|
18,
|
|
children: <Node>[
|
|
Node(ST.openBrace, 18, value: '{'),
|
|
Node(ST.identifier, 19, value: 'count'),
|
|
Node(ST.comma, 24, value: ','),
|
|
Node(ST.plural, 26, value: 'plural'),
|
|
Node(ST.comma, 32, value: ','),
|
|
Node(
|
|
ST.pluralParts,
|
|
34,
|
|
children: <Node>[
|
|
Node(
|
|
ST.pluralPart,
|
|
34,
|
|
children: <Node>[
|
|
Node(ST.equalSign, 34, value: '='),
|
|
Node(ST.number, 35, value: '1'),
|
|
Node(ST.openBrace, 36, value: '{'),
|
|
Node(ST.message, 37, children: <Node>[Node(ST.string, 37, value: 'cat')]),
|
|
Node(ST.closeBrace, 40, value: '}'),
|
|
],
|
|
),
|
|
Node(
|
|
ST.pluralPart,
|
|
42,
|
|
children: <Node>[
|
|
Node(ST.other, 42, value: 'other'),
|
|
Node(ST.openBrace, 47, value: '{'),
|
|
Node(ST.message, 48, children: <Node>[Node(ST.string, 48, value: 'cats')]),
|
|
Node(ST.closeBrace, 52, value: '}'),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
Node(ST.closeBrace, 53, value: '}'),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
Parser('gender', 'app_en.arb', '{gender, select, male{he} female{she} other{they}}').parse(),
|
|
equals(
|
|
Node(
|
|
ST.message,
|
|
0,
|
|
children: <Node>[
|
|
Node(
|
|
ST.selectExpr,
|
|
0,
|
|
children: <Node>[
|
|
Node(ST.openBrace, 0, value: '{'),
|
|
Node(ST.identifier, 1, value: 'gender'),
|
|
Node(ST.comma, 7, value: ','),
|
|
Node(ST.select, 9, value: 'select'),
|
|
Node(ST.comma, 15, value: ','),
|
|
Node(
|
|
ST.selectParts,
|
|
17,
|
|
children: <Node>[
|
|
Node(
|
|
ST.selectPart,
|
|
17,
|
|
children: <Node>[
|
|
Node(ST.identifier, 17, value: 'male'),
|
|
Node(ST.openBrace, 21, value: '{'),
|
|
Node(ST.message, 22, children: <Node>[Node(ST.string, 22, value: 'he')]),
|
|
Node(ST.closeBrace, 24, value: '}'),
|
|
],
|
|
),
|
|
Node(
|
|
ST.selectPart,
|
|
26,
|
|
children: <Node>[
|
|
Node(ST.identifier, 26, value: 'female'),
|
|
Node(ST.openBrace, 32, value: '{'),
|
|
Node(ST.message, 33, children: <Node>[Node(ST.string, 33, value: 'she')]),
|
|
Node(ST.closeBrace, 36, value: '}'),
|
|
],
|
|
),
|
|
Node(
|
|
ST.selectPart,
|
|
38,
|
|
children: <Node>[
|
|
Node(ST.other, 38, value: 'other'),
|
|
Node(ST.openBrace, 43, value: '{'),
|
|
Node(ST.message, 44, children: <Node>[Node(ST.string, 44, value: 'they')]),
|
|
Node(ST.closeBrace, 48, value: '}'),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
Node(ST.closeBrace, 49, value: '}'),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('parser escaping', () {
|
|
expect(
|
|
Parser('escaping', 'app_en.arb', "Flutter''s amazing!", useEscaping: true).parse(),
|
|
equals(
|
|
Node(
|
|
ST.message,
|
|
0,
|
|
children: <Node>[
|
|
Node(ST.string, 0, value: 'Flutter'),
|
|
Node(ST.string, 7, value: "'"),
|
|
Node(ST.string, 9, value: 's amazing!'),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
Parser('escaping', 'app_en.arb', "'Flutter''s amazing!'", useEscaping: true).parse(),
|
|
equals(
|
|
Node(
|
|
ST.message,
|
|
0,
|
|
children: <Node>[
|
|
Node(ST.string, 0, value: 'Flutter'),
|
|
Node(ST.string, 9, value: "'s amazing!"),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('parser recursive', () {
|
|
expect(
|
|
Parser(
|
|
'pluralGender',
|
|
'app_en.arb',
|
|
'{count, plural, =1{{gender, select, male{he} female{she} other{they}}} other{they}}',
|
|
).parse(),
|
|
equals(
|
|
Node(
|
|
ST.message,
|
|
0,
|
|
children: <Node>[
|
|
Node(
|
|
ST.pluralExpr,
|
|
0,
|
|
children: <Node>[
|
|
Node(ST.openBrace, 0, value: '{'),
|
|
Node(ST.identifier, 1, value: 'count'),
|
|
Node(ST.comma, 6, value: ','),
|
|
Node(ST.plural, 8, value: 'plural'),
|
|
Node(ST.comma, 14, value: ','),
|
|
Node(
|
|
ST.pluralParts,
|
|
16,
|
|
children: <Node>[
|
|
Node(
|
|
ST.pluralPart,
|
|
16,
|
|
children: <Node>[
|
|
Node(ST.equalSign, 16, value: '='),
|
|
Node(ST.number, 17, value: '1'),
|
|
Node(ST.openBrace, 18, value: '{'),
|
|
Node(
|
|
ST.message,
|
|
19,
|
|
children: <Node>[
|
|
Node(
|
|
ST.selectExpr,
|
|
19,
|
|
children: <Node>[
|
|
Node(ST.openBrace, 19, value: '{'),
|
|
Node(ST.identifier, 20, value: 'gender'),
|
|
Node(ST.comma, 26, value: ','),
|
|
Node(ST.select, 28, value: 'select'),
|
|
Node(ST.comma, 34, value: ','),
|
|
Node(
|
|
ST.selectParts,
|
|
36,
|
|
children: <Node>[
|
|
Node(
|
|
ST.selectPart,
|
|
36,
|
|
children: <Node>[
|
|
Node(ST.identifier, 36, value: 'male'),
|
|
Node(ST.openBrace, 40, value: '{'),
|
|
Node(
|
|
ST.message,
|
|
41,
|
|
children: <Node>[Node(ST.string, 41, value: 'he')],
|
|
),
|
|
Node(ST.closeBrace, 43, value: '}'),
|
|
],
|
|
),
|
|
Node(
|
|
ST.selectPart,
|
|
45,
|
|
children: <Node>[
|
|
Node(ST.identifier, 45, value: 'female'),
|
|
Node(ST.openBrace, 51, value: '{'),
|
|
Node(
|
|
ST.message,
|
|
52,
|
|
children: <Node>[Node(ST.string, 52, value: 'she')],
|
|
),
|
|
Node(ST.closeBrace, 55, value: '}'),
|
|
],
|
|
),
|
|
Node(
|
|
ST.selectPart,
|
|
57,
|
|
children: <Node>[
|
|
Node(ST.other, 57, value: 'other'),
|
|
Node(ST.openBrace, 62, value: '{'),
|
|
Node(
|
|
ST.message,
|
|
63,
|
|
children: <Node>[Node(ST.string, 63, value: 'they')],
|
|
),
|
|
Node(ST.closeBrace, 67, value: '}'),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
Node(ST.closeBrace, 68, value: '}'),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
Node(ST.closeBrace, 69, value: '}'),
|
|
],
|
|
),
|
|
Node(
|
|
ST.pluralPart,
|
|
71,
|
|
children: <Node>[
|
|
Node(ST.other, 71, value: 'other'),
|
|
Node(ST.openBrace, 76, value: '{'),
|
|
Node(ST.message, 77, children: <Node>[Node(ST.string, 77, value: 'they')]),
|
|
Node(ST.closeBrace, 81, value: '}'),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
Node(ST.closeBrace, 82, value: '}'),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('parser unexpected token', () {
|
|
// unexpected token
|
|
const String expectedError1 = '''
|
|
[app_en.arb:unexpectedToken] ICU Syntax Error: Expected "}" but found "=".
|
|
{ placeholder =
|
|
^''';
|
|
expect(
|
|
() => Parser('unexpectedToken', 'app_en.arb', '{ placeholder =').parseIntoTree(),
|
|
throwsA(
|
|
isA<L10nException>().having(
|
|
(L10nException e) => e.message,
|
|
'message',
|
|
contains(expectedError1),
|
|
),
|
|
),
|
|
);
|
|
|
|
const String expectedError2 = '''
|
|
[app_en.arb:unexpectedToken] ICU Syntax Error: Expected "number" but found "}".
|
|
{ count, plural, = }
|
|
^''';
|
|
expect(
|
|
() => Parser('unexpectedToken', 'app_en.arb', '{ count, plural, = }').parseIntoTree(),
|
|
throwsA(
|
|
isA<L10nException>().having(
|
|
(L10nException e) => e.message,
|
|
'message',
|
|
contains(expectedError2),
|
|
),
|
|
),
|
|
);
|
|
|
|
const String expectedError3 = '''
|
|
[app_en.arb:unexpectedToken] ICU Syntax Error: Expected "identifier" but found ",".
|
|
{ , plural , = }
|
|
^''';
|
|
expect(
|
|
() => Parser('unexpectedToken', 'app_en.arb', '{ , plural , = }').parseIntoTree(),
|
|
throwsA(
|
|
isA<L10nException>().having(
|
|
(L10nException e) => e.message,
|
|
'message',
|
|
contains(expectedError3),
|
|
),
|
|
),
|
|
);
|
|
});
|
|
|
|
testWithoutContext('parser allows select cases with numbers', () {
|
|
final Node node =
|
|
Parser(
|
|
'numberSelect',
|
|
'app_en.arb',
|
|
'{ count, select, 0{none} 100{perfect} other{required!} }',
|
|
).parse();
|
|
final Node selectExpr = node.children[0];
|
|
final Node selectParts = selectExpr.children[5];
|
|
final Node selectPart = selectParts.children[0];
|
|
expect(selectPart.children[0].value, equals('0'));
|
|
expect(selectPart.children[1].value, equals('{'));
|
|
expect(selectPart.children[2].type, equals(ST.message));
|
|
expect(selectPart.children[3].value, equals('}'));
|
|
});
|
|
}
|