mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 11:42:11 +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>
|
<body>
|
||||||
<h1>Analysis Server API Specification</h1>
|
<h1>Analysis Server API Specification</h1>
|
||||||
<h1 style="color:#999999">Version
|
<h1 style="color:#999999">Version
|
||||||
1.27.4
|
1.28.0
|
||||||
</h1>
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
This document contains a specification of the API provided by the
|
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.
|
An enumeration of the kinds of folding regions.
|
||||||
</p>
|
</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>
|
<p>
|
||||||
A description of a region that can be folded.
|
A description of a region that can be folded.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// To regenerate the file, use the script
|
// To regenerate the file, use the script
|
||||||
// "pkg/analysis_server/tool/spec/generate_files".
|
// "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 = 'analysis.analyzedFiles';
|
||||||
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
|
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
|
||||||
|
|
|
@ -19,6 +19,35 @@ class DartUnitFoldingComputer {
|
||||||
|
|
||||||
DartUnitFoldingComputer(this._lineInfo, this._unit);
|
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`.
|
/// Returns a list of folding regions, not `null`.
|
||||||
List<FoldingRegion> compute() {
|
List<FoldingRegion> compute() {
|
||||||
_addFileHeaderRegion();
|
_addFileHeaderRegion();
|
||||||
|
@ -181,6 +210,17 @@ class _DartUnitFoldingComputerVisitor extends RecursiveAstVisitor<void> {
|
||||||
super.visitFunctionExpressionInvocation(node);
|
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
|
@override
|
||||||
void visitImportDirective(ImportDirective node) {
|
void visitImportDirective(ImportDirective node) {
|
||||||
_computer._recordDirective(node);
|
_computer._recordDirective(node);
|
||||||
|
|
|
@ -701,6 +701,7 @@ final Matcher isFlutterWidgetPropertyValueEnumItem = LazyMatcher(() =>
|
||||||
///
|
///
|
||||||
/// enum {
|
/// enum {
|
||||||
/// ANNOTATIONS
|
/// ANNOTATIONS
|
||||||
|
/// BLOCK
|
||||||
/// CLASS_BODY
|
/// CLASS_BODY
|
||||||
/// DIRECTIVES
|
/// DIRECTIVES
|
||||||
/// DOCUMENTATION_COMMENT
|
/// DOCUMENTATION_COMMENT
|
||||||
|
@ -711,6 +712,7 @@ final Matcher isFlutterWidgetPropertyValueEnumItem = LazyMatcher(() =>
|
||||||
/// }
|
/// }
|
||||||
final Matcher isFoldingKind = MatchesEnum('FoldingKind', [
|
final Matcher isFoldingKind = MatchesEnum('FoldingKind', [
|
||||||
'ANNOTATIONS',
|
'ANNOTATIONS',
|
||||||
|
'BLOCK',
|
||||||
'CLASS_BODY',
|
'CLASS_BODY',
|
||||||
'DIRECTIVES',
|
'DIRECTIVES',
|
||||||
'DOCUMENTATION_COMMENT',
|
'DOCUMENTATION_COMMENT',
|
||||||
|
|
|
@ -162,6 +162,40 @@ class FoldingTest extends AbstractLspAnalysisServerTest {
|
||||||
expect(regions, unorderedEquals(expectedRegions));
|
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 {
|
Future<void> test_nonDartFile() async {
|
||||||
await initialize();
|
await initialize();
|
||||||
await openFile(pubspecFileUri, simplePubspecContent);
|
await openFile(pubspecFileUri, simplePubspecContent);
|
||||||
|
|
|
@ -17,6 +17,8 @@ public class FoldingKind {
|
||||||
|
|
||||||
public static final String ANNOTATIONS = "ANNOTATIONS";
|
public static final String ANNOTATIONS = "ANNOTATIONS";
|
||||||
|
|
||||||
|
public static final String BLOCK = "BLOCK";
|
||||||
|
|
||||||
public static final String CLASS_BODY = "CLASS_BODY";
|
public static final String CLASS_BODY = "CLASS_BODY";
|
||||||
|
|
||||||
public static final String DIRECTIVES = "DIRECTIVES";
|
public static final String DIRECTIVES = "DIRECTIVES";
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<body>
|
<body>
|
||||||
<h1>Analysis Server API Specification</h1>
|
<h1>Analysis Server API Specification</h1>
|
||||||
<h1 style="color:#999999">Version
|
<h1 style="color:#999999">Version
|
||||||
<version>1.27.4</version>
|
<version>1.28.0</version>
|
||||||
</h1>
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
This document contains a specification of the API provided by the
|
This document contains a specification of the API provided by the
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// To regenerate the file, use the script
|
// To regenerate the file, use the script
|
||||||
// "pkg/analysis_server/tool/spec/generate_files".
|
// "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 = 'analysis.analyzedFiles';
|
||||||
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
|
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
|
||||||
|
|
|
@ -1306,7 +1306,7 @@ a:focus, a:hover {
|
||||||
An enumeration of the kinds of folding regions.
|
An enumeration of the kinds of folding regions.
|
||||||
</p>
|
</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>
|
<p>
|
||||||
A description of a region that can be folded.
|
A description of a region that can be folded.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -1894,6 +1894,7 @@ class ElementKind implements Enum {
|
||||||
///
|
///
|
||||||
/// enum {
|
/// enum {
|
||||||
/// ANNOTATIONS
|
/// ANNOTATIONS
|
||||||
|
/// BLOCK
|
||||||
/// CLASS_BODY
|
/// CLASS_BODY
|
||||||
/// DIRECTIVES
|
/// DIRECTIVES
|
||||||
/// DOCUMENTATION_COMMENT
|
/// DOCUMENTATION_COMMENT
|
||||||
|
@ -1907,6 +1908,8 @@ class ElementKind implements Enum {
|
||||||
class FoldingKind implements Enum {
|
class FoldingKind implements Enum {
|
||||||
static const FoldingKind ANNOTATIONS = FoldingKind._('ANNOTATIONS');
|
static const FoldingKind ANNOTATIONS = FoldingKind._('ANNOTATIONS');
|
||||||
|
|
||||||
|
static const FoldingKind BLOCK = FoldingKind._('BLOCK');
|
||||||
|
|
||||||
static const FoldingKind CLASS_BODY = FoldingKind._('CLASS_BODY');
|
static const FoldingKind CLASS_BODY = FoldingKind._('CLASS_BODY');
|
||||||
|
|
||||||
static const FoldingKind DIRECTIVES = FoldingKind._('DIRECTIVES');
|
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.
|
/// A list containing all of the enum values that are defined.
|
||||||
static const List<FoldingKind> VALUES = <FoldingKind>[
|
static const List<FoldingKind> VALUES = <FoldingKind>[
|
||||||
ANNOTATIONS,
|
ANNOTATIONS,
|
||||||
|
BLOCK,
|
||||||
CLASS_BODY,
|
CLASS_BODY,
|
||||||
DIRECTIVES,
|
DIRECTIVES,
|
||||||
DOCUMENTATION_COMMENT,
|
DOCUMENTATION_COMMENT,
|
||||||
|
@ -1943,6 +1947,8 @@ class FoldingKind implements Enum {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'ANNOTATIONS':
|
case 'ANNOTATIONS':
|
||||||
return ANNOTATIONS;
|
return ANNOTATIONS;
|
||||||
|
case 'BLOCK':
|
||||||
|
return BLOCK;
|
||||||
case 'CLASS_BODY':
|
case 'CLASS_BODY':
|
||||||
return CLASS_BODY;
|
return CLASS_BODY;
|
||||||
case 'DIRECTIVES':
|
case 'DIRECTIVES':
|
||||||
|
|
|
@ -301,6 +301,7 @@ final Matcher isFilePath = isString;
|
||||||
///
|
///
|
||||||
/// enum {
|
/// enum {
|
||||||
/// ANNOTATIONS
|
/// ANNOTATIONS
|
||||||
|
/// BLOCK
|
||||||
/// CLASS_BODY
|
/// CLASS_BODY
|
||||||
/// DIRECTIVES
|
/// DIRECTIVES
|
||||||
/// DOCUMENTATION_COMMENT
|
/// DOCUMENTATION_COMMENT
|
||||||
|
@ -311,6 +312,7 @@ final Matcher isFilePath = isString;
|
||||||
/// }
|
/// }
|
||||||
final Matcher isFoldingKind = MatchesEnum('FoldingKind', [
|
final Matcher isFoldingKind = MatchesEnum('FoldingKind', [
|
||||||
'ANNOTATIONS',
|
'ANNOTATIONS',
|
||||||
|
'BLOCK',
|
||||||
'CLASS_BODY',
|
'CLASS_BODY',
|
||||||
'DIRECTIVES',
|
'DIRECTIVES',
|
||||||
'DOCUMENTATION_COMMENT',
|
'DOCUMENTATION_COMMENT',
|
||||||
|
|
|
@ -569,6 +569,7 @@
|
||||||
</p>
|
</p>
|
||||||
<enum>
|
<enum>
|
||||||
<value><code>ANNOTATIONS</code></value>
|
<value><code>ANNOTATIONS</code></value>
|
||||||
|
<value><code>BLOCK</code></value>
|
||||||
<value><code>CLASS_BODY</code></value>
|
<value><code>CLASS_BODY</code></value>
|
||||||
<value><code>DIRECTIVES</code></value>
|
<value><code>DIRECTIVES</code></value>
|
||||||
<value><code>DOCUMENTATION_COMMENT</code></value>
|
<value><code>DOCUMENTATION_COMMENT</code></value>
|
||||||
|
|
Loading…
Reference in a new issue