mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
Parse the 'patches' argument in SDK libraries declarations.
R=brianwilkerson@google.com, paulberry@google.com BUG= Review URL: https://codereview.chromium.org/2408863002 .
This commit is contained in:
parent
2495f6a060
commit
1a70ff791a
4 changed files with 229 additions and 2 deletions
|
@ -397,4 +397,7 @@ class MockSdkLibrary implements SdkLibrary {
|
|||
bool get isVmLibrary => throw unimplemented;
|
||||
|
||||
UnimplementedError get unimplemented => new UnimplementedError();
|
||||
|
||||
@override
|
||||
List<String> getPatches(int platform) => const <String>[];
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ library analyzer.src.generated.sdk;
|
|||
import 'dart:collection';
|
||||
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/ast/token.dart';
|
||||
import 'package:analyzer/dart/ast/visitor.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart'
|
||||
show AnalysisContext, AnalysisOptions, AnalysisOptionsImpl;
|
||||
|
@ -274,6 +275,7 @@ class SdkDescription {
|
|||
buffer.write(optionName);
|
||||
needsSeparator = true;
|
||||
}
|
||||
|
||||
for (String path in paths) {
|
||||
add(path);
|
||||
}
|
||||
|
@ -307,6 +309,11 @@ class SdkLibrariesReader_LibraryBuilder extends RecursiveAstVisitor<Object> {
|
|||
*/
|
||||
static String _DART2JS_PATH = "dart2jsPath";
|
||||
|
||||
/**
|
||||
* The name of the `dart2js` platform.
|
||||
*/
|
||||
static String _DART2JS_PLATFORM = 'DART2JS_PLATFORM';
|
||||
|
||||
/**
|
||||
* The name of the optional parameter used to indicate whether the library is
|
||||
* documented.
|
||||
|
@ -319,6 +326,12 @@ class SdkLibrariesReader_LibraryBuilder extends RecursiveAstVisitor<Object> {
|
|||
*/
|
||||
static String _CATEGORIES = "categories";
|
||||
|
||||
/**
|
||||
* The name of the optional parameter used to specify the patches for
|
||||
* the library.
|
||||
*/
|
||||
static String _PATCHES = "patches";
|
||||
|
||||
/**
|
||||
* The name of the optional parameter used to specify the platforms on which
|
||||
* the library can be used.
|
||||
|
@ -397,6 +410,28 @@ class SdkLibrariesReader_LibraryBuilder extends RecursiveAstVisitor<Object> {
|
|||
library._implementation = (expression as BooleanLiteral).value;
|
||||
} else if (name == _DOCUMENTED) {
|
||||
library.documented = (expression as BooleanLiteral).value;
|
||||
} else if (name == _PATCHES) {
|
||||
if (expression is MapLiteral) {
|
||||
expression.entries.forEach((MapLiteralEntry entry) {
|
||||
int platforms = _convertPlatforms(entry.key);
|
||||
Expression pathsListLiteral = entry.value;
|
||||
if (pathsListLiteral is ListLiteral) {
|
||||
List<String> paths = <String>[];
|
||||
pathsListLiteral.elements.forEach((Expression pathExpr) {
|
||||
if (pathExpr is SimpleStringLiteral) {
|
||||
paths.add(pathExpr.value);
|
||||
} else {
|
||||
throw new ArgumentError(
|
||||
'The "patch" argument items must be simple strings.');
|
||||
}
|
||||
});
|
||||
library.setPatchPaths(platforms, paths);
|
||||
} else {
|
||||
throw new ArgumentError(
|
||||
'The "patch" argument values must be list literals.');
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (name == _PLATFORMS) {
|
||||
if (expression is SimpleIdentifier) {
|
||||
String identifier = expression.name;
|
||||
|
@ -417,6 +452,43 @@ class SdkLibrariesReader_LibraryBuilder extends RecursiveAstVisitor<Object> {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the platform constant value for the given [expr].
|
||||
* Throw [ArgumentError] if not a valid platform name given.
|
||||
*/
|
||||
static int _convertPlatform(Expression expr) {
|
||||
if (expr is SimpleIdentifier) {
|
||||
String name = expr.name;
|
||||
if (name == _DART2JS_PLATFORM) {
|
||||
return SdkLibraryImpl.DART2JS_PLATFORM;
|
||||
}
|
||||
if (name == _VM_PLATFORM) {
|
||||
return SdkLibraryImpl.VM_PLATFORM;
|
||||
}
|
||||
throw new ArgumentError('Invalid platform name: $name');
|
||||
}
|
||||
throw new ArgumentError('Invalid platform type: ${expr.runtimeType}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the platforms combination value for the [expr], which should be
|
||||
* either `name1 | name2` or `name`. Throw [ArgumentError] if any of the
|
||||
* names is not a valid platform name.
|
||||
*/
|
||||
static int _convertPlatforms(Expression expr) {
|
||||
if (expr is BinaryExpression) {
|
||||
TokenType operator = expr.operator?.type;
|
||||
if (operator == TokenType.BAR) {
|
||||
return _convertPlatforms(expr.leftOperand) |
|
||||
_convertPlatforms(expr.rightOperand);
|
||||
} else {
|
||||
throw new ArgumentError('Invalid platforms combination: $operator');
|
||||
}
|
||||
} else {
|
||||
return _convertPlatform(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -469,6 +541,12 @@ abstract class SdkLibrary {
|
|||
* including `dart:`.
|
||||
*/
|
||||
String get shortName;
|
||||
|
||||
/**
|
||||
* Return the list of paths to the patch files that should be applied
|
||||
* to this library for the given [platform], not `null`.
|
||||
*/
|
||||
List<String> getPatches(int platform);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -520,6 +598,14 @@ class SdkLibraryImpl implements SdkLibrary {
|
|||
*/
|
||||
int _platforms = 0;
|
||||
|
||||
/**
|
||||
* The mapping from the platform combination to the list of paths (relative
|
||||
* to the `sdk/lib` folder) of patches that should be applied to this library
|
||||
* on every platform in the combination.
|
||||
*/
|
||||
final Map<int, List<String>> _platformsToPatchPaths =
|
||||
new HashMap<int, List<String>>();
|
||||
|
||||
/**
|
||||
* Initialize a newly created library to represent the library with the given
|
||||
* [name].
|
||||
|
@ -551,6 +637,17 @@ class SdkLibraryImpl implements SdkLibrary {
|
|||
@override
|
||||
bool get isVmLibrary => (_platforms & VM_PLATFORM) != 0;
|
||||
|
||||
@override
|
||||
List<String> getPatches(int platform) {
|
||||
List<String> paths = <String>[];
|
||||
_platformsToPatchPaths.forEach((int platforms, List<String> value) {
|
||||
if ((platforms & platform) != 0) {
|
||||
paths.addAll(value);
|
||||
}
|
||||
});
|
||||
return paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that this library can be compiled to JavaScript by dart2js.
|
||||
*/
|
||||
|
@ -558,6 +655,14 @@ class SdkLibraryImpl implements SdkLibrary {
|
|||
_platforms |= DART2JS_PLATFORM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new patch with the given [path] that should be applied for the
|
||||
* given [platforms].
|
||||
*/
|
||||
void setPatchPaths(int platforms, List<String> paths) {
|
||||
_platformsToPatchPaths[platforms] = paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that this library can be run on the VM.
|
||||
*/
|
||||
|
|
|
@ -498,6 +498,9 @@ class _MockSdkLibrary implements SdkLibrary {
|
|||
|
||||
@override
|
||||
bool get isVmLibrary => throw new UnimplementedError();
|
||||
|
||||
@override
|
||||
List<String> getPatches(int platform) => const <String>[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,7 +25,8 @@ main() {
|
|||
defineReflectiveTests(EmbedderSdkTest);
|
||||
defineReflectiveTests(FolderBasedDartSdkTest);
|
||||
defineReflectiveTests(SdkExtensionFinderTest);
|
||||
defineReflectiveTests(SDKLibrariesReaderTest);
|
||||
defineReflectiveTests(SdkLibrariesReaderTest);
|
||||
defineReflectiveTests(SdkLibraryImplTest);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -391,7 +392,7 @@ class SdkExtensionFinderTest {
|
|||
}
|
||||
|
||||
@reflectiveTest
|
||||
class SDKLibrariesReaderTest extends EngineTestCase {
|
||||
class SdkLibrariesReaderTest extends EngineTestCase {
|
||||
/**
|
||||
* The resource provider used by these tests.
|
||||
*/
|
||||
|
@ -473,4 +474,119 @@ final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
|
|||
expect(second.isImplementation, true);
|
||||
expect(second.isVmLibrary, false);
|
||||
}
|
||||
|
||||
void test_readFrom_patches() {
|
||||
LibraryMap libraryMap = new SdkLibrariesReader(false).readFromFile(
|
||||
resourceProvider.getFile('/libs.dart'),
|
||||
r'''
|
||||
final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
|
||||
'foo' : const LibraryInfo(
|
||||
'foo/foo.dart',
|
||||
patches: {
|
||||
DART2JS_PLATFORM | VM_PLATFORM: ['a', 'b'],
|
||||
DART2JS_PLATFORM: ['c', 'd'],
|
||||
VM_PLATFORM: ['e']}),
|
||||
};''');
|
||||
expect(libraryMap, isNotNull);
|
||||
expect(libraryMap.size(), 1);
|
||||
SdkLibrary library = libraryMap.getLibrary('dart:foo');
|
||||
expect(library, isNotNull);
|
||||
expect(library.path, 'foo/foo.dart');
|
||||
expect(library.shortName, 'dart:foo');
|
||||
expect(library.getPatches(SdkLibraryImpl.DART2JS_PLATFORM),
|
||||
unorderedEquals(['a', 'b', 'c', 'd']));
|
||||
expect(library.getPatches(SdkLibraryImpl.VM_PLATFORM),
|
||||
unorderedEquals(['a', 'b', 'e']));
|
||||
}
|
||||
|
||||
void test_readFrom_patches_invalid_notList() {
|
||||
expect(() {
|
||||
new SdkLibrariesReader(false).readFromFile(
|
||||
resourceProvider.getFile('/libs.dart'),
|
||||
r'''
|
||||
final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
|
||||
'foo' : const LibraryInfo(
|
||||
'foo/foo.dart',
|
||||
patches: {
|
||||
VM_PLATFORM: 'X'}),
|
||||
};''');
|
||||
}, throwsArgumentError);
|
||||
}
|
||||
|
||||
void test_readFrom_patches_invalid_notString_inList() {
|
||||
expect(() {
|
||||
new SdkLibrariesReader(false).readFromFile(
|
||||
resourceProvider.getFile('/libs.dart'),
|
||||
r'''
|
||||
final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
|
||||
'foo' : const LibraryInfo(
|
||||
'foo/foo.dart',
|
||||
patches: {
|
||||
VM_PLATFORM: [42]}),
|
||||
};''');
|
||||
}, throwsArgumentError);
|
||||
}
|
||||
|
||||
void test_readFrom_patches_invalid_platformCombinator() {
|
||||
expect(() {
|
||||
new SdkLibrariesReader(false).readFromFile(
|
||||
resourceProvider.getFile('/libs.dart'),
|
||||
r'''
|
||||
final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
|
||||
'foo' : const LibraryInfo(
|
||||
'foo/foo.dart',
|
||||
patches: {
|
||||
DART2JS_PLATFORM + VM_PLATFORM: ['X']}),
|
||||
};''');
|
||||
}, throwsArgumentError);
|
||||
}
|
||||
|
||||
void test_readFrom_patches_invalid_unknownPlatform() {
|
||||
expect(() {
|
||||
new SdkLibrariesReader(false).readFromFile(
|
||||
resourceProvider.getFile('/libs.dart'),
|
||||
r'''
|
||||
final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
|
||||
'foo' : const LibraryInfo(
|
||||
'foo/foo.dart',
|
||||
patches: {
|
||||
MY_UNKNOWN_PLATFORM: ['foo/bar_patch.dart']}),
|
||||
};''');
|
||||
}, throwsArgumentError);
|
||||
}
|
||||
|
||||
void test_readFrom_patches_no() {
|
||||
LibraryMap libraryMap = new SdkLibrariesReader(false).readFromFile(
|
||||
resourceProvider.getFile('/libs.dart'),
|
||||
r'''
|
||||
final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
|
||||
'my' : const LibraryInfo('my/my.dart')
|
||||
};''');
|
||||
expect(libraryMap, isNotNull);
|
||||
expect(libraryMap.size(), 1);
|
||||
SdkLibrary library = libraryMap.getLibrary('dart:my');
|
||||
expect(library, isNotNull);
|
||||
expect(library.path, 'my/my.dart');
|
||||
expect(library.shortName, 'dart:my');
|
||||
expect(library.getPatches(SdkLibraryImpl.VM_PLATFORM), isEmpty);
|
||||
expect(library.getPatches(SdkLibraryImpl.DART2JS_PLATFORM), isEmpty);
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class SdkLibraryImplTest extends EngineTestCase {
|
||||
void test_patches() {
|
||||
SdkLibraryImpl library = new SdkLibraryImpl('dart:foo');
|
||||
// Set patches.
|
||||
library.setPatchPaths(
|
||||
SdkLibraryImpl.DART2JS_PLATFORM | SdkLibraryImpl.VM_PLATFORM,
|
||||
['a', 'b']);
|
||||
library.setPatchPaths(SdkLibraryImpl.DART2JS_PLATFORM, ['c', 'd']);
|
||||
library.setPatchPaths(SdkLibraryImpl.VM_PLATFORM, ['e']);
|
||||
// Get patches.
|
||||
expect(library.getPatches(SdkLibraryImpl.DART2JS_PLATFORM),
|
||||
unorderedEquals(['a', 'b', 'c', 'd']));
|
||||
expect(library.getPatches(SdkLibraryImpl.VM_PLATFORM),
|
||||
unorderedEquals(['a', 'b', 'e']));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue