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
4 changes: 2 additions & 2 deletions lib/src/generator/templates.runtime_renderers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12715,7 +12715,7 @@ class _Renderer_Package extends RendererBase<Package> {
}
}

String renderSearchPage(PackageTemplateData context, Template template) {
String renderIndex(PackageTemplateData context, Template template) {
var buffer = StringBuffer();
_render_PackageTemplateData(context, template.ast, template, buffer);
return buffer.toString();
Expand Down Expand Up @@ -12953,7 +12953,7 @@ class _Renderer_PackageTemplateData extends RendererBase<PackageTemplateData> {
}
}

String renderIndex(PackageTemplateData context, Template template) {
String renderSearchPage(PackageTemplateData context, Template template) {
var buffer = StringBuffer();
_render_PackageTemplateData(context, template.ast, template, buffer);
return buffer.toString();
Expand Down
13 changes: 9 additions & 4 deletions lib/src/model/accessor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,15 @@ class Accessor extends ModelElement implements EnclosedElement {
late final GetterSetterCombo definingCombo =
modelBuilder.fromElement(element.variable) as GetterSetterCombo;

late final String _sourceCode = isSynthetic
? _sourceCodeRenderer.renderSourceCode(
packageGraph.getModelNodeFor(definingCombo.element)!.sourceCode)
: super.sourceCode;
String get _sourceCode {
if (!isSynthetic) {
return super.sourceCode;
}
var modelNode = packageGraph.getModelNodeFor(definingCombo.element);
return modelNode == null
? ''
: _sourceCodeRenderer.renderSourceCode(modelNode.sourceCode);
}

@override
String get sourceCode => _sourceCode;
Expand Down
116 changes: 2 additions & 114 deletions lib/src/model/library.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import 'dart:collection';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/source/line_info.dart';
// ignore: implementation_imports
import 'package:analyzer/src/generated/sdk.dart' show SdkLibrary;
Expand All @@ -16,116 +15,6 @@ import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/package_meta.dart' show PackageMeta;
import 'package:dartdoc/src/warnings.dart';

/// Finds all hashable children of a given element that are defined in the
/// [LibraryElement] given at initialization.
// TODO(srawlins): Do we not need to visit the parameters in
// [ConstructorElement], [FunctionElement], [MethodElement],
// [PropertyAccessorElement], [TypeAliasElement]?
class _HashableChildLibraryElementVisitor
extends RecursiveElementVisitor<void> {
final DartDocResolvedLibrary resolvedLibrary;
final PackageGraph packageGraph;

_HashableChildLibraryElementVisitor(this.resolvedLibrary, this.packageGraph);

@override
void visitClassElement(ClassElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
super.visitClassElement(element);
}

@override
void visitConstructorElement(ConstructorElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
}

@override
void visitEnumElement(EnumElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
super.visitEnumElement(element);
}

@override
void visitExtensionElement(ExtensionElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
super.visitExtensionElement(element);
}

@override
void visitFieldElement(FieldElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
}

@override
void visitFieldFormalParameterElement(FieldFormalParameterElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
}

@override
void visitFunctionElement(FunctionElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
}

@override
void visitLibraryElement(LibraryElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
super.visitLibraryElement(element);
}

@override
void visitMixinElement(MixinElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
super.visitMixinElement(element);
}

@override
void visitMultiplyDefinedElement(MultiplyDefinedElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
super.visitMultiplyDefinedElement(element);
}

@override
void visitMethodElement(MethodElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
}

@override
void visitParameterElement(ParameterElement element) {
// [ParameterElement]s without names do not provide sufficiently distinct
// hashes / comparison, so just skip them all. (dart-lang/sdk#30146)
}

@override
void visitPrefixElement(PrefixElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
}

@override
void visitPropertyAccessorElement(PropertyAccessorElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
}

@override
void visitSuperFormalParameterElement(SuperFormalParameterElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
}

@override
void visitTopLevelVariableElement(TopLevelVariableElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
}

@override
void visitTypeAliasElement(TypeAliasElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
}

@override
void visitTypeParameterElement(TypeParameterElement element) {
packageGraph.populateModelNodeFor(element, resolvedLibrary);
}
}

class _LibrarySentinel implements Library {
@override
dynamic noSuchMethod(Invocation invocation) =>
Expand Down Expand Up @@ -165,10 +54,9 @@ class Library extends ModelElement

factory Library.fromLibraryResult(DartDocResolvedLibrary resolvedLibrary,
PackageGraph packageGraph, Package package) {
var element = resolvedLibrary.element;
packageGraph.gatherModelNodes(resolvedLibrary);

_HashableChildLibraryElementVisitor(resolvedLibrary, packageGraph)
.visitLibraryElement(element);
var element = resolvedLibrary.element;

var exportedAndLocalElements = {
// Initialize the list of elements defined in this library and
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 @@ -385,7 +385,7 @@ abstract class ModelElement extends Canonicalization
Iterable<Category?> get displayedCategories => const [];

@override
late final ModelNode? modelNode = packageGraph.getModelNodeFor(element);
ModelNode? get modelNode => packageGraph.getModelNodeFor(element);

/// This element's [Annotation]s.
///
Expand Down
24 changes: 2 additions & 22 deletions lib/src/model/package_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart'
show AnalysisContextCollectionImpl;
// ignore: implementation_imports
import 'package:analyzer/src/dart/ast/utilities.dart' show NodeLocator2;
// ignore: implementation_imports
import 'package:analyzer/src/dart/sdk/sdk.dart'
show EmbedderSdk, FolderBasedDartSdk;
// ignore: implementation_imports
Expand Down Expand Up @@ -479,27 +477,9 @@ class PubPackageBuilder implements PackageBuilder {
/// the library.
class DartDocResolvedLibrary {
final LibraryElement element;
final Map<String, CompilationUnit> _units;
final List<CompilationUnit> units;

DartDocResolvedLibrary(ResolvedLibraryResult result)
: element = result.element,
_units = {
for (var unit in result.units) unit.path: unit.unit,
};

/// Returns the [AstNode] for a given [Element].
///
/// Uses a precomputed map of `element.source.fullName` to [CompilationUnit]
/// to avoid linear traversal in
/// `ResolvedLibraryElementImpl.getElementDeclaration`.
AstNode? getAstNode(Element element) {
var fullName = element.source?.fullName;
if (fullName != null && !element.isSynthetic && element.nameOffset != -1) {
var unit = _units[fullName];
if (unit != null) {
return NodeLocator2(element.nameOffset).searchWithin(unit);
}
}
return null;
}
units = result.units.map((unit) => unit.unit).toList();
}
74 changes: 68 additions & 6 deletions lib/src/model/package_graph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'dart:collection';

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
// ignore: implementation_imports
Expand Down Expand Up @@ -170,15 +171,76 @@ class PackageGraph with CommentReferable, Nameable, ModelBuilder {
// than once for them.
final Map<Element, ModelNode> _modelNodes = {};

void populateModelNodeFor(
Element element, DartDocResolvedLibrary resolvedLibrary) {
/// Populate's [_modelNodes] with elements in [resolvedLibrary].
///
/// This is done as [Library] model objects are created, while we are holding
/// onto [resolvedLibrary] objects.
// TODO(srawlins): I suspect we populate this mapping with way too many
// objects, too eagerly. They are only needed when writing the source code of
// an element to HTML, and maybe for resolving doc comments. We should find a
// way to get this data only when needed. But it's not immediately obvious to
// me how, because the data is on AST nodes, not the element model.
void gatherModelNodes(DartDocResolvedLibrary resolvedLibrary) {
for (var unit in resolvedLibrary.units) {
for (var declaration in unit.declarations) {
_populateModelNodeFor(declaration);
switch (declaration) {
case ClassDeclaration():
for (var member in declaration.members) {
_populateModelNodeFor(member);
}
case EnumDeclaration():
if (declaration.declaredElement?.isPublic ?? false) {
for (var member in declaration.members) {
_populateModelNodeFor(member);
}
}
case MixinDeclaration():
for (var member in declaration.members) {
_populateModelNodeFor(member);
}
case ExtensionDeclaration():
if (declaration.declaredElement?.isPublic ?? false) {
for (var member in declaration.members) {
_populateModelNodeFor(member);
}
}
case ExtensionTypeDeclaration():
if (declaration.declaredElement?.isPublic ?? false) {
for (var member in declaration.members) {
_populateModelNodeFor(member);
}
}
}
}
}
}

void _populateModelNodeFor(Declaration declaration) {
if (declaration is FieldDeclaration) {
var fields = declaration.fields.variables;
for (var field in fields) {
var element = field.declaredElement!;
_modelNodes.putIfAbsent(
element, () => ModelNode(field, element, resourceProvider));
}
return;
}
if (declaration is TopLevelVariableDeclaration) {
var fields = declaration.variables.variables;
for (var field in fields) {
var element = field.declaredElement!;
_modelNodes.putIfAbsent(
element, () => ModelNode(field, element, resourceProvider));
}
return;
}
var element = declaration.declaredElement!;
_modelNodes.putIfAbsent(
element,
() => ModelNode(
resolvedLibrary.getAstNode(element), element, resourceProvider));
element, () => ModelNode(declaration, element, resourceProvider));
}

ModelNode? getModelNodeFor(Element? element) => _modelNodes[element!];
ModelNode? getModelNodeFor(Element element) => _modelNodes[element];

late SpecialClasses specialClasses;

Expand Down