| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library test.services.correction.assist; | 5 library test.services.correction.assist; |
| 6 | 6 |
| 7 import 'package:analysis_server/src/protocol.dart'; | 7 import 'package:analysis_server/src/protocol.dart'; |
| 8 import 'package:analysis_server/src/services/correction/assist.dart'; | 8 import 'package:analysis_server/src/services/correction/assist.dart'; |
| 9 import 'package:analyzer/src/generated/source.dart'; | 9 import 'package:analyzer/src/generated/source.dart'; |
| 10 import 'package:unittest/unittest.dart'; | 10 import 'package:unittest/unittest.dart'; |
| 11 | 11 |
| 12 import '../../abstract_single_unit.dart'; | 12 import '../../abstract_single_unit.dart'; |
| 13 import '../../reflective_tests.dart'; | 13 import '../../reflective_tests.dart'; |
| 14 | 14 |
| 15 | |
| 16 main() { | 15 main() { |
| 17 groupSep = ' | '; | 16 groupSep = ' | '; |
| 18 runReflectiveTests(AssistProcessorTest); | 17 runReflectiveTests(AssistProcessorTest); |
| 19 } | 18 } |
| 20 | 19 |
| 21 | |
| 22 @reflectiveTest | 20 @reflectiveTest |
| 23 class AssistProcessorTest extends AbstractSingleUnitTest { | 21 class AssistProcessorTest extends AbstractSingleUnitTest { |
| 24 int offset; | 22 int offset; |
| 25 int length; | 23 int length; |
| 26 | 24 |
| 27 Assist assist; | 25 Assist assist; |
| 28 SourceChange change; | 26 SourceChange change; |
| 29 String resultCode; | 27 String resultCode; |
| 30 LinkedEditGroup linkedPositionGroup; | 28 LinkedEditGroup linkedPositionGroup; |
| 31 | 29 |
| 32 /** | 30 /** |
| 33 * Asserts that there is an [Assist] of the given [kind] at [offset] which | 31 * Asserts that there is an [Assist] of the given [kind] at [offset] which |
| 34 * produces the [expected] code when applied to [testCode]. | 32 * produces the [expected] code when applied to [testCode]. |
| 35 */ | 33 */ |
| 36 void assertHasAssist(AssistKind kind, String expected) { | 34 void assertHasAssist(AssistKind kind, String expected) { |
| 37 assist = _assertHasAssist(kind); | 35 assist = _assertHasAssist(kind); |
| 38 change = assist.change; | 36 change = assist.change; |
| 39 // apply to "file" | 37 // apply to "file" |
| 40 List<SourceFileEdit> fileEdits = change.edits; | 38 List<SourceFileEdit> fileEdits = change.edits; |
| 41 expect(fileEdits, hasLength(1)); | 39 expect(fileEdits, hasLength(1)); |
| 42 resultCode = SourceEdit.applySequence(testCode, change.edits[0].edits); | 40 resultCode = SourceEdit.applySequence(testCode, change.edits[0].edits); |
| 43 // verify | 41 // verify |
| 44 expect(resultCode, expected); | 42 expect(resultCode, expected); |
| 45 } | 43 } |
| 46 | 44 |
| 47 /** | 45 /** |
| 48 * Calls [assertHasAssist] at the offset of [offsetSearch] in [testCode]. | 46 * Calls [assertHasAssist] at the offset of [offsetSearch] in [testCode]. |
| 49 */ | 47 */ |
| 50 void assertHasAssistAt(String offsetSearch, AssistKind kind, | 48 void assertHasAssistAt( |
| 51 String expected) { | 49 String offsetSearch, AssistKind kind, String expected) { |
| 52 offset = findOffset(offsetSearch); | 50 offset = findOffset(offsetSearch); |
| 53 assertHasAssist(kind, expected); | 51 assertHasAssist(kind, expected); |
| 54 } | 52 } |
| 55 | 53 |
| 56 /** | 54 /** |
| 57 * Asserts that there is no [Assist] of the given [kind] at [offset]. | 55 * Asserts that there is no [Assist] of the given [kind] at [offset]. |
| 58 */ | 56 */ |
| 59 void assertNoAssist(AssistKind kind) { | 57 void assertNoAssist(AssistKind kind) { |
| 60 List<Assist> assists = computeAssists(testUnit, offset, length); | 58 List<Assist> assists = computeAssists(testUnit, offset, length); |
| 61 for (Assist assist in assists) { | 59 for (Assist assist in assists) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 79 } | 77 } |
| 80 | 78 |
| 81 List<Position> expectedPositions(List<String> patterns) { | 79 List<Position> expectedPositions(List<String> patterns) { |
| 82 List<Position> positions = <Position>[]; | 80 List<Position> positions = <Position>[]; |
| 83 patterns.forEach((String search) { | 81 patterns.forEach((String search) { |
| 84 positions.add(expectedPosition(search)); | 82 positions.add(expectedPosition(search)); |
| 85 }); | 83 }); |
| 86 return positions; | 84 return positions; |
| 87 } | 85 } |
| 88 | 86 |
| 89 List<LinkedEditSuggestion> expectedSuggestions(LinkedEditSuggestionKind kind, | 87 List<LinkedEditSuggestion> expectedSuggestions( |
| 90 List<String> values) { | 88 LinkedEditSuggestionKind kind, List<String> values) { |
| 91 return values.map((value) { | 89 return values.map((value) { |
| 92 return new LinkedEditSuggestion(value, kind); | 90 return new LinkedEditSuggestion(value, kind); |
| 93 }).toList(); | 91 }).toList(); |
| 94 } | 92 } |
| 95 | 93 |
| 96 void setUp() { | 94 void setUp() { |
| 97 super.setUp(); | 95 super.setUp(); |
| 98 offset = 0; | 96 offset = 0; |
| 99 length = 0; | 97 length = 0; |
| 100 } | 98 } |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 } | 586 } |
| 589 List<int> readBytes() => <int>[]; | 587 List<int> readBytes() => <int>[]; |
| 590 '''); | 588 '''); |
| 591 assertHasAssistAt('readBytes();', AssistKind.ASSIGN_TO_LOCAL_VARIABLE, ''' | 589 assertHasAssistAt('readBytes();', AssistKind.ASSIGN_TO_LOCAL_VARIABLE, ''' |
| 592 main() { | 590 main() { |
| 593 List<int> bytes; | 591 List<int> bytes; |
| 594 var readBytes = readBytes(); | 592 var readBytes = readBytes(); |
| 595 } | 593 } |
| 596 List<int> readBytes() => <int>[]; | 594 List<int> readBytes() => <int>[]; |
| 597 '''); | 595 '''); |
| 598 _assertLinkedGroup( | 596 _assertLinkedGroup(change.linkedEditGroups[0], [ |
| 599 change.linkedEditGroups[0], | 597 'readBytes = ' |
| 600 ['readBytes = '], | 598 ], expectedSuggestions( |
| 601 expectedSuggestions( | 599 LinkedEditSuggestionKind.VARIABLE, ['list', 'bytes2', 'readBytes'])); |
| 602 LinkedEditSuggestionKind.VARIABLE, | |
| 603 ['list', 'bytes2', 'readBytes'])); | |
| 604 } | 600 } |
| 605 | 601 |
| 606 void test_assignToLocalVariable_alreadyAssignment() { | 602 void test_assignToLocalVariable_alreadyAssignment() { |
| 607 resolveTestUnit(''' | 603 resolveTestUnit(''' |
| 608 main() { | 604 main() { |
| 609 var vvv; | 605 var vvv; |
| 610 vvv = 42; | 606 vvv = 42; |
| 611 } | 607 } |
| 612 '''); | 608 '''); |
| 613 assertNoAssistAt('vvv =', AssistKind.ASSIGN_TO_LOCAL_VARIABLE); | 609 assertNoAssistAt('vvv =', AssistKind.ASSIGN_TO_LOCAL_VARIABLE); |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 } | 778 } |
| 783 | 779 |
| 784 void test_convertToExpressionBody_OK_method_onBlock() { | 780 void test_convertToExpressionBody_OK_method_onBlock() { |
| 785 resolveTestUnit(''' | 781 resolveTestUnit(''' |
| 786 class A { | 782 class A { |
| 787 m() { // marker | 783 m() { // marker |
| 788 return 42; | 784 return 42; |
| 789 } | 785 } |
| 790 } | 786 } |
| 791 '''); | 787 '''); |
| 792 assertHasAssistAt( | 788 assertHasAssistAt('{ // marker', AssistKind.CONVERT_INTO_EXPRESSION_BODY, |
| 793 '{ // marker', | |
| 794 AssistKind.CONVERT_INTO_EXPRESSION_BODY, | |
| 795 ''' | 789 ''' |
| 796 class A { | 790 class A { |
| 797 m() => 42; | 791 m() => 42; |
| 798 } | 792 } |
| 799 '''); | 793 '''); |
| 800 } | 794 } |
| 801 | 795 |
| 802 void test_convertToExpressionBody_OK_topFunction_onReturnStatement() { | 796 void test_convertToExpressionBody_OK_topFunction_onReturnStatement() { |
| 803 resolveTestUnit(''' | 797 resolveTestUnit(''' |
| 804 fff() { | 798 fff() { |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1135 1 + 2 - 3 + 4; | 1129 1 + 2 - 3 + 4; |
| 1136 } | 1130 } |
| 1137 '''); | 1131 '''); |
| 1138 assertHasAssistAt('+ 2', AssistKind.EXCHANGE_OPERANDS, ''' | 1132 assertHasAssistAt('+ 2', AssistKind.EXCHANGE_OPERANDS, ''' |
| 1139 main() { | 1133 main() { |
| 1140 2 + 1 - 3 + 4; | 1134 2 + 1 - 3 + 4; |
| 1141 } | 1135 } |
| 1142 '''); | 1136 '''); |
| 1143 } | 1137 } |
| 1144 | 1138 |
| 1145 void | 1139 void test_exchangeBinaryExpressionArguments_OK_extended_sameOperator_afterFirs
t() { |
| 1146 test_exchangeBinaryExpressionArguments_OK_extended_sameOperator_afterFirst
() { | |
| 1147 resolveTestUnit(''' | 1140 resolveTestUnit(''' |
| 1148 main() { | 1141 main() { |
| 1149 1 + 2 + 3; | 1142 1 + 2 + 3; |
| 1150 } | 1143 } |
| 1151 '''); | 1144 '''); |
| 1152 assertHasAssistAt('+ 2', AssistKind.EXCHANGE_OPERANDS, ''' | 1145 assertHasAssistAt('+ 2', AssistKind.EXCHANGE_OPERANDS, ''' |
| 1153 main() { | 1146 main() { |
| 1154 2 + 3 + 1; | 1147 2 + 3 + 1; |
| 1155 } | 1148 } |
| 1156 '''); | 1149 '''); |
| 1157 } | 1150 } |
| 1158 | 1151 |
| 1159 void | 1152 void test_exchangeBinaryExpressionArguments_OK_extended_sameOperator_afterSeco
nd() { |
| 1160 test_exchangeBinaryExpressionArguments_OK_extended_sameOperator_afterSecon
d() { | |
| 1161 resolveTestUnit(''' | 1153 resolveTestUnit(''' |
| 1162 main() { | 1154 main() { |
| 1163 1 + 2 + 3; | 1155 1 + 2 + 3; |
| 1164 } | 1156 } |
| 1165 '''); | 1157 '''); |
| 1166 assertHasAssistAt('+ 3', AssistKind.EXCHANGE_OPERANDS, ''' | 1158 assertHasAssistAt('+ 3', AssistKind.EXCHANGE_OPERANDS, ''' |
| 1167 main() { | 1159 main() { |
| 1168 3 + 1 + 2; | 1160 3 + 1 + 2; |
| 1169 } | 1161 } |
| 1170 '''); | 1162 '''); |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1365 String expected = ''' | 1357 String expected = ''' |
| 1366 class MyTypeName {} | 1358 class MyTypeName {} |
| 1367 main(p) { | 1359 main(p) { |
| 1368 if (p is MyTypeName) { | 1360 if (p is MyTypeName) { |
| 1369 MyTypeName myTypeName = p; | 1361 MyTypeName myTypeName = p; |
| 1370 } | 1362 } |
| 1371 p = null; | 1363 p = null; |
| 1372 } | 1364 } |
| 1373 '''; | 1365 '''; |
| 1374 assertHasAssistAt( | 1366 assertHasAssistAt( |
| 1375 'is MyType', | 1367 'is MyType', AssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected); |
| 1376 AssistKind.INTRODUCE_LOCAL_CAST_TYPE, | 1368 _assertLinkedGroup(change.linkedEditGroups[0], [ |
| 1377 expected); | 1369 'myTypeName = ' |
| 1378 _assertLinkedGroup( | 1370 ], expectedSuggestions( |
| 1379 change.linkedEditGroups[0], | 1371 LinkedEditSuggestionKind.VARIABLE, ['myTypeName', 'typeName', 'name'])); |
| 1380 ['myTypeName = '], | |
| 1381 expectedSuggestions( | |
| 1382 LinkedEditSuggestionKind.VARIABLE, | |
| 1383 ['myTypeName', 'typeName', 'name'])); | |
| 1384 // another good location | 1372 // another good location |
| 1385 assertHasAssistAt('if (p', AssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected); | 1373 assertHasAssistAt('if (p', AssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected); |
| 1386 } | 1374 } |
| 1387 | 1375 |
| 1388 void test_introduceLocalTestedType_OK_while() { | 1376 void test_introduceLocalTestedType_OK_while() { |
| 1389 resolveTestUnit(''' | 1377 resolveTestUnit(''' |
| 1390 main(p) { | 1378 main(p) { |
| 1391 while (p is String) { | 1379 while (p is String) { |
| 1392 } | 1380 } |
| 1393 p = null; | 1381 p = null; |
| 1394 } | 1382 } |
| 1395 '''); | 1383 '''); |
| 1396 String expected = ''' | 1384 String expected = ''' |
| 1397 main(p) { | 1385 main(p) { |
| 1398 while (p is String) { | 1386 while (p is String) { |
| 1399 String s = p; | 1387 String s = p; |
| 1400 } | 1388 } |
| 1401 p = null; | 1389 p = null; |
| 1402 } | 1390 } |
| 1403 '''; | 1391 '''; |
| 1404 assertHasAssistAt( | 1392 assertHasAssistAt( |
| 1405 'is String', | 1393 'is String', AssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected); |
| 1406 AssistKind.INTRODUCE_LOCAL_CAST_TYPE, | |
| 1407 expected); | |
| 1408 assertHasAssistAt( | 1394 assertHasAssistAt( |
| 1409 'while (p', | 1395 'while (p', AssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected); |
| 1410 AssistKind.INTRODUCE_LOCAL_CAST_TYPE, | |
| 1411 expected); | |
| 1412 } | 1396 } |
| 1413 | 1397 |
| 1414 void test_invalidSelection() { | 1398 void test_invalidSelection() { |
| 1415 resolveTestUnit(''); | 1399 resolveTestUnit(''); |
| 1416 List<Assist> assists = computeAssists(testUnit, -1, 0); | 1400 List<Assist> assists = computeAssists(testUnit, -1, 0); |
| 1417 expect(assists, isEmpty); | 1401 expect(assists, isEmpty); |
| 1418 } | 1402 } |
| 1419 | 1403 |
| 1420 void test_invertIfStatement_blocks() { | 1404 void test_invertIfStatement_blocks() { |
| 1421 resolveTestUnit(''' | 1405 resolveTestUnit(''' |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2021 void test_joinVariableDeclaration_onDeclaration_wrong_lastStatement() { | 2005 void test_joinVariableDeclaration_onDeclaration_wrong_lastStatement() { |
| 2022 resolveTestUnit(''' | 2006 resolveTestUnit(''' |
| 2023 main() { | 2007 main() { |
| 2024 if (true) | 2008 if (true) |
| 2025 var v; | 2009 var v; |
| 2026 } | 2010 } |
| 2027 '''); | 2011 '''); |
| 2028 assertNoAssistAt('v;', AssistKind.JOIN_VARIABLE_DECLARATION); | 2012 assertNoAssistAt('v;', AssistKind.JOIN_VARIABLE_DECLARATION); |
| 2029 } | 2013 } |
| 2030 | 2014 |
| 2031 void | 2015 void test_joinVariableDeclaration_onDeclaration_wrong_nextNotAssignmentExpress
ion() { |
| 2032 test_joinVariableDeclaration_onDeclaration_wrong_nextNotAssignmentExpressi
on() { | |
| 2033 resolveTestUnit(''' | 2016 resolveTestUnit(''' |
| 2034 main() { | 2017 main() { |
| 2035 var v; | 2018 var v; |
| 2036 42; | 2019 42; |
| 2037 } | 2020 } |
| 2038 '''); | 2021 '''); |
| 2039 assertNoAssistAt('v;', AssistKind.JOIN_VARIABLE_DECLARATION); | 2022 assertNoAssistAt('v;', AssistKind.JOIN_VARIABLE_DECLARATION); |
| 2040 } | 2023 } |
| 2041 | 2024 |
| 2042 void | 2025 void test_joinVariableDeclaration_onDeclaration_wrong_nextNotExpressionStateme
nt() { |
| 2043 test_joinVariableDeclaration_onDeclaration_wrong_nextNotExpressionStatemen
t() { | |
| 2044 resolveTestUnit(''' | 2026 resolveTestUnit(''' |
| 2045 main() { | 2027 main() { |
| 2046 var v; | 2028 var v; |
| 2047 if (true) return; | 2029 if (true) return; |
| 2048 } | 2030 } |
| 2049 '''); | 2031 '''); |
| 2050 assertNoAssistAt('v;', AssistKind.JOIN_VARIABLE_DECLARATION); | 2032 assertNoAssistAt('v;', AssistKind.JOIN_VARIABLE_DECLARATION); |
| 2051 } | 2033 } |
| 2052 | 2034 |
| 2053 void | 2035 void test_joinVariableDeclaration_onDeclaration_wrong_nextNotPureAssignment()
{ |
| 2054 test_joinVariableDeclaration_onDeclaration_wrong_nextNotPureAssignment() { | |
| 2055 resolveTestUnit(''' | 2036 resolveTestUnit(''' |
| 2056 main() { | 2037 main() { |
| 2057 var v; | 2038 var v; |
| 2058 v += 1; | 2039 v += 1; |
| 2059 } | 2040 } |
| 2060 '''); | 2041 '''); |
| 2061 assertNoAssistAt('v;', AssistKind.JOIN_VARIABLE_DECLARATION); | 2042 assertNoAssistAt('v;', AssistKind.JOIN_VARIABLE_DECLARATION); |
| 2062 } | 2043 } |
| 2063 | 2044 |
| 2064 void test_joinVariableDeclaration_onDeclaration_wrong_notOneVariable() { | 2045 void test_joinVariableDeclaration_onDeclaration_wrong_notOneVariable() { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2136 } | 2117 } |
| 2137 '''); | 2118 '''); |
| 2138 } | 2119 } |
| 2139 | 2120 |
| 2140 void test_replaceConditionalWithIfElse_OK_return() { | 2121 void test_replaceConditionalWithIfElse_OK_return() { |
| 2141 resolveTestUnit(''' | 2122 resolveTestUnit(''' |
| 2142 main() { | 2123 main() { |
| 2143 return true ? 111 : 222; | 2124 return true ? 111 : 222; |
| 2144 } | 2125 } |
| 2145 '''); | 2126 '''); |
| 2146 assertHasAssistAt( | 2127 assertHasAssistAt('return ', AssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE, |
| 2147 'return ', | |
| 2148 AssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE, | |
| 2149 ''' | 2128 ''' |
| 2150 main() { | 2129 main() { |
| 2151 if (true) { | 2130 if (true) { |
| 2152 return 111; | 2131 return 111; |
| 2153 } else { | 2132 } else { |
| 2154 return 222; | 2133 return 222; |
| 2155 } | 2134 } |
| 2156 } | 2135 } |
| 2157 '''); | 2136 '''); |
| 2158 } | 2137 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2195 resolveTestUnit(''' | 2174 resolveTestUnit(''' |
| 2196 main() { | 2175 main() { |
| 2197 int vvv; | 2176 int vvv; |
| 2198 if (true) { | 2177 if (true) { |
| 2199 vvv = 111; | 2178 vvv = 111; |
| 2200 } else { | 2179 } else { |
| 2201 vvv = 222; | 2180 vvv = 222; |
| 2202 } | 2181 } |
| 2203 } | 2182 } |
| 2204 '''); | 2183 '''); |
| 2205 assertHasAssistAt( | 2184 assertHasAssistAt('if (true)', AssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL, |
| 2206 'if (true)', | |
| 2207 AssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL, | |
| 2208 ''' | 2185 ''' |
| 2209 main() { | 2186 main() { |
| 2210 int vvv; | 2187 int vvv; |
| 2211 vvv = true ? 111 : 222; | 2188 vvv = true ? 111 : 222; |
| 2212 } | 2189 } |
| 2213 '''); | 2190 '''); |
| 2214 } | 2191 } |
| 2215 | 2192 |
| 2216 void test_replaceIfElseWithConditional_OK_return() { | 2193 void test_replaceIfElseWithConditional_OK_return() { |
| 2217 resolveTestUnit(''' | 2194 resolveTestUnit(''' |
| 2218 main() { | 2195 main() { |
| 2219 if (true) { | 2196 if (true) { |
| 2220 return 111; | 2197 return 111; |
| 2221 } else { | 2198 } else { |
| 2222 return 222; | 2199 return 222; |
| 2223 } | 2200 } |
| 2224 } | 2201 } |
| 2225 '''); | 2202 '''); |
| 2226 assertHasAssistAt( | 2203 assertHasAssistAt('if (true)', AssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL, |
| 2227 'if (true)', | |
| 2228 AssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL, | |
| 2229 ''' | 2204 ''' |
| 2230 main() { | 2205 main() { |
| 2231 return true ? 111 : 222; | 2206 return true ? 111 : 222; |
| 2232 } | 2207 } |
| 2233 '''); | 2208 '''); |
| 2234 } | 2209 } |
| 2235 | 2210 |
| 2236 void test_replaceIfElseWithConditional_wrong_expressionVsReturn() { | 2211 void test_replaceIfElseWithConditional_wrong_expressionVsReturn() { |
| 2237 resolveTestUnit(''' | 2212 resolveTestUnit(''' |
| 2238 main() { | 2213 main() { |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2657 positions.add(new Position(testFile, offset)); | 2632 positions.add(new Position(testFile, offset)); |
| 2658 } | 2633 } |
| 2659 return positions; | 2634 return positions; |
| 2660 } | 2635 } |
| 2661 | 2636 |
| 2662 void _setStartEndSelection() { | 2637 void _setStartEndSelection() { |
| 2663 offset = findOffset('// start\n') + '// start\n'.length; | 2638 offset = findOffset('// start\n') + '// start\n'.length; |
| 2664 length = findOffset('// end') - offset; | 2639 length = findOffset('// end') - offset; |
| 2665 } | 2640 } |
| 2666 } | 2641 } |
| OLD | NEW |