resolveUri function
The project file uri points at, or null when it points outside.
Three forms name a project file: a package: URI of the root package or
of one of packages, a path relative to from, and a root-relative one.
All go through the same segment walk, so ., .. and empty segments mean
the same thing in each; a URI climbing above the project is null.
Root-relative means a leading /, which Dart resolves against the lib/
of the importing file's own package — export '/features/x.dart' from
lib/index.dart is package:<self>/features/x.dart. FlutterFlow writes
its barrels this way, so dropping the form made every file such a barrel
exported look unreachable.
Implementation
String? resolveUri(
String uri, {
required String from,
required String packageName,
Map<String, String> packages = const {},
}) {
if (uri.startsWith('dart:')) return null;
if (uri.startsWith('http:') || uri.startsWith('https:')) return null;
final List<String> base;
final String rest;
if (uri.startsWith('/')) {
final root = _libRootOf(from, packages);
// Outside a lib/ there is no package root to be relative to.
if (root == null) return null;
base = root;
rest = uri.substring(1);
} else if (uri.startsWith('package:')) {
final slash = uri.indexOf('/');
if (slash < 0) return null;
final name = uri.substring('package:'.length, slash);
rest = uri.substring(slash + 1);
if (name == packageName) {
base = ['lib'];
} else {
String? dir;
for (final entry in packages.entries) {
if (entry.value == name && entry.key.isNotEmpty) {
dir = entry.key;
break;
}
}
if (dir == null) return null;
base = [...dir.split('/'), 'lib'];
}
} else {
base = from.split('/')..removeLast();
rest = uri;
}
final parts = [...base];
for (final segment in rest.split('/')) {
if (segment == '.' || segment.isEmpty) continue;
if (segment == '..') {
if (parts.isEmpty) return null;
parts.removeLast();
continue;
}
parts.add(segment);
}
return parts.isEmpty ? null : parts.join('/');
}