fix(dart/transformer): Correctly handle const object annotations

Previously, annotations which were const objects (as opposed to const
instance creation expressions) were incorrectly output as instance
creation expressions.

Before:
```
const override() // A const instance creation expression
```

After
```
override // A const instance
```

Closes #4481
This commit is contained in:
Tim Blasi
2015-10-02 15:54:32 -07:00
parent 01fb06a377
commit decdbea7d7
9 changed files with 216 additions and 59 deletions
@@ -16,49 +16,65 @@ void allTests() {
it('should generate a setter for an `inputs` property in an annotation.',
() async {
var inputPath = 'bind_generator/basic_bind_files/bar.ng_deps.dart';
var expected = formatter.format(
readFile('bind_generator/basic_bind_files/expected/bar.ng_deps.dart'));
var inputPath = 'basic_bind_files/bar.ng_deps.dart';
var expected = _readFile('basic_bind_files/expected/bar.ng_deps.dart');
var output = formatter.format(
await createNgSettersAndGetters(reader, new AssetId('a', inputPath)));
var output = formatter
.format(await createNgSettersAndGetters(reader, _assetId(inputPath)));
expect(output).toEqual(expected);
});
it(
'should generate a single setter when multiple annotations bind to the '
'same `inputs` property.', () async {
var inputPath =
'bind_generator/duplicate_bind_name_files/soup.ng_deps.dart';
var expected = formatter.format(readFile(
'bind_generator/duplicate_bind_name_files/expected/soup.ng_deps.dart'));
var inputPath = 'duplicate_bind_name_files/soup.ng_deps.dart';
var expected =
_readFile('duplicate_bind_name_files/expected/soup.ng_deps.dart');
var output = formatter.format(
await createNgSettersAndGetters(reader, new AssetId('a', inputPath)));
var output = formatter
.format(await createNgSettersAndGetters(reader, _assetId(inputPath)));
expect(output).toEqual(expected);
});
it('should generate setters for queries defined in the class annotation.',
() async {
var inputPath =
'bind_generator/queries_class_annotation_files/bar.ng_deps.dart';
var expected = formatter.format(readFile(
'bind_generator/queries_class_annotation_files/expected/bar.ng_deps.dart'));
var inputPath = 'queries_class_annotation_files/bar.ng_deps.dart';
var expected =
_readFile('queries_class_annotation_files/expected/bar.ng_deps.dart');
var output = formatter.format(
await createNgSettersAndGetters(reader, new AssetId('a', inputPath)));
var output = formatter
.format(await createNgSettersAndGetters(reader, _assetId(inputPath)));
expect(output).toEqual(expected);
});
it('should generate setters for queries defined via prop annotations.',
() async {
var inputPath =
'bind_generator/queries_prop_annotations_files/bar.ng_deps.dart';
var expected = formatter.format(readFile(
'bind_generator/queries_prop_annotations_files/expected/bar.ng_deps.dart'));
var inputPath = 'queries_prop_annotations_files/bar.ng_deps.dart';
var expected =
_readFile('queries_prop_annotations_files/expected/bar.ng_deps.dart');
var output = formatter.format(
await createNgSettersAndGetters(reader, new AssetId('a', inputPath)));
var output = formatter
.format(await createNgSettersAndGetters(reader, _assetId(inputPath)));
expect(output).toEqual(expected);
});
it('should gracefully handle const objects as prop annotations.', () async {
var inputPath = 'queries_override_annotation_files/bar.ng_deps.dart';
var expected = formatter.format(_readFile(
'queries_override_annotation_files/expected/bar.ng_deps.dart'));
var output = formatter
.format(await createNgSettersAndGetters(reader, _assetId(inputPath)));
expect(output).toEqual(expected);
});
}
AssetId _assetId(String path) => new AssetId('a', 'bind_generator/$path');
String _readFile(String path) {
var code = readFile('bind_generator/$path');
if (path.endsWith('.dart')) {
code = formatter.format(code);
}
return code;
}
@@ -0,0 +1,21 @@
library bar.ng_deps.dart;
import 'bar.dart';
import 'package:angular2/src/core/metadata.dart';
var _visited = false;
void initReflector(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(
ToolTip,
new ReflectionInfo(
const [const Directive(selector: '[tool-tip]')],
const [],
() => new ToolTip(),
null,
const {
'queryField': const [override]
}));
}
@@ -0,0 +1,21 @@
library bar.ng_deps.dart;
import 'bar.dart';
import 'package:angular2/src/core/metadata.dart';
var _visited = false;
void initReflector(reflector) {
if (_visited) return;
_visited = true;
reflector
..registerType(
ToolTip,
new ReflectionInfo(
const [const Directive(selector: '[tool-tip]')],
const [],
() => new ToolTip(),
null,
const {
'queryField': const [override]
}));
}
@@ -9,6 +9,7 @@ import 'package:angular2/src/core/linker/interfaces.dart' show LifecycleHooks;
import 'package:angular2/src/core/dom/html_adapter.dart';
import 'package:angular2/src/transform/directive_processor/rewriter.dart';
import 'package:angular2/src/transform/common/annotation_matcher.dart';
import 'package:angular2/src/transform/common/code/ng_deps_code.dart';
import 'package:angular2/src/transform/common/asset_reader.dart';
import 'package:angular2/src/transform/common/logging.dart' as log;
import 'package:angular2/src/transform/common/model/reflection_info_model.pb.dart';
@@ -210,9 +211,32 @@ void allTests() {
expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue();
expect(model.reflectables.first.propertyMetadata.first.name)
.toEqual('getVal');
expect(model.reflectables.first.propertyMetadata.first.annotations
.firstWhere((a) => a.name == 'GetDecorator', orElse: () => null))
.toBeNotNull();
var getDecoratorAnnotation = model
.reflectables.first.propertyMetadata.first.annotations
.firstWhere((a) => a.name == 'GetDecorator', orElse: () => null);
expect(getDecoratorAnnotation).toBeNotNull();
expect(getDecoratorAnnotation.isConstObject).toBeFalse();
});
it('should gracefully handle const instances of annotations', () async {
// Regression test for i/4481
var model = await _testCreateModel('prop_metadata_files/override.dart');
expect(model.reflectables.first.propertyMetadata).toBeNotNull();
expect(model.reflectables.first.propertyMetadata.isNotEmpty).toBeTrue();
expect(model.reflectables.first.propertyMetadata.first.name)
.toEqual('getVal');
var overrideAnnotation = model
.reflectables.first.propertyMetadata.first.annotations
.firstWhere((a) => a.name == 'override', orElse: () => null);
expect(overrideAnnotation).toBeNotNull();
expect(overrideAnnotation.isConstObject).toBeTrue();
var buf = new StringBuffer();
new NgDepsWriter(buf).writeAnnotationModel(overrideAnnotation);
expect(buf.toString()).toEqual('override');
});
it('should be recorded on setters', () async {
@@ -0,0 +1,14 @@
library override;
import 'package:angular2/src/core/metadata.dart';
@Component(selector: '[getters]')
@View(template: '')
class FieldComponent implements ValGetter {
@override
String get getVal => 'a';
}
abstract class ValGetter {
String get getVal;
}