2
0

test_code_edit.h 116 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190
  1. /*************************************************************************/
  2. /* test_code_edit.h */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #ifndef TEST_CODE_EDIT_H
  31. #define TEST_CODE_EDIT_H
  32. #include "core/input/input_map.h"
  33. #include "core/object/message_queue.h"
  34. #include "core/os/keyboard.h"
  35. #include "core/string/string_builder.h"
  36. #include "scene/gui/code_edit.h"
  37. #include "scene/resources/default_theme/default_theme.h"
  38. #include "tests/test_macros.h"
  39. namespace TestCodeEdit {
  40. TEST_CASE("[SceneTree][CodeEdit] line gutters") {
  41. CodeEdit *code_edit = memnew(CodeEdit);
  42. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  43. SUBCASE("[CodeEdit] breakpoints") {
  44. SIGNAL_WATCH(code_edit, "breakpoint_toggled");
  45. SUBCASE("[CodeEdit] draw breakpoints gutter") {
  46. code_edit->set_draw_breakpoints_gutter(false);
  47. CHECK_FALSE(code_edit->is_drawing_breakpoints_gutter());
  48. code_edit->set_draw_breakpoints_gutter(true);
  49. CHECK(code_edit->is_drawing_breakpoints_gutter());
  50. }
  51. SUBCASE("[CodeEdit] set line as breakpoint") {
  52. /* Out of bounds. */
  53. ERR_PRINT_OFF;
  54. code_edit->set_line_as_breakpoint(-1, true);
  55. CHECK_FALSE(code_edit->is_line_breakpointed(-1));
  56. SIGNAL_CHECK_FALSE("breakpoint_toggled");
  57. code_edit->set_line_as_breakpoint(1, true);
  58. CHECK_FALSE(code_edit->is_line_breakpointed(1));
  59. SIGNAL_CHECK_FALSE("breakpoint_toggled");
  60. ERR_PRINT_ON;
  61. Array arg1;
  62. arg1.push_back(0);
  63. Array args;
  64. args.push_back(arg1);
  65. code_edit->set_line_as_breakpoint(0, true);
  66. CHECK(code_edit->is_line_breakpointed(0));
  67. CHECK(code_edit->get_breakpointed_lines()[0] == Variant(0));
  68. SIGNAL_CHECK("breakpoint_toggled", args);
  69. code_edit->set_line_as_breakpoint(0, false);
  70. CHECK_FALSE(code_edit->is_line_breakpointed(0));
  71. SIGNAL_CHECK("breakpoint_toggled", args);
  72. }
  73. SUBCASE("[CodeEdit] clear breakpointed lines") {
  74. code_edit->clear_breakpointed_lines();
  75. SIGNAL_CHECK_FALSE("breakpoint_toggled");
  76. Array arg1;
  77. arg1.push_back(0);
  78. Array args;
  79. args.push_back(arg1);
  80. code_edit->set_line_as_breakpoint(0, true);
  81. CHECK(code_edit->is_line_breakpointed(0));
  82. SIGNAL_CHECK("breakpoint_toggled", args);
  83. code_edit->clear_breakpointed_lines();
  84. CHECK_FALSE(code_edit->is_line_breakpointed(0));
  85. SIGNAL_CHECK("breakpoint_toggled", args);
  86. }
  87. SUBCASE("[CodeEdit] breakpoints and set text") {
  88. Array arg1;
  89. arg1.push_back(0);
  90. Array args;
  91. args.push_back(arg1);
  92. code_edit->set_text("test\nline");
  93. code_edit->set_line_as_breakpoint(0, true);
  94. CHECK(code_edit->is_line_breakpointed(0));
  95. SIGNAL_CHECK("breakpoint_toggled", args);
  96. /* breakpoint on lines that still exist are kept. */
  97. code_edit->set_text("");
  98. MessageQueue::get_singleton()->flush();
  99. CHECK(code_edit->is_line_breakpointed(0));
  100. SIGNAL_CHECK_FALSE("breakpoint_toggled");
  101. /* breakpoint on lines that are removed should also be removed. */
  102. code_edit->clear_breakpointed_lines();
  103. SIGNAL_DISCARD("breakpoint_toggled")
  104. ((Array)args[0])[0] = 1;
  105. code_edit->set_text("test\nline");
  106. code_edit->set_line_as_breakpoint(1, true);
  107. CHECK(code_edit->is_line_breakpointed(1));
  108. SIGNAL_CHECK("breakpoint_toggled", args);
  109. code_edit->set_text("");
  110. MessageQueue::get_singleton()->flush();
  111. CHECK_FALSE(code_edit->is_line_breakpointed(0));
  112. ERR_PRINT_OFF;
  113. CHECK_FALSE(code_edit->is_line_breakpointed(1));
  114. ERR_PRINT_ON;
  115. SIGNAL_CHECK("breakpoint_toggled", args);
  116. }
  117. SUBCASE("[CodeEdit] breakpoints and clear") {
  118. Array arg1;
  119. arg1.push_back(0);
  120. Array args;
  121. args.push_back(arg1);
  122. code_edit->set_text("test\nline");
  123. code_edit->set_line_as_breakpoint(0, true);
  124. CHECK(code_edit->is_line_breakpointed(0));
  125. SIGNAL_CHECK("breakpoint_toggled", args);
  126. /* breakpoint on lines that still exist are removed. */
  127. code_edit->clear();
  128. MessageQueue::get_singleton()->flush();
  129. CHECK_FALSE(code_edit->is_line_breakpointed(0));
  130. SIGNAL_CHECK("breakpoint_toggled", args);
  131. /* breakpoint on lines that are removed should also be removed. */
  132. code_edit->clear_breakpointed_lines();
  133. SIGNAL_DISCARD("breakpoint_toggled")
  134. ((Array)args[0])[0] = 1;
  135. code_edit->set_text("test\nline");
  136. code_edit->set_line_as_breakpoint(1, true);
  137. CHECK(code_edit->is_line_breakpointed(1));
  138. SIGNAL_CHECK("breakpoint_toggled", args);
  139. code_edit->clear();
  140. MessageQueue::get_singleton()->flush();
  141. CHECK_FALSE(code_edit->is_line_breakpointed(0));
  142. ERR_PRINT_OFF;
  143. CHECK_FALSE(code_edit->is_line_breakpointed(1));
  144. ERR_PRINT_ON;
  145. SIGNAL_CHECK("breakpoint_toggled", args);
  146. }
  147. SUBCASE("[CodeEdit] breakpoints and new lines no text") {
  148. Array arg1;
  149. arg1.push_back(0);
  150. Array args;
  151. args.push_back(arg1);
  152. /* No text moves breakpoint. */
  153. code_edit->set_line_as_breakpoint(0, true);
  154. CHECK(code_edit->is_line_breakpointed(0));
  155. SIGNAL_CHECK("breakpoint_toggled", args);
  156. /* Normal. */
  157. ((Array)args[0])[0] = 0;
  158. Array arg2;
  159. arg2.push_back(1);
  160. args.push_back(arg2);
  161. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  162. CHECK(code_edit->get_line_count() == 2);
  163. CHECK_FALSE(code_edit->is_line_breakpointed(0));
  164. CHECK(code_edit->is_line_breakpointed(1));
  165. SIGNAL_CHECK("breakpoint_toggled", args);
  166. /* Non-Breaking. */
  167. ((Array)args[0])[0] = 1;
  168. ((Array)args[1])[0] = 2;
  169. SEND_GUI_ACTION(code_edit, "ui_text_newline_blank");
  170. CHECK(code_edit->get_line_count() == 3);
  171. CHECK_FALSE(code_edit->is_line_breakpointed(1));
  172. CHECK(code_edit->is_line_breakpointed(2));
  173. SIGNAL_CHECK("breakpoint_toggled", args);
  174. /* Above. */
  175. ((Array)args[0])[0] = 2;
  176. ((Array)args[1])[0] = 3;
  177. SEND_GUI_ACTION(code_edit, "ui_text_newline_above");
  178. CHECK(code_edit->get_line_count() == 4);
  179. CHECK_FALSE(code_edit->is_line_breakpointed(2));
  180. CHECK(code_edit->is_line_breakpointed(3));
  181. SIGNAL_CHECK("breakpoint_toggled", args);
  182. }
  183. SUBCASE("[CodeEdit] breakpoints and new lines with text") {
  184. Array arg1;
  185. arg1.push_back(0);
  186. Array args;
  187. args.push_back(arg1);
  188. /* Having text does not move breakpoint. */
  189. code_edit->insert_text_at_caret("text");
  190. code_edit->set_line_as_breakpoint(0, true);
  191. CHECK(code_edit->is_line_breakpointed(0));
  192. SIGNAL_CHECK("breakpoint_toggled", args);
  193. /* Normal. */
  194. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  195. CHECK(code_edit->get_line_count() == 2);
  196. CHECK(code_edit->is_line_breakpointed(0));
  197. CHECK_FALSE(code_edit->is_line_breakpointed(1));
  198. SIGNAL_CHECK_FALSE("breakpoint_toggled");
  199. /* Non-Breaking. */
  200. code_edit->set_caret_line(0);
  201. SEND_GUI_ACTION(code_edit, "ui_text_newline_blank");
  202. CHECK(code_edit->get_line_count() == 3);
  203. CHECK(code_edit->is_line_breakpointed(0));
  204. CHECK_FALSE(code_edit->is_line_breakpointed(1));
  205. SIGNAL_CHECK_FALSE("breakpoint_toggled");
  206. /* Above does move. */
  207. ((Array)args[0])[0] = 0;
  208. Array arg2;
  209. arg2.push_back(1);
  210. args.push_back(arg2);
  211. code_edit->set_caret_line(0);
  212. SEND_GUI_ACTION(code_edit, "ui_text_newline_above");
  213. CHECK(code_edit->get_line_count() == 4);
  214. CHECK_FALSE(code_edit->is_line_breakpointed(0));
  215. CHECK(code_edit->is_line_breakpointed(1));
  216. SIGNAL_CHECK("breakpoint_toggled", args);
  217. }
  218. SUBCASE("[CodeEdit] breakpoints and backspace") {
  219. Array arg1;
  220. arg1.push_back(1);
  221. Array args;
  222. args.push_back(arg1);
  223. code_edit->set_text("\n\n");
  224. code_edit->set_line_as_breakpoint(1, true);
  225. CHECK(code_edit->is_line_breakpointed(1));
  226. SIGNAL_CHECK("breakpoint_toggled", args);
  227. code_edit->set_caret_line(2);
  228. /* backspace onto line does not remove breakpoint */
  229. SEND_GUI_ACTION(code_edit, "ui_text_backspace");
  230. CHECK(code_edit->is_line_breakpointed(1));
  231. SIGNAL_CHECK_FALSE("breakpoint_toggled");
  232. /* backspace on breakpointed line removes it */
  233. SEND_GUI_ACTION(code_edit, "ui_text_backspace");
  234. CHECK_FALSE(code_edit->is_line_breakpointed(0));
  235. ERR_PRINT_OFF;
  236. CHECK_FALSE(code_edit->is_line_breakpointed(1));
  237. ERR_PRINT_ON;
  238. SIGNAL_CHECK("breakpoint_toggled", args);
  239. /* Backspace above breakpointed line moves it. */
  240. ((Array)args[0])[0] = 2;
  241. code_edit->set_text("\n\n");
  242. code_edit->set_line_as_breakpoint(2, true);
  243. CHECK(code_edit->is_line_breakpointed(2));
  244. SIGNAL_CHECK("breakpoint_toggled", args);
  245. code_edit->set_caret_line(1);
  246. Array arg2;
  247. arg2.push_back(1);
  248. args.push_back(arg2);
  249. SEND_GUI_ACTION(code_edit, "ui_text_backspace");
  250. ERR_PRINT_OFF;
  251. CHECK_FALSE(code_edit->is_line_breakpointed(2));
  252. ERR_PRINT_ON;
  253. CHECK(code_edit->is_line_breakpointed(1));
  254. SIGNAL_CHECK("breakpoint_toggled", args);
  255. }
  256. SUBCASE("[CodeEdit] breakpoints and delete") {
  257. Array arg1;
  258. arg1.push_back(1);
  259. Array args;
  260. args.push_back(arg1);
  261. code_edit->set_text("\n\n");
  262. code_edit->set_line_as_breakpoint(1, true);
  263. CHECK(code_edit->is_line_breakpointed(1));
  264. SIGNAL_CHECK("breakpoint_toggled", args);
  265. code_edit->set_caret_line(1);
  266. /* Delete onto breakpointed lines does not remove it. */
  267. SEND_GUI_ACTION(code_edit, "ui_text_delete");
  268. CHECK(code_edit->get_line_count() == 2);
  269. CHECK(code_edit->is_line_breakpointed(1));
  270. SIGNAL_CHECK_FALSE("breakpoint_toggled");
  271. /* Delete moving breakpointed line up removes it. */
  272. code_edit->set_caret_line(0);
  273. SEND_GUI_ACTION(code_edit, "ui_text_delete");
  274. CHECK(code_edit->get_line_count() == 1);
  275. ERR_PRINT_OFF;
  276. CHECK_FALSE(code_edit->is_line_breakpointed(1));
  277. ERR_PRINT_ON;
  278. SIGNAL_CHECK("breakpoint_toggled", args);
  279. /* Delete above breakpointed line moves it. */
  280. ((Array)args[0])[0] = 2;
  281. code_edit->set_text("\n\n");
  282. code_edit->set_line_as_breakpoint(2, true);
  283. CHECK(code_edit->is_line_breakpointed(2));
  284. SIGNAL_CHECK("breakpoint_toggled", args);
  285. code_edit->set_caret_line(0);
  286. Array arg2;
  287. arg2.push_back(1);
  288. args.push_back(arg2);
  289. SEND_GUI_ACTION(code_edit, "ui_text_delete");
  290. ERR_PRINT_OFF;
  291. CHECK_FALSE(code_edit->is_line_breakpointed(2));
  292. ERR_PRINT_ON;
  293. CHECK(code_edit->is_line_breakpointed(1));
  294. SIGNAL_CHECK("breakpoint_toggled", args);
  295. }
  296. SUBCASE("[CodeEdit] breakpoints and delete selection") {
  297. Array arg1;
  298. arg1.push_back(1);
  299. Array args;
  300. args.push_back(arg1);
  301. code_edit->set_text("\n\n");
  302. code_edit->set_line_as_breakpoint(1, true);
  303. CHECK(code_edit->is_line_breakpointed(1));
  304. SIGNAL_CHECK("breakpoint_toggled", args);
  305. code_edit->select(0, 0, 2, 0);
  306. code_edit->delete_selection();
  307. MessageQueue::get_singleton()->flush();
  308. CHECK_FALSE(code_edit->is_line_breakpointed(0));
  309. SIGNAL_CHECK("breakpoint_toggled", args);
  310. /* Should handle breakpoint move when deleting selection by adding less text then removed. */
  311. ((Array)args[0])[0] = 9;
  312. code_edit->set_text("\n\n\n\n\n\n\n\n\n");
  313. code_edit->set_line_as_breakpoint(9, true);
  314. CHECK(code_edit->is_line_breakpointed(9));
  315. SIGNAL_CHECK("breakpoint_toggled", args);
  316. code_edit->select(0, 0, 6, 0);
  317. Array arg2;
  318. arg2.push_back(4);
  319. args.push_back(arg2);
  320. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  321. ERR_PRINT_OFF;
  322. CHECK_FALSE(code_edit->is_line_breakpointed(9));
  323. ERR_PRINT_ON;
  324. CHECK(code_edit->is_line_breakpointed(4));
  325. SIGNAL_CHECK("breakpoint_toggled", args);
  326. /* Should handle breakpoint move when deleting selection by adding more text then removed. */
  327. ((Array)args[0])[0] = 9;
  328. ((Array)args[1])[0] = 14;
  329. code_edit->insert_text_at_caret("\n\n\n\n\n");
  330. MessageQueue::get_singleton()->flush();
  331. SIGNAL_DISCARD("breakpoint_toggled")
  332. CHECK(code_edit->is_line_breakpointed(9));
  333. code_edit->select(0, 0, 6, 0);
  334. code_edit->insert_text_at_caret("\n\n\n\n\n\n\n\n\n\n\n");
  335. MessageQueue::get_singleton()->flush();
  336. CHECK(code_edit->is_line_breakpointed(14));
  337. SIGNAL_CHECK("breakpoint_toggled", args);
  338. }
  339. SUBCASE("[CodeEdit] breakpoints and undo") {
  340. Array arg1;
  341. arg1.push_back(1);
  342. Array args;
  343. args.push_back(arg1);
  344. code_edit->set_text("\n\n");
  345. code_edit->set_line_as_breakpoint(1, true);
  346. CHECK(code_edit->is_line_breakpointed(1));
  347. SIGNAL_CHECK("breakpoint_toggled", args);
  348. code_edit->select(0, 0, 2, 0);
  349. code_edit->delete_selection();
  350. MessageQueue::get_singleton()->flush();
  351. CHECK_FALSE(code_edit->is_line_breakpointed(0));
  352. SIGNAL_CHECK("breakpoint_toggled", args);
  353. /* Undo does not restore breakpoint. */
  354. code_edit->undo();
  355. CHECK_FALSE(code_edit->is_line_breakpointed(1));
  356. SIGNAL_CHECK_FALSE("breakpoint_toggled");
  357. }
  358. SIGNAL_UNWATCH(code_edit, "breakpoint_toggled");
  359. }
  360. SUBCASE("[CodeEdit] bookmarks") {
  361. SUBCASE("[CodeEdit] draw bookmarks gutter") {
  362. code_edit->set_draw_bookmarks_gutter(false);
  363. CHECK_FALSE(code_edit->is_drawing_bookmarks_gutter());
  364. code_edit->set_draw_bookmarks_gutter(true);
  365. CHECK(code_edit->is_drawing_bookmarks_gutter());
  366. }
  367. SUBCASE("[CodeEdit] set line as bookmarks") {
  368. /* Out of bounds. */
  369. ERR_PRINT_OFF;
  370. code_edit->set_line_as_bookmarked(-1, true);
  371. CHECK_FALSE(code_edit->is_line_bookmarked(-1));
  372. code_edit->set_line_as_bookmarked(1, true);
  373. CHECK_FALSE(code_edit->is_line_bookmarked(1));
  374. ERR_PRINT_ON;
  375. code_edit->set_line_as_bookmarked(0, true);
  376. CHECK(code_edit->get_bookmarked_lines()[0] == Variant(0));
  377. CHECK(code_edit->is_line_bookmarked(0));
  378. code_edit->set_line_as_bookmarked(0, false);
  379. CHECK_FALSE(code_edit->is_line_bookmarked(0));
  380. }
  381. SUBCASE("[CodeEdit] clear bookmarked lines") {
  382. code_edit->clear_bookmarked_lines();
  383. code_edit->set_line_as_bookmarked(0, true);
  384. CHECK(code_edit->is_line_bookmarked(0));
  385. code_edit->clear_bookmarked_lines();
  386. CHECK_FALSE(code_edit->is_line_bookmarked(0));
  387. }
  388. SUBCASE("[CodeEdit] bookmarks and set text") {
  389. code_edit->set_text("test\nline");
  390. code_edit->set_line_as_bookmarked(0, true);
  391. CHECK(code_edit->is_line_bookmarked(0));
  392. /* bookmarks on lines that still exist are kept. */
  393. code_edit->set_text("");
  394. MessageQueue::get_singleton()->flush();
  395. CHECK(code_edit->is_line_bookmarked(0));
  396. /* bookmarks on lines that are removed should also be removed. */
  397. code_edit->clear_bookmarked_lines();
  398. code_edit->set_text("test\nline");
  399. code_edit->set_line_as_bookmarked(1, true);
  400. CHECK(code_edit->is_line_bookmarked(1));
  401. code_edit->set_text("");
  402. MessageQueue::get_singleton()->flush();
  403. CHECK_FALSE(code_edit->is_line_bookmarked(0));
  404. ERR_PRINT_OFF;
  405. CHECK_FALSE(code_edit->is_line_bookmarked(1));
  406. ERR_PRINT_ON;
  407. }
  408. SUBCASE("[CodeEdit] bookmarks and clear") {
  409. code_edit->set_text("test\nline");
  410. code_edit->set_line_as_bookmarked(0, true);
  411. CHECK(code_edit->is_line_bookmarked(0));
  412. /* bookmarks on lines that still exist are removed. */
  413. code_edit->clear();
  414. MessageQueue::get_singleton()->flush();
  415. CHECK_FALSE(code_edit->is_line_bookmarked(0));
  416. /* bookmarks on lines that are removed should also be removed. */
  417. code_edit->clear_bookmarked_lines();
  418. code_edit->set_text("test\nline");
  419. code_edit->set_line_as_bookmarked(1, true);
  420. CHECK(code_edit->is_line_bookmarked(1));
  421. code_edit->clear();
  422. MessageQueue::get_singleton()->flush();
  423. CHECK_FALSE(code_edit->is_line_bookmarked(0));
  424. ERR_PRINT_OFF;
  425. CHECK_FALSE(code_edit->is_line_bookmarked(1));
  426. ERR_PRINT_ON;
  427. }
  428. SUBCASE("[CodeEdit] bookmarks and new lines no text") {
  429. /* No text moves bookmarks. */
  430. code_edit->set_line_as_bookmarked(0, true);
  431. CHECK(code_edit->is_line_bookmarked(0));
  432. /* Normal. */
  433. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  434. CHECK(code_edit->get_line_count() == 2);
  435. CHECK_FALSE(code_edit->is_line_bookmarked(0));
  436. CHECK(code_edit->is_line_bookmarked(1));
  437. /* Non-Breaking. */
  438. SEND_GUI_ACTION(code_edit, "ui_text_newline_blank");
  439. CHECK(code_edit->get_line_count() == 3);
  440. CHECK_FALSE(code_edit->is_line_bookmarked(1));
  441. CHECK(code_edit->is_line_bookmarked(2));
  442. /* Above. */
  443. SEND_GUI_ACTION(code_edit, "ui_text_newline_above");
  444. CHECK(code_edit->get_line_count() == 4);
  445. CHECK_FALSE(code_edit->is_line_bookmarked(2));
  446. CHECK(code_edit->is_line_bookmarked(3));
  447. }
  448. SUBCASE("[CodeEdit] bookmarks and new lines with text") {
  449. /* Having text does not move bookmark. */
  450. code_edit->insert_text_at_caret("text");
  451. code_edit->set_line_as_bookmarked(0, true);
  452. CHECK(code_edit->is_line_bookmarked(0));
  453. /* Normal. */
  454. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  455. CHECK(code_edit->get_line_count() == 2);
  456. CHECK(code_edit->is_line_bookmarked(0));
  457. CHECK_FALSE(code_edit->is_line_bookmarked(1));
  458. /* Non-Breaking. */
  459. code_edit->set_caret_line(0);
  460. SEND_GUI_ACTION(code_edit, "ui_text_newline_blank");
  461. CHECK(code_edit->get_line_count() == 3);
  462. CHECK(code_edit->is_line_bookmarked(0));
  463. CHECK_FALSE(code_edit->is_line_bookmarked(1));
  464. /* Above does move. */
  465. code_edit->set_caret_line(0);
  466. SEND_GUI_ACTION(code_edit, "ui_text_newline_above");
  467. CHECK(code_edit->get_line_count() == 4);
  468. CHECK_FALSE(code_edit->is_line_bookmarked(0));
  469. CHECK(code_edit->is_line_bookmarked(1));
  470. }
  471. SUBCASE("[CodeEdit] bookmarks and backspace") {
  472. code_edit->set_text("\n\n");
  473. code_edit->set_line_as_bookmarked(1, true);
  474. CHECK(code_edit->is_line_bookmarked(1));
  475. code_edit->set_caret_line(2);
  476. /* backspace onto line does not remove bookmark */
  477. SEND_GUI_ACTION(code_edit, "ui_text_backspace");
  478. CHECK(code_edit->is_line_bookmarked(1));
  479. /* backspace on bookmarked line removes it */
  480. SEND_GUI_ACTION(code_edit, "ui_text_backspace");
  481. CHECK_FALSE(code_edit->is_line_bookmarked(0));
  482. ERR_PRINT_OFF;
  483. CHECK_FALSE(code_edit->is_line_bookmarked(1));
  484. ERR_PRINT_ON;
  485. }
  486. SUBCASE("[CodeEdit] bookmarks and delete") {
  487. code_edit->set_text("\n\n");
  488. code_edit->set_line_as_bookmarked(1, true);
  489. CHECK(code_edit->is_line_bookmarked(1));
  490. code_edit->set_caret_line(1);
  491. /* Delete onto bookmarked lines does not remove it. */
  492. SEND_GUI_ACTION(code_edit, "ui_text_delete");
  493. CHECK(code_edit->get_line_count() == 2);
  494. CHECK(code_edit->is_line_bookmarked(1));
  495. /* Delete moving bookmarked line up removes it. */
  496. code_edit->set_caret_line(0);
  497. SEND_GUI_ACTION(code_edit, "ui_text_delete");
  498. CHECK(code_edit->get_line_count() == 1);
  499. ERR_PRINT_OFF;
  500. CHECK_FALSE(code_edit->is_line_bookmarked(1));
  501. ERR_PRINT_ON;
  502. }
  503. SUBCASE("[CodeEdit] bookmarks and delete selection") {
  504. code_edit->set_text("\n\n");
  505. code_edit->set_line_as_bookmarked(1, true);
  506. CHECK(code_edit->is_line_bookmarked(1));
  507. code_edit->select(0, 0, 2, 0);
  508. code_edit->delete_selection();
  509. MessageQueue::get_singleton()->flush();
  510. CHECK_FALSE(code_edit->is_line_bookmarked(0));
  511. }
  512. SUBCASE("[CodeEdit] bookmarks and undo") {
  513. code_edit->set_text("\n\n");
  514. code_edit->set_line_as_bookmarked(1, true);
  515. CHECK(code_edit->is_line_bookmarked(1));
  516. code_edit->select(0, 0, 2, 0);
  517. code_edit->delete_selection();
  518. MessageQueue::get_singleton()->flush();
  519. CHECK_FALSE(code_edit->is_line_bookmarked(0));
  520. /* Undo does not restore bookmark. */
  521. code_edit->undo();
  522. CHECK_FALSE(code_edit->is_line_bookmarked(1));
  523. }
  524. }
  525. SUBCASE("[CodeEdit] executing lines") {
  526. SUBCASE("[CodeEdit] draw executing lines gutter") {
  527. code_edit->set_draw_executing_lines_gutter(false);
  528. CHECK_FALSE(code_edit->is_drawing_executing_lines_gutter());
  529. code_edit->set_draw_executing_lines_gutter(true);
  530. CHECK(code_edit->is_drawing_executing_lines_gutter());
  531. }
  532. SUBCASE("[CodeEdit] set line as executing lines") {
  533. /* Out of bounds. */
  534. ERR_PRINT_OFF;
  535. code_edit->set_line_as_executing(-1, true);
  536. CHECK_FALSE(code_edit->is_line_executing(-1));
  537. code_edit->set_line_as_executing(1, true);
  538. CHECK_FALSE(code_edit->is_line_executing(1));
  539. ERR_PRINT_ON;
  540. code_edit->set_line_as_executing(0, true);
  541. CHECK(code_edit->get_executing_lines()[0] == Variant(0));
  542. CHECK(code_edit->is_line_executing(0));
  543. code_edit->set_line_as_executing(0, false);
  544. CHECK_FALSE(code_edit->is_line_executing(0));
  545. }
  546. SUBCASE("[CodeEdit] clear executing lines lines") {
  547. code_edit->clear_executing_lines();
  548. code_edit->set_line_as_executing(0, true);
  549. CHECK(code_edit->is_line_executing(0));
  550. code_edit->clear_executing_lines();
  551. CHECK_FALSE(code_edit->is_line_executing(0));
  552. }
  553. SUBCASE("[CodeEdit] executing lines and set text") {
  554. code_edit->set_text("test\nline");
  555. code_edit->set_line_as_executing(0, true);
  556. CHECK(code_edit->is_line_executing(0));
  557. /* executing on lines that still exist are kept. */
  558. code_edit->set_text("");
  559. MessageQueue::get_singleton()->flush();
  560. CHECK(code_edit->is_line_executing(0));
  561. /* executing on lines that are removed should also be removed. */
  562. code_edit->clear_executing_lines();
  563. code_edit->set_text("test\nline");
  564. code_edit->set_line_as_executing(1, true);
  565. CHECK(code_edit->is_line_executing(1));
  566. code_edit->set_text("");
  567. MessageQueue::get_singleton()->flush();
  568. CHECK_FALSE(code_edit->is_line_executing(0));
  569. ERR_PRINT_OFF;
  570. CHECK_FALSE(code_edit->is_line_executing(1));
  571. ERR_PRINT_ON;
  572. }
  573. SUBCASE("[CodeEdit] executing lines and clear") {
  574. code_edit->set_text("test\nline");
  575. code_edit->set_line_as_executing(0, true);
  576. CHECK(code_edit->is_line_executing(0));
  577. /* executing on lines that still exist are removed. */
  578. code_edit->clear();
  579. MessageQueue::get_singleton()->flush();
  580. CHECK_FALSE(code_edit->is_line_executing(0));
  581. /* executing on lines that are removed should also be removed. */
  582. code_edit->clear_executing_lines();
  583. code_edit->set_text("test\nline");
  584. code_edit->set_line_as_executing(1, true);
  585. CHECK(code_edit->is_line_executing(1));
  586. code_edit->clear();
  587. MessageQueue::get_singleton()->flush();
  588. CHECK_FALSE(code_edit->is_line_executing(0));
  589. ERR_PRINT_OFF;
  590. CHECK_FALSE(code_edit->is_line_executing(1));
  591. ERR_PRINT_ON;
  592. }
  593. SUBCASE("[CodeEdit] executing lines and new lines no text") {
  594. /* No text moves executing lines. */
  595. code_edit->set_line_as_executing(0, true);
  596. CHECK(code_edit->is_line_executing(0));
  597. /* Normal. */
  598. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  599. CHECK(code_edit->get_line_count() == 2);
  600. CHECK_FALSE(code_edit->is_line_executing(0));
  601. CHECK(code_edit->is_line_executing(1));
  602. /* Non-Breaking. */
  603. SEND_GUI_ACTION(code_edit, "ui_text_newline_blank");
  604. CHECK(code_edit->get_line_count() == 3);
  605. CHECK_FALSE(code_edit->is_line_executing(1));
  606. CHECK(code_edit->is_line_executing(2));
  607. /* Above. */
  608. SEND_GUI_ACTION(code_edit, "ui_text_newline_above");
  609. CHECK(code_edit->get_line_count() == 4);
  610. CHECK_FALSE(code_edit->is_line_executing(2));
  611. CHECK(code_edit->is_line_executing(3));
  612. }
  613. SUBCASE("[CodeEdit] executing lines and new lines with text") {
  614. /* Having text does not move executing lines. */
  615. code_edit->insert_text_at_caret("text");
  616. code_edit->set_line_as_executing(0, true);
  617. CHECK(code_edit->is_line_executing(0));
  618. /* Normal. */
  619. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  620. CHECK(code_edit->get_line_count() == 2);
  621. CHECK(code_edit->is_line_executing(0));
  622. CHECK_FALSE(code_edit->is_line_executing(1));
  623. /* Non-Breaking. */
  624. code_edit->set_caret_line(0);
  625. SEND_GUI_ACTION(code_edit, "ui_text_newline_blank");
  626. CHECK(code_edit->get_line_count() == 3);
  627. CHECK(code_edit->is_line_executing(0));
  628. CHECK_FALSE(code_edit->is_line_executing(1));
  629. /* Above does move. */
  630. code_edit->set_caret_line(0);
  631. SEND_GUI_ACTION(code_edit, "ui_text_newline_above");
  632. CHECK(code_edit->get_line_count() == 4);
  633. CHECK_FALSE(code_edit->is_line_executing(0));
  634. CHECK(code_edit->is_line_executing(1));
  635. }
  636. SUBCASE("[CodeEdit] executing lines and backspace") {
  637. code_edit->set_text("\n\n");
  638. code_edit->set_line_as_executing(1, true);
  639. CHECK(code_edit->is_line_executing(1));
  640. code_edit->set_caret_line(2);
  641. /* backspace onto line does not remove executing lines. */
  642. SEND_GUI_ACTION(code_edit, "ui_text_backspace");
  643. CHECK(code_edit->is_line_executing(1));
  644. /* backspace on executing line removes it */
  645. SEND_GUI_ACTION(code_edit, "ui_text_backspace");
  646. CHECK_FALSE(code_edit->is_line_executing(0));
  647. ERR_PRINT_OFF;
  648. CHECK_FALSE(code_edit->is_line_executing(1));
  649. ERR_PRINT_ON;
  650. }
  651. SUBCASE("[CodeEdit] executing lines and delete") {
  652. code_edit->set_text("\n\n");
  653. code_edit->set_line_as_executing(1, true);
  654. CHECK(code_edit->is_line_executing(1));
  655. code_edit->set_caret_line(1);
  656. /* Delete onto executing lines does not remove it. */
  657. SEND_GUI_ACTION(code_edit, "ui_text_delete");
  658. CHECK(code_edit->get_line_count() == 2);
  659. CHECK(code_edit->is_line_executing(1));
  660. /* Delete moving executing line up removes it. */
  661. code_edit->set_caret_line(0);
  662. SEND_GUI_ACTION(code_edit, "ui_text_delete");
  663. CHECK(code_edit->get_line_count() == 1);
  664. ERR_PRINT_OFF;
  665. CHECK_FALSE(code_edit->is_line_executing(1));
  666. ERR_PRINT_ON;
  667. }
  668. SUBCASE("[CodeEdit] executing lines and delete selection") {
  669. code_edit->set_text("\n\n");
  670. code_edit->set_line_as_executing(1, true);
  671. CHECK(code_edit->is_line_executing(1));
  672. code_edit->select(0, 0, 2, 0);
  673. code_edit->delete_selection();
  674. MessageQueue::get_singleton()->flush();
  675. CHECK_FALSE(code_edit->is_line_executing(0));
  676. }
  677. SUBCASE("[CodeEdit] executing lines and undo") {
  678. code_edit->set_text("\n\n");
  679. code_edit->set_line_as_executing(1, true);
  680. CHECK(code_edit->is_line_executing(1));
  681. code_edit->select(0, 0, 2, 0);
  682. code_edit->delete_selection();
  683. MessageQueue::get_singleton()->flush();
  684. CHECK_FALSE(code_edit->is_line_executing(0));
  685. /* Undo does not restore executing lines. */
  686. code_edit->undo();
  687. CHECK_FALSE(code_edit->is_line_executing(1));
  688. }
  689. }
  690. SUBCASE("[CodeEdit] line numbers") {
  691. SUBCASE("[CodeEdit] draw line numbers gutter and padding") {
  692. code_edit->set_draw_line_numbers(false);
  693. CHECK_FALSE(code_edit->is_draw_line_numbers_enabled());
  694. code_edit->set_draw_line_numbers(true);
  695. CHECK(code_edit->is_draw_line_numbers_enabled());
  696. code_edit->set_line_numbers_zero_padded(false);
  697. CHECK_FALSE(code_edit->is_line_numbers_zero_padded());
  698. code_edit->set_line_numbers_zero_padded(true);
  699. CHECK(code_edit->is_line_numbers_zero_padded());
  700. code_edit->set_line_numbers_zero_padded(false);
  701. CHECK_FALSE(code_edit->is_line_numbers_zero_padded());
  702. code_edit->set_draw_line_numbers(false);
  703. CHECK_FALSE(code_edit->is_draw_line_numbers_enabled());
  704. code_edit->set_line_numbers_zero_padded(true);
  705. CHECK(code_edit->is_line_numbers_zero_padded());
  706. }
  707. }
  708. SUBCASE("[CodeEdit] line folding") {
  709. SUBCASE("[CodeEdit] draw line folding gutter") {
  710. code_edit->set_draw_fold_gutter(false);
  711. CHECK_FALSE(code_edit->is_drawing_fold_gutter());
  712. code_edit->set_draw_fold_gutter(true);
  713. CHECK(code_edit->is_drawing_fold_gutter());
  714. }
  715. }
  716. memdelete(code_edit);
  717. }
  718. TEST_CASE("[SceneTree][CodeEdit] delimiters") {
  719. CodeEdit *code_edit = memnew(CodeEdit);
  720. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  721. const Point2 OUTSIDE_DELIMETER = Point2(-1, -1);
  722. code_edit->clear_string_delimiters();
  723. code_edit->clear_comment_delimiters();
  724. SUBCASE("[CodeEdit] add and remove delimiters") {
  725. SUBCASE("[CodeEdit] add and remove string delimiters") {
  726. /* Add a delimiter.*/
  727. code_edit->add_string_delimiter("\"", "\"", false);
  728. CHECK(code_edit->has_string_delimiter("\""));
  729. CHECK(code_edit->get_string_delimiters().size() == 1);
  730. ERR_PRINT_OFF;
  731. /* Adding a duplicate start key is not allowed. */
  732. code_edit->add_string_delimiter("\"", "\'", false);
  733. CHECK(code_edit->get_string_delimiters().size() == 1);
  734. /* Adding a duplicate end key is allowed. */
  735. code_edit->add_string_delimiter("'", "\"", false);
  736. CHECK(code_edit->has_string_delimiter("'"));
  737. CHECK(code_edit->get_string_delimiters().size() == 2);
  738. /* Both start and end keys have to be symbols. */
  739. code_edit->add_string_delimiter("f", "\"", false);
  740. CHECK_FALSE(code_edit->has_string_delimiter("f"));
  741. CHECK(code_edit->get_string_delimiters().size() == 2);
  742. code_edit->add_string_delimiter("f", "\"", false);
  743. CHECK_FALSE(code_edit->has_string_delimiter("f"));
  744. CHECK(code_edit->get_string_delimiters().size() == 2);
  745. code_edit->add_string_delimiter("@", "f", false);
  746. CHECK_FALSE(code_edit->has_string_delimiter("@"));
  747. CHECK(code_edit->get_string_delimiters().size() == 2);
  748. code_edit->add_string_delimiter("f", "f", false);
  749. CHECK_FALSE(code_edit->has_string_delimiter("f"));
  750. CHECK(code_edit->get_string_delimiters().size() == 2);
  751. /* Blank start keys are not allowed */
  752. code_edit->add_string_delimiter("", "#", false);
  753. CHECK_FALSE(code_edit->has_string_delimiter("#"));
  754. CHECK(code_edit->get_string_delimiters().size() == 2);
  755. ERR_PRINT_ON;
  756. /* Blank end keys are allowed. */
  757. code_edit->add_string_delimiter("#", "", false);
  758. CHECK(code_edit->has_string_delimiter("#"));
  759. CHECK(code_edit->get_string_delimiters().size() == 3);
  760. /* Remove a delimiter. */
  761. code_edit->remove_string_delimiter("#");
  762. CHECK_FALSE(code_edit->has_string_delimiter("#"));
  763. CHECK(code_edit->get_string_delimiters().size() == 2);
  764. /* Set should override existing, and test multiline */
  765. TypedArray<String> delimiters;
  766. delimiters.push_back("^^ ^^");
  767. code_edit->set_string_delimiters(delimiters);
  768. CHECK_FALSE(code_edit->has_string_delimiter("\""));
  769. CHECK(code_edit->has_string_delimiter("^^"));
  770. CHECK(code_edit->get_string_delimiters().size() == 1);
  771. /* clear should remove all. */
  772. code_edit->clear_string_delimiters();
  773. CHECK_FALSE(code_edit->has_string_delimiter("^^"));
  774. CHECK(code_edit->get_string_delimiters().size() == 0);
  775. }
  776. SUBCASE("[CodeEdit] add and remove comment delimiters") {
  777. /* Add a delimiter.*/
  778. code_edit->add_comment_delimiter("\"", "\"", false);
  779. CHECK(code_edit->has_comment_delimiter("\""));
  780. CHECK(code_edit->get_comment_delimiters().size() == 1);
  781. ERR_PRINT_OFF;
  782. /* Adding a duplicate start key is not allowed. */
  783. code_edit->add_comment_delimiter("\"", "\'", false);
  784. CHECK(code_edit->get_comment_delimiters().size() == 1);
  785. /* Adding a duplicate end key is allowed. */
  786. code_edit->add_comment_delimiter("'", "\"", false);
  787. CHECK(code_edit->has_comment_delimiter("'"));
  788. CHECK(code_edit->get_comment_delimiters().size() == 2);
  789. /* Both start and end keys have to be symbols. */
  790. code_edit->add_comment_delimiter("f", "\"", false);
  791. CHECK_FALSE(code_edit->has_comment_delimiter("f"));
  792. CHECK(code_edit->get_comment_delimiters().size() == 2);
  793. code_edit->add_comment_delimiter("f", "\"", false);
  794. CHECK_FALSE(code_edit->has_comment_delimiter("f"));
  795. CHECK(code_edit->get_comment_delimiters().size() == 2);
  796. code_edit->add_comment_delimiter("@", "f", false);
  797. CHECK_FALSE(code_edit->has_comment_delimiter("@"));
  798. CHECK(code_edit->get_comment_delimiters().size() == 2);
  799. code_edit->add_comment_delimiter("f", "f", false);
  800. CHECK_FALSE(code_edit->has_comment_delimiter("f"));
  801. CHECK(code_edit->get_comment_delimiters().size() == 2);
  802. /* Blank start keys are not allowed. */
  803. code_edit->add_comment_delimiter("", "#", false);
  804. CHECK_FALSE(code_edit->has_comment_delimiter("#"));
  805. CHECK(code_edit->get_comment_delimiters().size() == 2);
  806. ERR_PRINT_ON;
  807. /* Blank end keys are allowed. */
  808. code_edit->add_comment_delimiter("#", "", false);
  809. CHECK(code_edit->has_comment_delimiter("#"));
  810. CHECK(code_edit->get_comment_delimiters().size() == 3);
  811. /* Remove a delimiter. */
  812. code_edit->remove_comment_delimiter("#");
  813. CHECK_FALSE(code_edit->has_comment_delimiter("#"));
  814. CHECK(code_edit->get_comment_delimiters().size() == 2);
  815. /* Set should override existing, and test multiline. */
  816. TypedArray<String> delimiters;
  817. delimiters.push_back("^^ ^^");
  818. code_edit->set_comment_delimiters(delimiters);
  819. CHECK_FALSE(code_edit->has_comment_delimiter("\""));
  820. CHECK(code_edit->has_comment_delimiter("^^"));
  821. CHECK(code_edit->get_comment_delimiters().size() == 1);
  822. /* clear should remove all. */
  823. code_edit->clear_comment_delimiters();
  824. CHECK_FALSE(code_edit->has_comment_delimiter("^^"));
  825. CHECK(code_edit->get_comment_delimiters().size() == 0);
  826. }
  827. SUBCASE("[CodeEdit] add and remove mixed delimiters") {
  828. code_edit->add_comment_delimiter("#", "", false);
  829. CHECK(code_edit->has_comment_delimiter("#"));
  830. CHECK(code_edit->get_comment_delimiters().size() == 1);
  831. ERR_PRINT_OFF;
  832. /* Disallow adding a string with the same start key as comment. */
  833. code_edit->add_string_delimiter("#", "", false);
  834. CHECK_FALSE(code_edit->has_string_delimiter("#"));
  835. CHECK(code_edit->get_string_delimiters().size() == 0);
  836. code_edit->add_string_delimiter("\"", "\"", false);
  837. CHECK(code_edit->has_string_delimiter("\""));
  838. CHECK(code_edit->get_comment_delimiters().size() == 1);
  839. /* Disallow adding a comment with the same start key as string. */
  840. code_edit->add_comment_delimiter("\"", "", false);
  841. CHECK_FALSE(code_edit->has_comment_delimiter("\""));
  842. CHECK(code_edit->get_comment_delimiters().size() == 1);
  843. ERR_PRINT_ON;
  844. /* Cannot remove string with remove comment. */
  845. code_edit->remove_comment_delimiter("\"");
  846. CHECK(code_edit->has_string_delimiter("\""));
  847. CHECK(code_edit->get_string_delimiters().size() == 1);
  848. /* Cannot remove comment with remove string. */
  849. code_edit->remove_string_delimiter("#");
  850. CHECK(code_edit->has_comment_delimiter("#"));
  851. CHECK(code_edit->get_comment_delimiters().size() == 1);
  852. /* Clear comments leave strings. */
  853. code_edit->clear_comment_delimiters();
  854. CHECK(code_edit->has_string_delimiter("\""));
  855. CHECK(code_edit->get_string_delimiters().size() == 1);
  856. /* Clear string leave comments. */
  857. code_edit->add_comment_delimiter("#", "", false);
  858. CHECK(code_edit->has_comment_delimiter("#"));
  859. CHECK(code_edit->get_comment_delimiters().size() == 1);
  860. code_edit->clear_string_delimiters();
  861. CHECK(code_edit->has_comment_delimiter("#"));
  862. CHECK(code_edit->get_comment_delimiters().size() == 1);
  863. }
  864. }
  865. SUBCASE("[CodeEdit] single line delimiters") {
  866. SUBCASE("[CodeEdit] single line string delimiters") {
  867. /* Blank end key should set lineonly to true. */
  868. code_edit->add_string_delimiter("#", "", false);
  869. CHECK(code_edit->has_string_delimiter("#"));
  870. CHECK(code_edit->get_string_delimiters().size() == 1);
  871. /* Insert line above, line with string then line below. */
  872. code_edit->insert_text_at_caret(" \n#\n ");
  873. /* Check line above is not in string. */
  874. CHECK(code_edit->is_in_string(0, 1) == -1);
  875. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  876. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  877. /* Check column before start key is not in string. */
  878. CHECK(code_edit->is_in_string(1, 0) == -1);
  879. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  880. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  881. /* Check column after start key is in string and start / end positions are correct. */
  882. CHECK(code_edit->is_in_string(1, 1) != -1);
  883. CHECK(code_edit->get_delimiter_start_position(1, 1) == Point2(1, 1));
  884. CHECK(code_edit->get_delimiter_end_position(1, 1) == Point2(2, 1));
  885. /* Check line after is not in string. */
  886. CHECK(code_edit->is_in_string(2, 1) == -1);
  887. CHECK(code_edit->get_delimiter_start_position(2, 1) == OUTSIDE_DELIMETER);
  888. CHECK(code_edit->get_delimiter_end_position(2, 1) == OUTSIDE_DELIMETER);
  889. /* Check region metadata. */
  890. int idx = code_edit->is_in_string(1, 1);
  891. CHECK(code_edit->get_delimiter_start_key(idx) == "#");
  892. CHECK(code_edit->get_delimiter_end_key(idx) == "");
  893. /* Check nested strings are handeled correctly. */
  894. code_edit->set_text(" \n# # \n ");
  895. /* Check line above is not in string. */
  896. CHECK(code_edit->is_in_string(0, 1) == -1);
  897. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  898. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  899. /* Check column before first start key is not in string. */
  900. CHECK(code_edit->is_in_string(1, 0) == -1);
  901. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  902. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  903. /* Check column after the first start key is in string and start / end positions are correct. */
  904. CHECK(code_edit->is_in_string(1, 1) != -1);
  905. CHECK(code_edit->get_delimiter_start_position(1, 1) == Point2(1, 1));
  906. CHECK(code_edit->get_delimiter_end_position(1, 1) == Point2(6, 1));
  907. /* Check column after the second start key returns data for the first. */
  908. CHECK(code_edit->is_in_string(1, 5) != -1);
  909. CHECK(code_edit->get_delimiter_start_position(1, 5) == Point2(1, 1));
  910. CHECK(code_edit->get_delimiter_end_position(1, 5) == Point2(6, 1));
  911. /* Check line after is not in string. */
  912. CHECK(code_edit->is_in_string(2, 1) == -1);
  913. CHECK(code_edit->get_delimiter_start_position(2, 1) == OUTSIDE_DELIMETER);
  914. CHECK(code_edit->get_delimiter_end_position(2, 1) == OUTSIDE_DELIMETER);
  915. /* Check is in string with no column retruns true if entire line is comment excluding whitespace. */
  916. code_edit->set_text(" \n # # \n ");
  917. CHECK(code_edit->is_in_string(1) != -1);
  918. code_edit->set_text(" \n text # # \n ");
  919. CHECK(code_edit->is_in_string(1) == -1);
  920. /* Removing delimiter should update. */
  921. code_edit->set_text(" \n # # \n ");
  922. code_edit->remove_string_delimiter("#");
  923. CHECK_FALSE(code_edit->has_string_delimiter("$"));
  924. CHECK(code_edit->get_string_delimiters().size() == 0);
  925. CHECK(code_edit->is_in_string(1) == -1);
  926. /* Adding and clear should update. */
  927. code_edit->add_string_delimiter("#", "", false);
  928. CHECK(code_edit->has_string_delimiter("#"));
  929. CHECK(code_edit->get_string_delimiters().size() == 1);
  930. CHECK(code_edit->is_in_string(1) != -1);
  931. code_edit->clear_string_delimiters();
  932. CHECK_FALSE(code_edit->has_string_delimiter("$"));
  933. CHECK(code_edit->get_string_delimiters().size() == 0);
  934. CHECK(code_edit->is_in_string(1) == -1);
  935. }
  936. SUBCASE("[CodeEdit] single line comment delimiters") {
  937. /* Blank end key should set lineonly to true. */
  938. code_edit->add_comment_delimiter("#", "", false);
  939. CHECK(code_edit->has_comment_delimiter("#"));
  940. CHECK(code_edit->get_comment_delimiters().size() == 1);
  941. /* Insert line above, line with comment then line below. */
  942. code_edit->insert_text_at_caret(" \n#\n ");
  943. /* Check line above is not in comment. */
  944. CHECK(code_edit->is_in_comment(0, 1) == -1);
  945. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  946. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  947. /* Check column before start key is not in comment. */
  948. CHECK(code_edit->is_in_comment(1, 0) == -1);
  949. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  950. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  951. /* Check column after start key is in comment and start / end positions are correct. */
  952. CHECK(code_edit->is_in_comment(1, 1) != -1);
  953. CHECK(code_edit->get_delimiter_start_position(1, 1) == Point2(1, 1));
  954. CHECK(code_edit->get_delimiter_end_position(1, 1) == Point2(2, 1));
  955. /* Check line after is not in comment. */
  956. CHECK(code_edit->is_in_comment(2, 1) == -1);
  957. CHECK(code_edit->get_delimiter_start_position(2, 1) == OUTSIDE_DELIMETER);
  958. CHECK(code_edit->get_delimiter_end_position(2, 1) == OUTSIDE_DELIMETER);
  959. /* Check region metadata. */
  960. int idx = code_edit->is_in_comment(1, 1);
  961. CHECK(code_edit->get_delimiter_start_key(idx) == "#");
  962. CHECK(code_edit->get_delimiter_end_key(idx) == "");
  963. /* Check nested comments are handeled correctly. */
  964. code_edit->set_text(" \n# # \n ");
  965. /* Check line above is not in comment. */
  966. CHECK(code_edit->is_in_comment(0, 1) == -1);
  967. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  968. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  969. /* Check column before first start key is not in comment. */
  970. CHECK(code_edit->is_in_comment(1, 0) == -1);
  971. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  972. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  973. /* Check column after the first start key is in comment and start / end positions are correct. */
  974. CHECK(code_edit->is_in_comment(1, 1) != -1);
  975. CHECK(code_edit->get_delimiter_start_position(1, 1) == Point2(1, 1));
  976. CHECK(code_edit->get_delimiter_end_position(1, 1) == Point2(6, 1));
  977. /* Check column after the second start key returns data for the first. */
  978. CHECK(code_edit->is_in_comment(1, 5) != -1);
  979. CHECK(code_edit->get_delimiter_start_position(1, 5) == Point2(1, 1));
  980. CHECK(code_edit->get_delimiter_end_position(1, 5) == Point2(6, 1));
  981. /* Check line after is not in comment. */
  982. CHECK(code_edit->is_in_comment(2, 1) == -1);
  983. CHECK(code_edit->get_delimiter_start_position(2, 1) == OUTSIDE_DELIMETER);
  984. CHECK(code_edit->get_delimiter_end_position(2, 1) == OUTSIDE_DELIMETER);
  985. /* Check is in comment with no column retruns true if entire line is comment excluding whitespace. */
  986. code_edit->set_text(" \n # # \n ");
  987. CHECK(code_edit->is_in_comment(1) != -1);
  988. code_edit->set_text(" \n text # # \n ");
  989. CHECK(code_edit->is_in_comment(1) == -1);
  990. /* Removing delimiter should update. */
  991. code_edit->set_text(" \n # # \n ");
  992. code_edit->remove_comment_delimiter("#");
  993. CHECK_FALSE(code_edit->has_comment_delimiter("$"));
  994. CHECK(code_edit->get_comment_delimiters().size() == 0);
  995. CHECK(code_edit->is_in_comment(1) == -1);
  996. /* Adding and clear should update. */
  997. code_edit->add_comment_delimiter("#", "", false);
  998. CHECK(code_edit->has_comment_delimiter("#"));
  999. CHECK(code_edit->get_comment_delimiters().size() == 1);
  1000. CHECK(code_edit->is_in_comment(1) != -1);
  1001. code_edit->clear_comment_delimiters();
  1002. CHECK_FALSE(code_edit->has_comment_delimiter("$"));
  1003. CHECK(code_edit->get_comment_delimiters().size() == 0);
  1004. CHECK(code_edit->is_in_comment(1) == -1);
  1005. }
  1006. SUBCASE("[CodeEdit] single line mixed delimiters") {
  1007. /* Blank end key should set lineonly to true. */
  1008. /* Add string delimiter. */
  1009. code_edit->add_string_delimiter("&", "", false);
  1010. CHECK(code_edit->has_string_delimiter("&"));
  1011. CHECK(code_edit->get_string_delimiters().size() == 1);
  1012. /* Add comment delimiter. */
  1013. code_edit->add_comment_delimiter("#", "", false);
  1014. CHECK(code_edit->has_comment_delimiter("#"));
  1015. CHECK(code_edit->get_comment_delimiters().size() == 1);
  1016. /* Nest a string delimiter inside a comment. */
  1017. code_edit->set_text(" \n# & \n ");
  1018. /* Check line above is not in comment. */
  1019. CHECK(code_edit->is_in_comment(0, 1) == -1);
  1020. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  1021. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  1022. /* Check column before first start key is not in comment. */
  1023. CHECK(code_edit->is_in_comment(1, 0) == -1);
  1024. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  1025. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  1026. /* Check column after the first start key is in comment and start / end positions are correct. */
  1027. CHECK(code_edit->is_in_comment(1, 1) != -1);
  1028. CHECK(code_edit->get_delimiter_start_position(1, 1) == Point2(1, 1));
  1029. CHECK(code_edit->get_delimiter_end_position(1, 1) == Point2(6, 1));
  1030. /* Check column after the second start key returns data for the first, and does not state string. */
  1031. CHECK(code_edit->is_in_comment(1, 5) != -1);
  1032. CHECK(code_edit->get_delimiter_start_position(1, 5) == Point2(1, 1));
  1033. CHECK(code_edit->get_delimiter_end_position(1, 5) == Point2(6, 1));
  1034. CHECK(code_edit->is_in_string(1, 5) == -1);
  1035. /* Check line after is not in comment. */
  1036. CHECK(code_edit->is_in_comment(2, 1) == -1);
  1037. CHECK(code_edit->get_delimiter_start_position(2, 1) == OUTSIDE_DELIMETER);
  1038. CHECK(code_edit->get_delimiter_end_position(2, 1) == OUTSIDE_DELIMETER);
  1039. /* Remove the comment delimiter. */
  1040. code_edit->remove_comment_delimiter("#");
  1041. CHECK_FALSE(code_edit->has_comment_delimiter("$"));
  1042. CHECK(code_edit->get_comment_delimiters().size() == 0);
  1043. /* The "first" comment region is no longer valid. */
  1044. CHECK(code_edit->is_in_comment(1, 1) == -1);
  1045. CHECK(code_edit->get_delimiter_start_position(1, 1) == OUTSIDE_DELIMETER);
  1046. CHECK(code_edit->get_delimiter_end_position(1, 1) == OUTSIDE_DELIMETER);
  1047. /* The "second" region as string is now valid. */
  1048. CHECK(code_edit->is_in_string(1, 5) != -1);
  1049. CHECK(code_edit->get_delimiter_start_position(1, 5) == Point2(4, 1));
  1050. CHECK(code_edit->get_delimiter_end_position(1, 5) == Point2(6, 1));
  1051. }
  1052. }
  1053. SUBCASE("[CodeEdit] multiline delimiters") {
  1054. SUBCASE("[CodeEdit] multiline string delimiters") {
  1055. code_edit->clear_string_delimiters();
  1056. code_edit->clear_comment_delimiters();
  1057. /* Add string delimiter. */
  1058. code_edit->add_string_delimiter("#", "#", false);
  1059. CHECK(code_edit->has_string_delimiter("#"));
  1060. CHECK(code_edit->get_string_delimiters().size() == 1);
  1061. /* First test over a single line. */
  1062. code_edit->set_text(" \n # # \n ");
  1063. /* Check line above is not in string. */
  1064. CHECK(code_edit->is_in_string(0, 1) == -1);
  1065. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  1066. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  1067. /* Check column before start key is not in string. */
  1068. CHECK(code_edit->is_in_string(1, 0) == -1);
  1069. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  1070. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  1071. /* Check column before closing delimiter is in string. */
  1072. CHECK(code_edit->is_in_string(1, 2) != -1);
  1073. CHECK(code_edit->get_delimiter_start_position(1, 2) == Point2(2, 1));
  1074. CHECK(code_edit->get_delimiter_end_position(1, 2) == Point2(5, 1));
  1075. /* Check column after end key is not in string. */
  1076. CHECK(code_edit->is_in_string(1, 6) == -1);
  1077. CHECK(code_edit->get_delimiter_start_position(1, 6) == OUTSIDE_DELIMETER);
  1078. CHECK(code_edit->get_delimiter_end_position(1, 6) == OUTSIDE_DELIMETER);
  1079. /* Check line after is not in string. */
  1080. CHECK(code_edit->is_in_string(2, 1) == -1);
  1081. CHECK(code_edit->get_delimiter_start_position(2, 1) == OUTSIDE_DELIMETER);
  1082. CHECK(code_edit->get_delimiter_end_position(2, 1) == OUTSIDE_DELIMETER);
  1083. /* Check the region metadata. */
  1084. int idx = code_edit->is_in_string(1, 2);
  1085. CHECK(code_edit->get_delimiter_start_key(idx) == "#");
  1086. CHECK(code_edit->get_delimiter_end_key(idx) == "#");
  1087. /* Next test over a multiple blank lines. */
  1088. code_edit->set_text(" \n # \n\n # \n ");
  1089. /* Check line above is not in string. */
  1090. CHECK(code_edit->is_in_string(0, 1) == -1);
  1091. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  1092. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  1093. /* Check column before start key is not in string. */
  1094. CHECK(code_edit->is_in_string(1, 0) == -1);
  1095. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  1096. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  1097. /* Check column just after start key is in string. */
  1098. CHECK(code_edit->is_in_string(1, 2) != -1);
  1099. CHECK(code_edit->get_delimiter_start_position(1, 2) == Point2(2, 1));
  1100. CHECK(code_edit->get_delimiter_end_position(1, 2) == Point2(2, 3));
  1101. /* Check blank middle line. */
  1102. CHECK(code_edit->is_in_string(2, 0) != -1);
  1103. CHECK(code_edit->get_delimiter_start_position(2, 0) == Point2(2, 1));
  1104. CHECK(code_edit->get_delimiter_end_position(2, 0) == Point2(2, 3));
  1105. /* Check column just before end key is in string. */
  1106. CHECK(code_edit->is_in_string(3, 0) != -1);
  1107. CHECK(code_edit->get_delimiter_start_position(3, 0) == Point2(2, 1));
  1108. CHECK(code_edit->get_delimiter_end_position(3, 0) == Point2(2, 3));
  1109. /* Check column after end key is not in string. */
  1110. CHECK(code_edit->is_in_string(3, 3) == -1);
  1111. CHECK(code_edit->get_delimiter_start_position(3, 3) == OUTSIDE_DELIMETER);
  1112. CHECK(code_edit->get_delimiter_end_position(3, 3) == OUTSIDE_DELIMETER);
  1113. /* Check line after is not in string. */
  1114. CHECK(code_edit->is_in_string(4, 1) == -1);
  1115. CHECK(code_edit->get_delimiter_start_position(4, 1) == OUTSIDE_DELIMETER);
  1116. CHECK(code_edit->get_delimiter_end_position(4, 1) == OUTSIDE_DELIMETER);
  1117. /* Next test over a multiple non-blank lines. */
  1118. code_edit->set_text(" \n # \n \n # \n ");
  1119. /* Check line above is not in string. */
  1120. CHECK(code_edit->is_in_string(0, 1) == -1);
  1121. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  1122. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  1123. /* Check column before start key is not in string. */
  1124. CHECK(code_edit->is_in_string(1, 0) == -1);
  1125. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  1126. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  1127. /* Check column just after start key is in string. */
  1128. CHECK(code_edit->is_in_string(1, 2) != -1);
  1129. CHECK(code_edit->get_delimiter_start_position(1, 2) == Point2(2, 1));
  1130. CHECK(code_edit->get_delimiter_end_position(1, 2) == Point2(2, 3));
  1131. /* Check middle line. */
  1132. CHECK(code_edit->is_in_string(2, 0) != -1);
  1133. CHECK(code_edit->get_delimiter_start_position(2, 0) == Point2(2, 1));
  1134. CHECK(code_edit->get_delimiter_end_position(2, 0) == Point2(2, 3));
  1135. /* Check column just before end key is in string. */
  1136. CHECK(code_edit->is_in_string(3, 0) != -1);
  1137. CHECK(code_edit->get_delimiter_start_position(3, 0) == Point2(2, 1));
  1138. CHECK(code_edit->get_delimiter_end_position(3, 0) == Point2(2, 3));
  1139. /* Check column after end key is not in string. */
  1140. CHECK(code_edit->is_in_string(3, 3) == -1);
  1141. CHECK(code_edit->get_delimiter_start_position(3, 3) == OUTSIDE_DELIMETER);
  1142. CHECK(code_edit->get_delimiter_end_position(3, 3) == OUTSIDE_DELIMETER);
  1143. /* Check line after is not in string. */
  1144. CHECK(code_edit->is_in_string(4, 1) == -1);
  1145. CHECK(code_edit->get_delimiter_start_position(4, 1) == OUTSIDE_DELIMETER);
  1146. CHECK(code_edit->get_delimiter_end_position(4, 1) == OUTSIDE_DELIMETER);
  1147. /* check the region metadata. */
  1148. idx = code_edit->is_in_string(1, 2);
  1149. CHECK(code_edit->get_delimiter_start_key(idx) == "#");
  1150. CHECK(code_edit->get_delimiter_end_key(idx) == "#");
  1151. /* Next test nested strings. */
  1152. code_edit->add_string_delimiter("^", "^", false);
  1153. CHECK(code_edit->has_string_delimiter("^"));
  1154. CHECK(code_edit->get_string_delimiters().size() == 2);
  1155. code_edit->set_text(" \n # ^\n \n^ # \n ");
  1156. /* Check line above is not in string. */
  1157. CHECK(code_edit->is_in_string(0, 1) == -1);
  1158. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  1159. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  1160. /* Check column before start key is not in string. */
  1161. CHECK(code_edit->is_in_string(1, 0) == -1);
  1162. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  1163. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  1164. /* Check column just after start key is in string. */
  1165. CHECK(code_edit->is_in_string(1, 2) != -1);
  1166. CHECK(code_edit->get_delimiter_start_position(1, 2) == Point2(2, 1));
  1167. CHECK(code_edit->get_delimiter_end_position(1, 2) == Point2(3, 3));
  1168. /* Check middle line. */
  1169. CHECK(code_edit->is_in_string(2, 0) != -1);
  1170. CHECK(code_edit->get_delimiter_start_position(2, 0) == Point2(2, 1));
  1171. CHECK(code_edit->get_delimiter_end_position(2, 0) == Point2(3, 3));
  1172. /* Check column just before end key is in string. */
  1173. CHECK(code_edit->is_in_string(3, 0) != -1);
  1174. CHECK(code_edit->get_delimiter_start_position(3, 0) == Point2(2, 1));
  1175. CHECK(code_edit->get_delimiter_end_position(3, 0) == Point2(3, 3));
  1176. /* Check column after end key is not in string. */
  1177. CHECK(code_edit->is_in_string(3, 3) == -1);
  1178. CHECK(code_edit->get_delimiter_start_position(3, 3) == OUTSIDE_DELIMETER);
  1179. CHECK(code_edit->get_delimiter_end_position(3, 3) == OUTSIDE_DELIMETER);
  1180. /* Check line after is not in string. */
  1181. CHECK(code_edit->is_in_string(4, 1) == -1);
  1182. CHECK(code_edit->get_delimiter_start_position(4, 1) == OUTSIDE_DELIMETER);
  1183. CHECK(code_edit->get_delimiter_end_position(4, 1) == OUTSIDE_DELIMETER);
  1184. /* check the region metadata. */
  1185. idx = code_edit->is_in_string(1, 2);
  1186. CHECK(code_edit->get_delimiter_start_key(idx) == "#");
  1187. CHECK(code_edit->get_delimiter_end_key(idx) == "#");
  1188. /* Next test no end key. */
  1189. code_edit->set_text(" \n # \n ");
  1190. /* check the region metadata. */
  1191. idx = code_edit->is_in_string(1, 2);
  1192. CHECK(code_edit->get_delimiter_start_position(1, 2) == Point2(2, 1));
  1193. CHECK(code_edit->get_delimiter_end_position(1, 2) == Point2(-1, -1));
  1194. CHECK(code_edit->get_delimiter_start_key(idx) == "#");
  1195. CHECK(code_edit->get_delimiter_end_key(idx) == "#");
  1196. /* Check is in string with no column retruns true if entire line is string excluding whitespace. */
  1197. code_edit->set_text(" \n # \n\n #\n ");
  1198. CHECK(code_edit->is_in_string(1) != -1);
  1199. CHECK(code_edit->is_in_string(2) != -1);
  1200. CHECK(code_edit->is_in_string(3) != -1);
  1201. code_edit->set_text(" \n test # \n\n # test \n ");
  1202. CHECK(code_edit->is_in_string(1) == -1);
  1203. CHECK(code_edit->is_in_string(2) != -1);
  1204. CHECK(code_edit->is_in_string(3) == -1);
  1205. }
  1206. SUBCASE("[CodeEdit] multiline comment delimiters") {
  1207. /* Add comment delimiter. */
  1208. code_edit->add_comment_delimiter("#", "#", false);
  1209. CHECK(code_edit->has_comment_delimiter("#"));
  1210. CHECK(code_edit->get_comment_delimiters().size() == 1);
  1211. /* First test over a single line. */
  1212. code_edit->set_text(" \n # # \n ");
  1213. /* Check line above is not in comment. */
  1214. CHECK(code_edit->is_in_comment(0, 1) == -1);
  1215. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  1216. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  1217. /* Check column before start key is not in comment. */
  1218. CHECK(code_edit->is_in_comment(1, 0) == -1);
  1219. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  1220. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  1221. /* Check column before closing delimiter is in comment. */
  1222. CHECK(code_edit->is_in_comment(1, 2) != -1);
  1223. CHECK(code_edit->get_delimiter_start_position(1, 2) == Point2(2, 1));
  1224. CHECK(code_edit->get_delimiter_end_position(1, 2) == Point2(5, 1));
  1225. /* Check column after end key is not in comment. */
  1226. CHECK(code_edit->is_in_comment(1, 6) == -1);
  1227. CHECK(code_edit->get_delimiter_start_position(1, 6) == OUTSIDE_DELIMETER);
  1228. CHECK(code_edit->get_delimiter_end_position(1, 6) == OUTSIDE_DELIMETER);
  1229. /* Check line after is not in comment. */
  1230. CHECK(code_edit->is_in_comment(2, 1) == -1);
  1231. CHECK(code_edit->get_delimiter_start_position(2, 1) == OUTSIDE_DELIMETER);
  1232. CHECK(code_edit->get_delimiter_end_position(2, 1) == OUTSIDE_DELIMETER);
  1233. /* Check the region metadata. */
  1234. int idx = code_edit->is_in_comment(1, 2);
  1235. CHECK(code_edit->get_delimiter_start_key(idx) == "#");
  1236. CHECK(code_edit->get_delimiter_end_key(idx) == "#");
  1237. /* Next test over a multiple blank lines. */
  1238. code_edit->set_text(" \n # \n\n # \n ");
  1239. /* Check line above is not in comment. */
  1240. CHECK(code_edit->is_in_comment(0, 1) == -1);
  1241. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  1242. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  1243. /* Check column before start key is not in comment. */
  1244. CHECK(code_edit->is_in_comment(1, 0) == -1);
  1245. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  1246. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  1247. /* Check column just after start key is in comment. */
  1248. CHECK(code_edit->is_in_comment(1, 2) != -1);
  1249. CHECK(code_edit->get_delimiter_start_position(1, 2) == Point2(2, 1));
  1250. CHECK(code_edit->get_delimiter_end_position(1, 2) == Point2(2, 3));
  1251. /* Check blank middle line. */
  1252. CHECK(code_edit->is_in_comment(2, 0) != -1);
  1253. CHECK(code_edit->get_delimiter_start_position(2, 0) == Point2(2, 1));
  1254. CHECK(code_edit->get_delimiter_end_position(2, 0) == Point2(2, 3));
  1255. /* Check column just before end key is in comment. */
  1256. CHECK(code_edit->is_in_comment(3, 0) != -1);
  1257. CHECK(code_edit->get_delimiter_start_position(3, 0) == Point2(2, 1));
  1258. CHECK(code_edit->get_delimiter_end_position(3, 0) == Point2(2, 3));
  1259. /* Check column after end key is not in comment. */
  1260. CHECK(code_edit->is_in_comment(3, 3) == -1);
  1261. CHECK(code_edit->get_delimiter_start_position(3, 3) == OUTSIDE_DELIMETER);
  1262. CHECK(code_edit->get_delimiter_end_position(3, 3) == OUTSIDE_DELIMETER);
  1263. /* Check line after is not in comment. */
  1264. CHECK(code_edit->is_in_comment(4, 1) == -1);
  1265. CHECK(code_edit->get_delimiter_start_position(4, 1) == OUTSIDE_DELIMETER);
  1266. CHECK(code_edit->get_delimiter_end_position(4, 1) == OUTSIDE_DELIMETER);
  1267. /* Next test over a multiple non-blank lines. */
  1268. code_edit->set_text(" \n # \n \n # \n ");
  1269. /* Check line above is not in comment. */
  1270. CHECK(code_edit->is_in_comment(0, 1) == -1);
  1271. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  1272. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  1273. /* Check column before start key is not in comment. */
  1274. CHECK(code_edit->is_in_comment(1, 0) == -1);
  1275. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  1276. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  1277. /* Check column just after start key is in comment. */
  1278. CHECK(code_edit->is_in_comment(1, 2) != -1);
  1279. CHECK(code_edit->get_delimiter_start_position(1, 2) == Point2(2, 1));
  1280. CHECK(code_edit->get_delimiter_end_position(1, 2) == Point2(2, 3));
  1281. /* Check middle line. */
  1282. CHECK(code_edit->is_in_comment(2, 0) != -1);
  1283. CHECK(code_edit->get_delimiter_start_position(2, 0) == Point2(2, 1));
  1284. CHECK(code_edit->get_delimiter_end_position(2, 0) == Point2(2, 3));
  1285. /* Check column just before end key is in comment. */
  1286. CHECK(code_edit->is_in_comment(3, 0) != -1);
  1287. CHECK(code_edit->get_delimiter_start_position(3, 0) == Point2(2, 1));
  1288. CHECK(code_edit->get_delimiter_end_position(3, 0) == Point2(2, 3));
  1289. /* Check column after end key is not in comment. */
  1290. CHECK(code_edit->is_in_comment(3, 3) == -1);
  1291. CHECK(code_edit->get_delimiter_start_position(3, 3) == OUTSIDE_DELIMETER);
  1292. CHECK(code_edit->get_delimiter_end_position(3, 3) == OUTSIDE_DELIMETER);
  1293. /* Check line after is not in comment. */
  1294. CHECK(code_edit->is_in_comment(4, 1) == -1);
  1295. CHECK(code_edit->get_delimiter_start_position(4, 1) == OUTSIDE_DELIMETER);
  1296. CHECK(code_edit->get_delimiter_end_position(4, 1) == OUTSIDE_DELIMETER);
  1297. /* check the region metadata. */
  1298. idx = code_edit->is_in_comment(1, 2);
  1299. CHECK(code_edit->get_delimiter_start_key(idx) == "#");
  1300. CHECK(code_edit->get_delimiter_end_key(idx) == "#");
  1301. /* Next test nested comments. */
  1302. code_edit->add_comment_delimiter("^", "^", false);
  1303. CHECK(code_edit->has_comment_delimiter("^"));
  1304. CHECK(code_edit->get_comment_delimiters().size() == 2);
  1305. code_edit->set_text(" \n # ^\n \n^ # \n ");
  1306. /* Check line above is not in comment. */
  1307. CHECK(code_edit->is_in_comment(0, 1) == -1);
  1308. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  1309. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  1310. /* Check column before start key is not in comment. */
  1311. CHECK(code_edit->is_in_comment(1, 0) == -1);
  1312. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  1313. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  1314. /* Check column just after start key is in comment. */
  1315. CHECK(code_edit->is_in_comment(1, 2) != -1);
  1316. CHECK(code_edit->get_delimiter_start_position(1, 2) == Point2(2, 1));
  1317. CHECK(code_edit->get_delimiter_end_position(1, 2) == Point2(3, 3));
  1318. /* Check middle line. */
  1319. CHECK(code_edit->is_in_comment(2, 0) != -1);
  1320. CHECK(code_edit->get_delimiter_start_position(2, 0) == Point2(2, 1));
  1321. CHECK(code_edit->get_delimiter_end_position(2, 0) == Point2(3, 3));
  1322. /* Check column just before end key is in comment. */
  1323. CHECK(code_edit->is_in_comment(3, 0) != -1);
  1324. CHECK(code_edit->get_delimiter_start_position(3, 0) == Point2(2, 1));
  1325. CHECK(code_edit->get_delimiter_end_position(3, 0) == Point2(3, 3));
  1326. /* Check column after end key is not in comment. */
  1327. CHECK(code_edit->is_in_comment(3, 3) == -1);
  1328. CHECK(code_edit->get_delimiter_start_position(3, 3) == OUTSIDE_DELIMETER);
  1329. CHECK(code_edit->get_delimiter_end_position(3, 3) == OUTSIDE_DELIMETER);
  1330. /* Check line after is not in comment. */
  1331. CHECK(code_edit->is_in_comment(4, 1) == -1);
  1332. CHECK(code_edit->get_delimiter_start_position(4, 1) == OUTSIDE_DELIMETER);
  1333. CHECK(code_edit->get_delimiter_end_position(4, 1) == OUTSIDE_DELIMETER);
  1334. /* check the region metadata. */
  1335. idx = code_edit->is_in_comment(1, 2);
  1336. CHECK(code_edit->get_delimiter_start_key(idx) == "#");
  1337. CHECK(code_edit->get_delimiter_end_key(idx) == "#");
  1338. /* Next test no end key. */
  1339. code_edit->set_text(" \n # \n ");
  1340. /* check the region metadata. */
  1341. idx = code_edit->is_in_comment(1, 2);
  1342. CHECK(code_edit->get_delimiter_start_position(1, 2) == Point2(2, 1));
  1343. CHECK(code_edit->get_delimiter_end_position(1, 2) == Point2(-1, -1));
  1344. CHECK(code_edit->get_delimiter_start_key(idx) == "#");
  1345. CHECK(code_edit->get_delimiter_end_key(idx) == "#");
  1346. /* Check is in comment with no column retruns true if entire line is comment excluding whitespace. */
  1347. code_edit->set_text(" \n # \n\n #\n ");
  1348. CHECK(code_edit->is_in_comment(1) != -1);
  1349. CHECK(code_edit->is_in_comment(2) != -1);
  1350. CHECK(code_edit->is_in_comment(3) != -1);
  1351. code_edit->set_text(" \n test # \n\n # test \n ");
  1352. CHECK(code_edit->is_in_comment(1) == -1);
  1353. CHECK(code_edit->is_in_comment(2) != -1);
  1354. CHECK(code_edit->is_in_comment(3) == -1);
  1355. }
  1356. SUBCASE("[CodeEdit] multiline mixed delimiters") {
  1357. /* Add comment delimiter. */
  1358. code_edit->add_comment_delimiter("#", "#", false);
  1359. CHECK(code_edit->has_comment_delimiter("#"));
  1360. CHECK(code_edit->get_comment_delimiters().size() == 1);
  1361. /* Add string delimiter. */
  1362. code_edit->add_string_delimiter("^", "^", false);
  1363. CHECK(code_edit->has_string_delimiter("^"));
  1364. CHECK(code_edit->get_string_delimiters().size() == 1);
  1365. /* Nest a string inside a comment. */
  1366. code_edit->set_text(" \n # ^\n \n^ # \n ");
  1367. /* Check line above is not in comment. */
  1368. CHECK(code_edit->is_in_comment(0, 1) == -1);
  1369. CHECK(code_edit->get_delimiter_start_position(0, 1) == OUTSIDE_DELIMETER);
  1370. CHECK(code_edit->get_delimiter_end_position(0, 1) == OUTSIDE_DELIMETER);
  1371. /* Check column before start key is not in comment. */
  1372. CHECK(code_edit->is_in_comment(1, 0) == -1);
  1373. CHECK(code_edit->get_delimiter_start_position(1, 0) == OUTSIDE_DELIMETER);
  1374. CHECK(code_edit->get_delimiter_end_position(1, 0) == OUTSIDE_DELIMETER);
  1375. /* Check column just after start key is in comment. */
  1376. CHECK(code_edit->is_in_comment(1, 2) != -1);
  1377. CHECK(code_edit->get_delimiter_start_position(1, 2) == Point2(2, 1));
  1378. CHECK(code_edit->get_delimiter_end_position(1, 2) == Point2(3, 3));
  1379. /* Check middle line. */
  1380. CHECK(code_edit->is_in_comment(2, 0) != -1);
  1381. CHECK(code_edit->get_delimiter_start_position(2, 0) == Point2(2, 1));
  1382. CHECK(code_edit->get_delimiter_end_position(2, 0) == Point2(3, 3));
  1383. /* Check column just before end key is in comment. */
  1384. CHECK(code_edit->is_in_comment(3, 0) != -1);
  1385. CHECK(code_edit->get_delimiter_start_position(3, 0) == Point2(2, 1));
  1386. CHECK(code_edit->get_delimiter_end_position(3, 0) == Point2(3, 3));
  1387. /* Check column after end key is not in comment. */
  1388. CHECK(code_edit->is_in_comment(3, 3) == -1);
  1389. CHECK(code_edit->get_delimiter_start_position(3, 3) == OUTSIDE_DELIMETER);
  1390. CHECK(code_edit->get_delimiter_end_position(3, 3) == OUTSIDE_DELIMETER);
  1391. /* Check line after is not in comment. */
  1392. CHECK(code_edit->is_in_comment(4, 1) == -1);
  1393. CHECK(code_edit->get_delimiter_start_position(4, 1) == OUTSIDE_DELIMETER);
  1394. CHECK(code_edit->get_delimiter_end_position(4, 1) == OUTSIDE_DELIMETER);
  1395. /* check the region metadata. */
  1396. int idx = code_edit->is_in_comment(1, 2);
  1397. CHECK(code_edit->get_delimiter_start_key(idx) == "#");
  1398. CHECK(code_edit->get_delimiter_end_key(idx) == "#");
  1399. /* Check is in comment with no column retruns true as inner delimiter should not be counted. */
  1400. CHECK(code_edit->is_in_comment(1) != -1);
  1401. CHECK(code_edit->is_in_comment(2) != -1);
  1402. CHECK(code_edit->is_in_comment(3) != -1);
  1403. }
  1404. }
  1405. memdelete(code_edit);
  1406. }
  1407. TEST_CASE("[SceneTree][CodeEdit] indent") {
  1408. CodeEdit *code_edit = memnew(CodeEdit);
  1409. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  1410. SUBCASE("[CodeEdit] indent settings") {
  1411. code_edit->set_indent_size(10);
  1412. CHECK(code_edit->get_indent_size() == 10);
  1413. CHECK(code_edit->get_tab_size() == 10);
  1414. code_edit->set_auto_indent_enabled(false);
  1415. CHECK_FALSE(code_edit->is_auto_indent_enabled());
  1416. code_edit->set_auto_indent_enabled(true);
  1417. CHECK(code_edit->is_auto_indent_enabled());
  1418. code_edit->set_indent_using_spaces(false);
  1419. CHECK_FALSE(code_edit->is_indent_using_spaces());
  1420. code_edit->set_indent_using_spaces(true);
  1421. CHECK(code_edit->is_indent_using_spaces());
  1422. /* Only the first char is registered. */
  1423. TypedArray<String> auto_indent_prefixes;
  1424. auto_indent_prefixes.push_back("::");
  1425. auto_indent_prefixes.push_back("s");
  1426. auto_indent_prefixes.push_back("1");
  1427. code_edit->set_auto_indent_prefixes(auto_indent_prefixes);
  1428. auto_indent_prefixes = code_edit->get_auto_indent_prefixes();
  1429. CHECK(auto_indent_prefixes.has(":"));
  1430. CHECK(auto_indent_prefixes.has("s"));
  1431. CHECK(auto_indent_prefixes.has("1"));
  1432. }
  1433. SUBCASE("[CodeEdit] indent tabs") {
  1434. code_edit->set_indent_size(4);
  1435. code_edit->set_auto_indent_enabled(true);
  1436. code_edit->set_indent_using_spaces(false);
  1437. /* Do nothing if not editable. */
  1438. code_edit->set_editable(false);
  1439. code_edit->do_indent();
  1440. CHECK(code_edit->get_line(0).is_empty());
  1441. code_edit->indent_lines();
  1442. CHECK(code_edit->get_line(0).is_empty());
  1443. code_edit->set_editable(true);
  1444. /* Simple indent. */
  1445. code_edit->do_indent();
  1446. CHECK(code_edit->get_line(0) == "\t");
  1447. /* Check input action. */
  1448. SEND_GUI_ACTION(code_edit, "ui_text_indent");
  1449. CHECK(code_edit->get_line(0) == "\t\t");
  1450. /* Insert in place. */
  1451. code_edit->set_text("");
  1452. code_edit->insert_text_at_caret("test");
  1453. code_edit->do_indent();
  1454. CHECK(code_edit->get_line(0) == "test\t");
  1455. /* Indent lines does entire line and works without selection. */
  1456. code_edit->set_text("");
  1457. code_edit->insert_text_at_caret("test");
  1458. code_edit->indent_lines();
  1459. CHECK(code_edit->get_line(0) == "\ttest");
  1460. /* Selection does entire line. */
  1461. code_edit->set_text("test");
  1462. code_edit->select_all();
  1463. code_edit->do_indent();
  1464. CHECK(code_edit->get_line(0) == "\ttest");
  1465. /* Handles multiple lines. */
  1466. code_edit->set_text("test\ntext");
  1467. code_edit->select_all();
  1468. code_edit->do_indent();
  1469. CHECK(code_edit->get_line(0) == "\ttest");
  1470. CHECK(code_edit->get_line(1) == "\ttext");
  1471. /* Do not indent line if last col is zero. */
  1472. code_edit->set_text("test\ntext");
  1473. code_edit->select(0, 0, 1, 0);
  1474. code_edit->do_indent();
  1475. CHECK(code_edit->get_line(0) == "\ttest");
  1476. CHECK(code_edit->get_line(1) == "text");
  1477. /* Indent even if last column of first line. */
  1478. code_edit->set_text("test\ntext");
  1479. code_edit->select(0, 4, 1, 0);
  1480. code_edit->do_indent();
  1481. CHECK(code_edit->get_line(0) == "\ttest");
  1482. CHECK(code_edit->get_line(1) == "text");
  1483. /* Check selection is adjusted. */
  1484. code_edit->set_text("test");
  1485. code_edit->select(0, 1, 0, 2);
  1486. code_edit->do_indent();
  1487. CHECK(code_edit->get_selection_from_column() == 2);
  1488. CHECK(code_edit->get_selection_to_column() == 3);
  1489. CHECK(code_edit->get_line(0) == "\ttest");
  1490. code_edit->undo();
  1491. }
  1492. SUBCASE("[CodeEdit] indent spaces") {
  1493. code_edit->set_indent_size(4);
  1494. code_edit->set_auto_indent_enabled(true);
  1495. code_edit->set_indent_using_spaces(true);
  1496. /* Do nothing if not editable. */
  1497. code_edit->set_editable(false);
  1498. code_edit->do_indent();
  1499. CHECK(code_edit->get_line(0).is_empty());
  1500. code_edit->indent_lines();
  1501. CHECK(code_edit->get_line(0).is_empty());
  1502. code_edit->set_editable(true);
  1503. /* Simple indent. */
  1504. code_edit->do_indent();
  1505. CHECK(code_edit->get_line(0) == " ");
  1506. /* Check input action. */
  1507. SEND_GUI_ACTION(code_edit, "ui_text_indent");
  1508. CHECK(code_edit->get_line(0) == " ");
  1509. /* Insert in place. */
  1510. code_edit->set_text("");
  1511. code_edit->insert_text_at_caret("test");
  1512. code_edit->do_indent();
  1513. CHECK(code_edit->get_line(0) == "test ");
  1514. /* Indent lines does entire line and works without selection. */
  1515. code_edit->set_text("");
  1516. code_edit->insert_text_at_caret("test");
  1517. code_edit->indent_lines();
  1518. CHECK(code_edit->get_line(0) == " test");
  1519. /* Selection does entire line. */
  1520. code_edit->set_text("test");
  1521. code_edit->select_all();
  1522. code_edit->do_indent();
  1523. CHECK(code_edit->get_line(0) == " test");
  1524. /* single indent only add required spaces. */
  1525. code_edit->set_text(" test");
  1526. code_edit->select_all();
  1527. code_edit->do_indent();
  1528. CHECK(code_edit->get_line(0) == " test");
  1529. /* Handles multiple lines. */
  1530. code_edit->set_text("test\ntext");
  1531. code_edit->select_all();
  1532. code_edit->do_indent();
  1533. CHECK(code_edit->get_line(0) == " test");
  1534. CHECK(code_edit->get_line(1) == " text");
  1535. /* Do not indent line if last col is zero. */
  1536. code_edit->set_text("test\ntext");
  1537. code_edit->select(0, 0, 1, 0);
  1538. code_edit->do_indent();
  1539. CHECK(code_edit->get_line(0) == " test");
  1540. CHECK(code_edit->get_line(1) == "text");
  1541. /* Indent even if last column of first line. */
  1542. code_edit->set_text("test\ntext");
  1543. code_edit->select(0, 4, 1, 0);
  1544. code_edit->do_indent();
  1545. CHECK(code_edit->get_line(0) == " test");
  1546. CHECK(code_edit->get_line(1) == "text");
  1547. /* Check selection is adjusted. */
  1548. code_edit->set_text("test");
  1549. code_edit->select(0, 1, 0, 2);
  1550. code_edit->do_indent();
  1551. CHECK(code_edit->get_selection_from_column() == 5);
  1552. CHECK(code_edit->get_selection_to_column() == 6);
  1553. CHECK(code_edit->get_line(0) == " test");
  1554. }
  1555. SUBCASE("[CodeEdit] unindent tabs") {
  1556. code_edit->set_indent_size(4);
  1557. code_edit->set_auto_indent_enabled(true);
  1558. code_edit->set_indent_using_spaces(false);
  1559. /* Do nothing if not editable. */
  1560. code_edit->set_text("\t");
  1561. code_edit->set_editable(false);
  1562. code_edit->do_unindent();
  1563. CHECK(code_edit->get_line(0) == "\t");
  1564. code_edit->unindent_lines();
  1565. CHECK(code_edit->get_line(0) == "\t");
  1566. code_edit->set_editable(true);
  1567. /* Simple unindent. */
  1568. code_edit->do_unindent();
  1569. CHECK(code_edit->get_line(0) == "");
  1570. /* Should inindent inplace. */
  1571. code_edit->set_text("");
  1572. code_edit->insert_text_at_caret("test\t");
  1573. code_edit->do_unindent();
  1574. CHECK(code_edit->get_line(0) == "test");
  1575. /* Backspace does a simple unindent. */
  1576. code_edit->set_text("");
  1577. code_edit->insert_text_at_caret("\t");
  1578. code_edit->backspace();
  1579. CHECK(code_edit->get_line(0) == "");
  1580. /* Unindent lines does entire line and works without selection. */
  1581. code_edit->set_text("");
  1582. code_edit->insert_text_at_caret("\ttest");
  1583. code_edit->unindent_lines();
  1584. CHECK(code_edit->get_line(0) == "test");
  1585. /* Caret on col zero unindent line. */
  1586. code_edit->set_text("\t\ttest");
  1587. code_edit->do_unindent();
  1588. CHECK(code_edit->get_line(0) == "\ttest");
  1589. /* Check input action. */
  1590. code_edit->set_text("\t\ttest");
  1591. SEND_GUI_ACTION(code_edit, "ui_text_dedent");
  1592. CHECK(code_edit->get_line(0) == "\ttest");
  1593. /* Selection does entire line. */
  1594. code_edit->set_text("\t\ttest");
  1595. code_edit->select_all();
  1596. code_edit->do_unindent();
  1597. CHECK(code_edit->get_line(0) == "\ttest");
  1598. /* Handles multiple lines. */
  1599. code_edit->set_text("\ttest\n\ttext");
  1600. code_edit->select_all();
  1601. code_edit->do_unindent();
  1602. CHECK(code_edit->get_line(0) == "test");
  1603. CHECK(code_edit->get_line(1) == "text");
  1604. /* Do not unindent line if last col is zero. */
  1605. code_edit->set_text("\ttest\n\ttext");
  1606. code_edit->select(0, 0, 1, 0);
  1607. code_edit->do_unindent();
  1608. CHECK(code_edit->get_line(0) == "test");
  1609. CHECK(code_edit->get_line(1) == "\ttext");
  1610. /* Unindent even if last column of first line. */
  1611. code_edit->set_text("\ttest\n\ttext");
  1612. code_edit->select(0, 5, 1, 1);
  1613. code_edit->do_unindent();
  1614. CHECK(code_edit->get_line(0) == "test");
  1615. CHECK(code_edit->get_line(1) == "text");
  1616. /* Check selection is adjusted. */
  1617. code_edit->set_text("\ttest");
  1618. code_edit->select(0, 1, 0, 2);
  1619. code_edit->do_unindent();
  1620. CHECK(code_edit->get_selection_from_column() == 0);
  1621. CHECK(code_edit->get_selection_to_column() == 1);
  1622. CHECK(code_edit->get_line(0) == "test");
  1623. }
  1624. SUBCASE("[CodeEdit] unindent spaces") {
  1625. code_edit->set_indent_size(4);
  1626. code_edit->set_auto_indent_enabled(true);
  1627. code_edit->set_indent_using_spaces(true);
  1628. /* Do nothing if not editable. */
  1629. code_edit->set_text(" ");
  1630. code_edit->set_editable(false);
  1631. code_edit->do_unindent();
  1632. CHECK(code_edit->get_line(0) == " ");
  1633. code_edit->unindent_lines();
  1634. CHECK(code_edit->get_line(0) == " ");
  1635. code_edit->set_editable(true);
  1636. /* Simple unindent. */
  1637. code_edit->do_unindent();
  1638. CHECK(code_edit->get_line(0) == "");
  1639. /* Should inindent inplace. */
  1640. code_edit->set_text("");
  1641. code_edit->insert_text_at_caret("test ");
  1642. code_edit->do_unindent();
  1643. CHECK(code_edit->get_line(0) == "test");
  1644. /* Backspace does a simple unindent. */
  1645. code_edit->set_text("");
  1646. code_edit->insert_text_at_caret(" ");
  1647. code_edit->backspace();
  1648. CHECK(code_edit->get_line(0) == "");
  1649. /* Backspace with letter. */
  1650. code_edit->set_text("");
  1651. code_edit->insert_text_at_caret(" a");
  1652. code_edit->backspace();
  1653. CHECK(code_edit->get_line(0) == " ");
  1654. /* Unindent lines does entire line and works without selection. */
  1655. code_edit->set_text("");
  1656. code_edit->insert_text_at_caret(" test");
  1657. code_edit->unindent_lines();
  1658. CHECK(code_edit->get_line(0) == "test");
  1659. /* Caret on col zero unindent line. */
  1660. code_edit->set_text(" test");
  1661. code_edit->do_unindent();
  1662. CHECK(code_edit->get_line(0) == " test");
  1663. /* Only as far as needed */
  1664. code_edit->set_text(" test");
  1665. code_edit->do_unindent();
  1666. CHECK(code_edit->get_line(0) == " test");
  1667. /* Check input action. */
  1668. code_edit->set_text(" test");
  1669. SEND_GUI_ACTION(code_edit, "ui_text_dedent");
  1670. CHECK(code_edit->get_line(0) == " test");
  1671. /* Selection does entire line. */
  1672. code_edit->set_text(" test");
  1673. code_edit->select_all();
  1674. code_edit->do_unindent();
  1675. CHECK(code_edit->get_line(0) == " test");
  1676. /* Handles multiple lines. */
  1677. code_edit->set_text(" test\n text");
  1678. code_edit->select_all();
  1679. code_edit->do_unindent();
  1680. CHECK(code_edit->get_line(0) == "test");
  1681. CHECK(code_edit->get_line(1) == "text");
  1682. /* Do not unindent line if last col is zero. */
  1683. code_edit->set_text(" test\n text");
  1684. code_edit->select(0, 0, 1, 0);
  1685. code_edit->do_unindent();
  1686. CHECK(code_edit->get_line(0) == "test");
  1687. CHECK(code_edit->get_line(1) == " text");
  1688. /* Unindent even if last column of first line. */
  1689. code_edit->set_text(" test\n text");
  1690. code_edit->select(0, 5, 1, 1);
  1691. code_edit->do_unindent();
  1692. CHECK(code_edit->get_line(0) == "test");
  1693. CHECK(code_edit->get_line(1) == "text");
  1694. /* Check selection is adjusted. */
  1695. code_edit->set_text(" test");
  1696. code_edit->select(0, 4, 0, 5);
  1697. code_edit->do_unindent();
  1698. CHECK(code_edit->get_selection_from_column() == 0);
  1699. CHECK(code_edit->get_selection_to_column() == 1);
  1700. CHECK(code_edit->get_line(0) == "test");
  1701. }
  1702. SUBCASE("[CodeEdit] auto indent") {
  1703. SUBCASE("[CodeEdit] auto indent tabs") {
  1704. code_edit->set_indent_size(4);
  1705. code_edit->set_auto_indent_enabled(true);
  1706. code_edit->set_indent_using_spaces(false);
  1707. /* Simple indent on new line. */
  1708. code_edit->set_text("");
  1709. code_edit->insert_text_at_caret("test:");
  1710. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  1711. CHECK(code_edit->get_line(0) == "test:");
  1712. CHECK(code_edit->get_line(1) == "\t");
  1713. /* new blank line should still indent. */
  1714. code_edit->set_text("");
  1715. code_edit->insert_text_at_caret("test:");
  1716. SEND_GUI_ACTION(code_edit, "ui_text_newline_blank");
  1717. CHECK(code_edit->get_line(0) == "test:");
  1718. CHECK(code_edit->get_line(1) == "\t");
  1719. /* new line above should not indent. */
  1720. code_edit->set_text("");
  1721. code_edit->insert_text_at_caret("test:");
  1722. SEND_GUI_ACTION(code_edit, "ui_text_newline_above");
  1723. CHECK(code_edit->get_line(0) == "");
  1724. CHECK(code_edit->get_line(1) == "test:");
  1725. /* Whitespace between symbol and caret is okay. */
  1726. code_edit->set_text("");
  1727. code_edit->insert_text_at_caret("test: ");
  1728. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  1729. CHECK(code_edit->get_line(0) == "test: ");
  1730. CHECK(code_edit->get_line(1) == "\t");
  1731. /* Comment between symbol and caret is okay. */
  1732. code_edit->add_comment_delimiter("#", "");
  1733. code_edit->set_text("");
  1734. code_edit->insert_text_at_caret("test: # comment");
  1735. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  1736. CHECK(code_edit->get_line(0) == "test: # comment");
  1737. CHECK(code_edit->get_line(1) == "\t");
  1738. code_edit->remove_comment_delimiter("#");
  1739. /* Strings between symbol and caret are not okay. */
  1740. code_edit->add_string_delimiter("#", "");
  1741. code_edit->set_text("");
  1742. code_edit->insert_text_at_caret("test: # string");
  1743. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  1744. CHECK(code_edit->get_line(0) == "test: # string");
  1745. CHECK(code_edit->get_line(1) == "");
  1746. code_edit->remove_comment_delimiter("#");
  1747. /* If between brace pairs an extra line is added. */
  1748. code_edit->set_text("");
  1749. code_edit->insert_text_at_caret("test{}");
  1750. code_edit->set_caret_column(5);
  1751. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  1752. CHECK(code_edit->get_line(0) == "test{");
  1753. CHECK(code_edit->get_line(1) == "\t");
  1754. CHECK(code_edit->get_line(2) == "}");
  1755. /* Except when we are going above. */
  1756. code_edit->set_text("");
  1757. code_edit->insert_text_at_caret("test{}");
  1758. code_edit->set_caret_column(5);
  1759. SEND_GUI_ACTION(code_edit, "ui_text_newline_above");
  1760. CHECK(code_edit->get_line(0) == "");
  1761. CHECK(code_edit->get_line(1) == "test{}");
  1762. /* or below. */
  1763. code_edit->set_text("");
  1764. code_edit->insert_text_at_caret("test{}");
  1765. code_edit->set_caret_column(5);
  1766. SEND_GUI_ACTION(code_edit, "ui_text_newline_blank");
  1767. CHECK(code_edit->get_line(0) == "test{}");
  1768. CHECK(code_edit->get_line(1) == "");
  1769. }
  1770. SUBCASE("[CodeEdit] auto indent spaces") {
  1771. code_edit->set_indent_size(4);
  1772. code_edit->set_auto_indent_enabled(true);
  1773. code_edit->set_indent_using_spaces(true);
  1774. /* Simple indent on new line. */
  1775. code_edit->set_text("");
  1776. code_edit->insert_text_at_caret("test:");
  1777. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  1778. CHECK(code_edit->get_line(0) == "test:");
  1779. CHECK(code_edit->get_line(1) == " ");
  1780. /* new blank line should still indent. */
  1781. code_edit->set_text("");
  1782. code_edit->insert_text_at_caret("test:");
  1783. SEND_GUI_ACTION(code_edit, "ui_text_newline_blank");
  1784. CHECK(code_edit->get_line(0) == "test:");
  1785. CHECK(code_edit->get_line(1) == " ");
  1786. /* new line above should not indent. */
  1787. code_edit->set_text("");
  1788. code_edit->insert_text_at_caret("test:");
  1789. SEND_GUI_ACTION(code_edit, "ui_text_newline_above");
  1790. CHECK(code_edit->get_line(0) == "");
  1791. CHECK(code_edit->get_line(1) == "test:");
  1792. /* Whitespace between symbol and caret is okay. */
  1793. code_edit->set_text("");
  1794. code_edit->insert_text_at_caret("test: ");
  1795. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  1796. CHECK(code_edit->get_line(0) == "test: ");
  1797. CHECK(code_edit->get_line(1) == " ");
  1798. /* Comment between symbol and caret is okay. */
  1799. code_edit->add_comment_delimiter("#", "");
  1800. code_edit->set_text("");
  1801. code_edit->insert_text_at_caret("test: # comment");
  1802. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  1803. CHECK(code_edit->get_line(0) == "test: # comment");
  1804. CHECK(code_edit->get_line(1) == " ");
  1805. code_edit->remove_comment_delimiter("#");
  1806. /* Strings between symbol and caret are not okay. */
  1807. code_edit->add_string_delimiter("#", "");
  1808. code_edit->set_text("");
  1809. code_edit->insert_text_at_caret("test: # string");
  1810. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  1811. CHECK(code_edit->get_line(0) == "test: # string");
  1812. CHECK(code_edit->get_line(1) == "");
  1813. code_edit->remove_comment_delimiter("#");
  1814. /* If between brace pairs an extra line is added. */
  1815. code_edit->set_text("");
  1816. code_edit->insert_text_at_caret("test{}");
  1817. code_edit->set_caret_column(5);
  1818. SEND_GUI_ACTION(code_edit, "ui_text_newline");
  1819. CHECK(code_edit->get_line(0) == "test{");
  1820. CHECK(code_edit->get_line(1) == " ");
  1821. CHECK(code_edit->get_line(2) == "}");
  1822. /* Except when we are going above. */
  1823. code_edit->set_text("");
  1824. code_edit->insert_text_at_caret("test{}");
  1825. code_edit->set_caret_column(5);
  1826. SEND_GUI_ACTION(code_edit, "ui_text_newline_above");
  1827. CHECK(code_edit->get_line(0) == "");
  1828. CHECK(code_edit->get_line(1) == "test{}");
  1829. /* or below. */
  1830. code_edit->set_text("");
  1831. code_edit->insert_text_at_caret("test{}");
  1832. code_edit->set_caret_column(5);
  1833. SEND_GUI_ACTION(code_edit, "ui_text_newline_blank");
  1834. CHECK(code_edit->get_line(0) == "test{}");
  1835. CHECK(code_edit->get_line(1) == "");
  1836. }
  1837. }
  1838. memdelete(code_edit);
  1839. }
  1840. TEST_CASE("[SceneTree][CodeEdit] folding") {
  1841. CodeEdit *code_edit = memnew(CodeEdit);
  1842. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  1843. SUBCASE("[CodeEdit] folding settings") {
  1844. code_edit->set_line_folding_enabled(true);
  1845. CHECK(code_edit->is_line_folding_enabled());
  1846. code_edit->set_line_folding_enabled(false);
  1847. CHECK_FALSE(code_edit->is_line_folding_enabled());
  1848. }
  1849. SUBCASE("[CodeEdit] folding") {
  1850. code_edit->set_line_folding_enabled(true);
  1851. // No indent.
  1852. code_edit->set_text("line1\nline2\nline3");
  1853. for (int i = 0; i < 2; i++) {
  1854. CHECK_FALSE(code_edit->can_fold_line(i));
  1855. code_edit->fold_line(i);
  1856. CHECK_FALSE(code_edit->is_line_folded(i));
  1857. }
  1858. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1859. // Indented lines.
  1860. code_edit->set_text("\tline1\n\tline2\n\tline3");
  1861. for (int i = 0; i < 2; i++) {
  1862. CHECK_FALSE(code_edit->can_fold_line(i));
  1863. code_edit->fold_line(i);
  1864. CHECK_FALSE(code_edit->is_line_folded(i));
  1865. }
  1866. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1867. // Indent.
  1868. code_edit->set_text("line1\n\tline2\nline3");
  1869. CHECK(code_edit->can_fold_line(0));
  1870. for (int i = 1; i < 2; i++) {
  1871. CHECK_FALSE(code_edit->can_fold_line(i));
  1872. code_edit->fold_line(i);
  1873. CHECK_FALSE(code_edit->is_line_folded(i));
  1874. }
  1875. code_edit->fold_line(0);
  1876. CHECK(code_edit->is_line_folded(0));
  1877. CHECK_FALSE(code_edit->is_line_folded(1));
  1878. CHECK_FALSE(code_edit->is_line_folded(2));
  1879. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  1880. // Nested indents.
  1881. code_edit->set_text("line1\n\tline2\n\t\tline3\nline4");
  1882. CHECK(code_edit->can_fold_line(0));
  1883. CHECK(code_edit->can_fold_line(1));
  1884. for (int i = 2; i < 3; i++) {
  1885. CHECK_FALSE(code_edit->can_fold_line(i));
  1886. code_edit->fold_line(i);
  1887. CHECK_FALSE(code_edit->is_line_folded(i));
  1888. }
  1889. code_edit->fold_line(1);
  1890. CHECK_FALSE(code_edit->is_line_folded(0));
  1891. CHECK(code_edit->is_line_folded(1));
  1892. CHECK_FALSE(code_edit->is_line_folded(2));
  1893. CHECK_FALSE(code_edit->is_line_folded(3));
  1894. CHECK(code_edit->get_next_visible_line_offset_from(2, 1) == 2);
  1895. code_edit->fold_line(0);
  1896. CHECK(code_edit->is_line_folded(0));
  1897. CHECK_FALSE(code_edit->is_line_folded(1));
  1898. CHECK_FALSE(code_edit->is_line_folded(2));
  1899. CHECK_FALSE(code_edit->is_line_folded(3));
  1900. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  1901. // Check metadata.
  1902. CHECK(code_edit->get_folded_lines().size() == 1);
  1903. CHECK((int)code_edit->get_folded_lines()[0] == 0);
  1904. // Cannot unfold nested.
  1905. code_edit->unfold_line(1);
  1906. CHECK_FALSE(code_edit->is_line_folded(0));
  1907. CHECK_FALSE(code_edit->is_line_folded(1));
  1908. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1909. // (un)Fold all / toggle.
  1910. code_edit->unfold_line(0);
  1911. CHECK_FALSE(code_edit->is_line_folded(0));
  1912. CHECK_FALSE(code_edit->is_line_folded(1));
  1913. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1914. // Check metadata.
  1915. CHECK(code_edit->get_folded_lines().size() == 0);
  1916. code_edit->fold_all_lines();
  1917. CHECK(code_edit->is_line_folded(0));
  1918. CHECK_FALSE(code_edit->is_line_folded(1));
  1919. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  1920. code_edit->unfold_all_lines();
  1921. CHECK_FALSE(code_edit->is_line_folded(0));
  1922. CHECK_FALSE(code_edit->is_line_folded(1));
  1923. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1924. code_edit->toggle_foldable_line(0);
  1925. CHECK(code_edit->is_line_folded(0));
  1926. CHECK_FALSE(code_edit->is_line_folded(1));
  1927. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  1928. // Can also unfold from hidden line.
  1929. code_edit->unfold_line(1);
  1930. CHECK_FALSE(code_edit->is_line_folded(0));
  1931. CHECK_FALSE(code_edit->is_line_folded(1));
  1932. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1933. // Blank lines.
  1934. code_edit->set_text("line1\n\tline2\n\n\n\ttest\n\nline3");
  1935. CHECK(code_edit->can_fold_line(0));
  1936. for (int i = 1; i < code_edit->get_line_count(); i++) {
  1937. CHECK_FALSE(code_edit->can_fold_line(i));
  1938. code_edit->fold_line(i);
  1939. CHECK_FALSE(code_edit->is_line_folded(i));
  1940. }
  1941. code_edit->fold_line(0);
  1942. CHECK(code_edit->is_line_folded(0));
  1943. for (int i = 1; i < code_edit->get_line_count(); i++) {
  1944. CHECK_FALSE(code_edit->is_line_folded(i));
  1945. }
  1946. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 6);
  1947. // End of file.
  1948. code_edit->set_text("line1\n\tline2");
  1949. CHECK(code_edit->can_fold_line(0));
  1950. CHECK_FALSE(code_edit->can_fold_line(1));
  1951. code_edit->fold_line(1);
  1952. CHECK_FALSE(code_edit->is_line_folded(1));
  1953. code_edit->fold_line(0);
  1954. CHECK(code_edit->is_line_folded(0));
  1955. CHECK_FALSE(code_edit->is_line_folded(1));
  1956. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1957. // Comment & string blocks.
  1958. // Single line block
  1959. code_edit->add_comment_delimiter("#", "", true);
  1960. code_edit->set_text("#line1\n#\tline2");
  1961. CHECK(code_edit->can_fold_line(0));
  1962. CHECK_FALSE(code_edit->can_fold_line(1));
  1963. code_edit->fold_line(1);
  1964. CHECK_FALSE(code_edit->is_line_folded(1));
  1965. code_edit->fold_line(0);
  1966. CHECK(code_edit->is_line_folded(0));
  1967. CHECK_FALSE(code_edit->is_line_folded(1));
  1968. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1969. // Has to be full line.
  1970. code_edit->set_text("test #line1\n#\tline2");
  1971. CHECK_FALSE(code_edit->can_fold_line(0));
  1972. CHECK_FALSE(code_edit->can_fold_line(1));
  1973. code_edit->fold_line(1);
  1974. CHECK_FALSE(code_edit->is_line_folded(1));
  1975. code_edit->fold_line(0);
  1976. CHECK_FALSE(code_edit->is_line_folded(0));
  1977. CHECK_FALSE(code_edit->is_line_folded(1));
  1978. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1979. code_edit->set_text("#line1\ntest #\tline2");
  1980. CHECK_FALSE(code_edit->can_fold_line(0));
  1981. CHECK_FALSE(code_edit->can_fold_line(1));
  1982. code_edit->fold_line(1);
  1983. CHECK_FALSE(code_edit->is_line_folded(1));
  1984. code_edit->fold_line(0);
  1985. CHECK_FALSE(code_edit->is_line_folded(0));
  1986. CHECK_FALSE(code_edit->is_line_folded(1));
  1987. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1988. // String.
  1989. code_edit->add_string_delimiter("^", "", true);
  1990. code_edit->set_text("^line1\n^\tline2");
  1991. CHECK(code_edit->can_fold_line(0));
  1992. CHECK_FALSE(code_edit->can_fold_line(1));
  1993. code_edit->fold_line(1);
  1994. CHECK_FALSE(code_edit->is_line_folded(1));
  1995. code_edit->fold_line(0);
  1996. CHECK(code_edit->is_line_folded(0));
  1997. CHECK_FALSE(code_edit->is_line_folded(1));
  1998. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1999. // Has to be full line.
  2000. code_edit->set_text("test ^line1\n^\tline2");
  2001. CHECK_FALSE(code_edit->can_fold_line(0));
  2002. CHECK_FALSE(code_edit->can_fold_line(1));
  2003. code_edit->fold_line(1);
  2004. CHECK_FALSE(code_edit->is_line_folded(1));
  2005. code_edit->fold_line(0);
  2006. CHECK_FALSE(code_edit->is_line_folded(0));
  2007. CHECK_FALSE(code_edit->is_line_folded(1));
  2008. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2009. code_edit->set_text("^line1\ntest ^\tline2");
  2010. CHECK_FALSE(code_edit->can_fold_line(0));
  2011. CHECK_FALSE(code_edit->can_fold_line(1));
  2012. code_edit->fold_line(1);
  2013. CHECK_FALSE(code_edit->is_line_folded(1));
  2014. code_edit->fold_line(0);
  2015. CHECK_FALSE(code_edit->is_line_folded(0));
  2016. CHECK_FALSE(code_edit->is_line_folded(1));
  2017. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2018. // Multiline blocks.
  2019. code_edit->add_comment_delimiter("&", "&", false);
  2020. code_edit->set_text("&line1\n\tline2&");
  2021. CHECK(code_edit->can_fold_line(0));
  2022. CHECK_FALSE(code_edit->can_fold_line(1));
  2023. code_edit->fold_line(1);
  2024. CHECK_FALSE(code_edit->is_line_folded(1));
  2025. code_edit->fold_line(0);
  2026. CHECK(code_edit->is_line_folded(0));
  2027. CHECK_FALSE(code_edit->is_line_folded(1));
  2028. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2029. // Has to be full line.
  2030. code_edit->set_text("test &line1\n\tline2&");
  2031. CHECK_FALSE(code_edit->can_fold_line(0));
  2032. CHECK_FALSE(code_edit->can_fold_line(1));
  2033. code_edit->fold_line(1);
  2034. CHECK_FALSE(code_edit->is_line_folded(1));
  2035. code_edit->fold_line(0);
  2036. CHECK_FALSE(code_edit->is_line_folded(0));
  2037. CHECK_FALSE(code_edit->is_line_folded(1));
  2038. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2039. code_edit->set_text("&line1\n\tline2& test");
  2040. CHECK_FALSE(code_edit->can_fold_line(0));
  2041. CHECK_FALSE(code_edit->can_fold_line(1));
  2042. code_edit->fold_line(1);
  2043. CHECK_FALSE(code_edit->is_line_folded(1));
  2044. code_edit->fold_line(0);
  2045. CHECK_FALSE(code_edit->is_line_folded(0));
  2046. CHECK_FALSE(code_edit->is_line_folded(1));
  2047. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2048. // Strings.
  2049. code_edit->add_string_delimiter("$", "$", false);
  2050. code_edit->set_text("$line1\n\tline2$");
  2051. CHECK(code_edit->can_fold_line(0));
  2052. CHECK_FALSE(code_edit->can_fold_line(1));
  2053. code_edit->fold_line(1);
  2054. CHECK_FALSE(code_edit->is_line_folded(1));
  2055. code_edit->fold_line(0);
  2056. CHECK(code_edit->is_line_folded(0));
  2057. CHECK_FALSE(code_edit->is_line_folded(1));
  2058. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2059. // Has to be full line.
  2060. code_edit->set_text("test $line1\n\tline2$");
  2061. CHECK_FALSE(code_edit->can_fold_line(0));
  2062. CHECK_FALSE(code_edit->can_fold_line(1));
  2063. code_edit->fold_line(1);
  2064. CHECK_FALSE(code_edit->is_line_folded(1));
  2065. code_edit->fold_line(0);
  2066. CHECK_FALSE(code_edit->is_line_folded(0));
  2067. CHECK_FALSE(code_edit->is_line_folded(1));
  2068. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2069. code_edit->set_text("$line1\n\tline2$ test");
  2070. CHECK_FALSE(code_edit->can_fold_line(0));
  2071. CHECK_FALSE(code_edit->can_fold_line(1));
  2072. code_edit->fold_line(1);
  2073. CHECK_FALSE(code_edit->is_line_folded(1));
  2074. code_edit->fold_line(0);
  2075. CHECK_FALSE(code_edit->is_line_folded(0));
  2076. CHECK_FALSE(code_edit->is_line_folded(1));
  2077. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2078. // Non-indented comments/ strings.
  2079. // Single line
  2080. code_edit->set_text("test\n\tline1\n#line1\n#line2\n\ttest");
  2081. CHECK(code_edit->can_fold_line(0));
  2082. CHECK_FALSE(code_edit->can_fold_line(1));
  2083. code_edit->fold_line(1);
  2084. CHECK_FALSE(code_edit->is_line_folded(1));
  2085. code_edit->fold_line(0);
  2086. CHECK(code_edit->is_line_folded(0));
  2087. CHECK_FALSE(code_edit->is_line_folded(1));
  2088. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2089. code_edit->set_text("test\n\tline1\n^line1\n^line2\n\ttest");
  2090. CHECK(code_edit->can_fold_line(0));
  2091. CHECK_FALSE(code_edit->can_fold_line(1));
  2092. code_edit->fold_line(1);
  2093. CHECK_FALSE(code_edit->is_line_folded(1));
  2094. code_edit->fold_line(0);
  2095. CHECK(code_edit->is_line_folded(0));
  2096. CHECK_FALSE(code_edit->is_line_folded(1));
  2097. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2098. // Multiline
  2099. code_edit->set_text("test\n\tline1\n&line1\nline2&\n\ttest");
  2100. CHECK(code_edit->can_fold_line(0));
  2101. CHECK_FALSE(code_edit->can_fold_line(1));
  2102. code_edit->fold_line(1);
  2103. CHECK_FALSE(code_edit->is_line_folded(1));
  2104. code_edit->fold_line(0);
  2105. CHECK(code_edit->is_line_folded(0));
  2106. CHECK_FALSE(code_edit->is_line_folded(1));
  2107. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2108. code_edit->set_text("test\n\tline1\n$line1\nline2$\n\ttest");
  2109. CHECK(code_edit->can_fold_line(0));
  2110. CHECK_FALSE(code_edit->can_fold_line(1));
  2111. code_edit->fold_line(1);
  2112. CHECK_FALSE(code_edit->is_line_folded(1));
  2113. code_edit->fold_line(0);
  2114. CHECK(code_edit->is_line_folded(0));
  2115. CHECK_FALSE(code_edit->is_line_folded(1));
  2116. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2117. }
  2118. memdelete(code_edit);
  2119. }
  2120. TEST_CASE("[SceneTree][CodeEdit] completion") {
  2121. CodeEdit *code_edit = memnew(CodeEdit);
  2122. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  2123. SUBCASE("[CodeEdit] auto brace completion") {
  2124. code_edit->set_auto_brace_completion_enabled(true);
  2125. CHECK(code_edit->is_auto_brace_completion_enabled());
  2126. code_edit->set_highlight_matching_braces_enabled(true);
  2127. CHECK(code_edit->is_highlight_matching_braces_enabled());
  2128. /* Try setters, any length. */
  2129. Dictionary auto_brace_completion_pairs;
  2130. auto_brace_completion_pairs["["] = "]";
  2131. auto_brace_completion_pairs["'"] = "'";
  2132. auto_brace_completion_pairs[";"] = "'";
  2133. auto_brace_completion_pairs["'''"] = "'''";
  2134. code_edit->set_auto_brace_completion_pairs(auto_brace_completion_pairs);
  2135. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2136. CHECK(code_edit->get_auto_brace_completion_pairs()["["] == "]");
  2137. CHECK(code_edit->get_auto_brace_completion_pairs()["'"] == "'");
  2138. CHECK(code_edit->get_auto_brace_completion_pairs()[";"] == "'");
  2139. CHECK(code_edit->get_auto_brace_completion_pairs()["'''"] == "'''");
  2140. ERR_PRINT_OFF;
  2141. /* No duplicate start keys. */
  2142. code_edit->add_auto_brace_completion_pair("[", "]");
  2143. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2144. /* No empty keys. */
  2145. code_edit->add_auto_brace_completion_pair("[", "");
  2146. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2147. code_edit->add_auto_brace_completion_pair("", "]");
  2148. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2149. code_edit->add_auto_brace_completion_pair("", "");
  2150. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2151. /* Must be a symbol. */
  2152. code_edit->add_auto_brace_completion_pair("a", "]");
  2153. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2154. code_edit->add_auto_brace_completion_pair("[", "a");
  2155. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2156. code_edit->add_auto_brace_completion_pair("a", "a");
  2157. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2158. ERR_PRINT_ON;
  2159. /* Check metadata. */
  2160. CHECK(code_edit->has_auto_brace_completion_open_key("["));
  2161. CHECK(code_edit->has_auto_brace_completion_open_key("'"));
  2162. CHECK(code_edit->has_auto_brace_completion_open_key(";"));
  2163. CHECK(code_edit->has_auto_brace_completion_open_key("'''"));
  2164. CHECK_FALSE(code_edit->has_auto_brace_completion_open_key("("));
  2165. CHECK(code_edit->has_auto_brace_completion_close_key("]"));
  2166. CHECK(code_edit->has_auto_brace_completion_close_key("'"));
  2167. CHECK(code_edit->has_auto_brace_completion_close_key("'''"));
  2168. CHECK_FALSE(code_edit->has_auto_brace_completion_close_key(")"));
  2169. CHECK(code_edit->get_auto_brace_completion_close_key("[") == "]");
  2170. CHECK(code_edit->get_auto_brace_completion_close_key("'") == "'");
  2171. CHECK(code_edit->get_auto_brace_completion_close_key(";") == "'");
  2172. CHECK(code_edit->get_auto_brace_completion_close_key("'''") == "'''");
  2173. CHECK(code_edit->get_auto_brace_completion_close_key("(").is_empty());
  2174. /* Check typing inserts closing pair. */
  2175. code_edit->clear();
  2176. SEND_GUI_KEY_EVENT(code_edit, KEY_BRACKETLEFT);
  2177. CHECK(code_edit->get_line(0) == "[]");
  2178. /* Should first match and insert smaller key. */
  2179. code_edit->clear();
  2180. SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE);
  2181. CHECK(code_edit->get_line(0) == "''");
  2182. CHECK(code_edit->get_caret_column() == 1);
  2183. /* Move out from centre, Should match and insert larger key. */
  2184. SEND_GUI_ACTION(code_edit, "ui_text_caret_right");
  2185. SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE);
  2186. CHECK(code_edit->get_line(0) == "''''''");
  2187. CHECK(code_edit->get_caret_column() == 3);
  2188. /* Backspace should remove all. */
  2189. SEND_GUI_ACTION(code_edit, "ui_text_backspace");
  2190. CHECK(code_edit->get_line(0).is_empty());
  2191. /* If in between and typing close key should "skip". */
  2192. SEND_GUI_KEY_EVENT(code_edit, KEY_BRACKETLEFT);
  2193. CHECK(code_edit->get_line(0) == "[]");
  2194. CHECK(code_edit->get_caret_column() == 1);
  2195. SEND_GUI_KEY_EVENT(code_edit, KEY_BRACKETRIGHT);
  2196. CHECK(code_edit->get_line(0) == "[]");
  2197. CHECK(code_edit->get_caret_column() == 2);
  2198. /* If current is char and inserting a string, do not autocomplete. */
  2199. code_edit->clear();
  2200. SEND_GUI_KEY_EVENT(code_edit, KEY_A);
  2201. SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE);
  2202. CHECK(code_edit->get_line(0) == "A'");
  2203. /* If in comment, do not complete. */
  2204. code_edit->add_comment_delimiter("#", "");
  2205. code_edit->clear();
  2206. SEND_GUI_KEY_EVENT(code_edit, KEY_NUMBERSIGN);
  2207. SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE);
  2208. CHECK(code_edit->get_line(0) == "#'");
  2209. /* If in string, and inserting string do not complete. */
  2210. code_edit->clear();
  2211. SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE);
  2212. SEND_GUI_KEY_EVENT(code_edit, KEY_QUOTEDBL);
  2213. CHECK(code_edit->get_line(0) == "'\"'");
  2214. }
  2215. SUBCASE("[CodeEdit] autocomplete") {
  2216. code_edit->set_code_completion_enabled(true);
  2217. CHECK(code_edit->is_code_completion_enabled());
  2218. /* Set prefixes, single char only, disallow empty. */
  2219. TypedArray<String> completion_prefixes;
  2220. completion_prefixes.push_back("");
  2221. completion_prefixes.push_back(".");
  2222. completion_prefixes.push_back(".");
  2223. completion_prefixes.push_back(",,");
  2224. ERR_PRINT_OFF;
  2225. code_edit->set_code_completion_prefixes(completion_prefixes);
  2226. ERR_PRINT_ON;
  2227. completion_prefixes = code_edit->get_code_completion_prefixes();
  2228. CHECK(completion_prefixes.size() == 2);
  2229. CHECK(completion_prefixes.has("."));
  2230. CHECK(completion_prefixes.has(","));
  2231. code_edit->set_text("test\ntest");
  2232. CHECK(code_edit->get_text_for_code_completion() == String::chr(0xFFFF) + "test\ntest");
  2233. }
  2234. SUBCASE("[CodeEdit] autocomplete request") {
  2235. SIGNAL_WATCH(code_edit, "request_code_completion");
  2236. code_edit->set_code_completion_enabled(true);
  2237. Array signal_args;
  2238. signal_args.push_back(Array());
  2239. /* Force request. */
  2240. code_edit->request_code_completion();
  2241. SIGNAL_CHECK_FALSE("request_code_completion");
  2242. code_edit->request_code_completion(true);
  2243. SIGNAL_CHECK("request_code_completion", signal_args);
  2244. /* Manual request should force. */
  2245. SEND_GUI_ACTION(code_edit, "ui_text_completion_query");
  2246. SIGNAL_CHECK("request_code_completion", signal_args);
  2247. /* Insert prefix. */
  2248. TypedArray<String> completion_prefixes;
  2249. completion_prefixes.push_back(".");
  2250. code_edit->set_code_completion_prefixes(completion_prefixes);
  2251. code_edit->insert_text_at_caret(".");
  2252. code_edit->request_code_completion();
  2253. SIGNAL_CHECK("request_code_completion", signal_args);
  2254. /* Should work with space too. */
  2255. code_edit->insert_text_at_caret(" ");
  2256. code_edit->request_code_completion();
  2257. SIGNAL_CHECK("request_code_completion", signal_args);
  2258. /* Should work when complete ends with prefix. */
  2259. code_edit->clear();
  2260. code_edit->insert_text_at_caret("t");
  2261. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "test.", "test.");
  2262. code_edit->update_code_completion_options();
  2263. code_edit->confirm_code_completion();
  2264. CHECK(code_edit->get_line(0) == "test.");
  2265. SIGNAL_CHECK("request_code_completion", signal_args);
  2266. SIGNAL_UNWATCH(code_edit, "request_code_completion");
  2267. }
  2268. SUBCASE("[CodeEdit] autocomplete completion") {
  2269. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2270. code_edit->set_code_completion_enabled(true);
  2271. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2272. code_edit->update_code_completion_options();
  2273. code_edit->set_code_completion_selected_index(1);
  2274. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2275. CHECK(code_edit->get_code_completion_option(0).size() == 0);
  2276. CHECK(code_edit->get_code_completion_options().size() == 0);
  2277. /* Adding does not update the list. */
  2278. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_0.", "item_0");
  2279. code_edit->set_code_completion_selected_index(1);
  2280. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2281. CHECK(code_edit->get_code_completion_option(0).size() == 0);
  2282. CHECK(code_edit->get_code_completion_options().size() == 0);
  2283. /* After update, pending add should not be counted, */
  2284. /* also does not work on col 0 */
  2285. code_edit->insert_text_at_caret("i");
  2286. code_edit->update_code_completion_options();
  2287. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0", Color(1, 0, 0), RES(), Color(1, 0, 0));
  2288. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_1.", "item_1");
  2289. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_2.", "item_2");
  2290. ERR_PRINT_OFF;
  2291. code_edit->set_code_completion_selected_index(1);
  2292. ERR_PRINT_ON;
  2293. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2294. CHECK(code_edit->get_code_completion_option(0).size() == 6);
  2295. CHECK(code_edit->get_code_completion_options().size() == 1);
  2296. /* Check cancel closes completion. */
  2297. SEND_GUI_ACTION(code_edit, "ui_cancel");
  2298. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2299. code_edit->update_code_completion_options();
  2300. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2301. code_edit->set_code_completion_selected_index(1);
  2302. CHECK(code_edit->get_code_completion_selected_index() == 1);
  2303. CHECK(code_edit->get_code_completion_option(0).size() == 6);
  2304. CHECK(code_edit->get_code_completion_options().size() == 3);
  2305. /* Check data. */
  2306. Dictionary option = code_edit->get_code_completion_option(0);
  2307. CHECK((int)option["kind"] == (int)CodeEdit::CodeCompletionKind::KIND_CLASS);
  2308. CHECK(option["display_text"] == "item_0.");
  2309. CHECK(option["insert_text"] == "item_0");
  2310. CHECK(option["font_color"] == Color(1, 0, 0));
  2311. CHECK(option["icon"] == RES());
  2312. CHECK(option["default_value"] == Color(1, 0, 0));
  2313. /* Set size for mouse input. */
  2314. code_edit->set_size(Size2(100, 100));
  2315. /* Check input. */
  2316. SEND_GUI_ACTION(code_edit, "ui_end");
  2317. CHECK(code_edit->get_code_completion_selected_index() == 2);
  2318. SEND_GUI_ACTION(code_edit, "ui_home");
  2319. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2320. SEND_GUI_ACTION(code_edit, "ui_page_down");
  2321. CHECK(code_edit->get_code_completion_selected_index() == 2);
  2322. SEND_GUI_ACTION(code_edit, "ui_page_up");
  2323. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2324. SEND_GUI_ACTION(code_edit, "ui_up");
  2325. CHECK(code_edit->get_code_completion_selected_index() == 2);
  2326. SEND_GUI_ACTION(code_edit, "ui_down");
  2327. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2328. SEND_GUI_KEY_EVENT(code_edit, KEY_T);
  2329. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2330. SEND_GUI_ACTION(code_edit, "ui_left");
  2331. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2332. SEND_GUI_ACTION(code_edit, "ui_right");
  2333. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2334. SEND_GUI_ACTION(code_edit, "ui_text_backspace");
  2335. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2336. Point2 caret_pos = code_edit->get_caret_draw_pos();
  2337. caret_pos.y -= code_edit->get_line_height();
  2338. SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_WHEEL_DOWN, MOUSE_BUTTON_NONE);
  2339. CHECK(code_edit->get_code_completion_selected_index() == 1);
  2340. SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_WHEEL_UP, MOUSE_BUTTON_NONE);
  2341. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2342. /* Single click selects. */
  2343. SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MASK_LEFT);
  2344. CHECK(code_edit->get_code_completion_selected_index() == 2);
  2345. /* Double click inserts. */
  2346. SEND_GUI_DOUBLE_CLICK(code_edit, caret_pos);
  2347. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2348. CHECK(code_edit->get_line(0) == "item_2");
  2349. code_edit->set_auto_brace_completion_enabled(false);
  2350. /* Does nothing in readonly. */
  2351. code_edit->undo();
  2352. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2353. code_edit->update_code_completion_options();
  2354. code_edit->set_editable(false);
  2355. code_edit->confirm_code_completion();
  2356. code_edit->set_editable(true);
  2357. CHECK(code_edit->get_line(0) == "i");
  2358. /* Replace */
  2359. code_edit->clear();
  2360. code_edit->insert_text_at_caret("item_1 test");
  2361. code_edit->set_caret_column(2);
  2362. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2363. code_edit->update_code_completion_options();
  2364. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2365. CHECK(code_edit->get_line(0) == "item_0 test");
  2366. /* Replace string. */
  2367. code_edit->clear();
  2368. code_edit->insert_text_at_caret("\"item_1 test\"");
  2369. code_edit->set_caret_column(2);
  2370. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2371. code_edit->update_code_completion_options();
  2372. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2373. CHECK(code_edit->get_line(0) == "\"item_0\"");
  2374. /* Normal replace if no end is given. */
  2375. code_edit->clear();
  2376. code_edit->insert_text_at_caret("\"item_1 test");
  2377. code_edit->set_caret_column(2);
  2378. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2379. code_edit->update_code_completion_options();
  2380. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2381. CHECK(code_edit->get_line(0) == "\"item_0\" test");
  2382. /* Insert at completion. */
  2383. code_edit->clear();
  2384. code_edit->insert_text_at_caret("item_1 test");
  2385. code_edit->set_caret_column(2);
  2386. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2387. code_edit->update_code_completion_options();
  2388. SEND_GUI_ACTION(code_edit, "ui_text_completion_accept");
  2389. CHECK(code_edit->get_line(0) == "item_01 test");
  2390. /* Insert at completion with string should have same output. */
  2391. code_edit->clear();
  2392. code_edit->insert_text_at_caret("\"item_1 test\"");
  2393. code_edit->set_caret_column(2);
  2394. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2395. code_edit->update_code_completion_options();
  2396. SEND_GUI_ACTION(code_edit, "ui_text_completion_accept");
  2397. CHECK(code_edit->get_line(0) == "\"item_0\"1 test\"");
  2398. /* Merge symbol at end on insert text. */
  2399. /* End on completion entry. */
  2400. code_edit->clear();
  2401. code_edit->insert_text_at_caret("item_1 test");
  2402. code_edit->set_caret_column(2);
  2403. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2404. code_edit->update_code_completion_options();
  2405. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2406. CHECK(code_edit->get_line(0) == "item_0( test");
  2407. CHECK(code_edit->get_caret_column() == 7);
  2408. /* End of text*/
  2409. code_edit->clear();
  2410. code_edit->insert_text_at_caret("item_1( test");
  2411. code_edit->set_caret_column(2);
  2412. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  2413. code_edit->update_code_completion_options();
  2414. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2415. CHECK(code_edit->get_line(0) == "item_0( test");
  2416. CHECK(code_edit->get_caret_column() == 6);
  2417. /* End of both. */
  2418. code_edit->clear();
  2419. code_edit->insert_text_at_caret("item_1( test");
  2420. code_edit->set_caret_column(2);
  2421. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2422. code_edit->update_code_completion_options();
  2423. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2424. CHECK(code_edit->get_line(0) == "item_0( test");
  2425. CHECK(code_edit->get_caret_column() == 7);
  2426. /* Full set. */
  2427. /* End on completion entry. */
  2428. code_edit->clear();
  2429. code_edit->insert_text_at_caret("item_1 test");
  2430. code_edit->set_caret_column(2);
  2431. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  2432. code_edit->update_code_completion_options();
  2433. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2434. CHECK(code_edit->get_line(0) == "item_0() test");
  2435. CHECK(code_edit->get_caret_column() == 8);
  2436. /* End of text*/
  2437. code_edit->clear();
  2438. code_edit->insert_text_at_caret("item_1() test");
  2439. code_edit->set_caret_column(2);
  2440. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  2441. code_edit->update_code_completion_options();
  2442. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2443. CHECK(code_edit->get_line(0) == "item_0() test");
  2444. CHECK(code_edit->get_caret_column() == 6);
  2445. /* End of both. */
  2446. code_edit->clear();
  2447. code_edit->insert_text_at_caret("item_1() test");
  2448. code_edit->set_caret_column(2);
  2449. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  2450. code_edit->update_code_completion_options();
  2451. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2452. CHECK(code_edit->get_line(0) == "item_0() test");
  2453. CHECK(code_edit->get_caret_column() == 8);
  2454. /* Autobrace completion. */
  2455. code_edit->set_auto_brace_completion_enabled(true);
  2456. /* End on completion entry. */
  2457. code_edit->clear();
  2458. code_edit->insert_text_at_caret("item_1 test");
  2459. code_edit->set_caret_column(2);
  2460. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2461. code_edit->update_code_completion_options();
  2462. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2463. CHECK(code_edit->get_line(0) == "item_0() test");
  2464. CHECK(code_edit->get_caret_column() == 7);
  2465. /* End of text*/
  2466. code_edit->clear();
  2467. code_edit->insert_text_at_caret("item_1( test");
  2468. code_edit->set_caret_column(2);
  2469. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  2470. code_edit->update_code_completion_options();
  2471. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2472. CHECK(code_edit->get_line(0) == "item_0( test");
  2473. CHECK(code_edit->get_caret_column() == 6);
  2474. /* End of both. */
  2475. code_edit->clear();
  2476. code_edit->insert_text_at_caret("item_1( test");
  2477. code_edit->set_caret_column(2);
  2478. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2479. code_edit->update_code_completion_options();
  2480. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2481. CHECK(code_edit->get_line(0) == "item_0( test");
  2482. CHECK(code_edit->get_caret_column() == 7);
  2483. /* Full set. */
  2484. /* End on completion entry. */
  2485. code_edit->clear();
  2486. code_edit->insert_text_at_caret("item_1 test");
  2487. code_edit->set_caret_column(2);
  2488. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  2489. code_edit->update_code_completion_options();
  2490. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2491. CHECK(code_edit->get_line(0) == "item_0() test");
  2492. CHECK(code_edit->get_caret_column() == 8);
  2493. /* End of text*/
  2494. code_edit->clear();
  2495. code_edit->insert_text_at_caret("item_1() test");
  2496. code_edit->set_caret_column(2);
  2497. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  2498. code_edit->update_code_completion_options();
  2499. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2500. CHECK(code_edit->get_line(0) == "item_0() test");
  2501. CHECK(code_edit->get_caret_column() == 6);
  2502. /* End of both. */
  2503. code_edit->clear();
  2504. code_edit->insert_text_at_caret("item_1() test");
  2505. code_edit->set_caret_column(2);
  2506. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  2507. code_edit->update_code_completion_options();
  2508. SEND_GUI_ACTION(code_edit, "ui_text_completion_replace");
  2509. CHECK(code_edit->get_line(0) == "item_0() test");
  2510. CHECK(code_edit->get_caret_column() == 8);
  2511. }
  2512. memdelete(code_edit);
  2513. }
  2514. TEST_CASE("[SceneTree][CodeEdit] symbol lookup") {
  2515. CodeEdit *code_edit = memnew(CodeEdit);
  2516. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  2517. code_edit->set_symbol_lookup_on_click_enabled(true);
  2518. CHECK(code_edit->is_symbol_lookup_on_click_enabled());
  2519. /* Set size for mouse input. */
  2520. code_edit->set_size(Size2(100, 100));
  2521. code_edit->set_text("this is some text");
  2522. Point2 caret_pos = code_edit->get_caret_draw_pos();
  2523. caret_pos.x += 55;
  2524. SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_NONE, MOUSE_BUTTON_NONE);
  2525. CHECK(code_edit->get_text_for_symbol_lookup() == "this is s" + String::chr(0xFFFF) + "ome text");
  2526. SIGNAL_WATCH(code_edit, "symbol_validate");
  2527. #ifdef OSX_ENABLED
  2528. SEND_GUI_KEY_EVENT(code_edit, KEY_META);
  2529. #else
  2530. SEND_GUI_KEY_EVENT(code_edit, KEY_CTRL);
  2531. #endif
  2532. Array signal_args;
  2533. Array arg;
  2534. arg.push_back("some");
  2535. signal_args.push_back(arg);
  2536. SIGNAL_CHECK("symbol_validate", signal_args);
  2537. SIGNAL_UNWATCH(code_edit, "symbol_validate");
  2538. memdelete(code_edit);
  2539. }
  2540. TEST_CASE("[SceneTree][CodeEdit] line length guidelines") {
  2541. CodeEdit *code_edit = memnew(CodeEdit);
  2542. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  2543. TypedArray<int> guide_lines;
  2544. code_edit->set_line_length_guidelines(guide_lines);
  2545. CHECK(code_edit->get_line_length_guidelines().size() == 0);
  2546. guide_lines.push_back(80);
  2547. guide_lines.push_back(120);
  2548. /* Order should be preserved. */
  2549. code_edit->set_line_length_guidelines(guide_lines);
  2550. CHECK((int)code_edit->get_line_length_guidelines()[0] == 80);
  2551. CHECK((int)code_edit->get_line_length_guidelines()[1] == 120);
  2552. memdelete(code_edit);
  2553. }
  2554. TEST_CASE("[SceneTree][CodeEdit] Backspace delete") {
  2555. CodeEdit *code_edit = memnew(CodeEdit);
  2556. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  2557. /* Backspace with selection on first line. */
  2558. code_edit->set_text("");
  2559. code_edit->insert_text_at_caret("test backspace");
  2560. code_edit->select(0, 0, 0, 5);
  2561. code_edit->backspace();
  2562. CHECK(code_edit->get_line(0) == "backspace");
  2563. /* Backspace with selection on first line and caret at the beginning of file. */
  2564. code_edit->set_text("");
  2565. code_edit->insert_text_at_caret("test backspace");
  2566. code_edit->select(0, 0, 0, 5);
  2567. code_edit->set_caret_column(0);
  2568. code_edit->backspace();
  2569. CHECK(code_edit->get_line(0) == "backspace");
  2570. /* Move caret up to the previous line on backspace if carret is at the first column. */
  2571. code_edit->set_text("");
  2572. code_edit->insert_text_at_caret("line 1\nline 2");
  2573. code_edit->set_caret_line(1);
  2574. code_edit->set_caret_column(0);
  2575. code_edit->backspace();
  2576. CHECK(code_edit->get_line(0) == "line 1line 2");
  2577. CHECK(code_edit->get_caret_line() == 0);
  2578. CHECK(code_edit->get_caret_column() == 6);
  2579. /* Backspace delete all text if all text is selected. */
  2580. code_edit->set_text("");
  2581. code_edit->insert_text_at_caret("line 1\nline 2\nline 3");
  2582. code_edit->select_all();
  2583. code_edit->backspace();
  2584. CHECK(code_edit->get_text() == "");
  2585. /* Backspace at the beginning without selection has no effect. */
  2586. code_edit->set_text("");
  2587. code_edit->insert_text_at_caret("line 1\nline 2\nline 3");
  2588. code_edit->set_caret_line(0);
  2589. code_edit->set_caret_column(0);
  2590. code_edit->backspace();
  2591. CHECK(code_edit->get_text() == "line 1\nline 2\nline 3");
  2592. memdelete(code_edit);
  2593. }
  2594. } // namespace TestCodeEdit
  2595. #endif // TEST_CODE_EDIT_H