Files
sdk/pkg/code_transformers/lib/assets.dart
T
sigmund@google.com 088dfc5fbc Use warning instead of error in a couple places. In polymer we are hitting
scenarios where the resolution was incorrect, but we were still able to generate
valid code. We should not stop the whole build process on these cases.
(see for example https://code.google.com/p/dart/issues/detail?id=17914).

R=blois@google.com

Review URL: https://codereview.chromium.org//221673005

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@34656 260f80e4-7a28-3924-810f-c04153c831b5
2014-04-02 17:57:37 +00:00

108 lines
4.6 KiB
Dart

// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// Common methods used by transfomers for dealing with asset IDs.
library code_transformers.assets;
import 'dart:math' show min, max;
import 'package:barback/barback.dart';
import 'package:path/path.dart' as path;
import 'package:source_maps/span.dart' show Span;
/// Create an [AssetId] for a [url] seen in the [source] asset.
///
/// By default this is used to resolve relative urls that occur in HTML assets,
/// including cross-package urls of the form "packages/foo/bar.html". Dart
/// "package:" urls are not resolved unless [source] is Dart file (has a .dart
/// extension).
///
/// This function returns null if [url] can't be resolved. We log a warning
/// message in [logger] if we know the reason why resolution failed. This
/// happens, for example, when using incorrect paths to reach into another
/// package, or when [errorsOnAbsolute] is true and the url seems to be
/// absolute.
// TODO(sigmund): delete once this is part of barback (dartbug.com/12610)
AssetId uriToAssetId(AssetId source, String url, TransformLogger logger,
Span span, {bool errorOnAbsolute: true}) {
if (url == null || url == '') return null;
var uri = Uri.parse(url);
var urlBuilder = path.url;
if (uri.host != '' || uri.scheme != '' || urlBuilder.isAbsolute(url)) {
if (source.extension == '.dart' && uri.scheme == 'package') {
var index = uri.path.indexOf('/');
if (index != -1) {
return new AssetId(uri.path.substring(0, index),
'lib${uri.path.substring(index)}');
}
}
if (errorOnAbsolute) {
logger.warning('absolute paths not allowed: "$url"', span: span);
}
return null;
}
var targetPath = urlBuilder.normalize(
urlBuilder.join(urlBuilder.dirname(source.path), url));
var segments = urlBuilder.split(targetPath);
var sourceSegments = urlBuilder.split(source.path);
assert (sourceSegments.length > 0);
var topFolder = sourceSegments[0];
var entryFolder = topFolder != 'lib' && topFolder != 'asset';
// Find the first 'packages/' or 'assets/' segment:
var packagesIndex = segments.indexOf('packages');
var assetsIndex = segments.indexOf('assets');
var index = (packagesIndex >= 0 && assetsIndex >= 0)
? min(packagesIndex, assetsIndex)
: max(packagesIndex, assetsIndex);
if (index > -1) {
if (entryFolder) {
// URLs of the form "packages/foo/bar" seen under entry folders (like
// web/, test/, example/, etc) are resolved as an asset in another
// package. 'packages' can be used anywhere, there is no need to walk up
// where the entrypoint file was.
return _extractOtherPackageId(index, segments, logger, span);
} else if (index == 1 && segments[0] == '..') {
// Relative URLs of the form "../../packages/foo/bar" in an asset under
// lib/ or asset/ are also resolved as an asset in another package, but we
// check that the relative path goes all the way out where the packages
// folder lives (otherwise the app would not work in Dartium). Since
// [targetPath] has been normalized, "packages" or "assets" should be at
// index 1.
return _extractOtherPackageId(1, segments, logger, span);
} else {
var prefix = segments[index];
var fixedSegments = [];
fixedSegments.addAll(sourceSegments.map((_) => '..'));
fixedSegments.addAll(segments.sublist(index));
var fixedUrl = urlBuilder.joinAll(fixedSegments);
logger.warning('Invalid url to reach to another package: $url. Path '
'reaching to other packages must first reach up all the '
'way to the $prefix folder. For example, try changing the url above '
'to: $fixedUrl', span: span);
return null;
}
}
// Otherwise, resolve as a path in the same package.
return new AssetId(source.package, targetPath);
}
AssetId _extractOtherPackageId(int index, List segments,
TransformLogger logger, Span span) {
if (index >= segments.length) return null;
var prefix = segments[index];
if (prefix != 'packages' && prefix != 'assets') return null;
var folder = prefix == 'packages' ? 'lib' : 'asset';
if (segments.length < index + 3) {
logger.warning("incomplete $prefix/ path. It should have at least 3 "
"segments $prefix/name/path-from-name's-$folder-dir", span: span);
return null;
}
return new AssetId(segments[index + 1],
path.url.join(folder, path.url.joinAll(segments.sublist(index + 2))));
}