mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 11:31:57 +00:00
Add support for folding if/else/elseif blocks
Change-Id: I3cbf1f282ee59c577c6ba912e957f838e827fd3e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151520 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
90613154e5
commit
f0e1f32c87
|
@ -109,7 +109,7 @@ a:focus, a:hover {
|
|||
<body>
|
||||
<h1>Analysis Server API Specification</h1>
|
||||
<h1 style="color:#999999">Version
|
||||
1.27.4
|
||||
1.28.0
|
||||
</h1>
|
||||
<p>
|
||||
This document contains a specification of the API provided by the
|
||||
|
@ -4170,7 +4170,7 @@ a:focus, a:hover {
|
|||
An enumeration of the kinds of folding regions.
|
||||
</p>
|
||||
|
||||
<dl><dt class="value">ANNOTATIONS</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
|
||||
<dl><dt class="value">ANNOTATIONS</dt><dt class="value">BLOCK</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
|
||||
<p>
|
||||
A description of a region that can be folded.
|
||||
</p>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// To regenerate the file, use the script
|
||||
// "pkg/analysis_server/tool/spec/generate_files".
|
||||
|
||||
const String PROTOCOL_VERSION = '1.27.4';
|
||||
const String PROTOCOL_VERSION = '1.28.0';
|
||||
|
||||
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
|
||||
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
|
||||
|
|
|
@ -19,6 +19,35 @@ class DartUnitFoldingComputer {
|
|||
|
||||
DartUnitFoldingComputer(this._lineInfo, this._unit);
|
||||
|
||||
void addRegionForConditionalBlock(Block block) {
|
||||
// For class/function/method blocks, we usually include the whitespace up
|
||||
// until the `}` in the folding region so that when collapsed they would
|
||||
// look like:
|
||||
//
|
||||
// class Foo { [...] }
|
||||
//
|
||||
// For if statements, they may have else/elseIfs which would result in long
|
||||
// lines like:
|
||||
//
|
||||
// if (cond) { [...] } else { [...] }
|
||||
//
|
||||
// So these types of blocks should have their folding regions end at the
|
||||
// end of the preceeding statement.
|
||||
|
||||
final start = block.leftBracket.end;
|
||||
if (block.endToken.precedingComments != null) {
|
||||
// If there are comments before the end token, use the last of those.
|
||||
var lastComment = block.endToken.precedingComments;
|
||||
while (lastComment.next != null) {
|
||||
lastComment = lastComment.next;
|
||||
}
|
||||
_addRegion(start, lastComment.end, FoldingKind.BLOCK);
|
||||
} else if (block.statements.isNotEmpty) {
|
||||
// Otherwise, use the end of the last statement.
|
||||
_addRegion(start, block.statements.last.end, FoldingKind.BLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a list of folding regions, not `null`.
|
||||
List<FoldingRegion> compute() {
|
||||
_addFileHeaderRegion();
|
||||
|
@ -181,6 +210,17 @@ class _DartUnitFoldingComputerVisitor extends RecursiveAstVisitor<void> {
|
|||
super.visitFunctionExpressionInvocation(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitIfStatement(IfStatement node) {
|
||||
if (node.thenStatement is Block) {
|
||||
_computer.addRegionForConditionalBlock(node.thenStatement);
|
||||
}
|
||||
if (node.elseStatement is Block) {
|
||||
_computer.addRegionForConditionalBlock(node.elseStatement);
|
||||
}
|
||||
super.visitIfStatement(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitImportDirective(ImportDirective node) {
|
||||
_computer._recordDirective(node);
|
||||
|
|
|
@ -701,6 +701,7 @@ final Matcher isFlutterWidgetPropertyValueEnumItem = LazyMatcher(() =>
|
|||
///
|
||||
/// enum {
|
||||
/// ANNOTATIONS
|
||||
/// BLOCK
|
||||
/// CLASS_BODY
|
||||
/// DIRECTIVES
|
||||
/// DOCUMENTATION_COMMENT
|
||||
|
@ -711,6 +712,7 @@ final Matcher isFlutterWidgetPropertyValueEnumItem = LazyMatcher(() =>
|
|||
/// }
|
||||
final Matcher isFoldingKind = MatchesEnum('FoldingKind', [
|
||||
'ANNOTATIONS',
|
||||
'BLOCK',
|
||||
'CLASS_BODY',
|
||||
'DIRECTIVES',
|
||||
'DOCUMENTATION_COMMENT',
|
||||
|
|
|
@ -162,6 +162,40 @@ class FoldingTest extends AbstractLspAnalysisServerTest {
|
|||
expect(regions, unorderedEquals(expectedRegions));
|
||||
}
|
||||
|
||||
Future<void> test_ifElseElseIf() async {
|
||||
final content = '''
|
||||
f(int i) {
|
||||
if (i == 0) {[[
|
||||
// only
|
||||
// comments]]
|
||||
} else if (i == 1) {[[
|
||||
print('statements');]]
|
||||
} else if (i == 2) {
|
||||
} else {[[
|
||||
// else
|
||||
// comments]]
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
final ranges = rangesFromMarkers(content);
|
||||
final expectedRegions = ranges
|
||||
.map((range) => FoldingRange(
|
||||
range.start.line,
|
||||
range.start.character,
|
||||
range.end.line,
|
||||
range.end.character,
|
||||
null,
|
||||
))
|
||||
.toList();
|
||||
|
||||
await initialize();
|
||||
await openFile(mainFileUri, withoutMarkers(content));
|
||||
|
||||
final regions = await getFoldingRegions(mainFileUri);
|
||||
expect(regions, containsAll(expectedRegions));
|
||||
}
|
||||
|
||||
Future<void> test_nonDartFile() async {
|
||||
await initialize();
|
||||
await openFile(pubspecFileUri, simplePubspecContent);
|
||||
|
|
|
@ -17,6 +17,8 @@ public class FoldingKind {
|
|||
|
||||
public static final String ANNOTATIONS = "ANNOTATIONS";
|
||||
|
||||
public static final String BLOCK = "BLOCK";
|
||||
|
||||
public static final String CLASS_BODY = "CLASS_BODY";
|
||||
|
||||
public static final String DIRECTIVES = "DIRECTIVES";
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<body>
|
||||
<h1>Analysis Server API Specification</h1>
|
||||
<h1 style="color:#999999">Version
|
||||
<version>1.27.4</version>
|
||||
<version>1.28.0</version>
|
||||
</h1>
|
||||
<p>
|
||||
This document contains a specification of the API provided by the
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// To regenerate the file, use the script
|
||||
// "pkg/analysis_server/tool/spec/generate_files".
|
||||
|
||||
const String PROTOCOL_VERSION = '1.27.4';
|
||||
const String PROTOCOL_VERSION = '1.28.0';
|
||||
|
||||
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
|
||||
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
|
||||
|
|
|
@ -1306,7 +1306,7 @@ a:focus, a:hover {
|
|||
An enumeration of the kinds of folding regions.
|
||||
</p>
|
||||
|
||||
<dl><dt class="value">ANNOTATIONS</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
|
||||
<dl><dt class="value">ANNOTATIONS</dt><dt class="value">BLOCK</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
|
||||
<p>
|
||||
A description of a region that can be folded.
|
||||
</p>
|
||||
|
|
|
@ -1894,6 +1894,7 @@ class ElementKind implements Enum {
|
|||
///
|
||||
/// enum {
|
||||
/// ANNOTATIONS
|
||||
/// BLOCK
|
||||
/// CLASS_BODY
|
||||
/// DIRECTIVES
|
||||
/// DOCUMENTATION_COMMENT
|
||||
|
@ -1907,6 +1908,8 @@ class ElementKind implements Enum {
|
|||
class FoldingKind implements Enum {
|
||||
static const FoldingKind ANNOTATIONS = FoldingKind._('ANNOTATIONS');
|
||||
|
||||
static const FoldingKind BLOCK = FoldingKind._('BLOCK');
|
||||
|
||||
static const FoldingKind CLASS_BODY = FoldingKind._('CLASS_BODY');
|
||||
|
||||
static const FoldingKind DIRECTIVES = FoldingKind._('DIRECTIVES');
|
||||
|
@ -1925,6 +1928,7 @@ class FoldingKind implements Enum {
|
|||
/// A list containing all of the enum values that are defined.
|
||||
static const List<FoldingKind> VALUES = <FoldingKind>[
|
||||
ANNOTATIONS,
|
||||
BLOCK,
|
||||
CLASS_BODY,
|
||||
DIRECTIVES,
|
||||
DOCUMENTATION_COMMENT,
|
||||
|
@ -1943,6 +1947,8 @@ class FoldingKind implements Enum {
|
|||
switch (name) {
|
||||
case 'ANNOTATIONS':
|
||||
return ANNOTATIONS;
|
||||
case 'BLOCK':
|
||||
return BLOCK;
|
||||
case 'CLASS_BODY':
|
||||
return CLASS_BODY;
|
||||
case 'DIRECTIVES':
|
||||
|
|
|
@ -301,6 +301,7 @@ final Matcher isFilePath = isString;
|
|||
///
|
||||
/// enum {
|
||||
/// ANNOTATIONS
|
||||
/// BLOCK
|
||||
/// CLASS_BODY
|
||||
/// DIRECTIVES
|
||||
/// DOCUMENTATION_COMMENT
|
||||
|
@ -311,6 +312,7 @@ final Matcher isFilePath = isString;
|
|||
/// }
|
||||
final Matcher isFoldingKind = MatchesEnum('FoldingKind', [
|
||||
'ANNOTATIONS',
|
||||
'BLOCK',
|
||||
'CLASS_BODY',
|
||||
'DIRECTIVES',
|
||||
'DOCUMENTATION_COMMENT',
|
||||
|
|
|
@ -569,6 +569,7 @@
|
|||
</p>
|
||||
<enum>
|
||||
<value><code>ANNOTATIONS</code></value>
|
||||
<value><code>BLOCK</code></value>
|
||||
<value><code>CLASS_BODY</code></value>
|
||||
<value><code>DIRECTIVES</code></value>
|
||||
<value><code>DOCUMENTATION_COMMENT</code></value>
|
||||
|
|
Loading…
Reference in a new issue