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
64 changes: 4 additions & 60 deletions lib/src/comment_references/model_comment_reference.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,82 +4,26 @@
//

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:dartdoc/src/comment_references/parser.dart';

abstract class ModelCommentReference {
String get codeRef;
bool get hasCallableHint;
List<String> get referenceBy;
Element? get staticElement;

/// Construct a [ModelCommentReference] using the analyzer AST.
factory ModelCommentReference(
CommentReference ref, ResourceProvider resourceProvider) =>
_ModelCommentReferenceImpl(ref, resourceProvider);

/// Construct a [ModelCommentReference] given a raw string.
factory ModelCommentReference.synthetic(String codeRef) =>
_ModelCommentReferenceImpl.synthetic(codeRef, null);
}

/// A stripped down analyzer AST [CommentReference] containing only that
/// information needed for Dartdoc. Drops link to the [CommentReference]
/// and [ResourceProvider] after construction.
class _ModelCommentReferenceImpl implements ModelCommentReference {
@override
/// information needed for Dartdoc.
class ModelCommentReference {
final String codeRef;

@override
bool get hasCallableHint =>
parsed.isNotEmpty &&
((parsed.length > 1 && parsed.last.text == 'new') ||
parsed.last is CallableHintEndNode);

@override
List<String> get referenceBy => parsed
.whereType<IdentifierNode>()
.map<String>((i) => i.text)
.toList(growable: false);

@override
final Element? staticElement;

_ModelCommentReferenceImpl(
CommentReference ref, ResourceProvider resourceProvider)
: codeRef = _referenceText(ref, resourceProvider),
staticElement = ref.expression.element;

_ModelCommentReferenceImpl.synthetic(this.codeRef, this.staticElement);

/// "Unparse" the code reference into the raw text associated with the
/// [CommentReference].
static String _referenceText(
CommentReference ref, ResourceProvider resourceProvider) {
var token = (ref.parent as Comment)
.tokens
.firstWhere((t) => t.offset <= ref.offset && t.end >= ref.end);
// This is a little sketchy, but works since comments happen to be a token
// that is fully preserved in its string representation.
// TODO(jcollins-g): replace unparsing in general with lower level changes.
return token
.toString()
.substring(ref.offset - token.offset, ref.end - token.offset);
}
/// Constructs a [ModelCommentReference] given a raw string.
ModelCommentReference(this.codeRef);

late final List<CommentReferenceNode> parsed =
CommentReferenceParser(codeRef).parse();
}

extension on CommentReferableExpression {
Element? get element {
var self = this;
return switch (self) {
PrefixedIdentifier() => self.staticElement,
PropertyAccess() => self.propertyName.staticElement,
SimpleIdentifier() => self.staticElement,
_ => null
};
}
}
9 changes: 1 addition & 8 deletions lib/src/generator/templates.runtime_renderers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17009,14 +17009,7 @@ const _invisibleGetters = {
'superclassConstraints'
},
'ModelElementRenderer': {'hashCode', 'runtimeType'},
'ModelNode': {
'commentRefs',
'element',
'hashCode',
'resourceProvider',
'runtimeType',
'sourceCode'
},
'ModelNode': {'hashCode', 'runtimeType', 'sourceCode'},
'ModelObjectBuilder': {'hashCode', 'runtimeType'},
'PackageGraph': {
'allCanonicalModelElements',
Expand Down
2 changes: 1 addition & 1 deletion lib/src/markdown_processor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ bool _requireCallable(CommentReferable? referable) =>

MatchingLinkResult _getMatchingLinkElement(
String referenceText, Warnable element) {
var commentReference = ModelCommentReference.synthetic(referenceText);
var commentReference = ModelCommentReference(referenceText);

// A filter to be used by [CommentReferable.referenceBy].
bool Function(CommentReferable?) filter;
Expand Down
31 changes: 7 additions & 24 deletions lib/src/model/model_node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,21 @@ import 'dart:convert';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:dartdoc/src/comment_references/model_comment_reference.dart';
import 'package:dartdoc/src/model_utils.dart' as model_utils;
import 'package:meta/meta.dart';

/// Stripped down information derived from [AstNode] containing only information
/// needed for Dartdoc. Drops link to the [AstNode] after construction.
/// needed to resurrect the source code of [element].
class ModelNode {
final List<ModelCommentReference> commentRefs;
final Element element;
final ResourceProvider resourceProvider;
final Element _element;
final ResourceProvider _resourceProvider;
final int _sourceEnd;
final int _sourceOffset;

factory ModelNode(
AstNode? sourceNode, Element element, ResourceProvider resourceProvider) {
var commentRefs = _commentRefsFor(sourceNode, resourceProvider);
if (sourceNode == null) {
return ModelNode._(element, resourceProvider, commentRefs,
return ModelNode._(element, resourceProvider,
sourceEnd: -1, sourceOffset: -1);
} else {
// Get a node higher up the syntax tree that includes the semicolon.
Expand All @@ -35,38 +32,24 @@ class ModelNode {
assert(sourceNode is FieldDeclaration ||
sourceNode is TopLevelVariableDeclaration);
}
return ModelNode._(element, resourceProvider, commentRefs,
return ModelNode._(element, resourceProvider,
sourceEnd: sourceNode.end, sourceOffset: sourceNode.offset);
}
}

ModelNode._(this.element, this.resourceProvider, this.commentRefs,
ModelNode._(this._element, this._resourceProvider,
{required int sourceEnd, required int sourceOffset})
: _sourceEnd = sourceEnd,
_sourceOffset = sourceOffset;

static List<ModelCommentReference> _commentRefsFor(
AstNode? node, ResourceProvider resourceProvider) {
if (node is AnnotatedNode) {
var nodeDocumentationComment = node.documentationComment;
if (nodeDocumentationComment != null) {
return [
for (var m in nodeDocumentationComment.references)
ModelCommentReference(m, resourceProvider),
];
}
}
return const [];
}

bool get _isSynthetic => _sourceEnd < 0 || _sourceOffset < 0;

/// The text of the source code of this node, stripped of the leading
/// indentation, and stripped of the doc comments.
late final String sourceCode = _isSynthetic
? ''
: model_utils
.getFileContentsFor(element, resourceProvider)
.getFileContentsFor(_element, _resourceProvider)
.substringFromLineStart(_sourceOffset, _sourceEnd)
.stripIndent
.stripDocComments
Expand Down