resolveUri function

String? resolveUri(
  1. String uri, {
  2. required String from,
  3. required String packageName,
  4. Map<String, String> packages = const {},
})

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('/');
}