blob: cc6595d555b059e8257a353473626fad8c2ebd81 [file] [log] [blame]
// Copyright (c) 2018, 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.
import 'dart:io';
import 'package:front_end/src/api_prototype/macros.dart' as macros
show isMacroLibraryUri;
import 'package:path/path.dart' as p;
// TODO(nshahan) Merge all of this file the locations where they are used in
// the kernel (only) version of DDC.
/// Convert a [source] string to a Uri, where the source may be a
/// dart/file/package URI or a local win/mac/linux path.
Uri sourcePathToUri(String source, {bool? windows}) {
if (windows == null) {
// Running on the web the Platform check will fail, and we can't use
// fromEnvironment because internally it's set to true for dart.library.io.
// So just catch the exception and if it fails then we're definitely not on
// Windows.
try {
windows = Platform.isWindows;
} catch (e) {
windows = false;
}
}
if (windows) {
source = source.replaceAll('\\', '/');
}
var result = Uri.base.resolve(source);
if (windows && result.scheme.length == 1) {
// Assume c: or similar --- interpret as file path.
return Uri.file(source, windows: true);
}
return result;
}
Uri sourcePathToRelativeUri(String source, {bool? windows}) {
var uri = sourcePathToUri(source, windows: windows);
if (uri.isScheme('file')) {
var uriPath = uri.path;
var root = Uri.base.path;
if (uriPath.startsWith(root)) {
return p.toUri(uriPath.substring(root.length));
}
}
return uri;
}
/// Adjusts the source uris in [sourceMap] to be relative uris, and returns
/// the new map.
///
/// Source uris show up in two forms, absolute `file:` uris and custom
/// [multiRootScheme] uris (also "absolute" uris, but always relative to some
/// multi-root).
///
/// - `file:` uris are converted to be relative to [sourceMapBase], which
/// defaults to the dirname of [sourceMapPath] if not provided.
///
/// - [multiRootScheme] uris are prefixed by [multiRootOutputPath]. If the
/// path starts with `/lib`, then we strip that before making it relative
/// to the [multiRootOutputPath], and assert that [multiRootOutputPath]
/// starts with `/packages` (more explanation inline).
///
// TODO(#40251): Remove this logic from dev_compiler itself, push it to the
// invokers of dev_compiler which have more knowledge about how they want
// source paths to look.
Map<String, Object?> placeSourceMap(Map<String, Object?> sourceMap,
String sourceMapPath, String? multiRootScheme,
{String? multiRootOutputPath, String? sourceMapBase}) {
var map = Map.of(sourceMap);
// Convert to a local file path if it's not.
sourceMapPath = sourcePathToUri(p.absolute(p.fromUri(sourceMapPath))).path;
var sourceMapDir = p.url.dirname(sourceMapPath);
sourceMapBase ??= sourceMapDir;
var list = (map['sources'] as List).toList();
String makeRelative(String sourcePath) {
var uri = sourcePathToUri(sourcePath);
var scheme = uri.scheme;
if (scheme == 'dart' || scheme == 'package' || scheme == multiRootScheme) {
if (scheme == multiRootScheme) {
// TODO(sigmund): extract all source-map normalization outside ddc. This
// custom logic is BUILD specific and could be shared with other tools
// like dart2js.
var shortPath = uri.path.replaceAll('/sdk/', '/dart-sdk/');
var multiRootPath = "${multiRootOutputPath ?? ''}$shortPath";
multiRootPath = p.url
.joinAll(p.split(p.relative(multiRootPath, from: sourceMapDir)));
return multiRootPath;
}
return sourcePath;
}
if (macros.isMacroLibraryUri(uri)) {
// TODO: https://github.com/dart-lang/sdk/issues/53913
return sourcePath;
}
if (uri.isScheme('http')) return sourcePath;
// Convert to a local file path if it's not.
sourcePath = sourcePathToUri(p.absolute(p.fromUri(uri))).path;
// Fall back to a relative path against the source map itself.
sourcePath = p.url.relative(sourcePath, from: sourceMapBase);
// Convert from relative local path to relative URI.
return p.toUri(sourcePath).path;
}
for (var i = 0; i < list.length; i++) {
list[i] = makeRelative(list[i] as String);
}
map['sources'] = list;
map['file'] =
map['file'] != null ? makeRelative(map['file'] as String) : null;
return map;
}