Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(352)

Unified Diff: third_party/pkg/angular/lib/tools/transformer/referenced_uris.dart

Issue 257423008: Update all Angular libs (run update_all.sh). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/pkg/angular/lib/tools/transformer/referenced_uris.dart
diff --git a/third_party/pkg/angular/lib/tools/transformer/referenced_uris.dart b/third_party/pkg/angular/lib/tools/transformer/referenced_uris.dart
new file mode 100644
index 0000000000000000000000000000000000000000..25baf6ee3cf4ad5abe15f2e4c37ca9bfe2cfff04
--- /dev/null
+++ b/third_party/pkg/angular/lib/tools/transformer/referenced_uris.dart
@@ -0,0 +1,262 @@
+library angular.tools.transformers.referenced_uris;
+
+import 'dart:async';
+
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/element.dart';
+import 'package:angular/tools/transformer/options.dart';
+import 'package:barback/barback.dart';
+import 'package:code_transformers/resolver.dart';
+import 'package:path/path.dart' as path;
+
+/// Gathers the contents of all URIs which are referenced by the contents of
+/// the application.
+/// Returns a map from URI to contents.
+Future<Map<String, String>> gatherReferencedUris(Transform transform,
+ Resolver resolver, TransformOptions options,
+ {bool skipNonCached: false, bool templatesOnly: false}) {
+ return new _Processor(transform, resolver, options, skipNonCached,
+ templatesOnly).process();
+}
+
+class _Processor {
+ final Transform transform;
+ final Resolver resolver;
+ final TransformOptions options;
+ final Map<RegExp, String> templateUriRewrites = <RegExp, String>{};
+ final bool skipNonCached;
+ final bool templatesOnly;
+
+ ConstructorElement cacheAnnotation;
+ ConstructorElement componentAnnotation;
+
+ static const String cacheAnnotationName =
+ 'angular.template_cache_annotation.NgTemplateCache';
+ static const String componentAnnotationName = 'angular.core.annotation_src.Component';
+
+ _Processor(this.transform, this.resolver, this.options, this.skipNonCached,
+ this.templatesOnly) {
+ for (var key in options.templateUriRewrites.keys) {
+ templateUriRewrites[new RegExp(key)] = options.templateUriRewrites[key];
+ }
+ }
+
+ /// Gathers the contents of all URIs which are to be cached.
+ /// Returns a map from URI to contents.
+ Future<Map<String, String>> process() {
+ var cacheAnnotationType = resolver.getType(cacheAnnotationName);
+ if (cacheAnnotationType != null &&
+ cacheAnnotationType.unnamedConstructor != null) {
+ cacheAnnotation = cacheAnnotationType.unnamedConstructor;
+ }
+
+ var componentAnnotationType = resolver.getType(componentAnnotationName);
+ if (componentAnnotationType != null &&
+ componentAnnotationType.unnamedConstructor != null) {
+ componentAnnotation = componentAnnotationType.unnamedConstructor;
+ } else {
+ logger.warning('Unable to resolve $componentAnnotationName.');
+ }
+
+ var annotations = resolver.libraries
+ .expand((lib) => lib.units)
+ .expand((unit) => unit.types)
+ .where((type) => type.node != null)
+ .expand(_AnnotatedElement.fromElement)
+ .where((e) =>
+ (e.annotation.element == cacheAnnotation ||
+ e.annotation.element == componentAnnotation))
+ .toList();
+
+ var uriToEntry = <String, _CacheEntry>{};
+ annotations.where((anno) => anno.annotation.element == componentAnnotation)
+ .expand(processComponentAnnotation)
+ .forEach((entry) {
+ uriToEntry[entry.uri] = entry;
+ });
+ if (!templatesOnly) {
+ annotations.where((anno) => anno.annotation.element == cacheAnnotation)
+ .expand(processCacheAnnotation)
+ .forEach((entry) {
+ uriToEntry[entry.uri] = entry;
+ });
+ }
+
+ var futures = uriToEntry.values.map(cacheEntry);
+
+ return Future.wait(futures).then((_) {
+ var uriToContents = <String, String>{};
+ for (var entry in uriToEntry.values) {
+ if (entry.contents == null) continue;
+
+ uriToContents[entry.uri] = entry.contents;
+ }
+ return uriToContents;
+ });
+ }
+
+ /// Extracts the cacheable URIs from the Component annotation.
+ List<_CacheEntry> processComponentAnnotation(_AnnotatedElement annotation) {
+ var entries = <_CacheEntry>[];
+ if (skipNonCached && isCachingSuppressed(annotation.element)) {
+ return entries;
+ }
+ for (var arg in annotation.annotation.arguments.arguments) {
+ if (arg is NamedExpression) {
+ var paramName = arg.name.label.name;
+ if (paramName == 'templateUrl') {
+ var entry = extractString('templateUrl', arg.expression,
+ annotation.element);
+ if (entry != null) {
+ entries.add(entry);
+ }
+ } else if (paramName == 'cssUrl' && !templatesOnly) {
+ entries.addAll(extractListOrString(paramName, arg.expression,
+ annotation.element));
+ }
+ }
+ }
+
+ return entries;
+ }
+
+ bool isCachingSuppressed(Element e) {
+ if (cacheAnnotation == null) return false;
+ AnnotatedNode node = e.node;
+ for (var annotation in node.metadata) {
+ if (annotation.element == cacheAnnotation) {
+ for (var arg in annotation.arguments.arguments) {
+ if (arg is NamedExpression && arg.name.label.name == 'cache') {
+ var value = arg.expression;
+ if (value is! BooleanLiteral) {
+ warn('Expected boolean literal for NgTemplateCache.cache', e);
+ return false;
+ }
+ return !value.value;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ List<_CacheEntry> processCacheAnnotation(_AnnotatedElement annotation) {
+ var entries = <_CacheEntry>[];
+ for (var arg in annotation.annotation.arguments.arguments) {
+ if (arg is NamedExpression) {
+ var paramName = arg.name.label.name;
+ if (paramName == 'preCacheUrls') {
+ entries.addAll(extractListOrString(paramName, arg.expression,
+ annotation.element));
+ }
+ }
+ }
+ return entries;
+ }
+
+ List<_CacheEntry> extractListOrString(String paramName,
+ Expression expression, Element element) {
+ var entries = [];
+ if (expression is StringLiteral) {
+ var entry = uriToEntry(expression.stringValue, element);
+ if (entry != null) {
+ entries.add(entry);
+ }
+ } else if (expression is ListLiteral) {
+ for (var value in expression.elements) {
+ if (value is! StringLiteral) {
+ warn('Expected a string literal in $paramName', element);
+ continue;
+ }
+ var entry = uriToEntry(value.stringValue, element);
+ if (entry != null) {
+ entries.add(entry);
+ }
+ }
+ } else {
+ warn('$paramName must be a string or list literal.', element);
+ }
+ return entries;
+ }
+
+ _CacheEntry extractString(String paramName, Expression expression,
+ Element element) {
+ if (expression is StringLiteral) {
+ return uriToEntry(expression.stringValue, element);
+ }
+ warn('$paramName must be a string literal.', element);
+ return null;
+ }
+
+ Future<_CacheEntry> cacheEntry(_CacheEntry entry) {
+ return transform.readInputAsString(entry.assetId).then((contents) {
+ entry.contents = contents;
+ return entry;
+ }, onError: (e) {
+ warn('Unable to find ${entry.uri} at ${entry.assetId}', entry.element);
+ });
+ }
+
+ _CacheEntry uriToEntry(String uri, Element reference) {
+ uri = rewriteUri(uri);
+ if (Uri.parse(uri).scheme != '') {
+ warn('Cannot cache non-local URIs. $uri', reference);
+ return null;
+ }
+ if (path.url.isAbsolute(uri)) {
+ var parts = path.posix.split(uri);
+ if (parts[1] == 'packages') {
+ var pkgPath = path.url.join('lib', path.url.joinAll(parts.skip(3)));
+ return new _CacheEntry(uri, reference, new AssetId(parts[2], pkgPath));
+ }
+ warn('Cannot cache non-package absolute URIs. $uri', reference);
+ return null;
+ }
+ var assetId = new AssetId(transform.primaryInput.id.package, uri);
+ return new _CacheEntry(uri, reference, assetId);
+ }
+
+ String rewriteUri(String uri) {
+ templateUriRewrites.forEach((regexp, replacement) {
+ uri = uri.replaceFirst(regexp, replacement);
+ });
+ // Normalize packages/ uri's to be /packages/
+ if (uri.startsWith('packages/')) {
+ uri = '/' + uri;
+ }
+ return uri;
+ }
+
+ void warn(String msg, Element element) {
+ logger.warning(msg, asset: resolver.getSourceAssetId(element),
+ span: resolver.getSourceSpan(element));
+ }
+
+ TransformLogger get logger => transform.logger;
+}
+
+/// Wrapper for data related to a single cache entry.
+class _CacheEntry {
+ final String uri;
+ final Element element;
+ final AssetId assetId;
+ String contents;
+
+ _CacheEntry(this.uri, this.element, this.assetId);
+}
+
+/// Wrapper for annotation AST nodes to track the element they were declared on.
+class _AnnotatedElement {
+ /// The annotation node.
+ final Annotation annotation;
+ /// The element which the annotation was declared on.
+ final Element element;
+
+ _AnnotatedElement(this.annotation, this.element);
+
+ static Iterable<_AnnotatedElement> fromElement(Element element) {
+ AnnotatedNode node = element.node;
+ return node.metadata.map(
+ (annotation) => new _AnnotatedElement(annotation, element));
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698