Skip to content

Commit 8690a2d

Browse files
authored
issue 64 hidden comments dont generate foldable blocks (#65)
* issue 64 hidden comments dont generate foldable blocks * issue 64. now foldable blocks consider all service comments * issue 64. removed unused function * fixed import * issue 64. fix pr comments * format line
1 parent c74ce56 commit 8690a2d

File tree

7 files changed

+136
-51
lines changed

7 files changed

+136
-51
lines changed

lib/src/code/code.dart

+11-40
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import '../hidden_ranges/hidden_ranges.dart';
1111
import '../issues/issue.dart';
1212
import '../named_sections/named_section.dart';
1313
import '../named_sections/parsers/abstract.dart';
14+
import '../service_comment_filter/service_comment_filter.dart';
1415
import '../single_line_comments/parser/single_line_comment_parser.dart';
1516
import '../single_line_comments/parser/single_line_comments.dart';
1617
import '../single_line_comments/single_line_comment.dart';
@@ -46,17 +47,12 @@ class Code {
4647
singleLineCommentSequences: sequences,
4748
);
4849

49-
final serviceComments = _filterServiceComments(
50+
final serviceComments = ServiceCommentFilter.filter(
5051
commentParser.comments,
5152
namedSectionParser: namedSectionParser,
5253
);
5354

54-
final lines = _textToCodeLines(
55-
text: text,
56-
highlighted: highlighted,
57-
language: language,
58-
commentsByLines: commentParser.getCommentsByLines(),
59-
);
55+
final serviceCommentsNodesSet = serviceComments.sources;
6056

6157
final issues = <Issue>[];
6258
final List<FoldableBlock> foldableBlocks;
@@ -65,7 +61,7 @@ class Code {
6561
foldableBlocks = const [];
6662
} else {
6763
final parser = HighlightFoldableBlockParser();
68-
parser.parse(highlighted);
64+
parser.parse(highlighted, serviceCommentsNodesSet);
6965
foldableBlocks = parser.blocks;
7066
issues.addAll(parser.invalidBlocks.map((b) => b.issue));
7167
}
@@ -76,6 +72,13 @@ class Code {
7672
const [];
7773
final sectionsMap = {for (final s in sections) s.name: s};
7874

75+
final lines = _textToCodeLines(
76+
text: text,
77+
highlighted: highlighted,
78+
language: language,
79+
commentsByLines: commentParser.getCommentsByLines(),
80+
);
81+
7982
_applyNamedSectionsToLines(
8083
lines: lines,
8184
sections: sectionsMap,
@@ -125,38 +128,6 @@ class Code {
125128
visibleText: '',
126129
);
127130

128-
static Iterable<SingleLineComment> _filterServiceComments(
129-
List<SingleLineComment> comments, {
130-
required AbstractNamedSectionParser? namedSectionParser,
131-
}) sync* {
132-
for (final comment in comments) {
133-
if (_isServiceComment(comment, namedSectionParser: namedSectionParser)) {
134-
yield comment;
135-
}
136-
}
137-
}
138-
139-
static bool _isServiceComment(
140-
SingleLineComment comment, {
141-
required AbstractNamedSectionParser? namedSectionParser,
142-
}) {
143-
final words = _getCommentWords(comment.innerContent);
144-
if (words.contains(Tokens.readonly)) {
145-
return true;
146-
}
147-
148-
if (namedSectionParser != null) {
149-
final namedSections = namedSectionParser.parseUnsorted(
150-
singleLineComments: [comment],
151-
);
152-
if (namedSections.isNotEmpty) {
153-
return true;
154-
}
155-
}
156-
157-
return false;
158-
}
159-
160131
static List<CodeLine> _textToCodeLines({
161132
required String text,
162133
required Result? highlighted,

lib/src/folding/parsers/highlight.dart

+20-10
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,25 @@ class HighlightFoldableBlockParser extends AbstractFoldableBlockParser {
3131
/// not a comment.
3232
bool _foundNonWhitespace = false;
3333

34-
void parse(Result highlighted) {
34+
void parse(Result highlighted, Set<Object?> serviceCommentsSources) {
3535
if (highlighted.nodes != null) {
36-
_processNodes(highlighted.nodes!);
36+
_processNodes(highlighted.nodes!, serviceCommentsSources);
3737
}
3838

3939
_submitLine(); // In case the last one did not end with '\n'.
4040
finalize();
4141
}
4242

43-
void _processNodes(List<Node> nodes) {
44-
nodes.forEach(_processNode);
43+
void _processNodes(List<Node> nodes, Set<Object?> serviceCommentsSources) {
44+
for (final node in nodes) {
45+
_processNode(node, serviceCommentsSources);
46+
}
4547
}
4648

47-
void _processNode(Node node) {
49+
void _processNode(Node node, Set<Object?> serviceCommentsSources) {
4850
switch (node.className) {
4951
case NodeClasses.comment:
50-
_processComment(node);
52+
_processComment(node, serviceCommentsSources);
5153
break;
5254

5355
case NodeClasses.keyword:
@@ -59,13 +61,21 @@ class HighlightFoldableBlockParser extends AbstractFoldableBlockParser {
5961
break;
6062

6163
default:
62-
_processDefault(node);
64+
_processDefault(node, serviceCommentsSources);
6365
}
6466
}
6567

66-
void _processComment(Node node) {
68+
void _processComment(Node node, Set<Object?> serviceComments) {
6769
final newlineCount = node.getNewlineCount();
6870

71+
if (_foundNonWhitespace) {
72+
return;
73+
}
74+
75+
if (serviceComments.contains(node)) {
76+
return;
77+
}
78+
6979
if (newlineCount == 0) {
7080
_foundSingleLineComment = true;
7181
return;
@@ -114,11 +124,11 @@ class HighlightFoldableBlockParser extends AbstractFoldableBlockParser {
114124
_lineIndex += newlineCount;
115125
}
116126

117-
void _processDefault(Node node) {
127+
void _processDefault(Node node, Set<Object?> serviceCommentsSources) {
118128
_processDefaultValue(node);
119129

120130
if (node.children != null) {
121-
_processNodes(node.children!);
131+
_processNodes(node.children!, serviceCommentsSources);
122132
}
123133
}
124134

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import '../../flutter_code_editor.dart';
2+
import '../single_line_comments/single_line_comment.dart';
3+
4+
class ServiceCommentFilter {
5+
static Iterable<SingleLineComment> filter(
6+
List<SingleLineComment> comments, {
7+
required AbstractNamedSectionParser? namedSectionParser,
8+
}) sync* {
9+
for (final comment in comments) {
10+
if (_isServiceComment(comment, namedSectionParser: namedSectionParser)) {
11+
yield comment;
12+
}
13+
}
14+
}
15+
16+
static bool _isServiceComment(
17+
SingleLineComment comment, {
18+
required AbstractNamedSectionParser? namedSectionParser,
19+
}) {
20+
final words = _getCommentWords(comment.innerContent);
21+
if (words.contains(Tokens.readonly)) {
22+
return true;
23+
}
24+
25+
if (namedSectionParser != null) {
26+
final namedSections = namedSectionParser.parseUnsorted(
27+
singleLineComments: [comment],
28+
);
29+
if (namedSections.isNotEmpty) {
30+
return true;
31+
}
32+
}
33+
34+
return false;
35+
}
36+
37+
static List<String> _getCommentWords(
38+
String? comment,
39+
) {
40+
// Split by any whitespaces.
41+
return comment?.split(RegExp(r'\s+')) ?? const <String>[];
42+
}
43+
}

lib/src/single_line_comments/parser/highlight_single_line_comment_parser.dart

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class HighlightSingleLineCommentParser extends AbstractSingleLineCommentParser {
3535
lineIndex: lineIndex,
3636
characterIndex: characterIndex,
3737
sequences: singleLineCommentSequences,
38+
source: node,
3839
),
3940
);
4041
}

lib/src/single_line_comments/parser/text_single_line_comment_parser.dart

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class TextSingleLineCommentParser extends AbstractSingleLineCommentParser {
3232
lineIndex: lineIndex,
3333
characterIndex: characterIndex + column,
3434
sequences: singleLineCommentSequences,
35+
source: line,
3536
),
3637
);
3738
}

lib/src/single_line_comments/single_line_comment.dart

+12
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@ class SingleLineComment {
1414
/// The comment text with the characters signifying the comment.
1515
final String outerContent;
1616

17+
/// The object this comment was parsed from, if any.
18+
///
19+
/// The object class is specific to the parser.
20+
final Object? source;
21+
1722
const SingleLineComment({
1823
required this.innerContent,
1924
required this.lineIndex,
2025
this.characterIndex = 0,
2126
this.outerContent = '',
27+
this.source,
2228
});
2329

2430
/// Creates the object from [outerContent] by extracting [innerContent]
@@ -28,6 +34,7 @@ class SingleLineComment {
2834
required int characterIndex,
2935
required int lineIndex,
3036
required List<String> sequences,
37+
Object? source,
3138
}) : this(
3239
characterIndex: characterIndex,
3340
innerContent: _cutSequence(
@@ -36,6 +43,7 @@ class SingleLineComment {
3643
),
3744
lineIndex: lineIndex,
3845
outerContent: outerContent,
46+
source: source,
3947
);
4048

4149
@override
@@ -71,3 +79,7 @@ class SingleLineComment {
7179
throw Exception('$outerContent does not start with any of $sequences');
7280
}
7381
}
82+
83+
extension SingleLineCommentIterable on Iterable<SingleLineComment> {
84+
Set<Object?> get sources => {...map((e) => e.source)};
85+
}

test/src/folding/parsers/highlight_parser_test.dart

+48-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import 'package:flutter_code_editor/flutter_code_editor.dart';
2+
import 'package:flutter_code_editor/src/service_comment_filter/service_comment_filter.dart';
3+
import 'package:flutter_code_editor/src/single_line_comments/parser/single_line_comment_parser.dart';
4+
import 'package:flutter_code_editor/src/single_line_comments/parser/single_line_comments.dart';
5+
import 'package:flutter_code_editor/src/single_line_comments/single_line_comment.dart';
26
import 'package:flutter_test/flutter_test.dart';
37
import 'package:highlight/highlight.dart';
48
import 'package:highlight/languages/java.dart';
@@ -177,14 +181,57 @@ import java.lang.Exception;''',
177181
],
178182
expectedInvalid: const [],
179183
),
184+
185+
_Example(
186+
'Java. Comment after a closing brace',
187+
code: '''
188+
class MyClass {
189+
void method() {
190+
}// comment
191+
// comment
192+
}''',
193+
mode: java,
194+
expected: const [
195+
_FB(startLine: 0, endLine: 4, type: _T.braces),
196+
_FB(startLine: 1, endLine: 2, type: _T.braces),
197+
],
198+
expectedInvalid: const [],
199+
),
200+
201+
_Example(
202+
'Java. Service comment sequences do not form a foldable block.',
203+
code: '''
204+
class MyClass {
205+
// [START section1]
206+
// [END section2]
207+
}''',
208+
mode: java,
209+
expected: const [
210+
_FB(startLine: 0, endLine: 3, type: _T.braces),
211+
],
212+
expectedInvalid: const [],
213+
),
180214
];
181215

182216
for (final example in examples) {
183217
highlight.registerLanguage('language', example.mode);
184218
final highlighted = highlight.parse(example.code, language: 'language');
185219
final parser = HighlightFoldableBlockParser();
186220

187-
parser.parse(highlighted);
221+
final sequences = SingleLineComments.byMode[example.mode] ?? [];
222+
223+
final commentParser = SingleLineCommentParser.parseHighlighted(
224+
text: example.code,
225+
highlighted: highlighted,
226+
singleLineCommentSequences: sequences,
227+
);
228+
229+
final serviceComments = ServiceCommentFilter.filter(
230+
commentParser.comments,
231+
namedSectionParser: const BracketsStartEndNamedSectionParser(),
232+
);
233+
234+
parser.parse(highlighted, serviceComments.sources);
188235

189236
expect(
190237
parser.blocks,

0 commit comments

Comments
 (0)