blob: 73963d77d03b2da2a780b5e239b2e1345e9b21ab [file] [log] [blame]
// Copyright (c) 2015, 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.
//
// @dart=2.7
@TestOn('vm')
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:test/test.dart';
import 'package:test_core/src/util/string_literal_iterator.dart';
final _offset = 'final str = '.length;
void main() {
group('returns simple characters in', () {
test('a single simple string', () {
var iter = _parse('"abc"');
expect(iter.current, isNull);
expect(iter.offset, equals(_offset));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('a'));
expect(iter.offset, equals(_offset + 1));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('b'));
expect(iter.offset, equals(_offset + 2));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('c'));
expect(iter.offset, equals(_offset + 3));
expect(iter.moveNext(), isFalse);
expect(iter.current, isNull);
expect(iter.offset, equals(_offset + 4));
});
test('a raw string', () {
var iter = _parse('r"abc"');
expect(iter.current, isNull);
expect(iter.offset, equals(_offset + 1));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('a'));
expect(iter.offset, equals(_offset + 2));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('b'));
expect(iter.offset, equals(_offset + 3));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('c'));
expect(iter.offset, equals(_offset + 4));
expect(iter.moveNext(), isFalse);
expect(iter.current, isNull);
expect(iter.offset, equals(_offset + 5));
});
test('a multiline string', () {
var iter = _parse('"""ab\ncd"""');
expect(iter.current, isNull);
expect(iter.offset, equals(_offset + 2));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('a'));
expect(iter.offset, equals(_offset + 3));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('b'));
expect(iter.offset, equals(_offset + 4));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('\n'));
expect(iter.offset, equals(_offset + 5));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('c'));
expect(iter.offset, equals(_offset + 6));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('d'));
expect(iter.offset, equals(_offset + 7));
expect(iter.moveNext(), isFalse);
expect(iter.current, isNull);
expect(iter.offset, equals(_offset + 8));
});
test('a raw multiline string', () {
var iter = _parse('r"""ab\ncd"""');
expect(iter.current, isNull);
expect(iter.offset, equals(_offset + 3));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('a'));
expect(iter.offset, equals(_offset + 4));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('b'));
expect(iter.offset, equals(_offset + 5));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('\n'));
expect(iter.offset, equals(_offset + 6));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('c'));
expect(iter.offset, equals(_offset + 7));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('d'));
expect(iter.offset, equals(_offset + 8));
expect(iter.moveNext(), isFalse);
expect(iter.current, isNull);
expect(iter.offset, equals(_offset + 9));
});
test('adjacent strings', () {
var iter = _parse('"ab" r"cd" """ef\ngh"""');
expect(iter.current, isNull);
expect(iter.offset, equals(_offset));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('a'));
expect(iter.offset, equals(_offset + 1));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('b'));
expect(iter.offset, equals(_offset + 2));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('c'));
expect(iter.offset, equals(_offset + 7));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('d'));
expect(iter.offset, equals(_offset + 8));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('e'));
expect(iter.offset, equals(_offset + 14));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('f'));
expect(iter.offset, equals(_offset + 15));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('\n'));
expect(iter.offset, equals(_offset + 16));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('g'));
expect(iter.offset, equals(_offset + 17));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('h'));
expect(iter.offset, equals(_offset + 18));
expect(iter.moveNext(), isFalse);
expect(iter.current, isNull);
expect(iter.offset, equals(_offset + 19));
});
});
group('parses an escape sequence for', () {
test('a newline', () => _expectEscape(r'\n', '\n'));
test('a carriage return', () => _expectEscape(r'\r', '\r'));
test('a form feed', () => _expectEscape(r'\f', '\f'));
test('a backspace', () => _expectEscape(r'\b', '\b'));
test('a tab', () => _expectEscape(r'\t', '\t'));
test('a vertical tab', () => _expectEscape(r'\v', '\v'));
test('a quote', () => _expectEscape(r'\"', '"'));
test('a backslash', () => _expectEscape(r'\\', '\\'));
test('a hex character', () {
_expectEscape(r'\x62', 'b');
_expectEscape(r'\x7A', 'z');
_expectEscape(r'\x7a', 'z');
});
test('a fixed-length unicode character',
() => _expectEscape(r'\u0062', 'b'));
test('a short variable-length unicode character',
() => _expectEscape(r'\u{62}', 'b'));
test('a long variable-length unicode character',
() => _expectEscape(r'\u{000062}', 'b'));
});
group('throws an ArgumentError for', () {
test('interpolation', () {
expect(() => _parse(r'"$foo"'), throwsArgumentError);
});
test('interpolation in an adjacent string', () {
expect(() => _parse(r'"foo" "$bar" "baz"'), throwsArgumentError);
});
});
}
/// Asserts that [escape] is parsed as [value].
void _expectEscape(String escape, String value) {
var iter = _parse('"a${escape}b"');
expect(iter.current, isNull);
expect(iter.offset, equals(_offset));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('a'));
expect(iter.offset, equals(_offset + 1));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune(value));
expect(iter.offset, equals(_offset + 2));
expect(iter.moveNext(), isTrue);
expect(iter.current, _isRune('b'));
expect(iter.offset, equals(_offset + escape.length + 2));
expect(iter.moveNext(), isFalse);
expect(iter.current, isNull);
expect(iter.offset, equals(_offset + escape.length + 3));
}
/// Returns a matcher that asserts that the given rune is the rune for [char].
Matcher _isRune(String char) {
return predicate((rune) {
return rune is int && String.fromCharCode(rune) == char;
}, 'is the rune "$char"');
}
/// Parses [dart], which should be a string literal, into a
/// [StringLiteralIterator].
StringLiteralIterator _parse(String dart) {
var declaration = parseString(content: 'final str = $dart;')
.unit
.declarations
.single as TopLevelVariableDeclaration;
var literal = declaration.variables.variables.single.initializer;
return StringLiteralIterator(literal as StringLiteral);
}