Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/src/generator/templates.runtime_renderers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26267,6 +26267,7 @@ const _invisibleGetters = {
'libraries',
'libraryCount',
'libraryExports',
'libraryExports2',
'localPackages',
'localPublicLibraries',
'name',
Expand Down
81 changes: 64 additions & 17 deletions lib/src/model/canonicalization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,30 @@
// 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.

// ignore_for_file: analyzer_use_new_elements

import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
// ignore: implementation_imports
import 'package:analyzer/src/dart/element/element.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/warnings.dart';

const int _separatorChar = 0x3B;

/// Searches [PackageGraph.libraryExports] for a public, documented library
/// which exports this [ModelElement], ideally in its library's package.
Library? canonicalLibraryCandidate(ModelElement modelElement) {
var thisAndExported =
modelElement.packageGraph.libraryExports[modelElement.library.element];
modelElement.packageGraph.libraryExports[modelElement.library.element2];
if (thisAndExported == null) {
return null;
}

// Since we're looking for a library, find the [Element] immediately
// contained by a [CompilationUnitElement] in the tree.
var topLevelElement = modelElement.element;
while (topLevelElement.enclosingElement3 is! LibraryElement &&
topLevelElement.enclosingElement3 is! CompilationUnitElement &&
topLevelElement.enclosingElement3 != null) {
topLevelElement = topLevelElement.enclosingElement3!;
// Since we're looking for a library, go up in the tree until we find it.
var topLevelElement = modelElement.element2;
while (topLevelElement.enclosingElement2 is! LibraryElement2 &&
topLevelElement.enclosingElement2 != null) {
topLevelElement = topLevelElement.enclosingElement2!;
}
var topLevelElementName = topLevelElement.name;
var topLevelElementName = topLevelElement.name3;
if (topLevelElementName == null) {
// Any member of an unnamed extension is not public, and has no
// canonical library.
Expand All @@ -36,9 +36,9 @@ Library? canonicalLibraryCandidate(ModelElement modelElement) {
if (!l.isPublic) return false;
if (l.package.documentedWhere == DocumentLocation.missing) return false;
if (modelElement is Library) return true;
var lookup = l.element.exportNamespace.definedNames[topLevelElementName];
var lookup = l.element2.exportNamespace.definedNames2[topLevelElementName];
return topLevelElement ==
(lookup is PropertyAccessorElement ? lookup.variable2 : lookup);
(lookup is PropertyAccessorElement2 ? lookup.variable3 : lookup);
}).toList(growable: true);

if (candidateLibraries.isEmpty) {
Expand All @@ -58,7 +58,7 @@ Library? canonicalLibraryCandidate(ModelElement modelElement) {
}

var topLevelModelElement =
ModelElement.forElement(topLevelElement, modelElement.packageGraph);
ModelElement.forElement2(topLevelElement, modelElement.packageGraph);

return _Canonicalization(topLevelModelElement)
.canonicalLibraryCandidate(candidateLibraries);
Expand All @@ -74,10 +74,57 @@ final class _Canonicalization {

_Canonicalization(this._element);

/// Append an encoded form of the given [component] to the given [buffer].
void _encode(StringBuffer buffer, String component) {
var length = component.length;
for (var i = 0; i < length; i++) {
var currentChar = component.codeUnitAt(i);
if (currentChar == _separatorChar) {
buffer.writeCharCode(_separatorChar);
}
buffer.writeCharCode(currentChar);
}
}

// Copied from package analyzer ElementLocationImpl.fromElement.
String _getElementLocation(Element2 element) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a comment about where this comes from, so that we can look to the other implementation if bugs arise?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

var components = <String>[];
Element2? ancestor = element;
while (ancestor != null) {
if (ancestor is! ElementImpl2) {
if (ancestor is LibraryElementImpl) {
components.insert(0, ancestor.identifier);
} else if (ancestor is AugmentableElement) {
components.insert(0, ancestor.identifier);
} else {
throw Exception('${ancestor.runtimeType} is not an ElementImpl2');
}
ancestor = ancestor.enclosingElement2;
} else {
components.insert(0, ancestor.identifier);
if (ancestor is LocalFunctionElementImpl) {
ancestor = (ancestor.wrappedElement.enclosingElement2
as ExecutableElementImpl)
.element;
} else {
ancestor = ancestor.enclosingElement2;
}
}
}
var buffer = StringBuffer();
var length = components.length;
for (var i = 0; i < length; i++) {
if (i > 0) {
buffer.writeCharCode(_separatorChar);
}
_encode(buffer, components[i]);
}
return buffer.toString();
}

/// Calculates a candidate for the canonical library of [_element], among [libraries].
Library canonicalLibraryCandidate(Iterable<Library> libraries) {
var locationPieces = _element.element.location
.toString()
var locationPieces = _getElementLocation(_element.element2)
.split(_locationSplitter)
.where((s) => s.isNotEmpty)
.toSet();
Expand Down
2 changes: 1 addition & 1 deletion lib/src/model/model_element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ abstract class ModelElement
TypeAliasElement(aliasedType: FunctionType()) =>
FunctionTypedef(e, library, packageGraph),
TypeAliasElement()
when e.aliasedType.documentableElement is InterfaceElement =>
when e.aliasedType.documentableElement2.asElement is InterfaceElement =>
ClassTypedef(e, library, packageGraph),
TypeAliasElement() => GeneralizedTypedef(e, library, packageGraph),
MethodElement(isOperator: true) when enclosingContainer == null =>
Expand Down
47 changes: 34 additions & 13 deletions lib/src/model/package_graph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'dart:collection';

import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/source.dart';
// ignore: implementation_imports
Expand Down Expand Up @@ -510,16 +511,16 @@ class PackageGraph with CommentReferable, Nameable {
packages.where((p) => p.documentedWhere != DocumentLocation.missing);

/// A mapping from a [LibraryElement] to all of the [Library]s that export it.
Map<LibraryElement, Set<Library>> _libraryExports = {};
Map<LibraryElement2, Set<Library>> _libraryExports = {};

/// Marks [publicLibrary] as a library that exports [libraryElement] and all
/// libraries that [libraryElement] transitively exports.
///
/// [alreadyTagged] is used internall to prevent visiting in cycles.
void _tagExportsFor(
final Library publicLibrary,
final LibraryElement libraryElement, {
Set<(Library, LibraryElement)>? alreadyTagged,
final LibraryElement2 libraryElement, {
Set<(Library, LibraryElement2)>? alreadyTagged,
}) {
alreadyTagged ??= {};
var key = (publicLibrary, libraryElement);
Expand All @@ -529,14 +530,15 @@ class PackageGraph with CommentReferable, Nameable {
alreadyTagged.add(key);
// Mark that `publicLibrary` exports `libraryElement`.
_libraryExports.putIfAbsent(libraryElement, () => {}).add(publicLibrary);
for (var exportedElement
in libraryElement.definingCompilationUnit.libraryExports) {
var exportedLibrary = exportedElement.exportedLibrary;
if (exportedLibrary != null) {
// Follow the exports down; as `publicLibrary` exports `libraryElement`,
// it also exports each `exportedLibrary`.
_tagExportsFor(publicLibrary, exportedLibrary,
alreadyTagged: alreadyTagged);
for (var fragment in libraryElement.fragments) {
for (var exportedElement in fragment.libraryExports2) {
var exportedLibrary = exportedElement.exportedLibrary2;
if (exportedLibrary != null) {
// Follow the exports down; as `publicLibrary` exports `libraryElement`,
// it also exports each `exportedLibrary`.
_tagExportsFor(publicLibrary, exportedLibrary,
alreadyTagged: alreadyTagged);
}
}
}
}
Expand All @@ -545,7 +547,26 @@ class PackageGraph with CommentReferable, Nameable {

/// A mapping from a [LibraryElement] to all of the [Library]s that export it,
/// which is created if it is not yet populated.
Map<LibraryElement, Set<Library>> get libraryExports {
Map<LibraryElement2, Set<Library>> get libraryExports {
// The map must be reset if we're still in the middle of adding libraries
// (though this shouldn't happen).
if (_allLibraries.keys.length != _previousSizeOfAllLibraries) {
assert(
_previousSizeOfAllLibraries == 0,
'Re-entered `libraryExports` while building all libraries',
);
_previousSizeOfAllLibraries = _allLibraries.keys.length;
_libraryExports = {};
for (var library in publicLibraries) {
_tagExportsFor(library, library.element2);
}
}
return _libraryExports;
}

/// A mapping from a [LibraryElement] to all of the [Library]s that export it,
/// which is created if it is not yet populated.
Map<LibraryElement2, Set<Library>> get libraryExports2 {
// The map must be reset if we're still in the middle of adding libraries
// (though this shouldn't happen).
if (_allLibraries.keys.length != _previousSizeOfAllLibraries) {
Expand All @@ -556,7 +577,7 @@ class PackageGraph with CommentReferable, Nameable {
_previousSizeOfAllLibraries = _allLibraries.keys.length;
_libraryExports = {};
for (var library in publicLibraries) {
_tagExportsFor(library, library.element);
_tagExportsFor(library, library.element2);
}
}
return _libraryExports;
Expand Down
17 changes: 0 additions & 17 deletions lib/src/type_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,10 @@
// 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.

// ignore_for_file: analyzer_use_new_elements

import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/dart/element/type.dart';

extension DartTypeExtension on DartType {
/// The static element associataed with this type, where documentable, and
/// `null` otherwise.
///
/// For example, the documentable element of [DynamicType] is `null`, as there
/// is no documentation for `dynamic` which we can link to.
TypeDefiningElement? get documentableElement {
final self = this;
return switch (self) {
InterfaceType() => self.element,
NeverType() => self.element as TypeDefiningElement,
TypeParameterType() => self.element,
_ => null
};
}

/// The static element associataed with this type, where documentable, and
/// `null` otherwise.
Expand Down
34 changes: 1 addition & 33 deletions test/mustachio/builder_test_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@
// 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.

// ignore_for_file: analyzer_use_new_elements

import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart'
show AnalysisContextCollectionImpl;
import 'package:collection/collection.dart';
import 'package:path/path.dart' as path;
import 'package:test_descriptor/test_descriptor.dart' as d;

Expand Down Expand Up @@ -83,26 +79,6 @@ $sourceLibraryContent
root: path.join(d.sandbox, 'foo_package'));
}

Future<LibraryElement> resolveGeneratedLibrary(String libraryPath) async {
var contextCollection = AnalysisContextCollectionImpl(
includedPaths: [d.sandbox],
// TODO(jcollins-g): should we pass excluded directories here instead of
// handling it ourselves?
resourceProvider: PhysicalResourceProvider.INSTANCE,
sdkPath: sdkPath,
);
var analysisContext = contextCollection.contextFor(d.sandbox);
final libraryResult =
await analysisContext.currentSession.getResolvedLibrary(libraryPath);
if (libraryResult is! ResolvedLibraryResult) {
throw StateError(
'Expected library result to be ResolvedLibraryResult, but is '
'${libraryResult.runtimeType}');
}

return libraryResult.element;
}

Future<LibraryElement2> resolveGeneratedLibrary2(String libraryPath) async {
var contextCollection = AnalysisContextCollectionImpl(
includedPaths: [d.sandbox],
Expand All @@ -121,12 +97,4 @@ Future<LibraryElement2> resolveGeneratedLibrary2(String libraryPath) async {
}

return libraryResult.element2;
}

extension LibraryExtensions on LibraryElement {
/// Returns the top-level function in `this` library, named [name], or `null`
/// if no function is found.
FunctionElement? getTopLevelFunction(String name) => topLevelElements
.whereType<FunctionElement>()
.firstWhereOrNull((element) => element.name == name);
}
}
4 changes: 2 additions & 2 deletions tool/mustachio/codegen_runtime_renderer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ String buildRuntimeRenderers(Set<RendererSpec> specs, Uri sourceUri,
var visibleElements = specs
.map((spec) => spec.visibleTypes)
.reduce((value, element) => value.union(element))
.map((type) => type.documentableElement!)
.map((type) => type.documentableElement2.asElement!)
.toSet();
var raw = RuntimeRenderersBuilder(
sourceUri, typeProvider, typeSystem, visibleElements,
Expand Down Expand Up @@ -539,7 +539,7 @@ renderVariable:
// TODO(srawlins): Find a solution for this. We can track all of the
// concrete types substituted for `E` for example.
if (innerType is! TypeParameterType) {
var innerTypeElement = innerType.documentableElement;
var innerTypeElement = innerType.documentableElement2.asElement;
var renderFunctionName = _typeToRenderFunctionName[innerTypeElement];
String renderCall;
if (renderFunctionName == null) {
Expand Down
Loading