visitImportDirective method

  1. @override
Object? visitImportDirective(
  1. SImportDirective node
)
override

Visit a SImportDirective.

Implementation

@override
Object? visitImportDirective(SImportDirective node) {
  final importUriString = (node.uri as SSimpleStringLiteral?)?.value;
  if (importUriString == null) {
    Logger.warn(
      "[visitImportDirective] Import directive with null URI string.",
    );
    return null; // Return null if the URI is null
  }

  Logger.debug(
    "[InterpreterVisitor.visitImportDirective] START processing import: $importUriString",
  );

  Uri resolvedUri;
  final importUri = Uri.parse(importUriString);

  if (importUri.isScheme('dart') || importUri.isScheme('package')) {
    resolvedUri = importUri;
    Logger.debug(
      "[visitImportDirective] Using absolute/unresolvable URI: $resolvedUri",
    );
  } else {
    final baseUri = moduleContext.currentLibrary;

    if (baseUri != null) {
      Logger.debug(
        "[visitImportDirective] Attempting to resolve relative URI '$importUriString' relative to '$baseUri'",
      );
      resolvedUri = baseUri.resolveUri(importUri);
      Logger.debug(
        "[visitImportDirective] Resolved relative URI: $resolvedUri",
      );
    } else {
      throw RuntimeD4rtException(
        "Unable to resolve relative import '$importUriString': Base URI not defined in ModuleLoader. "
        "Either provide a basePath parameter or use absolute URIs.",
      );
    }
  }

  final prefixIdentifier = node.prefix; // Get the prefix identifier
  final prefixName = prefixIdentifier?.name;

  // Extract the show/hide combinators from the import directive BEFORE loading
  Set<String>? showNames;
  Set<String>? hideNames;

  for (final combinator in node.combinators) {
    if (combinator is SShowCombinator) {
      showNames ??= {};
      showNames.addAll(combinator.shownNames.map((id) => id.name));
      Logger.debug(
        "[visitImportDirective] Combinator: show ${combinator.shownNames.map((id) => id.name).join(', ')}",
      );
    } else if (combinator is SHideCombinator) {
      hideNames ??= {};
      hideNames.addAll(combinator.hiddenNames.map((id) => id.name));
      Logger.debug(
        "[visitImportDirective] Combinator: hide ${combinator.hiddenNames.map((id) => id.name).join(', ')}",
      );
    }
  }

  Logger.debug(
    "[visitImportDirective] Loading module for resolved URI: $resolvedUri (prefix: $prefixName, show: $showNames, hide: $hideNames)",
  );

  // Pass show/hide to loadModule so bridged content respects the filters
  LoadedModule loadedModule = moduleContext.loadModule(
    resolvedUri,
    showNames: showNames,
    hideNames: hideNames,
  );

  if (prefixName != null) {
    Logger.debug(
      "[visitImportDirective] Importation du module '${resolvedUri.toString()}' avec le préfixe '$prefixName'. Show: $showNames, Hide: $hideNames",
    );

    Environment envForPrefix;
    if (showNames != null || hideNames != null) {
      // Apply show/hide to the exported environment of the loaded module BEFORE defining it for the prefix
      envForPrefix = loadedModule.exportedEnvironment.shallowCopyFiltered(
        showNames: showNames,
        hideNames: hideNames,
      );
    } else {
      envForPrefix = loadedModule.exportedEnvironment;
    }
    environment.definePrefixedImport(prefixName, envForPrefix);
  } else {
    Logger.debug(
      "[visitImportDirective] Direct import of module '${resolvedUri.toString()}' into the current environment. Show: $showNames, Hide: $hideNames",
    );
    // Apply show/hide directly during import into the current environment
    environment.importEnvironment(
      loadedModule.exportedEnvironment,
      show: showNames,
      hide: hideNames,
    );
  }
  return null; // Import directives do not produce a value.
}