Use ExportDirectiveState to build LibraryElement.exports2, add ExportElement2.

Change-Id: I29242bb6f9514eccc93b1bef207ecd5b1e558571
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/251143
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/status/ast_writer.dart b/pkg/analysis_server/lib/src/status/ast_writer.dart
index b98c3d6..bc19b76 100644
--- a/pkg/analysis_server/lib/src/status/ast_writer.dart
+++ b/pkg/analysis_server/lib/src/status/ast_writer.dart
@@ -58,7 +58,7 @@
       properties['element'] = node.declaredElement;
       properties['keyword'] = node.keyword;
     } else if (node is ExportDirective) {
-      properties['element'] = node.element;
+      properties['element'] = node.element2;
       properties['selectedSource'] = node.selectedSource;
       properties['uriSource'] = node.uriSource;
     } else if (node is FieldDeclaration) {
diff --git a/pkg/analysis_server/lib/src/status/element_writer.dart b/pkg/analysis_server/lib/src/status/element_writer.dart
index 560fc23..1e5a123 100644
--- a/pkg/analysis_server/lib/src/status/element_writer.dart
+++ b/pkg/analysis_server/lib/src/status/element_writer.dart
@@ -82,9 +82,9 @@
       properties['returnType'] = element.returnType;
       properties['type'] = element.type;
     }
-    if (element is ExportElement) {
+    if (element is ExportElement2) {
       properties['combinators'] = element.combinators;
-      properties['library'] = element.library;
+      properties['library'] = element.exportedLibrary;
     }
     if (element is FieldElement) {
       properties['isEnumConstant'] = element.isEnumConstant;
@@ -102,7 +102,7 @@
     if (element is ImportElement2) {
       properties['combinators'] = element.combinators;
       properties['isDeferred'] = element.prefix is DeferredImportElementPrefix;
-      properties['library'] = element.library;
+      properties['library'] = element.importedLibrary;
     }
     if (element is LibraryElement) {
       properties['definingCompilationUnit'] = element.definingCompilationUnit;
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 5b3cd79..1f7ed5d 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -1703,9 +1703,14 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class ExportDirective implements NamespaceDirective {
+  @Deprecated('Use element2 instead')
   @override
   ExportElement? get element;
 
+  /// Return the element associated with this directive, or `null` if the AST
+  /// structure has not been resolved.
+  ExportElement2? get element2;
+
   /// The token representing the 'export' keyword.
   Token get exportKeyword;
 }
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 8d6f524..efcf572 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1092,8 +1092,11 @@
 
   R? visitConstructorElement(ConstructorElement element);
 
+  @Deprecated('Override visitExportElement2() instead')
   R? visitExportElement(ExportElement element);
 
+  R? visitExportElement2(ExportElement2 element);
+
   R? visitExtensionElement(ExtensionElement element);
 
   R? visitFieldElement(FieldElement element);
@@ -1194,6 +1197,7 @@
 /// An export directive within a library.
 ///
 /// Clients may not extend, implement or mix-in this class.
+@Deprecated('Use ExportElement2 instead')
 abstract class ExportElement implements UriReferencedElement {
   /// Return a list containing the combinators that were specified as part of
   /// the export directive in the order in which they were specified.
@@ -1204,6 +1208,24 @@
   LibraryElement? get exportedLibrary;
 }
 
+/// A single export directive within a library.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ExportElement2 implements _ExistingElement {
+  /// Return a list containing the combinators that were specified as part of
+  /// the export directive in the order in which they were specified.
+  List<NamespaceCombinator> get combinators;
+
+  /// Returns the [LibraryElement], if [uri] is a [DirectiveUriWithLibrary].
+  LibraryElement? get exportedLibrary;
+
+  /// The offset of the `export` keyword.
+  int get exportKeywordOffset;
+
+  /// The interpretation of the URI specified in the directive.
+  DirectiveUri get uri;
+}
+
 /// An element that represents an extension.
 ///
 /// Clients may not extend, implement or mix-in this class.
@@ -1549,8 +1571,12 @@
   CompilationUnitElement get definingCompilationUnit;
 
   /// Return a list containing all of the exports defined in this library.
+  @Deprecated('Use exports2 instead')
   List<ExportElement> get exports;
 
+  /// Return a list containing all of the exports defined in this library.
+  List<ExportElement2> get exports2;
+
   /// The set of features available to this library.
   ///
   /// Determined by the combination of the language version for the enclosing
diff --git a/pkg/analyzer/lib/dart/element/visitor.dart b/pkg/analyzer/lib/dart/element/visitor.dart
index 4735d6f..d359ddd 100644
--- a/pkg/analyzer/lib/dart/element/visitor.dart
+++ b/pkg/analyzer/lib/dart/element/visitor.dart
@@ -104,10 +104,14 @@
 
   R? visitExecutableElement(ExecutableElement element) => visitElement(element);
 
+  @Deprecated('Override visitExportElement2() instead')
   @override
   R? visitExportElement(ExportElement element) => visitElement(element);
 
   @override
+  R? visitExportElement2(ExportElement2 element) => visitElement(element);
+
+  @override
   R? visitExtensionElement(ExtensionElement element) => visitElement(element);
 
   @override
@@ -240,6 +244,7 @@
     return null;
   }
 
+  @Deprecated('Override visitExportElement2() instead')
   @override
   R? visitExportElement(ExportElement element) {
     element.visitChildren(this);
@@ -247,6 +252,12 @@
   }
 
   @override
+  R? visitExportElement2(ExportElement2 element) {
+    element.visitChildren(this);
+    return null;
+  }
+
+  @override
   R? visitExtensionElement(ExtensionElement element) {
     element.visitChildren(this);
     return null;
@@ -396,10 +407,14 @@
   @override
   R? visitConstructorElement(ConstructorElement element) => null;
 
+  @Deprecated('Override visitExportElement2() instead')
   @override
   R? visitExportElement(ExportElement element) => null;
 
   @override
+  R? visitExportElement2(ExportElement2 element) => null;
+
+  @override
   R? visitExtensionElement(ExtensionElement element) => null;
 
   @override
@@ -493,10 +508,14 @@
   @override
   R? visitConstructorElement(ConstructorElement element) => _throw(element);
 
+  @Deprecated('Override visitExportElement2() instead')
   @override
   R? visitExportElement(ExportElement element) => _throw(element);
 
   @override
+  R? visitExportElement2(ExportElement2 element) => _throw(element);
+
+  @override
   R? visitExtensionElement(ExtensionElement element) => _throw(element);
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 8ec05f7..1bdbc40 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -1125,6 +1125,7 @@
     return UnlinkedExportDirective(
       combinators: _serializeCombinators(node.combinators),
       configurations: _serializeConfigurations(node.configurations),
+      exportKeywordOffset: node.exportKeyword.offset,
       uri: node.uri.stringValue,
     );
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 695b5cd..5660f03 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -687,7 +687,7 @@
 
   @override
   void visitExportDirective(ExportDirective node) {
-    ExportElement? element = node.element;
+    final element = node.element2;
     recordUriReference(element?.exportedLibrary, node.uri);
     super.visitExportDirective(node);
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index fbbea18..acf3573 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -590,7 +590,7 @@
       } else if (directive is ExportDirectiveImpl) {
         _resolveExportDirective(
           directive: directive,
-          exportElement: _libraryElement.exports[exportIndex],
+          exportElement: _libraryElement.exports2[exportIndex],
           exportState: _library.exports[exportIndex],
           libraryErrorReporter: libraryErrorReporter,
         );
@@ -621,7 +621,7 @@
 
   void _resolveExportDirective({
     required ExportDirectiveImpl directive,
-    required ExportElement exportElement,
+    required ExportElement2 exportElement,
     required ExportDirectiveState exportState,
     required ErrorReporter libraryErrorReporter,
   }) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart b/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
index 43877b2..b487c95 100644
--- a/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
@@ -122,9 +122,12 @@
 
 /// Unlinked information about an `export` directive.
 class UnlinkedExportDirective extends UnlinkedNamespaceDirective {
+  final int exportKeywordOffset;
+
   UnlinkedExportDirective({
     required super.combinators,
     required super.configurations,
+    required this.exportKeywordOffset,
     required super.uri,
   });
 
@@ -136,6 +139,7 @@
       configurations: reader.readTypedList(
         () => UnlinkedNamespaceDirectiveConfiguration.read(reader),
       ),
+      exportKeywordOffset: reader.readUInt30(),
       uri: reader.readOptionalStringUtf8(),
     );
   }
@@ -151,6 +155,7 @@
         x.write(sink);
       },
     );
+    sink.writeUInt30(exportKeywordOffset);
     sink.writeOptionalStringUtf8(uri);
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index b8d68c1..56ef705 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3782,8 +3782,18 @@
       super.combinators,
       super.semicolon);
 
+  @Deprecated('Use element2 instead')
   @override
-  ExportElement? get element => super.element as ExportElement?;
+  ExportElement? get element {
+    final element2 = this.element2;
+    if (element2 is ExportElement2Impl) {
+      return ExportElementImpl(element2);
+    }
+    return null;
+  }
+
+  @override
+  ExportElement2? get element2 => super.element as ExportElement2?;
 
   @override
   Token get firstTokenAfterCommentAndMetadata => exportKeyword;
@@ -3794,7 +3804,7 @@
 
   @override
   LibraryElement? get uriElement {
-    return element?.exportedLibrary;
+    return element2?.exportedLibrary;
   }
 
   @override
@@ -6425,7 +6435,7 @@
   @override
   ImportElement? get element {
     final element2 = this.element2;
-    if (element2 != null) {
+    if (element2 is ImportElement2Impl) {
       return ImportElementImpl(element2);
     }
     return null;
diff --git a/pkg/analyzer/lib/src/dart/ast/element_locator.dart b/pkg/analyzer/lib/src/dart/ast/element_locator.dart
index dd37049..8f676e4 100644
--- a/pkg/analyzer/lib/src/dart/ast/element_locator.dart
+++ b/pkg/analyzer/lib/src/dart/ast/element_locator.dart
@@ -65,7 +65,7 @@
 
   @override
   Element? visitExportDirective(ExportDirective node) {
-    return node.element;
+    return node.element2;
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
index c3e6e47..afbce61 100644
--- a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
@@ -94,9 +94,9 @@
     }
   }
 
-  void writeExportElement(ExportElementImpl element) {
+  void writeExportElement(ExportElement2Impl element) {
     _write('export ');
-    (element.exportedLibrary as LibraryElementImpl).appendTo(this);
+    _writeDirectiveUri(element.uri);
   }
 
   void writeExtensionElement(ExtensionElementImpl element) {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 4215c02..5b8d90f 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3119,17 +3119,65 @@
   }
 }
 
-/// A concrete implementation of an [ExportElement].
-class ExportElementImpl extends UriReferencedElementImpl
-    implements ExportElement {
-  @override
-  LibraryElement? exportedLibrary;
-
+class ExportElement2Impl extends _ExistingElementImpl
+    implements ExportElement2 {
   @override
   List<NamespaceCombinator> combinators = const [];
 
-  /// Initialize a newly created export element at the given [offset].
-  ExportElementImpl(int offset) : super(null, offset);
+  @override
+  final int exportKeywordOffset;
+
+  @override
+  final DirectiveUri uri;
+
+  ExportElement2Impl({
+    required this.exportKeywordOffset,
+    required this.uri,
+  }) : super(null, exportKeywordOffset);
+
+  @override
+  LibraryElement? get exportedLibrary {
+    final uri = this.uri;
+    if (uri is DirectiveUriWithLibrary) {
+      return uri.library;
+    }
+    return null;
+  }
+
+  @override
+  int get hashCode => identityHashCode(this);
+
+  @override
+  ElementKind get kind => ElementKind.EXPORT;
+
+  @override
+  bool operator ==(Object other) {
+    return identical(this, other);
+  }
+
+  @override
+  T? accept<T>(ElementVisitor<T> visitor) {
+    return visitor.visitExportElement2(this);
+  }
+
+  @override
+  void appendTo(ElementDisplayStringBuilder builder) {
+    builder.writeExportElement(this);
+  }
+}
+
+/// A concrete implementation of an [ExportElement].
+@Deprecated('Use ExportElement2 instead')
+class ExportElementImpl extends ElementImpl
+    with WrapperElementImpl
+    implements ExportElement {
+  @override
+  final ExportElement2Impl base;
+
+  ExportElementImpl(this.base) : super(base.name, base.nameOffset);
+
+  @override
+  List<NamespaceCombinator> get combinators => base.combinators;
 
   @override
   CompilationUnitElementImpl get enclosingUnit {
@@ -3138,18 +3186,40 @@
   }
 
   @override
-  String get identifier => exportedLibrary!.name;
+  LibraryElement? get exportedLibrary {
+    final uri = base.uri;
+    if (uri is DirectiveUriWithLibrary) {
+      return uri.library;
+    }
+    return null;
+  }
+
+  @override
+  String get identifier => 'export@$nameOffset';
 
   @override
   ElementKind get kind => ElementKind.EXPORT;
 
   @override
-  T? accept<T>(ElementVisitor<T> visitor) => visitor.visitExportElement(this);
+  String? get uri {
+    final uri = base.uri;
+    if (uri is DirectiveUriWithRelativeUriString) {
+      return uri.relativeUriString;
+    } else {
+      return null;
+    }
+  }
 
   @override
-  void appendTo(ElementDisplayStringBuilder builder) {
-    builder.writeExportElement(this);
-  }
+  // TODO: implement uriEnd
+  int get uriEnd => throw UnimplementedError();
+
+  @override
+  // TODO: implement uriOffset
+  int get uriOffset => throw UnimplementedError();
+
+  @override
+  T? accept<T>(ElementVisitor<T> visitor) => visitor.visitExportElement(this);
 }
 
 /// A concrete implementation of an [ExtensionElement].
@@ -3693,8 +3763,11 @@
 
 /// A concrete implementation of an [ImportElement].
 @Deprecated('Use ImportElement2 instead')
-class ImportElementImpl extends ElementImpl implements ImportElement {
-  final ImportElement2 base;
+class ImportElementImpl extends ElementImpl
+    with WrapperElementImpl
+    implements ImportElement {
+  @override
+  final ImportElement2Impl base;
 
   ImportElementImpl(this.base) : super(base.name, base.nameOffset);
 
@@ -3702,82 +3775,10 @@
   List<NamespaceCombinator> get combinators => base.combinators;
 
   @override
-  AnalysisContext get context => base.context;
-
-  @override
-  Element get declaration => base.declaration;
-
-  @override
-  String get displayName => base.displayName;
-
-  @override
-  String? get documentationComment => base.documentationComment;
-
-  @override
-  Element? get enclosingElement => base.enclosingElement;
-
-  @override
-  bool get hasAlwaysThrows => base.hasAlwaysThrows;
-
-  @override
-  bool get hasDeprecated => base.hasDeprecated;
-
-  @override
-  bool get hasDoNotStore => base.hasDoNotStore;
-
-  @override
-  bool get hasFactory => base.hasFactory;
-
-  @override
-  bool get hasInternal => base.hasInternal;
-
-  @override
-  bool get hasIsTest => base.hasIsTest;
-
-  @override
-  bool get hasIsTestGroup => base.hasIsTestGroup;
-
-  @override
-  bool get hasJS => base.hasJS;
-
-  @override
-  bool get hasLiteral => base.hasLiteral;
-
-  @override
-  bool get hasMustCallSuper => base.hasMustCallSuper;
-
-  @override
-  bool get hasNonVirtual => base.hasNonVirtual;
-
-  @override
-  bool get hasOptionalTypeArgs => base.hasOptionalTypeArgs;
-
-  @override
-  bool get hasOverride => base.hasOverride;
-
-  @override
-  bool get hasProtected => base.hasProtected;
-
-  @override
-  bool get hasRequired => base.hasRequired;
-
-  @override
-  bool get hasSealed => base.hasSealed;
-
-  @override
-  bool get hasUseResult => base.hasUseResult;
-
-  @override
-  bool get hasVisibleForOverriding => base.hasVisibleForOverriding;
-
-  @override
-  bool get hasVisibleForTemplate => base.hasVisibleForTemplate;
-
-  @override
-  bool get hasVisibleForTesting => base.hasVisibleForTesting;
-
-  @override
-  int get id => base.id;
+  CompilationUnitElementImpl get enclosingUnit {
+    var enclosingLibrary = enclosingElement as LibraryElementImpl;
+    return enclosingLibrary._definingCompilationUnit;
+  }
 
   @override
   String get identifier => 'import@$nameOffset';
@@ -3795,54 +3796,12 @@
   bool get isDeferred => base.prefix is DeferredImportElementPrefix;
 
   @override
-  bool get isPrivate => base.isPrivate;
-
-  @override
-  bool get isPublic => base.isPublic;
-
-  @override
-  bool get isSynthetic => base.isSynthetic;
-
-  @override
-  ElementKind get kind => base.kind;
-
-  @override
-  LibraryElementImpl get library => base.library as LibraryElementImpl;
-
-  @override
-  Source get librarySource => base.librarySource;
-
-  @override
-  ElementLocation get location => base.location!;
-
-  @override
-  List<ElementAnnotation> get metadata => base.metadata;
-
-  @override
-  String? get name => base.name;
-
-  @override
-  int get nameLength => base.nameLength;
-
-  @override
-  int get nameOffset => base.nameOffset;
-
-  @override
   Namespace get namespace => base.namespace;
 
   @override
-  Element get nonSynthetic => this;
-
-  @override
   PrefixElement? get prefix => base.prefix?.element;
 
   @override
-  AnalysisSession? get session => base.session;
-
-  @override
-  Source get source => base.source;
-
-  @override
   String? get uri {
     final uri = base.uri;
     if (uri is DirectiveUriWithRelativeUriString) {
@@ -3869,47 +3828,6 @@
   T? accept<T>(ElementVisitor<T> visitor) {
     return visitor.visitImportElement(this);
   }
-
-  @override
-  String getDisplayString(
-      {required bool withNullability, bool multiline = false}) {
-    return base.getDisplayString(
-      withNullability: withNullability,
-      multiline: multiline,
-    );
-  }
-
-  @override
-  String getExtendedDisplayName(String? shortName) {
-    return base.getExtendedDisplayName(shortName);
-  }
-
-  @Deprecated('Use isAccessibleIn2() instead')
-  @override
-  bool isAccessibleIn(LibraryElement? library) {
-    return base.isAccessibleIn(library);
-  }
-
-  @override
-  bool isAccessibleIn2(LibraryElement library) {
-    return base.isAccessibleIn2(library);
-  }
-
-  @override
-  E thisOrAncestorMatching<E extends Element>(
-      bool Function(Element p1) predicate) {
-    return base.thisOrAncestorMatching(predicate) as E;
-  }
-
-  @override
-  E? thisOrAncestorOfType<E extends Element>() {
-    return base.thisOrAncestorOfType();
-  }
-
-  @override
-  void visitChildren(ElementVisitor visitor) {
-    base.visitChildren(visitor);
-  }
 }
 
 class ImportElementPrefixImpl implements ImportElementPrefix {
@@ -3979,6 +3897,10 @@
   List<ExtensionElement> get accessibleExtensions => throw UnimplementedError();
 
   @override
+  // TODO: implement exports2
+  List<ExportElement2> get exports2 => throw UnimplementedError();
+
+  @override
   FeatureSet get featureSet => augmented.featureSet;
 
   @override
@@ -4098,14 +4020,11 @@
 
   @override
   List<LibraryElement> get exportedLibraries {
-    HashSet<LibraryElement> libraries = HashSet<LibraryElement>();
-    for (ExportElement element in exports) {
-      var library = element.exportedLibrary;
-      if (library != null) {
-        libraries.add(library);
-      }
-    }
-    return libraries.toList(growable: false);
+    return exports2
+        .map((import) => import.exportedLibrary)
+        .whereNotNull()
+        .toSet()
+        .toList();
   }
 
   @override
@@ -4128,10 +4047,18 @@
     _exportNamespace = exportNamespace;
   }
 
+  @Deprecated('Use exports2 instead')
   @override
   List<ExportElement> get exports {
+    return exports2
+        .map((e) => ExportElementImpl(e as ExportElement2Impl))
+        .toList();
+  }
+
+  @override
+  List<ExportElement2> get exports2 {
     linkedData?.read(this);
-    return _exports;
+    return _exports2;
   }
 
   bool get hasPartOfDirective {
@@ -4148,9 +4075,8 @@
   @override
   List<LibraryElement> get importedLibraries {
     return imports2
-        .map((import) => import.uri)
-        .whereType<DirectiveUriWithLibrary>()
-        .map((uri) => uri.library)
+        .map((import) => import.importedLibrary)
+        .whereNotNull()
         .toSet()
         .toList();
   }
@@ -4158,7 +4084,9 @@
   @Deprecated('Use imports2 instead')
   @override
   List<ImportElement> get imports {
-    return imports2.map(ImportElementImpl.new).toList();
+    return imports2
+        .map((e) => ImportElementImpl(e as ImportElement2Impl))
+        .toList();
   }
 
   @override
@@ -4487,11 +4415,11 @@
 
   /// A list containing specifications of all of the imports defined in this
   /// library.
-  List<ImportElement2> _imports2 = _Sentinel.importElement2;
+  List<ExportElement2> _exports2 = _Sentinel.exportElement2;
 
-  /// A list containing specifications of all of the exports defined in this
+  /// A list containing specifications of all of the imports defined in this
   /// library.
-  List<ExportElement> _exports = _Sentinel.exportElement;
+  List<ImportElement2> _imports2 = _Sentinel.importElement2;
 
   /// The cached list of prefixes.
   List<PrefixElement>? _prefixes;
@@ -4530,22 +4458,25 @@
     return _definingCompilationUnit;
   }
 
+  @Deprecated('Use exports2 instead')
   @override
   List<ExportElement> get exports {
-    return _exports;
+    return exports2
+        .map((e) => ExportElementImpl(e as ExportElement2Impl))
+        .toList();
   }
 
   /// Set the specifications of all of the exports defined in this library to
   /// the given list of [exports].
-  set exports(List<ExportElement> exports) {
-    for (ExportElement exportElement in exports) {
-      (exportElement as ExportElementImpl).enclosingElement = this;
+  set exports2(List<ExportElement2> exports) {
+    for (final exportElement in exports) {
+      (exportElement as ExportElement2Impl).enclosingElement = this;
     }
-    _exports = exports;
+    _exports2 = exports;
   }
 
-  List<ExportElement> get exports_unresolved {
-    return _exports;
+  List<ExportElement2> get exports_unresolved {
+    return _exports2;
   }
 
   @override
@@ -4554,7 +4485,9 @@
   @Deprecated('Use imports2 instead')
   @override
   List<ImportElement> get imports {
-    return _imports2.map(ImportElementImpl.new).toList();
+    return imports2
+        .map((e) => ImportElementImpl(e as ImportElement2Impl))
+        .toList();
   }
 
   /// Set the specifications of all of the imports defined in this library to
@@ -4587,7 +4520,9 @@
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
     _definingCompilationUnit.accept(visitor);
+    // ignore: deprecated_member_use_from_same_package
     safelyVisitChildren(exports, visitor);
+    safelyVisitChildren(exports2, visitor);
     // ignore: deprecated_member_use_from_same_package
     safelyVisitChildren(imports, visitor);
     safelyVisitChildren(imports2, visitor);
@@ -6508,6 +6443,177 @@
   DartObject? computeConstantValue() => null;
 }
 
+@Deprecated('Remove it when removing its uses')
+mixin WrapperElementImpl implements ElementImpl {
+  _ExistingElementImpl get base;
+
+  @override
+  AnalysisContext get context => base.context;
+
+  @override
+  Element get declaration => base.declaration;
+
+  @override
+  String get displayName => base.displayName;
+
+  @override
+  String? get documentationComment => base.documentationComment;
+
+  @override
+  Element? get enclosingElement => base.enclosingElement;
+
+  @override
+  bool get hasAlwaysThrows => base.hasAlwaysThrows;
+
+  @override
+  bool get hasDeprecated => base.hasDeprecated;
+
+  @override
+  bool get hasDoNotStore => base.hasDoNotStore;
+
+  @override
+  bool get hasFactory => base.hasFactory;
+
+  @override
+  bool get hasInternal => base.hasInternal;
+
+  @override
+  bool get hasIsTest => base.hasIsTest;
+
+  @override
+  bool get hasIsTestGroup => base.hasIsTestGroup;
+
+  @override
+  bool get hasJS => base.hasJS;
+
+  @override
+  bool get hasLiteral => base.hasLiteral;
+
+  @override
+  bool get hasMustCallSuper => base.hasMustCallSuper;
+
+  @override
+  bool get hasNonVirtual => base.hasNonVirtual;
+
+  @override
+  bool get hasOptionalTypeArgs => base.hasOptionalTypeArgs;
+
+  @override
+  bool get hasOverride => base.hasOverride;
+
+  @override
+  bool get hasProtected => base.hasProtected;
+
+  @override
+  bool get hasRequired => base.hasRequired;
+
+  @override
+  bool get hasSealed => base.hasSealed;
+
+  @override
+  bool get hasUseResult => base.hasUseResult;
+
+  @override
+  bool get hasVisibleForOverriding => base.hasVisibleForOverriding;
+
+  @override
+  bool get hasVisibleForTemplate => base.hasVisibleForTemplate;
+
+  @override
+  bool get hasVisibleForTesting => base.hasVisibleForTesting;
+
+  @override
+  int get id => base.id;
+
+  @override
+  bool get isPrivate => base.isPrivate;
+
+  @override
+  bool get isPublic => base.isPublic;
+
+  @override
+  bool get isSynthetic => base.isSynthetic;
+
+  @override
+  ElementKind get kind => base.kind;
+
+  @override
+  LibraryElementImpl get library => base.library;
+
+  @override
+  Source get librarySource => base.librarySource;
+
+  @override
+  ElementLocation get location => base.location;
+
+  @override
+  List<ElementAnnotation> get metadata => base.metadata;
+
+  @override
+  String? get name => base.name;
+
+  @override
+  int get nameLength => base.nameLength;
+
+  @override
+  int get nameOffset => base.nameOffset;
+
+  @override
+  Element get nonSynthetic => this;
+
+  @override
+  AnalysisSession? get session => base.session;
+
+  @override
+  Source get source => base.source;
+
+  @override
+  bool operator ==(Object other) {
+    return identical(this, other);
+  }
+
+  @override
+  String getDisplayString(
+      {required bool withNullability, bool multiline = false}) {
+    return base.getDisplayString(
+      withNullability: withNullability,
+      multiline: multiline,
+    );
+  }
+
+  @override
+  String getExtendedDisplayName(String? shortName) {
+    return base.getExtendedDisplayName(shortName);
+  }
+
+  @Deprecated('Use isAccessibleIn2() instead')
+  @override
+  bool isAccessibleIn(LibraryElement? library) {
+    return base.isAccessibleIn(library);
+  }
+
+  @override
+  bool isAccessibleIn2(LibraryElement library) {
+    return base.isAccessibleIn2(library);
+  }
+
+  @override
+  E thisOrAncestorMatching<E extends Element>(
+      bool Function(Element p1) predicate) {
+    return base.thisOrAncestorMatching(predicate) as E;
+  }
+
+  @override
+  E? thisOrAncestorOfType<E extends Element>() {
+    return base.thisOrAncestorOfType();
+  }
+
+  @override
+  void visitChildren(ElementVisitor visitor) {
+    base.visitChildren(visitor);
+  }
+}
+
 abstract class _ExistingElementImpl extends ElementImpl with _HasLibraryMixin {
   _ExistingElementImpl(super.name, super.offset, {super.reference});
 }
@@ -6528,7 +6634,7 @@
 class _Sentinel {
   static final List<ConstructorElement> constructorElement =
       List.unmodifiable([]);
-  static final List<ExportElement> exportElement = List.unmodifiable([]);
+  static final List<ExportElement2> exportElement2 = List.unmodifiable([]);
   static final List<FieldElement> fieldElement = List.unmodifiable([]);
   static final List<AugmentationImportElement> augmentationImportElement =
       List.unmodifiable([]);
diff --git a/pkg/analyzer/lib/src/dart/element/scope.dart b/pkg/analyzer/lib/src/dart/element/scope.dart
index 1fab302..d9755fd 100644
--- a/pkg/analyzer/lib/src/dart/element/scope.dart
+++ b/pkg/analyzer/lib/src/dart/element/scope.dart
@@ -284,7 +284,7 @@
   ) {
     if (exportedReference is ExportedReferenceExported) {
       for (final exportIndex in exportedReference.indexes) {
-        final export = importedLibrary.exports[exportIndex];
+        final export = importedLibrary.exports2[exportIndex];
         if (!export.hasDeprecated) {
           return false;
         }
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index 5e0f754..ea681e1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -891,7 +891,7 @@
   /// Returns the 'type' of `this`, when accessed as a "reference", not
   /// immediately followed by parentheses and arguments.
   ///
-  /// For all elements that don't have a type (for example, [ExportElement]),
+  /// For all elements that don't have a type (for example, [ExportElement2]),
   /// `null` is returned. For [PropertyAccessorElement], the return value is
   /// returned. For all other elements, their `type` property is returned.
   DartType? get referenceType {
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 5f94025..0c0a941 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -432,8 +432,8 @@
 
   @override
   void visitExportDirective(ExportDirective node) {
-    var element = node.element;
-    if (element is ExportElementImpl) {
+    var element = node.element2;
+    if (element is ExportElement2Impl) {
       _setOrCreateMetadataElements(element, node.metadata);
     }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 79865a7..61e69b7 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -135,7 +135,7 @@
 class NamespaceBuilder {
   /// Create a namespace representing the export namespace of the given
   /// [element].
-  Namespace createExportNamespaceForDirective(ExportElement element) {
+  Namespace createExportNamespaceForDirective(ExportElement2 element) {
     var exportedLibrary = element.exportedLibrary;
     if (exportedLibrary == null) {
       //
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index bd89227..c39393a 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -1071,7 +1071,7 @@
           [libraryElement.displayName]);
     }
     var exportNamespace =
-        NamespaceBuilder().createExportNamespaceForDirective(node.element!);
+        NamespaceBuilder().createExportNamespaceForDirective(node.element2!);
     exportNamespace.definedNames.forEach((String name, Element element) {
       if (element.hasInternal) {
         _errorReporter.reportErrorForNode(
diff --git a/pkg/analyzer/lib/src/error/dead_code_verifier.dart b/pkg/analyzer/lib/src/error/dead_code_verifier.dart
index 9339c45..ecb9a0f 100644
--- a/pkg/analyzer/lib/src/error/dead_code_verifier.dart
+++ b/pkg/analyzer/lib/src/error/dead_code_verifier.dart
@@ -47,7 +47,7 @@
 
   @override
   void visitExportDirective(ExportDirective node) {
-    ExportElement? exportElement = node.element;
+    final exportElement = node.element2;
     if (exportElement != null) {
       // The element is null when the URI is invalid.
       LibraryElement? library = exportElement.exportedLibrary;
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 26fca88..b05920a 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -57,7 +57,7 @@
 /// 5. Every [ImportDirective] and [ExportDirective] should resolve to the
 ///    element representing the library being specified by the directive unless
 ///    the specified library does not exist (an [ImportElement2] or
-///    [ExportElement]).
+///    [ExportElement2]).
 /// 6. The identifier representing the prefix in an [ImportDirective] should
 ///    resolve to the element representing the prefix (a [PrefixElement]).
 /// 7. The identifiers in the hide and show combinators in [ImportDirective]s
@@ -188,7 +188,7 @@
   }
 
   void visitExportDirective(ExportDirective node) {
-    var exportElement = node.element;
+    var exportElement = node.element2;
     if (exportElement != null) {
       // The element is null when the URI is invalid
       // TODO(brianwilkerson) Figure out whether the element can ever be
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 28d5b16..4289ae3 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -621,7 +621,7 @@
 
   @override
   void visitExportDirective(ExportDirective node) {
-    var exportElement = node.element;
+    var exportElement = node.element2;
     if (exportElement != null) {
       var exportedLibrary = exportElement.exportedLibrary;
       _checkForAmbiguousExport(node, exportElement, exportedLibrary);
@@ -1528,13 +1528,13 @@
 
   /// Verify that the export namespace of the given export [directive] does not
   /// export any name already exported by another export directive. The
-  /// [exportElement] is the [ExportElement] retrieved from the node. If the
+  /// [exportElement] is the [ExportElement2] retrieved from the node. If the
   /// element in the node was `null`, then this method is not called. The
   /// [exportedLibrary] is the library element containing the exported element.
   ///
   /// See [CompileTimeErrorCode.AMBIGUOUS_EXPORT].
   void _checkForAmbiguousExport(ExportDirective directive,
-      ExportElement exportElement, LibraryElement? exportedLibrary) {
+      ExportElement2 exportElement, LibraryElement? exportedLibrary) {
     if (exportedLibrary == null) {
       return;
     }
@@ -2495,12 +2495,12 @@
 
   /// Check that if the visiting library is not system, then any given library
   /// should not be SDK internal library. The [exportElement] is the
-  /// [ExportElement] retrieved from the node, if the element in the node was
+  /// [ExportElement2] retrieved from the node, if the element in the node was
   /// `null`, then this method is not called.
   ///
   /// See [CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY].
   void _checkForExportInternalLibrary(
-      ExportDirective directive, ExportElement exportElement) {
+      ExportDirective directive, ExportElement2 exportElement) {
     if (_isInSystemLibrary) {
       return;
     }
@@ -2537,7 +2537,7 @@
       return;
     }
 
-    var element = node.element!;
+    var element = node.element2!;
     // TODO(scheglov) Expose from ExportElement.
     var namespace =
         NamespaceBuilder().createExportNamespaceForDirective(element);
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 49121ab4..8cdade2 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -136,14 +136,6 @@
           [List<DartType> argumentTypes = const []]) =>
       constructorElement(definingClass, name, false, argumentTypes);
 
-  static ExportElementImpl exportFor(LibraryElement exportedLibrary,
-      [List<NamespaceCombinator> combinators = const <NamespaceCombinator>[]]) {
-    ExportElementImpl spec = ExportElementImpl(-1);
-    spec.exportedLibrary = exportedLibrary;
-    spec.combinators = combinators;
-    return spec;
-  }
-
   static FieldElementImpl fieldElement(
       String name, bool isStatic, bool isFinal, bool isConst, DartType type,
       {Expression? initializer}) {
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 268706f..88a738e 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -381,12 +381,15 @@
       }
     }
 
-    for (var export in element.exports) {
-      export as ExportElementImpl;
+    for (var export in element.exports2) {
+      export as ExportElement2Impl;
       export.metadata = reader._readAnnotationList(
         unitElement: unitElement,
       );
-      export.exportedLibrary = reader.readElement() as LibraryElementImpl?;
+      final uri = export.uri;
+      if (uri is DirectiveUriWithLibraryImpl) {
+        uri.library = reader.libraryOfUri(uri.source.uri);
+      }
     }
 
     for (final part in element.parts2) {
@@ -453,7 +456,11 @@
         libraryElement: libraryElement,
       );
     });
-    libraryElement.exports = _reader.readTypedList(_readExportElement);
+    libraryElement.exports2 = _reader.readTypedList(() {
+      return _readExportElement(
+        libraryElement: libraryElement,
+      );
+    });
     LibraryElementFlags.read(_reader, libraryElement);
 
     for (final import in libraryElement.imports2) {
@@ -728,10 +735,19 @@
     }
   }
 
-  ExportElementImpl _readExportElement() {
-    var element = ExportElementImpl(-1);
-    element.uri = _reader.readOptionalStringReference();
-    element.combinators = _reader.readTypedList(_readNamespaceCombinator);
+  ExportElement2Impl _readExportElement({
+    required LibraryElementImpl libraryElement,
+  }) {
+    final uri = _readDirectiveUri(
+      libraryElement: libraryElement,
+    );
+    // TODO(scheglov) pass to the constructor
+    final combinators = _reader.readTypedList(_readNamespaceCombinator);
+
+    final element = ExportElement2Impl(
+      exportKeywordOffset: -1,
+      uri: uri,
+    )..combinators = combinators;
     return element;
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index 1d6844a..8ff8bbd 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -103,7 +103,7 @@
     _writeLanguageVersion(libraryElement.languageVersion);
     _resolutionSink._writeAnnotationList(libraryElement.metadata);
     _writeList(libraryElement.imports2, _writeImportElement);
-    _writeList(libraryElement.exports, _writeExportElement);
+    _writeList(libraryElement.exports2, _writeExportElement);
     for (final partElement in libraryElement.parts2) {
       _resolutionSink._writeAnnotationList(partElement.metadata);
     }
@@ -254,11 +254,11 @@
     });
   }
 
-  void _writeExportElement(ExportElement element) {
-    _sink._writeOptionalStringReference(element.uri);
-    _sink.writeList(element.combinators, _writeNamespaceCombinator);
+  void _writeExportElement(ExportElement2 element) {
+    element as ExportElement2Impl;
     _resolutionSink._writeAnnotationList(element.metadata);
-    _resolutionSink.writeElement(element.exportedLibrary);
+    _writeDirectiveUri(element.uri);
+    _sink.writeList(element.combinators, _writeNamespaceCombinator);
   }
 
   void _writeExtensionElement(ExtensionElement element) {
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index da83e3f..a4aace3 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -12,21 +12,19 @@
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary2/ast_binary_tokens.dart';
 import 'package:analyzer/src/summary2/library_builder.dart';
 import 'package:analyzer/src/summary2/link.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/util/comment.dart';
-import 'package:analyzer/src/util/uri.dart';
 import 'package:collection/collection.dart';
 
 class ElementBuilder extends ThrowingAstVisitor<void> {
   final LibraryBuilder _libraryBuilder;
   final CompilationUnitElementImpl _unitElement;
 
-  final _exports = <ExportElement>[];
   var _isFirstLibraryDirective = true;
+  var _exportDirectiveIndex = 0;
   var _importDirectiveIndex = 0;
   var _partDirectiveIndex = 0;
 
@@ -63,8 +61,6 @@
   void buildLibraryElementChildren(CompilationUnit unit) {
     unit.directives.accept(this);
 
-    _libraryElement.exports = _exports;
-
     if (_isFirstLibraryDirective) {
       _isFirstLibraryDirective = false;
       var firstDirective = unit.directives.firstOrNull;
@@ -369,20 +365,11 @@
 
   @override
   void visitExportDirective(covariant ExportDirectiveImpl node) {
-    var element = ExportElementImpl(node.exportKeyword.offset);
-    element.combinators = _buildCombinators(node.combinators);
-
-    try {
-      element.exportedLibrary = _selectLibrary(node);
-    } on ArgumentError {
-      // TODO(scheglov) Remove this when using `ExportDirectiveState`.
-    }
-
-    element.metadata = _buildAnnotations(node.metadata);
-    element.uri = node.uri.stringValue;
-
-    node.element = element;
-    _exports.add(element);
+    final index = _exportDirectiveIndex++;
+    final exportElement = _libraryElement.exports2[index];
+    exportElement as ExportElement2Impl;
+    exportElement.metadata = _buildAnnotations(node.metadata);
+    node.element = exportElement;
   }
 
   @override
@@ -1173,51 +1160,6 @@
     }
   }
 
-  Uri? _selectAbsoluteUri(NamespaceDirective directive) {
-    var relativeUriStr = _selectRelativeUri(
-      directive.configurations,
-      directive.uri.stringValue,
-    );
-    if (relativeUriStr == null) {
-      return null;
-    }
-
-    Uri relativeUri;
-    try {
-      relativeUri = Uri.parse(relativeUriStr);
-    } on FormatException {
-      return null;
-    }
-
-    var absoluteUri = resolveRelativeUri(_libraryBuilder.uri, relativeUri);
-
-    var sourceFactory = _linker.analysisContext.sourceFactory;
-    return rewriteToCanonicalUri(sourceFactory, absoluteUri);
-  }
-
-  LibraryElement? _selectLibrary(NamespaceDirective node) {
-    var uri = _selectAbsoluteUri(node);
-    if (uri == null) {
-      return null;
-    } else {
-      return _linker.elementFactory.libraryOfUri(uri);
-    }
-  }
-
-  String? _selectRelativeUri(
-    List<Configuration> configurations,
-    String? defaultUri,
-  ) {
-    for (var configuration in configurations) {
-      var name = configuration.name.components.join('.');
-      var value = configuration.value?.stringValue ?? 'true';
-      if (_linker.declaredVariables.get(name) == value) {
-        return configuration.uri.stringValue;
-      }
-    }
-    return defaultUri;
-  }
-
   bool _shouldBeConstField(FieldDeclaration node) {
     var fields = node.fields;
     return fields.isConst ||
@@ -1276,24 +1218,6 @@
     return annotations;
   }
 
-  static List<NamespaceCombinator> _buildCombinators(
-    List<Combinator> combinators,
-  ) {
-    return combinators.map((node) {
-      if (node is HideCombinator) {
-        return HideElementCombinatorImpl()
-          ..hiddenNames = node.hiddenNames.nameList;
-      }
-      if (node is ShowCombinator) {
-        return ShowElementCombinatorImpl()
-          ..offset = node.keyword.offset
-          ..end = node.end
-          ..shownNames = node.shownNames.nameList;
-      }
-      throw UnimplementedError('${node.runtimeType}');
-    }).toList();
-  }
-
   static void _setCodeRange(ElementImpl element, AstNode node) {
     var parent = node.parent;
     if (node is FormalParameter && parent is DefaultFormalParameter) {
@@ -1455,9 +1379,3 @@
     return reference;
   }
 }
-
-extension on Iterable<SimpleIdentifier> {
-  List<String> get nameList {
-    return map((e) => e.name).toList();
-  }
-}
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index b684e30..26451c7 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -464,11 +464,11 @@
       },
     );
 
-    forCorrespondingPairs<ExportElement, _InfoExport>(
+    forCorrespondingPairs<ExportElement2, _InfoExport>(
       element.exports_unresolved,
       info.exports,
       (element, info) {
-        element as ExportElementImpl;
+        element as ExportElement2Impl;
         element.nameOffset = info.nameOffset;
         _applyToCombinators(element.combinators, info.combinators);
       },
@@ -488,7 +488,7 @@
       (applier) {
         applier.applyToMetadata(element);
         applier.applyToImports(element.imports2);
-        applier.applyToDirectives(element.exports);
+        applier.applyToExports(element.exports2);
         applier.applyToPartDirectives(element.parts2);
       },
     );
@@ -1671,18 +1671,18 @@
     }
   }
 
-  void applyToDirectives(List<UriReferencedElement> elements) {
-    for (var element in elements) {
-      applyToMetadata(element);
-    }
-  }
-
   void applyToEnumConstants(List<FieldElement> constants) {
     for (var constant in constants) {
       applyToMetadata(constant);
     }
   }
 
+  void applyToExports(List<ExportElement2> elements) {
+    for (var element in elements) {
+      applyToMetadata(element);
+    }
+  }
+
   void applyToFormalParameters(List<ParameterElement> formalParameters) {
     for (var parameter in formalParameters) {
       applyToMetadata(parameter);
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 2e9b765..9af3b1b 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart' hide DirectiveUri;
 import 'package:analyzer/src/dart/analysis/file_state.dart' as file_state;
+import 'package:analyzer/src/dart/analysis/unlinked_data.dart';
 import 'package:analyzer/src/dart/ast/ast.dart' as ast;
 import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -89,7 +90,7 @@
   }
 
   void addExporters() {
-    final exportElements = element.exports;
+    final exportElements = element.exports2;
     for (var i = 0; i < exportElements.length; i++) {
       final exportElement = exportElements[i];
 
@@ -132,6 +133,7 @@
   /// Build elements for declarations in the library units, add top-level
   /// declarations to the local scope, for combining into export scopes.
   void buildElements() {
+    element.exports2 = kind.exports.map(_buildExport).toList();
     element.imports2 = kind.imports.map(_buildImport).toList();
 
     for (var linkingUnit in units) {
@@ -404,6 +406,89 @@
     }
   }
 
+  List<NamespaceCombinator> _buildCombinators(
+    List<UnlinkedCombinator> combinators2,
+  ) {
+    return combinators2.map((unlinked) {
+      if (unlinked.isShow) {
+        return ShowElementCombinatorImpl()
+          ..offset = unlinked.keywordOffset
+          ..end = unlinked.endOffset
+          ..shownNames = unlinked.names;
+      } else {
+        // TODO(scheglov) Why no offsets?
+        return HideElementCombinatorImpl()..hiddenNames = unlinked.names;
+      }
+    }).toList();
+  }
+
+  ExportElement2Impl _buildExport(ExportDirectiveState state) {
+    final combinators = _buildCombinators(
+      state.directive.combinators,
+    );
+
+    final DirectiveUri uri;
+    if (state is ExportDirectiveWithFile) {
+      final exportedLibraryKind = state.exportedLibrary;
+      if (exportedLibraryKind != null) {
+        final exportedFile = exportedLibraryKind.file;
+        final exportedUri = exportedFile.uri;
+        final elementFactory = linker.elementFactory;
+        final exportedLibrary = elementFactory.libraryOfUri2(exportedUri);
+        uri = DirectiveUriWithLibraryImpl(
+          relativeUriString: state.selectedUri.relativeUriStr,
+          relativeUri: state.selectedUri.relativeUri,
+          source: exportedLibrary.source,
+          library: exportedLibrary,
+        );
+      } else {
+        uri = DirectiveUriWithSourceImpl(
+          relativeUriString: state.selectedUri.relativeUriStr,
+          relativeUri: state.selectedUri.relativeUri,
+          source: state.exportedSource,
+        );
+      }
+    } else if (state is ExportDirectiveWithInSummarySource) {
+      final exportedLibrarySource = state.exportedLibrarySource;
+      if (exportedLibrarySource != null) {
+        final exportedUri = exportedLibrarySource.uri;
+        final elementFactory = linker.elementFactory;
+        final exportedLibrary = elementFactory.libraryOfUri2(exportedUri);
+        uri = DirectiveUriWithLibraryImpl(
+          relativeUriString: state.selectedUri.relativeUriStr,
+          relativeUri: state.selectedUri.relativeUri,
+          source: exportedLibrary.source,
+          library: exportedLibrary,
+        );
+      } else {
+        uri = DirectiveUriWithSourceImpl(
+          relativeUriString: state.selectedUri.relativeUriStr,
+          relativeUri: state.selectedUri.relativeUri,
+          source: state.exportedSource,
+        );
+      }
+    } else {
+      final selectedUri = state.selectedUri;
+      if (selectedUri is file_state.DirectiveUriWithUri) {
+        uri = DirectiveUriWithRelativeUriImpl(
+          relativeUriString: selectedUri.relativeUriStr,
+          relativeUri: selectedUri.relativeUri,
+        );
+      } else if (selectedUri is file_state.DirectiveUriWithString) {
+        uri = DirectiveUriWithRelativeUriStringImpl(
+          relativeUriString: selectedUri.relativeUriStr,
+        );
+      } else {
+        uri = DirectiveUriImpl();
+      }
+    }
+
+    return ExportElement2Impl(
+      exportKeywordOffset: state.directive.exportKeywordOffset,
+      uri: uri,
+    )..combinators = combinators;
+  }
+
   ImportElement2Impl _buildImport(ImportDirectiveState state) {
     final importPrefix = state.directive.prefix.mapOrNull((unlinked) {
       if (unlinked.deferredOffset != null) {
@@ -423,17 +508,9 @@
       }
     });
 
-    final combinators = state.directive.combinators.map((unlinked) {
-      if (unlinked.isShow) {
-        return ShowElementCombinatorImpl()
-          ..offset = unlinked.keywordOffset
-          ..end = unlinked.endOffset
-          ..shownNames = unlinked.names;
-      } else {
-        // TODO(scheglov) Why no offsets?
-        return HideElementCombinatorImpl()..hiddenNames = unlinked.names;
-      }
-    }).toList();
+    final combinators = _buildCombinators(
+      state.directive.combinators,
+    );
 
     final DirectiveUri uri;
     if (state is ImportDirectiveWithFile) {
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index 3d7b0c3..d104ed3 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -18,10 +18,10 @@
   @override
   CompilationUnitElement get unitElement => unit.declaredElement!;
 
-  ExportElement export(String targetUri) {
-    ExportElement? result;
+  ExportElement2 export(String targetUri) {
+    ExportElement2? result;
 
-    for (var export in libraryElement.exports) {
+    for (var export in libraryElement.exports2) {
       var exportedUri = export.exportedLibrary?.source.uri.toString();
       if (exportedUri == targetUri) {
         if (result != null) {
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index af43c44..d34a268 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -373,7 +373,7 @@
     await assertNoErrorsInCode('''
 export 'dart:math';
 ''');
-    expect(findNode.export('dart:math').element!.exportedLibrary!.name,
+    expect(findNode.export('dart:math').element2!.exportedLibrary!.name,
         'dart.math');
   }
 
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index d0f7199..4a3c9563 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -87,7 +87,7 @@
 
   @override
   void visitExportDirective(ExportDirective node) {
-    _checkResolved(node, node.element, (node) => node is ExportElement);
+    _checkResolved(node, node.element2, (node) => node is ExportElement2);
   }
 
   @override
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index b2fac8c..d35edce 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -7755,7 +7755,7 @@
     final cImport = unit.declaredElement!.library.imports2[1];
 
     LibraryElement bLibrary = bImport.importedLibrary!;
-    LibraryElement aLibrary = bLibrary.exports[0].exportedLibrary!;
+    LibraryElement aLibrary = bLibrary.exports2[0].exportedLibrary!;
     ClassElement aClass = aLibrary.getType('A')!;
 
     {
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 5226986..559ed04 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -2090,8 +2090,8 @@
     ResolvedUnitResult result = await driver.getResultValid(testFile);
     expect(result.path, testFile);
     // Has only exports for valid URIs.
-    List<ExportElement> imports = result.libraryElement.exports;
-    expect(imports.map((import) {
+    final exports = result.libraryElement.exports2;
+    expect(exports.map((import) {
       return import.exportedLibrary?.source.uri.toString();
     }), ['dart:async', null, 'dart:math']);
   }
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 1177e37..0ca1f33 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -163,7 +163,7 @@
           .toList();
       _writeElements('imports', imports, _writeImportElement);
 
-      _writeElements('exports', e.exports, _writeExportElement);
+      _writeElements('exports', e.exports2, _writeExportElement);
 
       _writelnWithIndent('definingUnit');
       _withIndent(() {
@@ -496,9 +496,9 @@
     }
   }
 
-  void _writeExportElement(ExportElement e) {
+  void _writeExportElement(ExportElement2 e) {
     _writeIndentedLine(() {
-      _writeUri(e.exportedLibrary?.source);
+      _writeDirectiveUri(e.uri);
     });
 
     _withIndent(() {
@@ -979,19 +979,6 @@
     );
     _writeElements('functions', e.functions, _writeFunctionElement);
   }
-
-  void _writeUri(Source? source) {
-    if (source != null) {
-      Uri uri = source.uri;
-      String uriStr = uri.toString();
-      if (uri.isScheme('file')) {
-        uriStr = uri.pathSegments.last;
-      }
-      buffer.write(uriStr);
-    } else {
-      buffer.write('<unresolved>');
-    }
-  }
 }
 
 class _Replacement {
diff --git a/pkg/analyzer/test/src/summary/elements_test.dart b/pkg/analyzer/test/src/summary/elements_test.dart
index 91fbd41..309f16f 100644
--- a/pkg/analyzer/test/src/summary/elements_test.dart
+++ b/pkg/analyzer/test/src/summary/elements_test.dart
@@ -20038,7 +20038,7 @@
     A: package:test/foo.dart;A
 ''',
         withExportScope: true);
-    expect(library.exports[0].exportedLibrary!.source.shortName, 'foo.dart');
+    expect(library.exports2[0].exportedLibrary!.source.shortName, 'foo.dart');
   }
 
   test_export_configurations_useFirst() async {
@@ -20067,7 +20067,8 @@
     A: package:test/foo_io.dart;A
 ''',
         withExportScope: true);
-    expect(library.exports[0].exportedLibrary!.source.shortName, 'foo_io.dart');
+    expect(
+        library.exports2[0].exportedLibrary!.source.shortName, 'foo_io.dart');
   }
 
   test_export_configurations_useSecond() async {
@@ -20096,7 +20097,7 @@
     A: package:test/foo_html.dart;A
 ''',
         withExportScope: true);
-    ExportElement export = library.exports[0];
+    final export = library.exports2[0];
     expect(export.exportedLibrary!.source.shortName, 'foo_html.dart');
   }
 
@@ -20357,7 +20358,9 @@
     var library = await buildLibrary('''
 export 'foo.dart';
 ''');
-    expect(library.exports[0].uri, 'foo.dart');
+
+    final uri = library.exports2[0].uri as DirectiveUriWithLibrary;
+    expect(uri.relativeUriString, 'foo.dart');
   }
 
   test_export_variable() async {
@@ -25355,46 +25358,6 @@
 ''');
   }
 
-  test_invalidUris() async {
-    var library = await buildLibrary(r'''
-import ':[invaliduri]';
-import ':[invaliduri]:foo.dart';
-import 'a1.dart';
-import ':[invaliduri]';
-import ':[invaliduri]:foo.dart';
-
-export ':[invaliduri]';
-export ':[invaliduri]:foo.dart';
-export 'a2.dart';
-export ':[invaliduri]';
-export ':[invaliduri]:foo.dart';
-
-part ':[invaliduri]';
-part 'a3.dart';
-part ':[invaliduri]';
-''');
-    checkElementText(library, r'''
-library
-  imports
-    relativeUriString ':[invaliduri]'
-    relativeUriString ':[invaliduri]:foo.dart'
-    package:test/a1.dart
-    relativeUriString ':[invaliduri]'
-    relativeUriString ':[invaliduri]:foo.dart'
-  exports
-    <unresolved>
-    <unresolved>
-    package:test/a2.dart
-    <unresolved>
-    <unresolved>
-  definingUnit
-  parts
-    relativeUriString ':[invaliduri]'
-    source 'package:test/a3.dart'
-    relativeUriString ':[invaliduri]'
-''');
-  }
-
   test_library() async {
     var library = await buildLibrary('');
     checkElementText(library, r'''
@@ -25434,6 +25397,96 @@
 ''');
   }
 
+  test_library_exports_noRelativeUriStr() async {
+    final library = await buildLibrary(r'''
+export '${'foo'}.dart';
+''');
+    checkElementText(library, r'''
+library
+  exports
+    noRelativeUriString
+  definingUnit
+''');
+  }
+
+  test_library_exports_withRelativeUri_emptyUriSelf() async {
+    final library = await buildLibrary(r'''
+export '';
+''');
+    checkElementText(library, r'''
+library
+  exports
+    package:test/test.dart
+  definingUnit
+''');
+  }
+
+  test_library_exports_withRelativeUri_noSource() async {
+    final library = await buildLibrary(r'''
+export 'foo:bar';
+''');
+    checkElementText(library, r'''
+library
+  exports
+    relativeUri 'foo:bar'
+  definingUnit
+''');
+  }
+
+  test_library_exports_withRelativeUri_notExists() async {
+    final library = await buildLibrary(r'''
+export 'a.dart';
+''');
+    checkElementText(library, r'''
+library
+  exports
+    package:test/a.dart
+  definingUnit
+''');
+  }
+
+  test_library_exports_withRelativeUri_notLibrary_augmentation() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+''');
+    final library = await buildLibrary(r'''
+export 'a.dart';
+''');
+    checkElementText(library, r'''
+library
+  exports
+    source 'package:test/a.dart'
+  definingUnit
+''');
+  }
+
+  test_library_exports_withRelativeUri_notLibrary_part() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+part of other.lib;
+''');
+    final library = await buildLibrary(r'''
+export 'a.dart';
+''');
+    checkElementText(library, r'''
+library
+  exports
+    source 'package:test/a.dart'
+  definingUnit
+''');
+  }
+
+  test_library_exports_withRelativeUriString() async {
+    final library = await buildLibrary(r'''
+export ':';
+''');
+    checkElementText(library, r'''
+library
+  exports
+    relativeUriString ':'
+  definingUnit
+''');
+  }
+
   test_library_imports_noRelativeUriStr() async {
     final library = await buildLibrary(r'''
 import '${'foo'}.dart';
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index c88cc6a..52d0d26 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -398,7 +398,7 @@
     _writeln('ExportDirective');
     _withIndent(() {
       _writeNamedChildEntities(node);
-      _writeElement('element', node.element);
+      _writeElement('element', node.element2);
       _writeSource('selectedSource', node.selectedSource);
       _writeRaw('selectedUriContent', node.selectedUriContent);
       _writeRaw('uriContent', node.uriContent);
diff --git a/pkg/analyzer/test/util/element_type_matchers.dart b/pkg/analyzer/test/util/element_type_matchers.dart
index f05ab87..e03fa53 100644
--- a/pkg/analyzer/test/util/element_type_matchers.dart
+++ b/pkg/analyzer/test/util/element_type_matchers.dart
@@ -15,7 +15,7 @@
 
 const isExecutableElement = TypeMatcher<ExecutableElement>();
 
-const isExportElement = TypeMatcher<ExportElement>();
+const isExportElement = TypeMatcher<ExportElement2>();
 
 const isFieldElement = TypeMatcher<FieldElement>();
 
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index 23df1dd..de32a21 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -344,7 +344,7 @@
 
   @override
   void visitExportDirective(ExportDirective node) {
-    var exportElement = node.element;
+    var exportElement = node.element2;
     if (exportElement != null) {
       Element? libraryElement = exportElement.exportedLibrary;
       _addUriDirectiveRegion(node, libraryElement);