feat(dart/transform) Register parameter metadata information

Adds any metadata attached to a parameter to the "parameters" value
passed in to `registerType`.

For example:
`MyComponent(@Inject(Foo) foo)` generates
`"parameters": const [const [const Inject(Foo)]]`

Also reorganizes the testing code.

Closes #7
This commit is contained in:
Tim Blasi
2015-03-06 11:10:14 -08:00
parent e1a1dd07e4
commit f4e0f51f5a
41 changed files with 271 additions and 167 deletions
@@ -0,0 +1,141 @@
library angular2.test.transform.integration;
import 'dart:io';
import 'package:angular2/transformer.dart';
import 'package:code_transformers/tests.dart';
import 'package:dart_style/dart_style.dart';
import 'package:unittest/unittest.dart';
import '../common/read_file.dart';
var formatter = new DartFormatter();
var transform = new AngularTransformerGroup(new TransformerOptions(
'web/index.dart', reflectionEntryPoint: 'web/index.dart'));
class IntegrationTestConfig {
final String name;
final Map<String, String> assetPathToInputPath;
final Map<String, String> assetPathToExpectedOutputPath;
IntegrationTestConfig(this.name,
{Map<String, String> inputs, Map<String, String> outputs})
: this.assetPathToInputPath = inputs,
this.assetPathToExpectedOutputPath = outputs;
}
void allTests() {
/*
* Each test has its own directory for inputs & an `expected` directory for
* expected outputs.
*
* In addition to these declared inputs, we inject a set of common inputs for
* every test.
*/
var commonInputs = {
'angular2|lib/src/core/annotations/annotations.dart':
'../../../lib/src/core/annotations/annotations.dart',
'angular2|lib/src/core/application.dart': '../common/application.dart',
'angular2|lib/src/reflection/reflection_capabilities.dart':
'../common/reflection_capabilities.dart'
};
var tests = [
new IntegrationTestConfig(
'should generate proper code for a Component defining only a selector.',
inputs: {
'a|web/index.dart': 'simple_annotation_files/index.dart',
'a|web/bar.dart': 'simple_annotation_files/bar.dart'
},
outputs: {
'a|web/bar.ngDeps.dart':
'simple_annotation_files/expected/bar.ngDeps.dart',
'a|web/index.ngDeps.dart':
'simple_annotation_files/expected/index.ngDeps.dart'
}),
new IntegrationTestConfig(
'should generate proper code for a Component using a selector defined '
'in another file.',
inputs: {
'a|web/index.dart': 'two_deps_files/index.dart',
'a|web/foo.dart': 'two_deps_files/foo.dart',
'a|web/bar.dart': 'two_deps_files/bar.dart'
},
outputs: {
'a|web/bar.ngDeps.dart': 'two_deps_files/expected/bar.ngDeps.dart'
}),
new IntegrationTestConfig(
'should generate proper code for a Component declaring a '
'componentService defined in another file.',
inputs: {
'a|web/index.dart': 'list_of_types_files/index.dart',
'a|web/foo.dart': 'list_of_types_files/foo.dart',
'a|web/bar.dart': 'list_of_types_files/bar.dart'
},
outputs: {
'a|web/bar.ngDeps.dart': 'list_of_types_files/expected/bar.ngDeps.dart'
}),
new IntegrationTestConfig(
'should generate a factory for a class with no declared ctor.',
inputs: {
'a|web/index.dart': 'synthetic_ctor_files/index.dart',
'a|web/bar.dart': 'synthetic_ctor_files/bar.dart'
},
outputs: {
'a|web/bar.ngDeps.dart': 'synthetic_ctor_files/expected/bar.ngDeps.dart'
}),
new IntegrationTestConfig('should preserve multiple annotations.',
inputs: {
'a|web/index.dart': 'two_annotations_files/index.dart',
'a|web/bar.dart': 'two_annotations_files/bar.dart',
'angular2|lib/src/core/annotations/template.dart':
'../../../lib/src/core/annotations/template.dart'
},
outputs: {
'a|web/bar.ngDeps.dart': 'two_annotations_files/expected/bar.ngDeps.dart'
}),
new IntegrationTestConfig('should generate setters for `bind` values.',
inputs: {
'a|web/index.dart': 'basic_bind_files/index.dart',
'a|web/bar.dart': 'basic_bind_files/bar.dart'
},
outputs: {
'a|web/bar.ngDeps.dart': 'basic_bind_files/expected/bar.ngDeps.dart'
}),
new IntegrationTestConfig(
'should ensure that dependencies are property chained.',
inputs: {
'a|web/index.dart': 'chained_deps_files/index.dart',
'a|web/foo.dart': 'chained_deps_files/foo.dart',
'a|web/bar.dart': 'chained_deps_files/bar.dart'
},
outputs: {
'a|web/bar.ngDeps.dart': 'chained_deps_files/expected/bar.ngDeps.dart',
'a|web/foo.ngDeps.dart': 'chained_deps_files/expected/foo.ngDeps.dart'
})
];
var cache = {};
for (var config in tests) {
// Read in input & output files.
config.assetPathToInputPath
..addAll(commonInputs)
..forEach((key, value) {
config.assetPathToInputPath[key] =
cache.putIfAbsent(value, () => _readFile(value));
});
config.assetPathToExpectedOutputPath.forEach((key, value) {
config.assetPathToExpectedOutputPath[key] = cache.putIfAbsent(value, () {
var code = _readFile(value);
return value.endsWith('dart') ? formatter.format(code) : code;
});
});
testPhases(config.name, [
[transform]
], config.assetPathToInputPath, config.assetPathToExpectedOutputPath, []);
}
}
/// Smooths over differences in CWD between IDEs and running tests in Travis.
String _readFile(String path) => readFile('integration/$path');
@@ -0,0 +1,11 @@
library bar;
import 'package:angular2/src/core/annotations/annotations.dart';
@Component(selector: 'soup', componentServices: const [ToolTip])
class MyComponent {}
@Decorator(selector: '[tool-tip]', bind: const {'text': 'tool-tip'})
class ToolTip {
String text;
}
@@ -0,0 +1,27 @@
library bar;
import 'bar.dart';
import 'package:angular2/src/core/annotations/annotations.dart';
bool _visited = false;
void setupReflection(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(MyComponent, {
"factory": () => new MyComponent(),
"parameters": const [],
"annotations": const [
const Component(selector: 'soup', componentServices: const [ToolTip])
]
})
..registerType(ToolTip, {
"factory": () => new ToolTip(),
"parameters": const [],
"annotations": const [
const Decorator(
selector: '[tool-tip]', bind: const {'text': 'tool-tip'})
]
})
..registerSetters({"text": (ToolTip o, String value) => o.text = value});
}
@@ -0,0 +1,10 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}
@@ -0,0 +1,10 @@
library bar;
import 'package:angular2/src/core/annotations/annotations.dart';
import 'foo.dart' as dep;
@Component(
selector: '[soup]', componentServices: const [dep.DependencyComponent])
class MyComponent {
MyComponent();
}
@@ -0,0 +1,23 @@
library bar;
import 'bar.dart';
import 'package:angular2/src/core/annotations/annotations.dart';
import 'foo.dart' as dep;
import 'foo.ngDeps.dart' as i0;
bool _visited = false;
void setupReflection(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(MyComponent, {
"factory": () => new MyComponent(),
"parameters": const [],
"annotations": const [
const Component(
selector: '[soup]',
componentServices: const [dep.DependencyComponent])
]
});
i0.setupReflection(reflector);
}
@@ -0,0 +1,16 @@
library foo;
import 'foo.dart';
import 'package:angular2/src/core/annotations/annotations.dart';
bool _visited = false;
void setupReflection(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(DependencyComponent, {
"factory": () => new DependencyComponent(),
"parameters": const [],
"annotations": const [const Component(selector: '[salad]')]
});
}
@@ -0,0 +1,13 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
import 'a:web/bar.ngDeps.dart' as i0;
bool _visited = false;
void setupReflection(reflector) {
if (_visited) return;
_visited = true;
i0.setupReflection(reflector);
}
@@ -0,0 +1,8 @@
library foo;
import 'package:angular2/src/core/annotations/annotations.dart';
@Component(selector: '[salad]')
class DependencyComponent {
DependencyComponent();
}
@@ -0,0 +1,10 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}
@@ -0,0 +1,10 @@
library bar;
import 'package:angular2/src/core/annotations/annotations.dart';
import 'foo.dart';
@Component(componentServices: const [MyContext])
class MyComponent {
final MyContext c;
MyComponent(this.c);
}
@@ -0,0 +1,19 @@
library bar;
import 'bar.dart';
import 'package:angular2/src/core/annotations/annotations.dart';
import 'foo.dart';
bool _visited = false;
void setupReflection(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(MyComponent, {
"factory": (MyContext c) => new MyComponent(c),
"parameters": const [const [MyContext]],
"annotations": const [
const Component(componentServices: const [MyContext])
]
});
}
@@ -0,0 +1,6 @@
library foo;
class MyContext {
final String s;
const MyContext(this.s);
}
@@ -0,0 +1,10 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}
@@ -0,0 +1,8 @@
library bar;
import 'package:angular2/src/core/annotations/annotations.dart';
@Component(selector: '[soup]')
class MyComponent {
MyComponent();
}
@@ -0,0 +1,16 @@
library bar;
import 'bar.dart';
import 'package:angular2/src/core/annotations/annotations.dart';
bool _visited = false;
void setupReflection(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(MyComponent, {
"factory": () => new MyComponent(),
"parameters": const [],
"annotations": const [const Component(selector: '[soup]')]
});
}
@@ -0,0 +1,15 @@
library web_foo;
import 'index.dart';
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
import 'bar.ngDeps.dart' as i0;
bool _visited = false;
void setupReflection(reflector) {
if (_visited) return;
_visited = true;
i0.setupReflection(reflector);
}
@@ -0,0 +1,11 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}
@@ -0,0 +1,6 @@
library bar;
import 'package:angular2/src/core/annotations/annotations.dart';
@Component(selector: '[soup]')
class MyComponent {}
@@ -0,0 +1,16 @@
library bar;
import 'bar.dart';
import 'package:angular2/src/core/annotations/annotations.dart';
bool _visited = false;
void setupReflection(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(MyComponent, {
"factory": () => new MyComponent(),
"parameters": const [],
"annotations": const [const Component(selector: '[soup]')]
});
}
@@ -0,0 +1,10 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}
@@ -0,0 +1,10 @@
library bar;
import 'package:angular2/src/core/annotations/annotations.dart';
import 'package:angular2/src/core/annotations/template.dart';
@Component(selector: '[soup]')
@Template(inline: 'Salad')
class MyComponent {
MyComponent();
}
@@ -0,0 +1,20 @@
library bar;
import 'bar.dart';
import 'package:angular2/src/core/annotations/annotations.dart';
import 'package:angular2/src/core/annotations/template.dart';
bool _visited = false;
void setupReflection(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(MyComponent, {
"factory": () => new MyComponent(),
"parameters": const [],
"annotations": const [
const Component(selector: '[soup]'),
const Template(inline: 'Salad')
]
});
}
@@ -0,0 +1,10 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}
@@ -0,0 +1,13 @@
library bar;
import 'package:angular2/src/core/annotations/annotations.dart';
import 'foo.dart' as prefix;
@Component(selector: prefix.preDefinedSelector)
class MyComponent {
final prefix.MyContext c;
final String generatedValue;
MyComponent(this.c, String inValue) {
generatedValue = 'generated ' + inValue;
}
}
@@ -0,0 +1,20 @@
library bar;
import 'bar.dart';
import 'package:angular2/src/core/annotations/annotations.dart';
import 'foo.dart' as prefix;
bool _visited = false;
void setupReflection(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(MyComponent, {
"factory":
(prefix.MyContext c, String inValue) => new MyComponent(c, inValue),
"parameters": const [const [prefix.MyContext], const [String]],
"annotations": const [
const Component(selector: prefix.preDefinedSelector)
]
});
}
@@ -0,0 +1,8 @@
library foo;
const preDefinedSelector = 'soup';
class MyContext {
final String selector;
const MyContext(this.selector);
}
@@ -0,0 +1,10 @@
library web_foo;
import 'package:angular2/src/core/application.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'bar.dart';
void main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(MyComponent);
}