Skip to content

Commit adc5a45

Browse files
authored
Move source-manipulating code from model_utils to model_node (dart-lang#3074)
1 parent bf7cf51 commit adc5a45

File tree

6 files changed

+155
-125
lines changed

6 files changed

+155
-125
lines changed

lib/src/generator/templates.runtime_renderers.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9941,7 +9941,7 @@ class _Renderer_ModelElement extends RendererBase<ModelElement> {
99419941
List<String> remainingNames) =>
99429942
self.renderSimpleVariable(
99439943
c, remainingNames, 'CompilationUnitElement'),
9944-
isNullValue: (CT_ c) => c.compilationUnitElement == null,
9944+
isNullValue: (CT_ c) => false,
99459945
renderValue: (CT_ c, RendererBase<CT_> r,
99469946
List<MustachioNode> ast, StringSink sink) {
99479947
renderSimple(

lib/src/model/model_element.dart

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -671,18 +671,19 @@ abstract class ModelElement extends Canonicalization
671671

672672
@override
673673
late final CharacterLocation? characterLocation = () {
674-
var lineInfo = compilationUnitElement!.lineInfo;
675-
assert(element!.nameOffset >= 0,
674+
final lineInfo = compilationUnitElement.lineInfo;
675+
late final element = this.element!;
676+
assert(element.nameOffset >= 0,
676677
'Invalid location data for element: $fullyQualifiedName');
677-
var nameOffset = element!.nameOffset;
678+
var nameOffset = element.nameOffset;
678679
if (nameOffset >= 0) {
679680
return lineInfo.getLocation(nameOffset);
680681
}
681682
return null;
682683
}();
683684

684-
CompilationUnitElement? get compilationUnitElement =>
685-
element!.thisOrAncestorOfType<CompilationUnitElement>();
685+
CompilationUnitElement get compilationUnitElement =>
686+
element!.thisOrAncestorOfType<CompilationUnitElement>()!;
686687

687688
bool get hasAnnotations => annotations.isNotEmpty;
688689

lib/src/model/model_node.dart

Lines changed: 86 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:convert';
6+
57
import 'package:analyzer/dart/ast/ast.dart';
68
import 'package:analyzer/dart/element/element.dart';
79
import 'package:analyzer/file_system/file_system.dart';
810
import 'package:dartdoc/src/comment_references/model_comment_reference.dart';
911
import 'package:dartdoc/src/model_utils.dart' as model_utils;
12+
import 'package:meta/meta.dart';
1013

1114
/// Stripped down information derived from [AstNode] containing only information
1215
/// needed for Dartdoc. Drops link to the [AstNode] after construction.
@@ -20,13 +23,13 @@ class ModelNode {
2023
factory ModelNode(
2124
AstNode? sourceNode, Element element, ResourceProvider resourceProvider) {
2225
var commentRefs = _commentRefsFor(sourceNode, resourceProvider);
23-
// Get a node higher up the syntax tree that includes the semicolon.
24-
// In this case, it is either a [FieldDeclaration] or
25-
// [TopLevelVariableDeclaration]. (#2401)
2626
if (sourceNode == null) {
2727
return ModelNode._(element, resourceProvider, commentRefs,
2828
sourceEnd: -1, sourceOffset: -1);
2929
} else {
30+
// Get a node higher up the syntax tree that includes the semicolon.
31+
// In this case, it is either a [FieldDeclaration] or
32+
// [TopLevelVariableDeclaration]. (#2401)
3033
if (sourceNode is VariableDeclaration) {
3134
sourceNode = sourceNode.parent!.parent!;
3235
assert(sourceNode is FieldDeclaration ||
@@ -56,28 +59,94 @@ class ModelNode {
5659
return const [];
5760
}
5861

59-
late final String sourceCode = () {
60-
if (_sourceEnd < 0 || _sourceOffset < 0) {
61-
return '';
62-
}
62+
bool get _isSynthetic => _sourceEnd < 0 || _sourceOffset < 0;
6363

64-
var contents = model_utils.getFileContentsFor(element, resourceProvider);
65-
// Find the start of the line, so that we can line up all of the indents.
66-
var i = _sourceOffset;
64+
/// The text of the source code of this node, stripped of the leading
65+
/// indentation, and stripped of the doc comments.
66+
late final String sourceCode = _isSynthetic
67+
? ''
68+
: model_utils
69+
.getFileContentsFor(element, resourceProvider)
70+
.substringFromLineStart(_sourceOffset, _sourceEnd)
71+
.stripIndent
72+
.stripDocComments
73+
.trim();
74+
}
75+
76+
@visibleForTesting
77+
extension SourceStringExtensions on String {
78+
String substringFromLineStart(int offset, int endOffset) {
79+
var lineStartOffset = startOfLineWithOffset(offset);
80+
return substring(lineStartOffset, endOffset);
81+
}
82+
83+
// Finds the start of the line which contains the character at [offset].
84+
int startOfLineWithOffset(int offset) {
85+
var i = offset;
86+
// Walk backwards until we find the previous line's EOL character.
6787
while (i > 0) {
6888
i -= 1;
69-
if (contents[i] == '\n' || contents[i] == '\r') {
89+
if (this[i] == '\n' || this[i] == '\r') {
7090
i += 1;
7191
break;
7292
}
7393
}
94+
return i;
95+
}
7496

75-
// Trim the common indent from the source snippet.
76-
var source = contents.substring(i, _sourceEnd);
97+
/// Strips leading doc comments from the given source code.
98+
String get stripDocComments {
99+
var remainder = trimLeft();
100+
var lineComments = remainder.startsWith(_tripleSlash) ||
101+
remainder.startsWith(_escapedTripleSlash);
102+
var blockComments = remainder.startsWith(_slashStarStar) ||
103+
remainder.startsWith(_escapedSlashStarStar);
104+
105+
return split('\n').where((String line) {
106+
if (lineComments) {
107+
if (line.startsWith(_tripleSlash) ||
108+
line.startsWith(_escapedTripleSlash)) {
109+
return false;
110+
}
111+
lineComments = false;
112+
return true;
113+
} else if (blockComments) {
114+
if (line.contains(_starSlash) || line.contains(_escapedStarSlash)) {
115+
blockComments = false;
116+
return false;
117+
}
118+
if (line.startsWith(_slashStarStar) ||
119+
line.startsWith(_escapedSlashStarStar)) {
120+
return false;
121+
}
122+
return false;
123+
}
77124

78-
source = model_utils.stripIndentFromSource(source);
79-
source = model_utils.stripDartdocCommentsFromSource(source);
125+
return true;
126+
}).join('\n');
127+
}
80128

81-
return source.trim();
82-
}();
129+
/// Strips the common indent from the given source fragment.
130+
String get stripIndent {
131+
var remainder = trimLeft();
132+
var indent = substring(0, length - remainder.length);
133+
return split('\n').map((line) {
134+
line = line.trimRight();
135+
return line.startsWith(indent) ? line.substring(indent.length) : line;
136+
}).join('\n');
137+
}
83138
}
139+
140+
const HtmlEscape _escape = HtmlEscape();
141+
142+
const String _tripleSlash = '///';
143+
144+
final String _escapedTripleSlash = _escape.convert(_tripleSlash);
145+
146+
const String _slashStarStar = '/**';
147+
148+
final String _escapedSlashStarStar = _escape.convert(_slashStarStar);
149+
150+
const String _starSlash = '*/';
151+
152+
final String _escapedStarSlash = _escape.convert(_starSlash);

lib/src/model_utils.dart

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
library dartdoc.model_utils;
66

7-
import 'dart:convert';
87
import 'dart:io' show Platform;
98

109
import 'package:analyzer/dart/element/element.dart';
@@ -125,59 +124,3 @@ bool hasPrivateName(Element e) {
125124
}
126125

127126
bool hasPublicName(Element e) => !hasPrivateName(e);
128-
129-
/// Strip leading dartdoc comments from the given source code.
130-
String stripDartdocCommentsFromSource(String source) {
131-
var remainder = source.trimLeft();
132-
var lineComments = remainder.startsWith(_tripleSlash) ||
133-
remainder.startsWith(_escapedTripleSlash);
134-
var blockComments = remainder.startsWith(_slashStarStar) ||
135-
remainder.startsWith(_escapedSlashStarStar);
136-
137-
return source.split('\n').where((String line) {
138-
if (lineComments) {
139-
if (line.startsWith(_tripleSlash) ||
140-
line.startsWith(_escapedTripleSlash)) {
141-
return false;
142-
}
143-
lineComments = false;
144-
return true;
145-
} else if (blockComments) {
146-
if (line.contains(_starSlash) || line.contains(_escapedStarSlash)) {
147-
blockComments = false;
148-
return false;
149-
}
150-
if (line.startsWith(_slashStarStar) ||
151-
line.startsWith(_escapedSlashStarStar)) {
152-
return false;
153-
}
154-
return false;
155-
}
156-
157-
return true;
158-
}).join('\n');
159-
}
160-
161-
const HtmlEscape _escape = HtmlEscape();
162-
163-
const String _tripleSlash = '///';
164-
165-
final String _escapedTripleSlash = _escape.convert(_tripleSlash);
166-
167-
const String _slashStarStar = '/**';
168-
169-
final String _escapedSlashStarStar = _escape.convert(_slashStarStar);
170-
171-
const String _starSlash = '*/';
172-
173-
final String _escapedStarSlash = _escape.convert(_starSlash);
174-
175-
/// Strip the common indent from the given source fragment.
176-
String stripIndentFromSource(String source) {
177-
var remainder = source.trimLeft();
178-
var indent = source.substring(0, source.length - remainder.length);
179-
return source.split('\n').map((line) {
180-
line = line.trimRight();
181-
return line.startsWith(indent) ? line.substring(indent.length) : line;
182-
}).join('\n');
183-
}

test/model_node_test.dart

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:dartdoc/src/model/model_node.dart' show SourceStringExtensions;
6+
import 'package:test/test.dart';
7+
8+
void main() {
9+
group('model_utils stripIndentFromSource', () {
10+
test('no indent', () {
11+
expect(
12+
'void foo() {\n print(1);\n}\n'.stripIndent,
13+
'void foo() {\n print(1);\n}\n',
14+
);
15+
});
16+
17+
test('same indent', () {
18+
expect(
19+
' void foo() {\n print(1);\n }\n'.stripIndent,
20+
'void foo() {\n print(1);\n}\n',
21+
);
22+
});
23+
24+
test('odd indent', () {
25+
expect(
26+
' void foo() {\n print(1);\n }\n'.stripIndent,
27+
'void foo() {\n print(1);\n}\n',
28+
);
29+
});
30+
});
31+
32+
group('model_utils stripDartdocCommentsFromSource', () {
33+
test('no comments', () {
34+
expect(
35+
'void foo() {\n print(1);\n}\n'.stripDocComments,
36+
'void foo() {\n print(1);\n}\n',
37+
);
38+
});
39+
40+
test('line comments', () {
41+
expect(
42+
'/// foo comment\nvoid foo() {\n print(1);\n}\n'.stripDocComments,
43+
'void foo() {\n print(1);\n}\n',
44+
);
45+
});
46+
47+
test('block comments 1', () {
48+
expect(
49+
'/** foo comment */\nvoid foo() {\n print(1);\n}\n'.stripDocComments,
50+
'void foo() {\n print(1);\n}\n',
51+
);
52+
});
53+
54+
test('block comments 2', () {
55+
expect(
56+
'/**\n * foo comment\n */\nvoid foo() {\n print(1);\n}\n'
57+
.stripDocComments,
58+
'void foo() {\n print(1);\n}\n',
59+
);
60+
});
61+
});
62+
}

test/model_utils_test.dart

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -23,49 +23,4 @@ void main() {
2323
expect(matchGlobs([r'C:\a\b\*'], r'D:\a\b\d', isWindows: true), isFalse);
2424
});
2525
});
26-
27-
group('model_utils stripIndentFromSource', () {
28-
test('no indent', () {
29-
expect(stripIndentFromSource('void foo() {\n print(1);\n}\n'),
30-
'void foo() {\n print(1);\n}\n');
31-
});
32-
33-
test('same indent', () {
34-
expect(stripIndentFromSource(' void foo() {\n print(1);\n }\n'),
35-
'void foo() {\n print(1);\n}\n');
36-
});
37-
38-
test('odd indent', () {
39-
expect(stripIndentFromSource(' void foo() {\n print(1);\n }\n'),
40-
'void foo() {\n print(1);\n}\n');
41-
});
42-
});
43-
44-
group('model_utils stripDartdocCommentsFromSource', () {
45-
test('no comments', () {
46-
expect(stripDartdocCommentsFromSource('void foo() {\n print(1);\n}\n'),
47-
'void foo() {\n print(1);\n}\n');
48-
});
49-
50-
test('line comments', () {
51-
expect(
52-
stripDartdocCommentsFromSource(
53-
'/// foo comment\nvoid foo() {\n print(1);\n}\n'),
54-
'void foo() {\n print(1);\n}\n');
55-
});
56-
57-
test('block comments 1', () {
58-
expect(
59-
stripDartdocCommentsFromSource(
60-
'/** foo comment */\nvoid foo() {\n print(1);\n}\n'),
61-
'void foo() {\n print(1);\n}\n');
62-
});
63-
64-
test('block comments 2', () {
65-
expect(
66-
stripDartdocCommentsFromSource(
67-
'/**\n * foo comment\n */\nvoid foo() {\n print(1);\n}\n'),
68-
'void foo() {\n print(1);\n}\n');
69-
});
70-
});
7126
}

0 commit comments

Comments
 (0)