Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 92b22d2

Browse files
author
Tim Blasi
committed
feat(dart/transform): Add a .ng_deps.dart file parser.
Create a common, reusable `.ng_deps.dart` file parser. All future transformer phases build on the information in `.ng_deps.dart` files.
1 parent 95c9eca commit 92b22d2

File tree

4 files changed

+212
-0
lines changed

4 files changed

+212
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
library angular2.src.transform.common.asset_reader;
2+
3+
import 'dart:async';
4+
import 'dart:convert';
5+
6+
import 'package:barback/barback.dart';
7+
8+
abstract class AssetReader {
9+
Future<String> readAsString(AssetId id, {Encoding encoding});
10+
Future<bool> hasInput(AssetId id);
11+
12+
/// Creates an [AssetReader] using the `transform`, which should be a
13+
/// [Transform] or [AggregateTransform].
14+
factory AssetReader.fromTransform(dynamic transform) =>
15+
new _TransformAssetReader(transform);
16+
}
17+
18+
class _TransformAssetReader implements AssetReader {
19+
final dynamic t;
20+
_TransformAssetReader(this.t);
21+
22+
Future<String> readAsString(AssetId id, {Encoding encoding}) =>
23+
t.readInputAsString(id, encoding: encoding);
24+
25+
Future<bool> hasInput(AssetId id) => t.hasInput(id);
26+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
library angular2.src.transform.common.parser;
2+
3+
import 'dart:async';
4+
5+
import 'package:analyzer/analyzer.dart';
6+
import 'package:angular2/src/transform/common/asset_reader.dart';
7+
import 'package:angular2/src/transform/common/logging.dart';
8+
import 'package:angular2/src/transform/common/names.dart';
9+
import 'package:barback/barback.dart';
10+
import 'package:code_transformers/assets.dart';
11+
12+
import 'registered_type.dart';
13+
14+
export 'registered_type.dart';
15+
16+
class Parser {
17+
final AssetReader _reader;
18+
final _ParseNgDepsVisitor _visitor = new _ParseNgDepsVisitor();
19+
20+
Parser(AssetReader this._reader);
21+
22+
Future<List<NgDeps>> parseRecursive(AssetId id) async {
23+
return _recurse(id);
24+
}
25+
26+
Future<NgDeps> parse(AssetId id) async {
27+
if (!(await _reader.hasInput(id))) return null;
28+
var ngDeps = new NgDeps(await _reader.readAsString(id));
29+
_visitor.ngDeps = ngDeps;
30+
parseCompilationUnit(ngDeps.code, name: id.path).accept(_visitor);
31+
return ngDeps;
32+
}
33+
34+
/// Parses the `.ngDeps.dart` file represented by [id] into an [NgDeps]
35+
/// object. All `.ngDeps.dart` files imported by [id] are then parsed. The
36+
/// results are added to [allDeps].
37+
Future<List<NgDeps>> _recurse(AssetId id,
38+
[List<NgDeps> allDeps, Set<AssetId> seen]) async {
39+
if (seen == null) seen = new Set<AssetId>();
40+
if (seen.contains(id)) return;
41+
seen.add(id);
42+
43+
if (allDeps == null) allDeps = [];
44+
var ngDeps = await parse(id);
45+
allDeps.add(ngDeps);
46+
47+
var toWait = [];
48+
ngDeps.imports.forEach((ImportDirective node) {
49+
var uri = stringLiteralToString(node.uri);
50+
if (uri.endsWith(DEPS_EXTENSION)) {
51+
var importId = uriToAssetId(id, uri, logger, null);
52+
toWait.add(_recurse(importId, allDeps, seen));
53+
}
54+
});
55+
return Future.wait(toWait).then((_) => allDeps);
56+
}
57+
}
58+
59+
class NgDeps {
60+
final String code;
61+
final List<ImportDirective> imports = [];
62+
final List<ExportDirective> exports = [];
63+
final List<RegisteredType> registeredTypes = [];
64+
FunctionDeclaration setupMethod;
65+
66+
NgDeps(this.code);
67+
}
68+
69+
class _ParseNgDepsVisitor extends Object with RecursiveAstVisitor<Object> {
70+
NgDeps ngDeps = null;
71+
_RegisteredTypeBuilder current = null;
72+
73+
@override
74+
Object visitImportDirective(ImportDirective node) {
75+
ngDeps.imports.add(node);
76+
return super.visitImportDirective(node);
77+
}
78+
79+
@override
80+
Object visitExportDirective(ExportDirective node) {
81+
ngDeps.exports.add(node);
82+
return super.visitExportDirective(node);
83+
}
84+
85+
@override
86+
Object visitFunctionDeclaration(FunctionDeclaration node) {
87+
if ('${node.name}' == SETUP_METHOD_NAME) {
88+
ngDeps.setupMethod = node;
89+
}
90+
return super.visitFunctionDeclaration(node);
91+
}
92+
93+
@override
94+
Object visitMethodInvocation(MethodInvocation node) {
95+
var isRegisterType = '${node.methodName}' == REGISTER_TYPE_METHOD_NAME;
96+
97+
if (isRegisterType) {
98+
ngDeps.registeredTypes.add(new RegisteredType.fromMethodInvocation(node));
99+
}
100+
101+
return super.visitMethodInvocation(node);
102+
}
103+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
library angular2.src.transform.common.registered_type;
2+
3+
import 'package:analyzer/analyzer.dart';
4+
import 'package:angular2/src/transform/common/names.dart';
5+
6+
/// Represents a call to `Reflector#registerType` generated by
7+
/// `DirectiveProcessor`.
8+
class RegisteredType {
9+
final Identifier typeName;
10+
final MethodInvocation registerMethod;
11+
final Expression factory;
12+
final Expression parameters;
13+
final Expression annotations;
14+
15+
RegisteredType._(this.typeName, this.registerMethod, this.factory,
16+
this.parameters, this.annotations);
17+
18+
/// Creates a [RegisteredType] given a [MethodInvocation] node representing
19+
/// a call to `registerType`.
20+
factory RegisteredType.fromMethodInvocation(MethodInvocation registerMethod) {
21+
var visitor = new _ParseRegisterTypeVisitor();
22+
registerMethod.accept(visitor);
23+
return new RegisteredType._(visitor.typeName, registerMethod,
24+
visitor.factory, visitor.parameters, visitor.annotations);
25+
}
26+
}
27+
28+
class _ParseRegisterTypeVisitor extends Object
29+
with RecursiveAstVisitor<Object> {
30+
Identifier typeName;
31+
Expression factory;
32+
Expression parameters;
33+
Expression annotations;
34+
35+
@override
36+
Object visitMethodInvocation(MethodInvocation node) {
37+
assert('${node.methodName}' == REGISTER_TYPE_METHOD_NAME);
38+
39+
// The first argument to a `registerType` call is the type.
40+
typeName = node.argumentList.arguments[0] is Identifier
41+
? node.argumentList.arguments[0]
42+
: null;
43+
return super.visitMethodInvocation(node);
44+
}
45+
46+
@override
47+
Object visitMapLiteralEntry(MapLiteralEntry node) {
48+
if (node.key is StringLiteral) {
49+
var key = stringLiteralToString(node.key);
50+
switch (key) {
51+
case 'annotations':
52+
annotations = node.value;
53+
break;
54+
case 'factory':
55+
factory = node.value;
56+
break;
57+
case 'parameters':
58+
parameters = node.value;
59+
break;
60+
}
61+
}
62+
// Do not need to descend any further.
63+
return null;
64+
}
65+
}

modules/angular2/test/transform/common/read_file.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
library angular2.test.transform.common.read_file;
22

3+
import 'dart:async';
34
import 'dart:io';
45

6+
import 'package:angular2/src/transform/common/asset_reader.dart';
7+
import 'package:barback/barback.dart';
8+
59
/// Smooths over differences in CWD between IDEs and running tests in Travis.
610
String readFile(String path) {
711
for (var myPath in [path, 'test/transform/${path}']) {
@@ -12,3 +16,17 @@ String readFile(String path) {
1216
}
1317
return null;
1418
}
19+
20+
class TestAssetReader implements AssetReader {
21+
Future<String> readAsString(AssetId id, {Encoding encoding}) =>
22+
new Future.value(readFile(id.path));
23+
24+
Future<bool> hasInput(AssetId id) {
25+
var exists = false;
26+
for (var myPath in [id.path, 'test/transform/${id.path}']) {
27+
var file = new File(myPath);
28+
exists = exists || file.existsSync();
29+
}
30+
return new Future.value(exists);
31+
}
32+
}

0 commit comments

Comments
 (0)