050b740630
Change-Id: Ie26f89b4a1cf8bd72d014062379091d2d3c00315 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/427582 Auto-Submit: Mayank Patke <fishythefish@google.com> Commit-Queue: Stephen Adams <sra@google.com> Reviewed-by: Stephen Adams <sra@google.com>
236 lines
6.9 KiB
Dart
236 lines
6.9 KiB
Dart
// Copyright (c) 2019, 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:expect/expect.dart';
|
|
import 'package:js_ast/js_ast.dart';
|
|
import 'package:js_ast/src/precedence.dart';
|
|
|
|
void main() {
|
|
Map<Expression, DeferredExpression> map = {};
|
|
VariableUse variableUse = VariableUse('variable');
|
|
DeferredExpression deferred = map[variableUse] = _DeferredExpression(
|
|
variableUse,
|
|
);
|
|
VariableUse variableUseAlias = VariableUse('variable');
|
|
map[variableUseAlias] = _DeferredExpression(variableUseAlias);
|
|
|
|
map[deferred] = _DeferredExpression(deferred);
|
|
Literal literal = LiteralString('literal');
|
|
map[literal] = _DeferredExpression(literal);
|
|
|
|
test(map, '#', [variableUse], 'variable');
|
|
test(map, '#', [deferred], 'variable');
|
|
test(map, '{#: #}', [literal, variableUse], '{literal: variable}');
|
|
test(map, '{#: #}', [literal, deferred], '{literal: variable}');
|
|
test(map, '#.#', [variableUse, literal], 'variable.literal');
|
|
test(map, '#.#', [deferred, literal], 'variable.literal');
|
|
test(map, '# = # + 1', [variableUse, variableUseAlias], '++variable');
|
|
test(map, '# = # + 1', [deferred, variableUseAlias], '++variable');
|
|
test(map, '# = # - 1', [variableUse, variableUseAlias], '--variable');
|
|
test(map, '# = # - 1', [deferred, variableUseAlias], '--variable');
|
|
test(map, '# = # + 2', [variableUse, variableUseAlias], 'variable += 2');
|
|
test(map, '# = # + 2', [deferred, variableUseAlias], 'variable += 2');
|
|
test(map, '# = # * 2', [variableUse, variableUseAlias], 'variable *= 2');
|
|
test(map, '# = # * 2', [deferred, variableUseAlias], 'variable *= 2');
|
|
|
|
test(map, '# += # + 1', [
|
|
variableUse,
|
|
variableUseAlias,
|
|
], 'variable += variable + 1');
|
|
test(map, '# += # + 1', [
|
|
deferred,
|
|
variableUseAlias,
|
|
], 'variable += variable + 1');
|
|
test(map, '# += # - 1', [
|
|
variableUse,
|
|
variableUseAlias,
|
|
], 'variable += variable - 1');
|
|
test(map, '# += # - 1', [
|
|
deferred,
|
|
variableUseAlias,
|
|
], 'variable += variable - 1');
|
|
test(map, '# += # + 2', [
|
|
variableUse,
|
|
variableUseAlias,
|
|
], 'variable += variable + 2');
|
|
test(map, '# += # + 2', [
|
|
deferred,
|
|
variableUseAlias,
|
|
], 'variable += variable + 2');
|
|
test(map, '# += # * 2', [
|
|
variableUse,
|
|
variableUseAlias,
|
|
], 'variable += variable * 2');
|
|
test(map, '# += # * 2', [
|
|
deferred,
|
|
variableUseAlias,
|
|
], 'variable += variable * 2');
|
|
}
|
|
|
|
void test(
|
|
Map<Expression, DeferredExpression> map,
|
|
String template,
|
|
List<Expression> arguments,
|
|
String expectedOutput,
|
|
) {
|
|
Expression directExpression =
|
|
js.expressionTemplateFor(template).instantiate(arguments) as Expression;
|
|
_Context directContext = _Context();
|
|
Printer directPrinter = Printer(
|
|
const JavaScriptPrintingOptions(),
|
|
directContext,
|
|
);
|
|
directPrinter.visit(directExpression);
|
|
Expect.equals(expectedOutput, directContext.text);
|
|
|
|
Expression deferredExpression =
|
|
js
|
|
.expressionTemplateFor(template)
|
|
.instantiate(arguments.map((e) => map[e]).toList())
|
|
as Expression;
|
|
_Context deferredContext = _Context();
|
|
Printer deferredPrinter = Printer(
|
|
const JavaScriptPrintingOptions(),
|
|
deferredContext,
|
|
);
|
|
deferredPrinter.visit(deferredExpression);
|
|
Expect.equals(expectedOutput, deferredContext.text);
|
|
|
|
for (Expression argument in arguments) {
|
|
DeferredExpression deferred = map[argument]!;
|
|
Expect.isTrue(
|
|
directContext.enterPositions.containsKey(argument),
|
|
'Argument ${DebugPrint(argument)} not found in direct enter positions: '
|
|
'${directContext.enterPositions.keys}',
|
|
);
|
|
Expect.isTrue(
|
|
deferredContext.enterPositions.containsKey(argument),
|
|
'Argument ${DebugPrint(argument)} not found in '
|
|
'deferred enter positions: '
|
|
'${deferredContext.enterPositions.keys}',
|
|
);
|
|
Expect.isTrue(
|
|
deferredContext.enterPositions.containsKey(deferred),
|
|
'Argument ${DebugPrint(deferred)} not found in '
|
|
'deferred enter positions: '
|
|
'${deferredContext.enterPositions.keys}',
|
|
);
|
|
Expect.equals(
|
|
directContext.enterPositions[argument],
|
|
deferredContext.enterPositions[argument],
|
|
);
|
|
Expect.equals(
|
|
directContext.enterPositions[argument],
|
|
deferredContext.enterPositions[deferred],
|
|
);
|
|
|
|
Expect.isTrue(
|
|
directContext.exitPositions.containsKey(argument),
|
|
'Argument ${DebugPrint(argument)} not found in direct enter positions: '
|
|
'${directContext.exitPositions.keys}',
|
|
);
|
|
Expect.isTrue(
|
|
deferredContext.exitPositions.containsKey(argument),
|
|
'Argument ${DebugPrint(argument)} not found in '
|
|
'deferred enter positions: '
|
|
'${deferredContext.exitPositions.keys}',
|
|
);
|
|
Expect.isTrue(
|
|
deferredContext.exitPositions.containsKey(deferred),
|
|
'Argument ${DebugPrint(deferred)} not found in '
|
|
'deferred enter positions: '
|
|
'${deferredContext.exitPositions.keys}',
|
|
);
|
|
Expect.equals(
|
|
directContext.exitPositions[argument],
|
|
deferredContext.exitPositions[argument],
|
|
);
|
|
Expect.equals(
|
|
directContext.exitPositions[argument],
|
|
deferredContext.exitPositions[deferred],
|
|
);
|
|
}
|
|
}
|
|
|
|
class _DeferredExpression extends DeferredExpression {
|
|
@override
|
|
final Expression value;
|
|
|
|
_DeferredExpression(this.value);
|
|
|
|
@override
|
|
Precedence get precedenceLevel => value.precedenceLevel;
|
|
}
|
|
|
|
class _Context implements JavaScriptPrintingContext {
|
|
StringBuffer sb = StringBuffer();
|
|
List<String> errors = [];
|
|
Map<Node, int> enterPositions = {};
|
|
Map<Node, _Position> exitPositions = {};
|
|
|
|
@override
|
|
bool get isDebugContext => false;
|
|
|
|
@override
|
|
void emit(String string) {
|
|
sb.write(string);
|
|
}
|
|
|
|
@override
|
|
void enterNode(Node node, int startPosition) {
|
|
enterPositions[node] = startPosition;
|
|
}
|
|
|
|
@override
|
|
void exitNode(
|
|
Node node,
|
|
int startPosition,
|
|
int endPosition,
|
|
int? closingPosition,
|
|
) {
|
|
exitPositions[node] = _Position(
|
|
startPosition,
|
|
endPosition,
|
|
closingPosition,
|
|
);
|
|
Expect.equals(enterPositions[node], startPosition);
|
|
}
|
|
|
|
@override
|
|
void error(String message) {
|
|
errors.add(message);
|
|
}
|
|
|
|
String get text => sb.toString();
|
|
}
|
|
|
|
class _Position {
|
|
final int startPosition;
|
|
final int endPosition;
|
|
final int? closingPosition;
|
|
|
|
_Position(this.startPosition, this.endPosition, this.closingPosition);
|
|
|
|
@override
|
|
int get hashCode =>
|
|
13 * startPosition.hashCode +
|
|
17 * endPosition.hashCode +
|
|
19 * closingPosition.hashCode;
|
|
|
|
@override
|
|
bool operator ==(Object other) {
|
|
if (identical(this, other)) return true;
|
|
return other is _Position &&
|
|
startPosition == other.startPosition &&
|
|
endPosition == other.endPosition &&
|
|
closingPosition == other.closingPosition;
|
|
}
|
|
|
|
@override
|
|
String toString() {
|
|
return '_Position(start=$startPosition,'
|
|
'end=$endPosition,closing=$closingPosition)';
|
|
}
|
|
}
|