test_code_edit.h 124 KB

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