| // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'package:analysis_server/src/computer/computer_folding.dart'; |
| import 'package:analysis_server/src/protocol_server.dart'; |
| import 'package:analyzer/src/test_utilities/test_code_format.dart'; |
| import 'package:test/test.dart'; |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| |
| import '../../abstract_context.dart'; |
| |
| void main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(FoldingComputerTest); |
| }); |
| } |
| |
| @reflectiveTest |
| class FoldingComputerTest extends AbstractContextTest { |
| static const commentKinds = { |
| FoldingKind.FILE_HEADER, |
| FoldingKind.COMMENT, |
| FoldingKind.DOCUMENTATION_COMMENT, |
| }; |
| |
| late String sourcePath; |
| late TestCode code; |
| List<FoldingRegion> regions = []; |
| |
| /// Expects no [FoldingRegion]s. |
| /// |
| /// If [onlyVerify] is provided, folding regions of other kinds are allowed. |
| void expectNoRegions({Set<FoldingKind>? onlyVerify}) { |
| expectRegions({}, onlyVerify: onlyVerify); |
| } |
| |
| /// Expects to find a [FoldingRegion] for the code marked [index] with a |
| /// [FoldingKind] of [kind]. |
| /// |
| /// If [onlyVerify] is provided, only folding regions with matching kinds will |
| /// be verified. |
| void expectRegions( |
| Map<int, FoldingKind> expected, { |
| Set<FoldingKind>? onlyVerify, |
| }) { |
| var expectedRegions = |
| expected.entries.map((entry) { |
| var range = code.ranges[entry.key].sourceRange; |
| return FoldingRegion(entry.value, range.offset, range.length); |
| }).toSet(); |
| |
| var actualRegions = |
| onlyVerify == null |
| ? regions.toSet() |
| : regions |
| .where((region) => onlyVerify.contains(region.kind)) |
| .toSet(); |
| |
| expect(actualRegions, expectedRegions); |
| } |
| |
| @override |
| void setUp() { |
| super.setUp(); |
| sourcePath = convertPath('$testPackageLibPath/test.dart'); |
| } |
| |
| Future<void> test_annotations_class() async { |
| var content = ''' |
| @folded.classAnnotation1/*[0*/() |
| @foldedClassAnnotation2/*0]*/ |
| class MyClass {} |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.ANNOTATIONS}); |
| } |
| |
| Future<void> test_annotations_class_constructor() async { |
| var content = ''' |
| class MyClass { |
| @constructorAnnotation1/*[0*/ |
| @constructorAnnotation1/*0]*/ |
| MyClass() {} |
| |
| @constructorAnnotation1/*[1*/ |
| @constructorAnnotation1/*1]*/ |
| MyClass.named() {} |
| } |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions( |
| {0: FoldingKind.ANNOTATIONS, 1: FoldingKind.ANNOTATIONS}, |
| onlyVerify: {FoldingKind.ANNOTATIONS}, |
| ); |
| } |
| |
| Future<void> test_annotations_class_field() async { |
| var content = ''' |
| class MyClass { |
| @fieldAnnotation1/*[0*/ |
| @fieldAnnotation2/*0]*/ |
| int myField; |
| } |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions( |
| {0: FoldingKind.ANNOTATIONS}, |
| onlyVerify: {FoldingKind.ANNOTATIONS}, |
| ); |
| } |
| |
| Future<void> test_annotations_class_getterSetter() async { |
| var content = ''' |
| class MyClass { |
| @getterAnnotation1/*[0*/ |
| @getterAnnotation2/*0]*/ |
| int get myThing => 1; |
| |
| @setterAnnotation1/*[1*/ |
| @setterAnnotation2/*1]*/ |
| void set myThing(int value) {} |
| } |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions( |
| {0: FoldingKind.ANNOTATIONS, 1: FoldingKind.ANNOTATIONS}, |
| onlyVerify: {FoldingKind.ANNOTATIONS}, |
| ); |
| } |
| |
| Future<void> test_annotations_class_method() async { |
| var content = ''' |
| class MyClass { |
| @methodAnnotation1/*[0*/ |
| @methodAnnotation2/*0]*/ |
| void myMethod() {} |
| } |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions( |
| {0: FoldingKind.ANNOTATIONS}, |
| onlyVerify: {FoldingKind.ANNOTATIONS}, |
| ); |
| } |
| |
| Future<void> test_annotations_multiline() async { |
| var content = ''' |
| @myMultilineAnnotation/*[0*/( |
| "this", |
| "is a test" |
| )/*0]*/ |
| void f() {} |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions( |
| {0: FoldingKind.ANNOTATIONS}, |
| onlyVerify: {FoldingKind.ANNOTATIONS}, |
| ); |
| } |
| |
| Future<void> test_annotations_multiple() async { |
| var content = ''' |
| @multipleAnnotations1/*[0*/( |
| /*[1*/"this", |
| "is a test" |
| /*1]*/) |
| @multipleAnnotations2() |
| @multipleAnnotations3/*0]*/ |
| main3() {} |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions( |
| {0: FoldingKind.ANNOTATIONS}, |
| onlyVerify: {FoldingKind.ANNOTATIONS}, |
| ); |
| } |
| |
| Future<void> test_annotations_singleLine() async { |
| var content = ''' |
| @noFoldNecessary |
| main2() {} |
| |
| @noFoldsForSingleClassAnnotation |
| class MyClass {} |
| '''; |
| |
| await _computeRegions(content); |
| expectNoRegions(); |
| } |
| |
| Future<void> test_assertInitializer() async { |
| var content = ''' |
| class C/*[0*/ { |
| C/*[1*/() : assert( |
| /*[2*/true, |
| '' |
| /*2]*/);/*1]*/ |
| }/*0]*/ |
| '''; |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.CLASS_BODY, |
| 1: FoldingKind.FUNCTION_BODY, |
| 2: FoldingKind.INVOCATION, |
| }); |
| } |
| |
| Future<void> test_assertStatement() async { |
| var content = ''' |
| void f/*[0*/() { |
| assert(/*[1*/ |
| true, |
| '' |
| /*1]*/); |
| }/*0]*/ |
| '''; |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY, 1: FoldingKind.INVOCATION}); |
| } |
| |
| Future<void> test_class() async { |
| var content = ''' |
| // Content before |
| |
| class Person/*[0*/ { |
| Person/*[1*/() { |
| print("Hello, world!"); |
| }/*1]*/ |
| |
| void sayHello/*[2*/() { |
| print("Hello, world!"); |
| }/*2]*/ |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.CLASS_BODY, |
| 1: FoldingKind.FUNCTION_BODY, |
| 2: FoldingKind.FUNCTION_BODY, |
| }); |
| } |
| |
| Future<void> test_comment_is_not_considered_file_header() async { |
| var content = """ |
| // This is not the file header/*[0*/ |
| // It's just a comment/*0]*/ |
| void f() {} |
| """; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.COMMENT}); |
| } |
| |
| Future<void> test_comment_multiline() async { |
| var content = ''' |
| /*/*[0*/ |
| * comment 1 |
| *//*0]*/ |
| |
| /* this comment starts on the same line as delimiters/*[1*/ |
| * second line |
| *//*1]*/ |
| void f() {} |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.COMMENT, 1: FoldingKind.COMMENT}); |
| } |
| |
| Future<void> test_comment_singleFollowedByBlankLine() async { |
| var content = ''' |
| void f() { |
| // this is/*[0*/ |
| // a comment/*0]*/ |
| /// this is not part of it |
| } |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.COMMENT}, onlyVerify: commentKinds); |
| } |
| |
| Future<void> test_comment_singleFollowedByMulti() async { |
| var content = ''' |
| void f() { |
| // this is/*[0*/ |
| // a comment/*0]*/ |
| /* this is not part of it */ |
| String foo; |
| } |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.COMMENT}, onlyVerify: commentKinds); |
| } |
| |
| Future<void> test_comment_singleFollowedByTripleSlash() async { |
| var content = ''' |
| void f() { |
| // this is/*[0*/ |
| // a comment/*0]*/ |
| /// this is not part of it |
| } |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.COMMENT}, onlyVerify: commentKinds); |
| } |
| |
| Future<void> test_constructor_invocations() async { |
| var content = ''' |
| // Content before |
| |
| final a = new Text(/*[0*/ |
| "Hello, world!", |
| /*0]*/); |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.INVOCATION}); |
| } |
| |
| Future<void> test_extensionType() async { |
| var content = ''' |
| // Content before |
| |
| extension type E(int it) {/*[0*/ |
| void m/*[1*/() { |
| }/*1]*/ |
| /*0]*/} |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.CLASS_BODY, 1: FoldingKind.FUNCTION_BODY}); |
| } |
| |
| Future<void> test_file_header() async { |
| var content = """ |
| // Copyright some year by some people/*[0*/ |
| // See LICENCE etc./*0]*/ |
| |
| // This is not the file header |
| // It's just a comment |
| void f() {} |
| """; |
| |
| await _computeRegions(content); |
| expectRegions( |
| {0: FoldingKind.FILE_HEADER}, |
| onlyVerify: {FoldingKind.FILE_HEADER}, |
| ); |
| } |
| |
| Future<void> test_file_header_does_not_include_block_comments() async { |
| var content = """ |
| /* |
| * Copyright some year by some people |
| * See LICENCE etc. |
| */ |
| /* This shouldn't be part of the file header */ |
| |
| void f() {} |
| """; |
| |
| await _computeRegions(content); |
| expectNoRegions(onlyVerify: {FoldingKind.FILE_HEADER}); |
| } |
| |
| Future<void> test_file_header_with_no_function_comment() async { |
| var content = ''' |
| // Copyright some year by some people/*[0*/ |
| // See LICENCE etc./*0]*/ |
| |
| void f() {} |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FILE_HEADER}); |
| } |
| |
| Future<void> test_file_header_with_non_end_of_line_comment() async { |
| var content = """ |
| // Copyright some year by some people/*[0*/ |
| // See LICENCE etc./*0]*/ |
| /* This shouldn't be part of the file header */ |
| |
| void f() {} |
| """; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FILE_HEADER}); |
| } |
| |
| Future<void> test_file_header_with_script_prefix() async { |
| var content = """ |
| #! /usr/bin/dart |
| // Copyright some year by some people/*[0*/ |
| // See LICENCE etc./*0]*/ |
| |
| // This is not the file header |
| // It's just a comment |
| void f() {} |
| """; |
| |
| await _computeRegions(content); |
| expectRegions( |
| {0: FoldingKind.FILE_HEADER}, |
| onlyVerify: {FoldingKind.FILE_HEADER}, |
| ); |
| } |
| |
| Future<void> test_fileHeader_singleFollowedByBlank() async { |
| var content = ''' |
| // this is/*[0*/ |
| // a file header/*0]*/ |
| |
| // this is not part of it |
| void f() {} |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FILE_HEADER}); |
| } |
| |
| Future<void> test_function() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| print("Hello, world!"); |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY}); |
| } |
| |
| Future<void> test_function_expression_invocation() async { |
| var content = ''' |
| // Content before |
| |
| getFunc/*[0*/() => (String a, String b) { |
| print(a); |
| };/*0]*/ |
| |
| main2/*[1*/() { |
| getFunc()(/*[2*/ |
| "one", |
| "two" |
| /*2]*/); |
| }/*1]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FUNCTION_BODY, |
| 1: FoldingKind.FUNCTION_BODY, |
| 2: FoldingKind.INVOCATION, |
| }); |
| } |
| |
| Future<void> test_function_expression_underscore_preWildcards() async { |
| var content = ''' |
| // /*[0*/ |
| // @dart = 3.4 |
| // (pre wildcard-variables)/*0]*/ |
| |
| // Content before |
| |
| void f/*[1*/() { |
| _/*[2*/(){ |
| }/*2]*/ |
| }/*1]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FILE_HEADER, |
| 1: FoldingKind.FUNCTION_BODY, |
| 2: FoldingKind.FUNCTION_BODY, |
| }); |
| } |
| |
| Future<void> test_function_expression_wildcard() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| _/*[1*/(){ |
| }/*1]*/ |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY, 1: FoldingKind.FUNCTION_BODY}); |
| } |
| |
| Future<void> test_function_with_dart_doc() async { |
| var content = ''' |
| // Content before |
| |
| /// This is a doc comment/*[0*/ |
| /// that spans lines/*0]*/ |
| void f/*[1*/() { |
| print("Hello, world!"); |
| }/*1]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.DOCUMENTATION_COMMENT, |
| 1: FoldingKind.FUNCTION_BODY, |
| }); |
| } |
| |
| Future<void> test_invocations() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| print(/*[1*/ |
| "Hello, world!", |
| /*1]*/); |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY, 1: FoldingKind.INVOCATION}); |
| } |
| |
| Future<void> test_literal_list() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final List<String> things = <String>[/*[1*/ |
| "one", |
| "two" |
| /*1]*/]; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY, 1: FoldingKind.LITERAL}); |
| } |
| |
| Future<void> test_literal_list_insideNullAwareElement() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final List<List<String>> things = <List<String>>[/*[1*/ |
| ?<String>[/*[2*/ |
| "one", |
| "two" |
| /*2]*/]; |
| /*1]*/]; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FUNCTION_BODY, |
| 1: FoldingKind.LITERAL, |
| 2: FoldingKind.LITERAL, |
| }); |
| } |
| |
| Future<void> test_literal_list_insideNullAwareKey() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final Map<List<String>, bool> things = <List<String>, bool>{/*[1*/ |
| ?<String>[/*[2*/ |
| "one", |
| "two" |
| /*2]*/]: true |
| /*1]*/}; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FUNCTION_BODY, |
| 1: FoldingKind.LITERAL, |
| 2: FoldingKind.LITERAL, |
| }); |
| } |
| |
| Future<void> test_literal_list_insideNullAwareValue() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final Map<Symbol, List<String>> things = <Symbol, List<String>>{/*[1*/ |
| #key: ?<String>[/*[2*/ |
| "one", |
| "two" |
| /*2]*/] |
| /*1]*/}; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FUNCTION_BODY, |
| 1: FoldingKind.LITERAL, |
| 2: FoldingKind.LITERAL, |
| }); |
| } |
| |
| Future<void> test_literal_list_withNullAwareElement() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final List<String> things = <String>[/*[1*/ |
| "one", |
| ?null |
| "two" |
| /*1]*/]; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY, 1: FoldingKind.LITERAL}); |
| } |
| |
| Future<void> test_literal_map() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final Map<String, String> things = <String, String>{/*[1*/ |
| "one": "one", |
| "two": "two" |
| /*1]*/}; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY, 1: FoldingKind.LITERAL}); |
| } |
| |
| Future<void> test_literal_map_insideNullAwareKey() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final Map<Map<String, int>, false> things = <Map<String, int>, false>{/*[1*/ |
| ?<String, int>{/*[2*/ |
| "one": 1, |
| "two": 2 |
| /*2]*/}: true |
| /*1]*/}; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FUNCTION_BODY, |
| 1: FoldingKind.LITERAL, |
| 2: FoldingKind.LITERAL, |
| }); |
| } |
| |
| Future<void> test_literal_map_insideNullAwareValue() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final Map<Symbol, Map<String, int>> things = <Symbol, Map<String, int>>{/*[1*/ |
| #key: ?<String, int>{/*[2*/ |
| "one": 1, |
| "two": 2 |
| /*2]*/} |
| /*1]*/}; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FUNCTION_BODY, |
| 1: FoldingKind.LITERAL, |
| 2: FoldingKind.LITERAL, |
| }); |
| } |
| |
| Future<void> test_literal_map_withNullAwareKey() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final Map<String, int> things = <String, int>{/*[1*/ |
| "one": 1, |
| ?null: 0, |
| "two": 2 |
| /*1]*/}; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY, 1: FoldingKind.LITERAL}); |
| } |
| |
| Future<void> test_literal_map_withNullAwareValue() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final Map<String, int> things = <String, int>{/*[1*/ |
| "one": 1, |
| "null": ?null, |
| "two": 2 |
| /*1]*/}; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY, 1: FoldingKind.LITERAL}); |
| } |
| |
| Future<void> test_literal_record() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final r = (/*[1*/ |
| "one", |
| 2, |
| (/*[2*/ |
| 'nested', |
| 3, |
| 'field record', |
| /*2]*/), |
| /*1]*/); |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FUNCTION_BODY, |
| 1: FoldingKind.LITERAL, |
| 2: FoldingKind.LITERAL, |
| }); |
| } |
| |
| Future<void> test_literal_set_insideNullAwareElement() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final Set<Set<String>> things = <Set<String>>{/*[1*/ |
| ?<String>{/*[2*/ |
| "one", |
| "two" |
| /*2]*/} |
| /*1]*/}; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FUNCTION_BODY, |
| 1: FoldingKind.LITERAL, |
| 2: FoldingKind.LITERAL, |
| }); |
| } |
| |
| Future<void> test_literal_set_insideNullAwareKey() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final Map<Set<String>, bool> things = <Set<String>, bool>{/*[1*/ |
| ?<String>{/*[2*/ |
| "one", |
| "two" |
| /*2]*/}: true |
| /*1]*/}; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FUNCTION_BODY, |
| 1: FoldingKind.LITERAL, |
| 2: FoldingKind.LITERAL, |
| }); |
| } |
| |
| Future<void> test_literal_set_insideNullAwareValue() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final Map<Symbol, Set<String>> things = <Symbol, Set<String>>{/*[1*/ |
| #key: ?<String>{/*[2*/ |
| "one", |
| "two" |
| /*2]*/} |
| /*1]*/}; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FUNCTION_BODY, |
| 1: FoldingKind.LITERAL, |
| 2: FoldingKind.LITERAL, |
| }); |
| } |
| |
| Future<void> test_literal_set_withNullAwareElement() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| final Set<String> things = <String>{/*[1*/ |
| "one", |
| ?null |
| "two" |
| /*1]*/}; |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY, 1: FoldingKind.LITERAL}); |
| } |
| |
| Future<void> test_mixin() async { |
| var content = ''' |
| // Content before |
| |
| mixin M/*[0*/ { |
| void m/*[1*/() { |
| print("Got to m"); |
| }/*1]*/ |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.CLASS_BODY, 1: FoldingKind.FUNCTION_BODY}); |
| } |
| |
| Future<void> test_multiple_directive_types() async { |
| var content = """ |
| import/*[0*/ 'dart:async'; |
| |
| // We can have comments |
| import 'package:a/b.dart'; |
| import 'package:b/c.dart'; |
| |
| export '../a.dart';/*0]*/ |
| |
| void f() {} |
| """; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.DIRECTIVES}); |
| } |
| |
| Future<void> test_multiple_import_directives() async { |
| var content = """ |
| import/*[0*/ 'dart:async'; |
| |
| // We can have comments |
| import 'package:a/b.dart'; |
| import 'package:b/c.dart'; |
| |
| import '../a.dart';/*0]*/ |
| |
| void f() {} |
| """; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.DIRECTIVES}); |
| } |
| |
| Future<void> test_multiple_import_directives_partFile() async { |
| var content = """ |
| part/*[0*/ of 'part.dart'; |
| |
| import 'dart:async'; |
| |
| // We can have comments |
| import 'package:a/b.dart'; |
| import 'package:b/c.dart'; |
| |
| import '../a.dart';/*0]*/ |
| |
| void f() {} |
| """; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.DIRECTIVES}); |
| } |
| |
| Future<void> test_nested_function() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| doPrint/*[1*/() { |
| print("Hello, world!"); |
| }/*1]*/ |
| doPrint(); |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY, 1: FoldingKind.FUNCTION_BODY}); |
| } |
| |
| Future<void> test_nested_invocations() async { |
| var content = ''' |
| // Content before |
| |
| void f/*[0*/() { |
| a(/*[1*/ |
| b(/*[2*/ |
| c(/*[3*/ |
| d() |
| /*3]*/), |
| /*2]*/), |
| /*1]*/); |
| }/*0]*/ |
| |
| // Content after |
| '''; |
| |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.FUNCTION_BODY, |
| 1: FoldingKind.INVOCATION, |
| 2: FoldingKind.INVOCATION, |
| 3: FoldingKind.INVOCATION, |
| }); |
| } |
| |
| Future<void> test_parameters_function() async { |
| var content = ''' |
| foo/*[0*/( |
| /*[1*/String aaaaa, |
| String bbbbb, { |
| String ccccc, |
| }/*1]*/) {}/*0]*/ |
| '''; |
| await _computeRegions(content); |
| expectRegions({0: FoldingKind.FUNCTION_BODY, 1: FoldingKind.PARAMETERS}); |
| } |
| |
| Future<void> test_parameters_method() async { |
| var content = ''' |
| class C/*[0*/ { |
| C/*[1*/( |
| /*[2*/String aaaaa, |
| String bbbbb, |
| /*2]*/) : super();/*1]*/ |
| }/*0]*/ |
| '''; |
| await _computeRegions(content); |
| expectRegions({ |
| 0: FoldingKind.CLASS_BODY, |
| 1: FoldingKind.FUNCTION_BODY, |
| 2: FoldingKind.PARAMETERS, |
| }); |
| } |
| |
| Future<void> test_single_import_directives() async { |
| var content = """ |
| import 'dart:async'; |
| |
| void f() {} |
| """; |
| |
| await _computeRegions(content); |
| expectNoRegions(); |
| } |
| |
| Future<void> _computeRegions(String sourceContent) async { |
| code = TestCode.parse(normalizeSource(sourceContent)); |
| var file = newFile(sourcePath, code.code); |
| var result = await getResolvedUnit(file); |
| var computer = DartUnitFoldingComputer(result.lineInfo, result.unit); |
| regions = computer.compute(); |
| } |
| } |