mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:39:49 +00:00
Patch token stream when replace/add nodes.
R=paulberry@google.com, brianwilkerson@google.com BUG= Review URL: https://codereview.chromium.org/2413293002 .
This commit is contained in:
parent
9c83c381ec
commit
0ae79f6f4b
|
@ -132,15 +132,19 @@ class SdkPatcher {
|
|||
baseDeclaration.name.name == name) {
|
||||
if (_hasPatchAnnotation(patchDeclaration.metadata)) {
|
||||
// Remove the "external" keyword.
|
||||
if (baseDeclaration.externalKeyword != null) {
|
||||
Token externalKeyword = baseDeclaration.externalKeyword;
|
||||
if (externalKeyword != null) {
|
||||
baseDeclaration.externalKeyword = null;
|
||||
_removeToken(externalKeyword);
|
||||
} else {
|
||||
_failExternalKeyword(
|
||||
baseSource, name, baseDeclaration.offset);
|
||||
}
|
||||
// Replace the body.
|
||||
baseDeclaration.functionExpression.body =
|
||||
patchDeclaration.functionExpression.body;
|
||||
FunctionExpression oldExpr = baseDeclaration.functionExpression;
|
||||
FunctionBody newBody = patchDeclaration.functionExpression.body;
|
||||
_replaceNodeTokens(oldExpr.body, newBody);
|
||||
oldExpr.body = newBody;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +165,13 @@ class SdkPatcher {
|
|||
}
|
||||
}
|
||||
// Append new top-level declarations.
|
||||
baseUnit.declarations.addAll(declarationsToAppend);
|
||||
Token lastToken = baseUnit.endToken.previous;
|
||||
for (CompilationUnitMember newDeclaration in declarationsToAppend) {
|
||||
newDeclaration.endToken.setNext(lastToken.next);
|
||||
lastToken.setNext(newDeclaration.beginToken);
|
||||
baseUnit.declarations.add(newDeclaration);
|
||||
lastToken = newDeclaration.endToken;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,4 +206,19 @@ class SdkPatcher {
|
|||
name.name == 'patch';
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the [token] from the stream.
|
||||
*/
|
||||
static void _removeToken(Token token) {
|
||||
token.previous.setNext(token.next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace tokens of the [oldNode] with tokens of the [newNode].
|
||||
*/
|
||||
static void _replaceNodeTokens(AstNode oldNode, AstNode newNode) {
|
||||
oldNode.beginToken.previous.setNext(newNode.beginToken);
|
||||
newNode.endToken.setNext(oldNode.endToken.next);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/ast/token.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/file_system/memory_file_system.dart';
|
||||
import 'package:analyzer/src/dart/sdk/patch.dart';
|
||||
|
@ -86,22 +87,6 @@ final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
|
|||
}, throwsArgumentError);
|
||||
}
|
||||
|
||||
test_topLevel_append() {
|
||||
CompilationUnit unit = _doTopLevelPatching(
|
||||
r'''
|
||||
int bar() => 2;
|
||||
''',
|
||||
r'''
|
||||
int _foo1() => 1;
|
||||
int get _foo2 => 1;
|
||||
void set _foo3(int val) {}
|
||||
''');
|
||||
_assertUnitCode(
|
||||
unit,
|
||||
'int bar() => 2; int _foo1() => 1; '
|
||||
'int get _foo2 => 1; void set _foo3(int val) {}');
|
||||
}
|
||||
|
||||
test_topLevel_fail_topLevelVariable() {
|
||||
expect(() {
|
||||
_doTopLevelPatching(
|
||||
|
@ -114,6 +99,26 @@ int _bar;
|
|||
}, throwsArgumentError);
|
||||
}
|
||||
|
||||
test_topLevel_function_append() {
|
||||
CompilationUnit unit = _doTopLevelPatching(
|
||||
r'''
|
||||
int foo() => 0;
|
||||
''',
|
||||
r'''
|
||||
int _bar1() => 1;
|
||||
int _bar2() => 2;
|
||||
''');
|
||||
_assertUnitCode(
|
||||
unit, 'int foo() => 0; int _bar1() => 1; int _bar2() => 2;');
|
||||
|
||||
FunctionDeclaration foo = unit.declarations[0];
|
||||
FunctionDeclaration bar1 = unit.declarations[1];
|
||||
FunctionDeclaration bar2 = unit.declarations[2];
|
||||
|
||||
_assertPrevNextToken(foo.endToken, bar1.beginToken);
|
||||
_assertPrevNextToken(bar1.endToken, bar2.beginToken);
|
||||
}
|
||||
|
||||
test_topLevel_function_fail_noExternalKeyword() {
|
||||
expect(() {
|
||||
_doTopLevelPatching(
|
||||
|
@ -145,9 +150,20 @@ int bar() => 2;
|
|||
int foo() => 0;
|
||||
''',
|
||||
r'''
|
||||
typedef int _bar();
|
||||
typedef int _bar1();
|
||||
typedef int _bar2();
|
||||
''');
|
||||
_assertUnitCode(unit, 'int foo() => 0; typedef int _bar();');
|
||||
_assertUnitCode(
|
||||
unit, 'int foo() => 0; typedef int _bar1(); typedef int _bar2();');
|
||||
|
||||
FunctionDeclaration foo = unit.declarations[0];
|
||||
FunctionTypeAlias bar1 = unit.declarations[1];
|
||||
FunctionTypeAlias bar2 = unit.declarations[2];
|
||||
|
||||
_assertPrevNextToken(foo.endToken, bar1.beginToken);
|
||||
_assertPrevNextToken(bar1.endToken, bar2.beginToken);
|
||||
expect(unit.endToken.type, TokenType.EOF);
|
||||
expect(bar2.endToken.next, same(unit.endToken));
|
||||
}
|
||||
|
||||
test_topLevel_functionTypeAlias_fail_hasAnnotation() {
|
||||
|
@ -186,6 +202,26 @@ int bar() => 2;
|
|||
int foo() => 1;
|
||||
''');
|
||||
_assertUnitCode(unit, 'int foo() => 1; int bar() => 2;');
|
||||
|
||||
// Prepare functions.
|
||||
FunctionDeclaration foo = unit.declarations[0];
|
||||
FunctionDeclaration bar = unit.declarations[1];
|
||||
|
||||
// The "external" token is removed from the stream.
|
||||
{
|
||||
expect(foo.externalKeyword, isNull);
|
||||
Token token = foo.beginToken;
|
||||
expect(token.lexeme, 'int');
|
||||
expect(token.previous.type, TokenType.EOF);
|
||||
}
|
||||
|
||||
// The body tokens are included into the patched token stream.
|
||||
{
|
||||
FunctionExpression fooExpr = foo.functionExpression;
|
||||
FunctionBody fooBody = fooExpr.body;
|
||||
expect(fooBody.beginToken.previous, same(fooExpr.parameters.endToken));
|
||||
expect(fooBody.endToken.next, same(bar.beginToken));
|
||||
}
|
||||
}
|
||||
|
||||
test_topLevel_patch_function_blockBody() {
|
||||
|
@ -259,4 +295,9 @@ final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
|
|||
provider.newFile(
|
||||
_p('/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart'), code);
|
||||
}
|
||||
|
||||
static void _assertPrevNextToken(Token prev, Token next) {
|
||||
expect(prev.next, same(next));
|
||||
expect(next.previous, same(prev));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue