test_code_edit.h 125 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464
  1. /**************************************************************************/
  2. /* test_code_edit.h */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("ui_text_backspace");
  474. CHECK(code_edit->is_line_bookmarked(1));
  475. /* backspace on bookmarked line removes it */
  476. SEND_GUI_ACTION("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("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("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("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("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("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("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("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("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("ui_text_backspace");
  639. CHECK(code_edit->is_line_executing(1));
  640. /* backspace on executing line removes it */
  641. SEND_GUI_ACTION("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("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("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("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("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->unindent_lines();
  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->unindent_lines();
  1567. CHECK(code_edit->get_line(0) == "");
  1568. /* Backspace does a simple unindent. */
  1569. code_edit->set_text("");
  1570. code_edit->insert_text_at_caret("\t");
  1571. code_edit->backspace();
  1572. CHECK(code_edit->get_line(0) == "");
  1573. /* Unindent lines does entire line and works without selection. */
  1574. code_edit->set_text("");
  1575. code_edit->insert_text_at_caret("\ttest");
  1576. code_edit->unindent_lines();
  1577. CHECK(code_edit->get_line(0) == "test");
  1578. /* Caret on col zero unindent line. */
  1579. code_edit->set_text("\t\ttest");
  1580. code_edit->unindent_lines();
  1581. CHECK(code_edit->get_line(0) == "\ttest");
  1582. /* Check input action. */
  1583. code_edit->set_text("\t\ttest");
  1584. SEND_GUI_ACTION("ui_text_dedent");
  1585. CHECK(code_edit->get_line(0) == "\ttest");
  1586. /* Selection does entire line. */
  1587. code_edit->set_text("\t\ttest");
  1588. code_edit->select_all();
  1589. code_edit->unindent_lines();
  1590. CHECK(code_edit->get_line(0) == "\ttest");
  1591. /* Handles multiple lines. */
  1592. code_edit->set_text("\ttest\n\ttext");
  1593. code_edit->select_all();
  1594. code_edit->unindent_lines();
  1595. CHECK(code_edit->get_line(0) == "test");
  1596. CHECK(code_edit->get_line(1) == "text");
  1597. /* Do not unindent line if last col is zero. */
  1598. code_edit->set_text("\ttest\n\ttext");
  1599. code_edit->select(0, 0, 1, 0);
  1600. code_edit->unindent_lines();
  1601. CHECK(code_edit->get_line(0) == "test");
  1602. CHECK(code_edit->get_line(1) == "\ttext");
  1603. /* Unindent even if last column of first line. */
  1604. code_edit->set_text("\ttest\n\ttext");
  1605. code_edit->select(0, 5, 1, 1);
  1606. code_edit->unindent_lines();
  1607. CHECK(code_edit->get_line(0) == "test");
  1608. CHECK(code_edit->get_line(1) == "text");
  1609. /* Check selection is adjusted. */
  1610. code_edit->set_text("\ttest");
  1611. code_edit->select(0, 1, 0, 2);
  1612. code_edit->unindent_lines();
  1613. CHECK(code_edit->get_selection_from_column() == 0);
  1614. CHECK(code_edit->get_selection_to_column() == 1);
  1615. CHECK(code_edit->get_line(0) == "test");
  1616. }
  1617. SUBCASE("[CodeEdit] unindent spaces") {
  1618. code_edit->set_indent_size(4);
  1619. code_edit->set_auto_indent_enabled(true);
  1620. code_edit->set_indent_using_spaces(true);
  1621. /* Do nothing if not editable. */
  1622. code_edit->set_text(" ");
  1623. code_edit->set_editable(false);
  1624. code_edit->unindent_lines();
  1625. CHECK(code_edit->get_line(0) == " ");
  1626. code_edit->unindent_lines();
  1627. CHECK(code_edit->get_line(0) == " ");
  1628. code_edit->set_editable(true);
  1629. /* Simple unindent. */
  1630. code_edit->unindent_lines();
  1631. CHECK(code_edit->get_line(0) == "");
  1632. /* Backspace does a simple unindent. */
  1633. code_edit->set_text("");
  1634. code_edit->insert_text_at_caret(" ");
  1635. code_edit->backspace();
  1636. CHECK(code_edit->get_line(0) == "");
  1637. /* Backspace with letter. */
  1638. code_edit->set_text("");
  1639. code_edit->insert_text_at_caret(" a");
  1640. code_edit->backspace();
  1641. CHECK(code_edit->get_line(0) == " ");
  1642. /* Unindent lines does entire line and works without selection. */
  1643. code_edit->set_text("");
  1644. code_edit->insert_text_at_caret(" test");
  1645. code_edit->unindent_lines();
  1646. CHECK(code_edit->get_line(0) == "test");
  1647. /* Caret on col zero unindent line. */
  1648. code_edit->set_text(" test");
  1649. code_edit->unindent_lines();
  1650. CHECK(code_edit->get_line(0) == " test");
  1651. /* Only as far as needed */
  1652. code_edit->set_text(" test");
  1653. code_edit->unindent_lines();
  1654. CHECK(code_edit->get_line(0) == " test");
  1655. /* Check input action. */
  1656. code_edit->set_text(" test");
  1657. SEND_GUI_ACTION("ui_text_dedent");
  1658. CHECK(code_edit->get_line(0) == " test");
  1659. /* Selection does entire line. */
  1660. code_edit->set_text(" test");
  1661. code_edit->select_all();
  1662. code_edit->unindent_lines();
  1663. CHECK(code_edit->get_line(0) == " test");
  1664. /* Handles multiple lines. */
  1665. code_edit->set_text(" test\n text");
  1666. code_edit->select_all();
  1667. code_edit->unindent_lines();
  1668. CHECK(code_edit->get_line(0) == "test");
  1669. CHECK(code_edit->get_line(1) == "text");
  1670. /* Do not unindent line if last col is zero. */
  1671. code_edit->set_text(" test\n text");
  1672. code_edit->select(0, 0, 1, 0);
  1673. code_edit->unindent_lines();
  1674. CHECK(code_edit->get_line(0) == "test");
  1675. CHECK(code_edit->get_line(1) == " text");
  1676. /* Unindent even if last column of first line. */
  1677. code_edit->set_text(" test\n text");
  1678. code_edit->select(0, 5, 1, 1);
  1679. code_edit->unindent_lines();
  1680. CHECK(code_edit->get_line(0) == "test");
  1681. CHECK(code_edit->get_line(1) == "text");
  1682. /* Check selection is adjusted. */
  1683. code_edit->set_text(" test");
  1684. code_edit->select(0, 4, 0, 5);
  1685. code_edit->unindent_lines();
  1686. CHECK(code_edit->get_selection_from_column() == 0);
  1687. CHECK(code_edit->get_selection_to_column() == 1);
  1688. CHECK(code_edit->get_line(0) == "test");
  1689. }
  1690. SUBCASE("[CodeEdit] auto indent") {
  1691. SUBCASE("[CodeEdit] auto indent tabs") {
  1692. code_edit->set_indent_size(4);
  1693. code_edit->set_auto_indent_enabled(true);
  1694. code_edit->set_indent_using_spaces(false);
  1695. /* Simple indent on new line. */
  1696. code_edit->set_text("");
  1697. code_edit->insert_text_at_caret("test:");
  1698. SEND_GUI_ACTION("ui_text_newline");
  1699. CHECK(code_edit->get_line(0) == "test:");
  1700. CHECK(code_edit->get_line(1) == "\t");
  1701. /* new blank line should still indent. */
  1702. code_edit->set_text("");
  1703. code_edit->insert_text_at_caret("test:");
  1704. SEND_GUI_ACTION("ui_text_newline_blank");
  1705. CHECK(code_edit->get_line(0) == "test:");
  1706. CHECK(code_edit->get_line(1) == "\t");
  1707. /* new line above should not indent. */
  1708. code_edit->set_text("");
  1709. code_edit->insert_text_at_caret("test:");
  1710. SEND_GUI_ACTION("ui_text_newline_above");
  1711. CHECK(code_edit->get_line(0) == "");
  1712. CHECK(code_edit->get_line(1) == "test:");
  1713. /* Whitespace between symbol and caret is okay. */
  1714. code_edit->set_text("");
  1715. code_edit->insert_text_at_caret("test: ");
  1716. SEND_GUI_ACTION("ui_text_newline");
  1717. CHECK(code_edit->get_line(0) == "test: ");
  1718. CHECK(code_edit->get_line(1) == "\t");
  1719. /* Comment between symbol and caret is okay. */
  1720. code_edit->add_comment_delimiter("#", "");
  1721. code_edit->set_text("");
  1722. code_edit->insert_text_at_caret("test: # comment");
  1723. SEND_GUI_ACTION("ui_text_newline");
  1724. CHECK(code_edit->get_line(0) == "test: # comment");
  1725. CHECK(code_edit->get_line(1) == "\t");
  1726. code_edit->remove_comment_delimiter("#");
  1727. /* Strings between symbol and caret are not okay. */
  1728. code_edit->add_string_delimiter("#", "");
  1729. code_edit->set_text("");
  1730. code_edit->insert_text_at_caret("test: # string");
  1731. SEND_GUI_ACTION("ui_text_newline");
  1732. CHECK(code_edit->get_line(0) == "test: # string");
  1733. CHECK(code_edit->get_line(1) == "");
  1734. code_edit->remove_string_delimiter("#");
  1735. /* Non-whitespace prevents auto-indentation. */
  1736. code_edit->add_comment_delimiter("#", "");
  1737. code_edit->set_text("");
  1738. code_edit->insert_text_at_caret("test := 0 # comment");
  1739. SEND_GUI_ACTION("ui_text_newline");
  1740. CHECK(code_edit->get_line(0) == "test := 0 # comment");
  1741. CHECK(code_edit->get_line(1) == "");
  1742. code_edit->remove_comment_delimiter("#");
  1743. /* Even when there's no comments. */
  1744. code_edit->set_text("");
  1745. code_edit->insert_text_at_caret("test := 0");
  1746. SEND_GUI_ACTION("ui_text_newline");
  1747. CHECK(code_edit->get_line(0) == "test := 0");
  1748. CHECK(code_edit->get_line(1) == "");
  1749. /* If between brace pairs an extra line is added. */
  1750. code_edit->set_text("");
  1751. code_edit->insert_text_at_caret("test{}");
  1752. code_edit->set_caret_column(5);
  1753. SEND_GUI_ACTION("ui_text_newline");
  1754. CHECK(code_edit->get_line(0) == "test{");
  1755. CHECK(code_edit->get_line(1) == "\t");
  1756. CHECK(code_edit->get_line(2) == "}");
  1757. /* Except when we are going above. */
  1758. code_edit->set_text("");
  1759. code_edit->insert_text_at_caret("test{}");
  1760. code_edit->set_caret_column(5);
  1761. SEND_GUI_ACTION("ui_text_newline_above");
  1762. CHECK(code_edit->get_line(0) == "");
  1763. CHECK(code_edit->get_line(1) == "test{}");
  1764. /* or below. */
  1765. code_edit->set_text("");
  1766. code_edit->insert_text_at_caret("test{}");
  1767. code_edit->set_caret_column(5);
  1768. SEND_GUI_ACTION("ui_text_newline_blank");
  1769. CHECK(code_edit->get_line(0) == "test{}");
  1770. CHECK(code_edit->get_line(1) == "");
  1771. }
  1772. SUBCASE("[CodeEdit] auto indent spaces") {
  1773. code_edit->set_indent_size(4);
  1774. code_edit->set_auto_indent_enabled(true);
  1775. code_edit->set_indent_using_spaces(true);
  1776. /* Simple indent on new line. */
  1777. code_edit->set_text("");
  1778. code_edit->insert_text_at_caret("test:");
  1779. SEND_GUI_ACTION("ui_text_newline");
  1780. CHECK(code_edit->get_line(0) == "test:");
  1781. CHECK(code_edit->get_line(1) == " ");
  1782. /* new blank line should still indent. */
  1783. code_edit->set_text("");
  1784. code_edit->insert_text_at_caret("test:");
  1785. SEND_GUI_ACTION("ui_text_newline_blank");
  1786. CHECK(code_edit->get_line(0) == "test:");
  1787. CHECK(code_edit->get_line(1) == " ");
  1788. /* new line above should not indent. */
  1789. code_edit->set_text("");
  1790. code_edit->insert_text_at_caret("test:");
  1791. SEND_GUI_ACTION("ui_text_newline_above");
  1792. CHECK(code_edit->get_line(0) == "");
  1793. CHECK(code_edit->get_line(1) == "test:");
  1794. /* Whitespace between symbol and caret is okay. */
  1795. code_edit->set_text("");
  1796. code_edit->insert_text_at_caret("test: ");
  1797. SEND_GUI_ACTION("ui_text_newline");
  1798. CHECK(code_edit->get_line(0) == "test: ");
  1799. CHECK(code_edit->get_line(1) == " ");
  1800. /* Comment between symbol and caret is okay. */
  1801. code_edit->add_comment_delimiter("#", "");
  1802. code_edit->set_text("");
  1803. code_edit->insert_text_at_caret("test: # comment");
  1804. SEND_GUI_ACTION("ui_text_newline");
  1805. CHECK(code_edit->get_line(0) == "test: # comment");
  1806. CHECK(code_edit->get_line(1) == " ");
  1807. code_edit->remove_comment_delimiter("#");
  1808. /* Strings between symbol and caret are not okay. */
  1809. code_edit->add_string_delimiter("#", "");
  1810. code_edit->set_text("");
  1811. code_edit->insert_text_at_caret("test: # string");
  1812. SEND_GUI_ACTION("ui_text_newline");
  1813. CHECK(code_edit->get_line(0) == "test: # string");
  1814. CHECK(code_edit->get_line(1) == "");
  1815. code_edit->remove_string_delimiter("#");
  1816. /* Non-whitespace prevents auto-indentation. */
  1817. code_edit->add_comment_delimiter("#", "");
  1818. code_edit->set_text("");
  1819. code_edit->insert_text_at_caret("test := 0 # comment");
  1820. SEND_GUI_ACTION("ui_text_newline");
  1821. CHECK(code_edit->get_line(0) == "test := 0 # comment");
  1822. CHECK(code_edit->get_line(1) == "");
  1823. code_edit->remove_comment_delimiter("#");
  1824. /* Even when there's no comments. */
  1825. code_edit->set_text("");
  1826. code_edit->insert_text_at_caret("test := 0");
  1827. SEND_GUI_ACTION("ui_text_newline");
  1828. CHECK(code_edit->get_line(0) == "test := 0");
  1829. CHECK(code_edit->get_line(1) == "");
  1830. /* If between brace pairs an extra line is added. */
  1831. code_edit->set_text("");
  1832. code_edit->insert_text_at_caret("test{}");
  1833. code_edit->set_caret_column(5);
  1834. SEND_GUI_ACTION("ui_text_newline");
  1835. CHECK(code_edit->get_line(0) == "test{");
  1836. CHECK(code_edit->get_line(1) == " ");
  1837. CHECK(code_edit->get_line(2) == "}");
  1838. /* Except when we are going above. */
  1839. code_edit->set_text("");
  1840. code_edit->insert_text_at_caret("test{}");
  1841. code_edit->set_caret_column(5);
  1842. SEND_GUI_ACTION("ui_text_newline_above");
  1843. CHECK(code_edit->get_line(0) == "");
  1844. CHECK(code_edit->get_line(1) == "test{}");
  1845. /* or below. */
  1846. code_edit->set_text("");
  1847. code_edit->insert_text_at_caret("test{}");
  1848. code_edit->set_caret_column(5);
  1849. SEND_GUI_ACTION("ui_text_newline_blank");
  1850. CHECK(code_edit->get_line(0) == "test{}");
  1851. CHECK(code_edit->get_line(1) == "");
  1852. }
  1853. }
  1854. memdelete(code_edit);
  1855. }
  1856. TEST_CASE("[SceneTree][CodeEdit] folding") {
  1857. CodeEdit *code_edit = memnew(CodeEdit);
  1858. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  1859. code_edit->grab_focus();
  1860. SUBCASE("[CodeEdit] folding settings") {
  1861. code_edit->set_line_folding_enabled(true);
  1862. CHECK(code_edit->is_line_folding_enabled());
  1863. code_edit->set_line_folding_enabled(false);
  1864. CHECK_FALSE(code_edit->is_line_folding_enabled());
  1865. }
  1866. SUBCASE("[CodeEdit] folding") {
  1867. code_edit->set_line_folding_enabled(true);
  1868. // No indent.
  1869. code_edit->set_text("line1\nline2\nline3");
  1870. for (int i = 0; i < 2; i++) {
  1871. CHECK_FALSE(code_edit->can_fold_line(i));
  1872. code_edit->fold_line(i);
  1873. CHECK_FALSE(code_edit->is_line_folded(i));
  1874. }
  1875. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1876. // Indented lines.
  1877. code_edit->set_text("\tline1\n\tline2\n\tline3");
  1878. for (int i = 0; i < 2; i++) {
  1879. CHECK_FALSE(code_edit->can_fold_line(i));
  1880. code_edit->fold_line(i);
  1881. CHECK_FALSE(code_edit->is_line_folded(i));
  1882. }
  1883. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1884. // Indent.
  1885. code_edit->set_text("line1\n\tline2\nline3");
  1886. CHECK(code_edit->can_fold_line(0));
  1887. for (int i = 1; i < 2; i++) {
  1888. CHECK_FALSE(code_edit->can_fold_line(i));
  1889. code_edit->fold_line(i);
  1890. CHECK_FALSE(code_edit->is_line_folded(i));
  1891. }
  1892. code_edit->fold_line(0);
  1893. CHECK(code_edit->is_line_folded(0));
  1894. CHECK_FALSE(code_edit->is_line_folded(1));
  1895. CHECK_FALSE(code_edit->is_line_folded(2));
  1896. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  1897. // Indent with blank lines.
  1898. code_edit->set_text("line1\n\tline2\n\n\nline3");
  1899. CHECK(code_edit->can_fold_line(0));
  1900. for (int i = 1; i < 2; i++) {
  1901. CHECK_FALSE(code_edit->can_fold_line(i));
  1902. code_edit->fold_line(i);
  1903. CHECK_FALSE(code_edit->is_line_folded(i));
  1904. }
  1905. code_edit->fold_line(0);
  1906. CHECK(code_edit->is_line_folded(0));
  1907. CHECK_FALSE(code_edit->is_line_folded(1));
  1908. CHECK_FALSE(code_edit->is_line_folded(2));
  1909. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  1910. // Nested indents.
  1911. code_edit->set_text("line1\n\tline2\n\t\tline3\nline4");
  1912. CHECK(code_edit->can_fold_line(0));
  1913. CHECK(code_edit->can_fold_line(1));
  1914. for (int i = 2; i < 3; i++) {
  1915. CHECK_FALSE(code_edit->can_fold_line(i));
  1916. code_edit->fold_line(i);
  1917. CHECK_FALSE(code_edit->is_line_folded(i));
  1918. }
  1919. code_edit->fold_line(1);
  1920. CHECK_FALSE(code_edit->is_line_folded(0));
  1921. CHECK(code_edit->is_line_folded(1));
  1922. CHECK_FALSE(code_edit->is_line_folded(2));
  1923. CHECK_FALSE(code_edit->is_line_folded(3));
  1924. CHECK(code_edit->get_next_visible_line_offset_from(2, 1) == 2);
  1925. code_edit->fold_line(0);
  1926. CHECK(code_edit->is_line_folded(0));
  1927. CHECK_FALSE(code_edit->is_line_folded(1));
  1928. CHECK_FALSE(code_edit->is_line_folded(2));
  1929. CHECK_FALSE(code_edit->is_line_folded(3));
  1930. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  1931. // Check metadata.
  1932. CHECK(code_edit->get_folded_lines().size() == 1);
  1933. CHECK((int)code_edit->get_folded_lines()[0] == 0);
  1934. // Cannot unfold nested.
  1935. code_edit->unfold_line(1);
  1936. CHECK_FALSE(code_edit->is_line_folded(0));
  1937. CHECK_FALSE(code_edit->is_line_folded(1));
  1938. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1939. // (un)Fold all / toggle.
  1940. code_edit->unfold_line(0);
  1941. CHECK_FALSE(code_edit->is_line_folded(0));
  1942. CHECK_FALSE(code_edit->is_line_folded(1));
  1943. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1944. // Check metadata.
  1945. CHECK(code_edit->get_folded_lines().size() == 0);
  1946. code_edit->fold_all_lines();
  1947. CHECK(code_edit->is_line_folded(0));
  1948. CHECK_FALSE(code_edit->is_line_folded(1));
  1949. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  1950. code_edit->unfold_all_lines();
  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. code_edit->toggle_foldable_line(0);
  1955. CHECK(code_edit->is_line_folded(0));
  1956. CHECK_FALSE(code_edit->is_line_folded(1));
  1957. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  1958. // Can also unfold from hidden line.
  1959. code_edit->unfold_line(1);
  1960. CHECK_FALSE(code_edit->is_line_folded(0));
  1961. CHECK_FALSE(code_edit->is_line_folded(1));
  1962. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1963. // Blank lines.
  1964. code_edit->set_text("line1\n\tline2\n\n\n\ttest\n\nline3");
  1965. CHECK(code_edit->can_fold_line(0));
  1966. for (int i = 1; i < code_edit->get_line_count(); i++) {
  1967. CHECK_FALSE(code_edit->can_fold_line(i));
  1968. code_edit->fold_line(i);
  1969. CHECK_FALSE(code_edit->is_line_folded(i));
  1970. }
  1971. code_edit->fold_line(0);
  1972. CHECK(code_edit->is_line_folded(0));
  1973. for (int i = 1; i < code_edit->get_line_count(); i++) {
  1974. CHECK_FALSE(code_edit->is_line_folded(i));
  1975. }
  1976. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 5);
  1977. // End of file.
  1978. code_edit->set_text("line1\n\tline2");
  1979. CHECK(code_edit->can_fold_line(0));
  1980. CHECK_FALSE(code_edit->can_fold_line(1));
  1981. code_edit->fold_line(1);
  1982. CHECK_FALSE(code_edit->is_line_folded(1));
  1983. code_edit->fold_line(0);
  1984. CHECK(code_edit->is_line_folded(0));
  1985. CHECK_FALSE(code_edit->is_line_folded(1));
  1986. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1987. // Comment & string blocks.
  1988. // Single line block
  1989. code_edit->add_comment_delimiter("#", "", true);
  1990. code_edit->set_text("#line1\n#\tline2");
  1991. CHECK(code_edit->can_fold_line(0));
  1992. CHECK_FALSE(code_edit->can_fold_line(1));
  1993. code_edit->fold_line(1);
  1994. CHECK_FALSE(code_edit->is_line_folded(1));
  1995. code_edit->fold_line(0);
  1996. CHECK(code_edit->is_line_folded(0));
  1997. CHECK_FALSE(code_edit->is_line_folded(1));
  1998. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  1999. // Has to be full line.
  2000. code_edit->set_text("test #line1\n#\tline2");
  2001. CHECK_FALSE(code_edit->can_fold_line(0));
  2002. CHECK_FALSE(code_edit->can_fold_line(1));
  2003. code_edit->fold_line(1);
  2004. CHECK_FALSE(code_edit->is_line_folded(1));
  2005. code_edit->fold_line(0);
  2006. CHECK_FALSE(code_edit->is_line_folded(0));
  2007. CHECK_FALSE(code_edit->is_line_folded(1));
  2008. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2009. code_edit->set_text("#line1\ntest #\tline2");
  2010. CHECK_FALSE(code_edit->can_fold_line(0));
  2011. CHECK_FALSE(code_edit->can_fold_line(1));
  2012. code_edit->fold_line(1);
  2013. CHECK_FALSE(code_edit->is_line_folded(1));
  2014. code_edit->fold_line(0);
  2015. CHECK_FALSE(code_edit->is_line_folded(0));
  2016. CHECK_FALSE(code_edit->is_line_folded(1));
  2017. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2018. // String.
  2019. code_edit->add_string_delimiter("^", "", true);
  2020. code_edit->set_text("^line1\n^\tline2");
  2021. CHECK(code_edit->can_fold_line(0));
  2022. CHECK_FALSE(code_edit->can_fold_line(1));
  2023. code_edit->fold_line(1);
  2024. CHECK_FALSE(code_edit->is_line_folded(1));
  2025. code_edit->fold_line(0);
  2026. CHECK(code_edit->is_line_folded(0));
  2027. CHECK_FALSE(code_edit->is_line_folded(1));
  2028. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2029. // Has to be full line.
  2030. code_edit->set_text("test ^line1\n^\tline2");
  2031. CHECK_FALSE(code_edit->can_fold_line(0));
  2032. CHECK_FALSE(code_edit->can_fold_line(1));
  2033. code_edit->fold_line(1);
  2034. CHECK_FALSE(code_edit->is_line_folded(1));
  2035. code_edit->fold_line(0);
  2036. CHECK_FALSE(code_edit->is_line_folded(0));
  2037. CHECK_FALSE(code_edit->is_line_folded(1));
  2038. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2039. code_edit->set_text("^line1\ntest ^\tline2");
  2040. CHECK_FALSE(code_edit->can_fold_line(0));
  2041. CHECK_FALSE(code_edit->can_fold_line(1));
  2042. code_edit->fold_line(1);
  2043. CHECK_FALSE(code_edit->is_line_folded(1));
  2044. code_edit->fold_line(0);
  2045. CHECK_FALSE(code_edit->is_line_folded(0));
  2046. CHECK_FALSE(code_edit->is_line_folded(1));
  2047. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2048. // Multiline blocks.
  2049. code_edit->add_comment_delimiter("&", "&", false);
  2050. code_edit->set_text("&line1\n\tline2&\nline3");
  2051. CHECK(code_edit->can_fold_line(0));
  2052. CHECK_FALSE(code_edit->can_fold_line(1));
  2053. code_edit->fold_line(1);
  2054. CHECK_FALSE(code_edit->is_line_folded(1));
  2055. code_edit->fold_line(0);
  2056. CHECK(code_edit->is_line_folded(0));
  2057. CHECK_FALSE(code_edit->is_line_folded(1));
  2058. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  2059. // Multiline comment before last line.
  2060. code_edit->set_text("&line1\nline2&\ntest");
  2061. CHECK(code_edit->can_fold_line(0));
  2062. CHECK_FALSE(code_edit->can_fold_line(2));
  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(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  2068. // Has to be full line.
  2069. code_edit->set_text("test &line1\n\tline2&");
  2070. CHECK_FALSE(code_edit->can_fold_line(0));
  2071. CHECK_FALSE(code_edit->can_fold_line(1));
  2072. code_edit->fold_line(1);
  2073. CHECK_FALSE(code_edit->is_line_folded(1));
  2074. code_edit->fold_line(0);
  2075. CHECK_FALSE(code_edit->is_line_folded(0));
  2076. CHECK_FALSE(code_edit->is_line_folded(1));
  2077. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2078. code_edit->set_text("&line1\n\tline2& test");
  2079. CHECK_FALSE(code_edit->can_fold_line(0));
  2080. CHECK_FALSE(code_edit->can_fold_line(1));
  2081. code_edit->fold_line(1);
  2082. CHECK_FALSE(code_edit->is_line_folded(1));
  2083. code_edit->fold_line(0);
  2084. CHECK_FALSE(code_edit->is_line_folded(0));
  2085. CHECK_FALSE(code_edit->is_line_folded(1));
  2086. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2087. // Strings.
  2088. code_edit->add_string_delimiter("$", "$", false);
  2089. code_edit->set_text("$line1\n\tline2$");
  2090. CHECK(code_edit->can_fold_line(0));
  2091. CHECK_FALSE(code_edit->can_fold_line(1));
  2092. code_edit->fold_line(1);
  2093. CHECK_FALSE(code_edit->is_line_folded(1));
  2094. code_edit->fold_line(0);
  2095. CHECK(code_edit->is_line_folded(0));
  2096. CHECK_FALSE(code_edit->is_line_folded(1));
  2097. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2098. // Has to be full line.
  2099. code_edit->set_text("test $line1\n\tline2$");
  2100. CHECK_FALSE(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_FALSE(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. code_edit->set_text("$line1\n\tline2$ test");
  2109. CHECK_FALSE(code_edit->can_fold_line(0));
  2110. CHECK_FALSE(code_edit->can_fold_line(1));
  2111. code_edit->fold_line(1);
  2112. CHECK_FALSE(code_edit->is_line_folded(1));
  2113. code_edit->fold_line(0);
  2114. CHECK_FALSE(code_edit->is_line_folded(0));
  2115. CHECK_FALSE(code_edit->is_line_folded(1));
  2116. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2117. // Non-indented comments/strings.
  2118. // Single line
  2119. code_edit->set_text("test\n\tline1\n#line1\n#line2\n\ttest");
  2120. CHECK(code_edit->can_fold_line(0));
  2121. CHECK_FALSE(code_edit->can_fold_line(1));
  2122. code_edit->fold_line(1);
  2123. CHECK_FALSE(code_edit->is_line_folded(1));
  2124. code_edit->fold_line(0);
  2125. CHECK(code_edit->is_line_folded(0));
  2126. CHECK_FALSE(code_edit->is_line_folded(1));
  2127. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2128. code_edit->set_text("test\n\tline1\n^line1\n^line2\n\ttest");
  2129. CHECK(code_edit->can_fold_line(0));
  2130. CHECK_FALSE(code_edit->can_fold_line(1));
  2131. code_edit->fold_line(1);
  2132. CHECK_FALSE(code_edit->is_line_folded(1));
  2133. code_edit->fold_line(0);
  2134. CHECK(code_edit->is_line_folded(0));
  2135. CHECK_FALSE(code_edit->is_line_folded(1));
  2136. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2137. // Indent level 0->1, comment after lines
  2138. code_edit->set_text("line1\n\tline2\n#test");
  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) == 2);
  2147. // Indent level 0->1, comment between lines
  2148. code_edit->set_text("line1\n#test\n\tline2\nline3");
  2149. CHECK(code_edit->can_fold_line(0));
  2150. CHECK_FALSE(code_edit->can_fold_line(2));
  2151. code_edit->fold_line(2);
  2152. CHECK_FALSE(code_edit->is_line_folded(2));
  2153. code_edit->fold_line(0);
  2154. CHECK(code_edit->is_line_folded(0));
  2155. CHECK_FALSE(code_edit->is_line_folded(2));
  2156. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  2157. // Indent level 1->2, comment after lines
  2158. code_edit->set_text("\tline1\n\t\tline2\n#test");
  2159. CHECK(code_edit->can_fold_line(0));
  2160. CHECK_FALSE(code_edit->can_fold_line(1));
  2161. code_edit->fold_line(1);
  2162. CHECK_FALSE(code_edit->is_line_folded(1));
  2163. code_edit->fold_line(0);
  2164. CHECK(code_edit->is_line_folded(0));
  2165. CHECK_FALSE(code_edit->is_line_folded(1));
  2166. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  2167. // Indent level 1->2, comment between lines
  2168. code_edit->set_text("\tline1\n#test\n\t\tline2\nline3");
  2169. CHECK(code_edit->can_fold_line(0));
  2170. CHECK_FALSE(code_edit->can_fold_line(2));
  2171. code_edit->fold_line(2);
  2172. CHECK_FALSE(code_edit->is_line_folded(2));
  2173. code_edit->fold_line(0);
  2174. CHECK(code_edit->is_line_folded(0));
  2175. CHECK_FALSE(code_edit->is_line_folded(2));
  2176. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  2177. // Multiline
  2178. code_edit->set_text("test\n\tline1\n&line1\nline2&\n\ttest");
  2179. CHECK(code_edit->can_fold_line(0));
  2180. CHECK_FALSE(code_edit->can_fold_line(1));
  2181. code_edit->fold_line(1);
  2182. CHECK_FALSE(code_edit->is_line_folded(1));
  2183. code_edit->fold_line(0);
  2184. CHECK(code_edit->is_line_folded(0));
  2185. CHECK_FALSE(code_edit->is_line_folded(1));
  2186. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2187. code_edit->set_text("test\n\tline1\n$line1\nline2$\n\ttest");
  2188. CHECK(code_edit->can_fold_line(0));
  2189. CHECK_FALSE(code_edit->can_fold_line(1));
  2190. code_edit->fold_line(1);
  2191. CHECK_FALSE(code_edit->is_line_folded(1));
  2192. code_edit->fold_line(0);
  2193. CHECK(code_edit->is_line_folded(0));
  2194. CHECK_FALSE(code_edit->is_line_folded(1));
  2195. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2196. }
  2197. memdelete(code_edit);
  2198. }
  2199. TEST_CASE("[SceneTree][CodeEdit] completion") {
  2200. CodeEdit *code_edit = memnew(CodeEdit);
  2201. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  2202. code_edit->grab_focus();
  2203. SUBCASE("[CodeEdit] auto brace completion") {
  2204. code_edit->set_auto_brace_completion_enabled(true);
  2205. CHECK(code_edit->is_auto_brace_completion_enabled());
  2206. code_edit->set_highlight_matching_braces_enabled(true);
  2207. CHECK(code_edit->is_highlight_matching_braces_enabled());
  2208. /* Try setters, any length. */
  2209. Dictionary auto_brace_completion_pairs;
  2210. auto_brace_completion_pairs["["] = "]";
  2211. auto_brace_completion_pairs["'"] = "'";
  2212. auto_brace_completion_pairs[";"] = "'";
  2213. auto_brace_completion_pairs["'''"] = "'''";
  2214. code_edit->set_auto_brace_completion_pairs(auto_brace_completion_pairs);
  2215. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2216. CHECK(code_edit->get_auto_brace_completion_pairs()["["] == "]");
  2217. CHECK(code_edit->get_auto_brace_completion_pairs()["'"] == "'");
  2218. CHECK(code_edit->get_auto_brace_completion_pairs()[";"] == "'");
  2219. CHECK(code_edit->get_auto_brace_completion_pairs()["'''"] == "'''");
  2220. ERR_PRINT_OFF;
  2221. /* No duplicate start keys. */
  2222. code_edit->add_auto_brace_completion_pair("[", "]");
  2223. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2224. /* No empty keys. */
  2225. code_edit->add_auto_brace_completion_pair("[", "");
  2226. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2227. code_edit->add_auto_brace_completion_pair("", "]");
  2228. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2229. code_edit->add_auto_brace_completion_pair("", "");
  2230. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2231. /* Must be a symbol. */
  2232. code_edit->add_auto_brace_completion_pair("a", "]");
  2233. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2234. code_edit->add_auto_brace_completion_pair("[", "a");
  2235. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2236. code_edit->add_auto_brace_completion_pair("a", "a");
  2237. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2238. ERR_PRINT_ON;
  2239. /* Check metadata. */
  2240. CHECK(code_edit->has_auto_brace_completion_open_key("["));
  2241. CHECK(code_edit->has_auto_brace_completion_open_key("'"));
  2242. CHECK(code_edit->has_auto_brace_completion_open_key(";"));
  2243. CHECK(code_edit->has_auto_brace_completion_open_key("'''"));
  2244. CHECK_FALSE(code_edit->has_auto_brace_completion_open_key("("));
  2245. CHECK(code_edit->has_auto_brace_completion_close_key("]"));
  2246. CHECK(code_edit->has_auto_brace_completion_close_key("'"));
  2247. CHECK(code_edit->has_auto_brace_completion_close_key("'''"));
  2248. CHECK_FALSE(code_edit->has_auto_brace_completion_close_key(")"));
  2249. CHECK(code_edit->get_auto_brace_completion_close_key("[") == "]");
  2250. CHECK(code_edit->get_auto_brace_completion_close_key("'") == "'");
  2251. CHECK(code_edit->get_auto_brace_completion_close_key(";") == "'");
  2252. CHECK(code_edit->get_auto_brace_completion_close_key("'''") == "'''");
  2253. CHECK(code_edit->get_auto_brace_completion_close_key("(").is_empty());
  2254. /* Check typing inserts closing pair. */
  2255. code_edit->clear();
  2256. SEND_GUI_KEY_EVENT(Key::BRACKETLEFT);
  2257. CHECK(code_edit->get_line(0) == "[]");
  2258. /* Should first match and insert smaller key. */
  2259. code_edit->clear();
  2260. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2261. CHECK(code_edit->get_line(0) == "''");
  2262. CHECK(code_edit->get_caret_column() == 1);
  2263. /* Move out from center, Should match and insert larger key. */
  2264. SEND_GUI_ACTION("ui_text_caret_right");
  2265. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2266. CHECK(code_edit->get_line(0) == "''''''");
  2267. CHECK(code_edit->get_caret_column() == 3);
  2268. /* Backspace should remove all. */
  2269. SEND_GUI_ACTION("ui_text_backspace");
  2270. CHECK(code_edit->get_line(0).is_empty());
  2271. /* If in between and typing close key should "skip". */
  2272. SEND_GUI_KEY_EVENT(Key::BRACKETLEFT);
  2273. CHECK(code_edit->get_line(0) == "[]");
  2274. CHECK(code_edit->get_caret_column() == 1);
  2275. SEND_GUI_KEY_EVENT(Key::BRACKETRIGHT);
  2276. CHECK(code_edit->get_line(0) == "[]");
  2277. CHECK(code_edit->get_caret_column() == 2);
  2278. /* If current is char and inserting a string, do not autocomplete. */
  2279. code_edit->clear();
  2280. SEND_GUI_KEY_EVENT(Key::A);
  2281. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2282. CHECK(code_edit->get_line(0) == "A'");
  2283. /* If in comment, do not complete. */
  2284. code_edit->add_comment_delimiter("#", "");
  2285. code_edit->clear();
  2286. SEND_GUI_KEY_EVENT(Key::NUMBERSIGN);
  2287. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2288. CHECK(code_edit->get_line(0) == "#'");
  2289. /* If in string, and inserting string do not complete. */
  2290. code_edit->clear();
  2291. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2292. SEND_GUI_KEY_EVENT(Key::QUOTEDBL);
  2293. CHECK(code_edit->get_line(0) == "'\"'");
  2294. /* Wrap single line selection with brackets */
  2295. code_edit->clear();
  2296. code_edit->insert_text_at_caret("abc");
  2297. code_edit->select_all();
  2298. SEND_GUI_KEY_EVENT(Key::BRACKETLEFT);
  2299. CHECK(code_edit->get_line(0) == "[abc]");
  2300. /* Caret should be after the last character of the single line selection */
  2301. CHECK(code_edit->get_caret_column() == 4);
  2302. /* Wrap multi line selection with brackets */
  2303. code_edit->clear();
  2304. code_edit->insert_text_at_caret("abc\nabc");
  2305. code_edit->select_all();
  2306. SEND_GUI_KEY_EVENT(Key::BRACKETLEFT);
  2307. CHECK(code_edit->get_text() == "[abc\nabc]");
  2308. /* Caret should be after the last character of the multi line selection */
  2309. CHECK(code_edit->get_caret_line() == 1);
  2310. CHECK(code_edit->get_caret_column() == 3);
  2311. /* If inserted character is not a auto brace completion open key, replace selected text with the inserted character */
  2312. code_edit->clear();
  2313. code_edit->insert_text_at_caret("abc");
  2314. code_edit->select_all();
  2315. SEND_GUI_KEY_EVENT(Key::KEY_1);
  2316. CHECK(code_edit->get_text() == "1");
  2317. /* If potential multichar and single brace completion is matched, it should wrap the single. */
  2318. code_edit->clear();
  2319. code_edit->insert_text_at_caret("\'\'abc");
  2320. code_edit->select(0, 2, 0, 5);
  2321. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2322. CHECK(code_edit->get_text() == "\'\'\'abc\'");
  2323. /* If only the potential multichar brace completion is matched, it does not wrap or complete. */
  2324. auto_brace_completion_pairs.erase("\'");
  2325. code_edit->set_auto_brace_completion_pairs(auto_brace_completion_pairs);
  2326. CHECK_FALSE(code_edit->has_auto_brace_completion_open_key("\'"));
  2327. code_edit->clear();
  2328. code_edit->insert_text_at_caret("\'\'abc");
  2329. code_edit->select(0, 2, 0, 5);
  2330. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2331. CHECK(code_edit->get_text() == "\'\'\'");
  2332. }
  2333. SUBCASE("[CodeEdit] autocomplete with brace completion") {
  2334. code_edit->set_auto_brace_completion_enabled(true);
  2335. CHECK(code_edit->is_auto_brace_completion_enabled());
  2336. code_edit->insert_text_at_caret("(te)");
  2337. code_edit->set_caret_column(3);
  2338. // Full completion.
  2339. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test()", "test()");
  2340. code_edit->update_code_completion_options();
  2341. code_edit->confirm_code_completion();
  2342. CHECK(code_edit->get_line(0) == "(test())");
  2343. CHECK(code_edit->get_caret_column() == 7);
  2344. code_edit->undo();
  2345. // With "arg".
  2346. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test(", "test(");
  2347. code_edit->update_code_completion_options();
  2348. code_edit->confirm_code_completion();
  2349. CHECK(code_edit->get_line(0) == "(test())");
  2350. CHECK(code_edit->get_caret_column() == 6);
  2351. code_edit->undo();
  2352. // brace completion disabled
  2353. code_edit->set_auto_brace_completion_enabled(false);
  2354. // Full completion.
  2355. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test()", "test()");
  2356. code_edit->update_code_completion_options();
  2357. code_edit->confirm_code_completion();
  2358. CHECK(code_edit->get_line(0) == "(test())");
  2359. CHECK(code_edit->get_caret_column() == 7);
  2360. code_edit->undo();
  2361. // With "arg".
  2362. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test(", "test(");
  2363. code_edit->update_code_completion_options();
  2364. code_edit->confirm_code_completion();
  2365. CHECK(code_edit->get_line(0) == "(test()");
  2366. CHECK(code_edit->get_caret_column() == 6);
  2367. // String
  2368. code_edit->set_auto_brace_completion_enabled(true);
  2369. code_edit->clear();
  2370. code_edit->insert_text_at_caret("\"\"");
  2371. code_edit->set_caret_column(1);
  2372. // Full completion.
  2373. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test\"", "\"test\"");
  2374. code_edit->update_code_completion_options();
  2375. code_edit->confirm_code_completion();
  2376. CHECK(code_edit->get_line(0) == "\"test\"");
  2377. CHECK(code_edit->get_caret_column() == 6);
  2378. code_edit->undo();
  2379. // With "arg".
  2380. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test", "\"test");
  2381. code_edit->update_code_completion_options();
  2382. code_edit->confirm_code_completion();
  2383. CHECK(code_edit->get_line(0) == "\"\"test\"");
  2384. CHECK(code_edit->get_caret_column() == 7);
  2385. code_edit->undo();
  2386. // brace completion disabled
  2387. code_edit->set_auto_brace_completion_enabled(false);
  2388. // Full completion.
  2389. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test\"", "\"test\"");
  2390. code_edit->update_code_completion_options();
  2391. code_edit->confirm_code_completion();
  2392. CHECK(code_edit->get_line(0) == "\"test\"");
  2393. CHECK(code_edit->get_caret_column() == 6);
  2394. code_edit->undo();
  2395. // With "arg".
  2396. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test", "\"test");
  2397. code_edit->update_code_completion_options();
  2398. code_edit->confirm_code_completion();
  2399. CHECK(code_edit->get_line(0) == "\"\"test\"");
  2400. CHECK(code_edit->get_caret_column() == 7);
  2401. code_edit->undo();
  2402. }
  2403. SUBCASE("[CodeEdit] autocomplete") {
  2404. code_edit->set_code_completion_enabled(true);
  2405. CHECK(code_edit->is_code_completion_enabled());
  2406. /* Set prefixes, single char only, disallow empty. */
  2407. TypedArray<String> completion_prefixes;
  2408. completion_prefixes.push_back("");
  2409. completion_prefixes.push_back(".");
  2410. completion_prefixes.push_back(".");
  2411. completion_prefixes.push_back(",,");
  2412. ERR_PRINT_OFF;
  2413. code_edit->set_code_completion_prefixes(completion_prefixes);
  2414. ERR_PRINT_ON;
  2415. completion_prefixes = code_edit->get_code_completion_prefixes();
  2416. CHECK(completion_prefixes.size() == 2);
  2417. CHECK(completion_prefixes.has("."));
  2418. CHECK(completion_prefixes.has(","));
  2419. code_edit->set_text("test\ntest");
  2420. CHECK(code_edit->get_text_for_code_completion() == String::chr(0xFFFF) + "test\ntest");
  2421. }
  2422. SUBCASE("[CodeEdit] autocomplete request") {
  2423. SIGNAL_WATCH(code_edit, "code_completion_requested");
  2424. code_edit->set_code_completion_enabled(true);
  2425. Array signal_args;
  2426. signal_args.push_back(Array());
  2427. /* Force request. */
  2428. code_edit->request_code_completion();
  2429. SIGNAL_CHECK_FALSE("code_completion_requested");
  2430. code_edit->request_code_completion(true);
  2431. SIGNAL_CHECK("code_completion_requested", signal_args);
  2432. /* Manual request should force. */
  2433. SEND_GUI_ACTION("ui_text_completion_query");
  2434. SIGNAL_CHECK("code_completion_requested", signal_args);
  2435. /* Insert prefix. */
  2436. TypedArray<String> completion_prefixes;
  2437. completion_prefixes.push_back(".");
  2438. code_edit->set_code_completion_prefixes(completion_prefixes);
  2439. code_edit->insert_text_at_caret(".");
  2440. code_edit->request_code_completion();
  2441. SIGNAL_CHECK("code_completion_requested", signal_args);
  2442. /* Should work with space too. */
  2443. code_edit->insert_text_at_caret(" ");
  2444. code_edit->request_code_completion();
  2445. SIGNAL_CHECK("code_completion_requested", signal_args);
  2446. /* Should work when complete ends with prefix. */
  2447. code_edit->clear();
  2448. code_edit->insert_text_at_caret("t");
  2449. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "test.", "test.");
  2450. code_edit->update_code_completion_options();
  2451. code_edit->confirm_code_completion();
  2452. CHECK(code_edit->get_line(0) == "test.");
  2453. SIGNAL_CHECK("code_completion_requested", signal_args);
  2454. SIGNAL_UNWATCH(code_edit, "code_completion_requested");
  2455. }
  2456. SUBCASE("[CodeEdit] autocomplete completion") {
  2457. if (TS->has_feature(TextServer::FEATURE_FONT_DYNAMIC) && TS->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
  2458. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2459. code_edit->set_code_completion_enabled(true);
  2460. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2461. code_edit->update_code_completion_options();
  2462. code_edit->set_code_completion_selected_index(1);
  2463. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2464. CHECK(code_edit->get_code_completion_option(0).size() == 0);
  2465. CHECK(code_edit->get_code_completion_options().size() == 0);
  2466. /* Adding does not update the list. */
  2467. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_0.", "item_0");
  2468. code_edit->set_code_completion_selected_index(1);
  2469. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2470. CHECK(code_edit->get_code_completion_option(0).size() == 0);
  2471. CHECK(code_edit->get_code_completion_options().size() == 0);
  2472. /* After update, pending add should not be counted, */
  2473. /* also does not work on col 0 */
  2474. code_edit->insert_text_at_caret("i");
  2475. code_edit->update_code_completion_options();
  2476. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0", Color(1, 0, 0), Ref<Resource>(), Color(1, 0, 0));
  2477. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_1.", "item_1");
  2478. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_2.", "item_2");
  2479. ERR_PRINT_OFF;
  2480. code_edit->set_code_completion_selected_index(1);
  2481. ERR_PRINT_ON;
  2482. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2483. CHECK(code_edit->get_code_completion_option(0).size() == 6);
  2484. CHECK(code_edit->get_code_completion_options().size() == 1);
  2485. /* Check cancel closes completion. */
  2486. SEND_GUI_ACTION("ui_cancel");
  2487. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2488. code_edit->update_code_completion_options();
  2489. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2490. code_edit->set_code_completion_selected_index(1);
  2491. CHECK(code_edit->get_code_completion_selected_index() == 1);
  2492. CHECK(code_edit->get_code_completion_option(0).size() == 6);
  2493. CHECK(code_edit->get_code_completion_options().size() == 3);
  2494. /* Check data. */
  2495. Dictionary option = code_edit->get_code_completion_option(0);
  2496. CHECK((int)option["kind"] == (int)CodeEdit::CodeCompletionKind::KIND_CLASS);
  2497. CHECK(option["display_text"] == "item_0.");
  2498. CHECK(option["insert_text"] == "item_0");
  2499. CHECK(option["font_color"] == Color(1, 0, 0));
  2500. CHECK(option["icon"] == Ref<Resource>());
  2501. CHECK(option["default_value"] == Color(1, 0, 0));
  2502. /* Set size for mouse input. */
  2503. code_edit->set_size(Size2(100, 100));
  2504. /* Check input. */
  2505. SEND_GUI_ACTION("ui_end");
  2506. CHECK(code_edit->get_code_completion_selected_index() == 2);
  2507. SEND_GUI_ACTION("ui_home");
  2508. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2509. SEND_GUI_ACTION("ui_page_down");
  2510. CHECK(code_edit->get_code_completion_selected_index() == 2);
  2511. SEND_GUI_ACTION("ui_page_up");
  2512. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2513. SEND_GUI_ACTION("ui_up");
  2514. CHECK(code_edit->get_code_completion_selected_index() == 2);
  2515. SEND_GUI_ACTION("ui_down");
  2516. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2517. SEND_GUI_KEY_EVENT(Key::T);
  2518. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2519. SEND_GUI_ACTION("ui_left");
  2520. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2521. SEND_GUI_ACTION("ui_right");
  2522. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2523. SEND_GUI_ACTION("ui_text_backspace");
  2524. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2525. Point2 caret_pos = code_edit->get_caret_draw_pos();
  2526. caret_pos.y += code_edit->get_line_height();
  2527. SEND_GUI_MOUSE_BUTTON_EVENT(caret_pos, MouseButton::WHEEL_DOWN, 0, Key::NONE);
  2528. CHECK(code_edit->get_code_completion_selected_index() == 1);
  2529. SEND_GUI_MOUSE_BUTTON_EVENT(caret_pos, MouseButton::WHEEL_UP, 0, Key::NONE);
  2530. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2531. /* Single click selects. */
  2532. caret_pos.y += code_edit->get_line_height() * 2;
  2533. SEND_GUI_MOUSE_BUTTON_EVENT(caret_pos, MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
  2534. CHECK(code_edit->get_code_completion_selected_index() == 2);
  2535. /* Double click inserts. */
  2536. SEND_GUI_DOUBLE_CLICK(caret_pos, Key::NONE);
  2537. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2538. CHECK(code_edit->get_line(0) == "item_2");
  2539. code_edit->set_auto_brace_completion_enabled(false);
  2540. /* Does nothing in readonly. */
  2541. code_edit->undo();
  2542. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2543. code_edit->update_code_completion_options();
  2544. code_edit->set_editable(false);
  2545. code_edit->confirm_code_completion();
  2546. code_edit->set_editable(true);
  2547. CHECK(code_edit->get_line(0) == "i");
  2548. /* Replace */
  2549. code_edit->clear();
  2550. code_edit->insert_text_at_caret("item_1 test");
  2551. code_edit->set_caret_column(2);
  2552. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2553. code_edit->update_code_completion_options();
  2554. SEND_GUI_ACTION("ui_text_completion_replace");
  2555. CHECK(code_edit->get_line(0) == "item_0 test");
  2556. /* Replace string. */
  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("ui_text_completion_replace");
  2563. CHECK(code_edit->get_line(0) == "\"item_0\"");
  2564. /* Normal replace if no end is given. */
  2565. code_edit->clear();
  2566. code_edit->insert_text_at_caret("\"item_1 test");
  2567. code_edit->set_caret_column(2);
  2568. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2569. code_edit->update_code_completion_options();
  2570. SEND_GUI_ACTION("ui_text_completion_replace");
  2571. CHECK(code_edit->get_line(0) == "\"item_0\" test");
  2572. /* Insert at completion. */
  2573. code_edit->clear();
  2574. code_edit->insert_text_at_caret("item_1 test");
  2575. code_edit->set_caret_column(2);
  2576. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2577. code_edit->update_code_completion_options();
  2578. SEND_GUI_ACTION("ui_text_completion_accept");
  2579. CHECK(code_edit->get_line(0) == "item_01 test");
  2580. /* Insert at completion with string should have same output. */
  2581. code_edit->clear();
  2582. code_edit->insert_text_at_caret("\"item_1 test\"");
  2583. code_edit->set_caret_column(2);
  2584. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2585. code_edit->update_code_completion_options();
  2586. SEND_GUI_ACTION("ui_text_completion_accept");
  2587. CHECK(code_edit->get_line(0) == "\"item_0\"1 test\"");
  2588. /* Merge symbol at end on insert text. */
  2589. /* End on completion entry. */
  2590. code_edit->clear();
  2591. code_edit->insert_text_at_caret("item_1 test");
  2592. code_edit->set_caret_column(2);
  2593. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2594. code_edit->update_code_completion_options();
  2595. SEND_GUI_ACTION("ui_text_completion_replace");
  2596. CHECK(code_edit->get_line(0) == "item_0( test");
  2597. CHECK(code_edit->get_caret_column() == 7);
  2598. /* End of text*/
  2599. code_edit->clear();
  2600. code_edit->insert_text_at_caret("item_1( test");
  2601. code_edit->set_caret_column(2);
  2602. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  2603. code_edit->update_code_completion_options();
  2604. SEND_GUI_ACTION("ui_text_completion_replace");
  2605. CHECK(code_edit->get_line(0) == "item_0( test");
  2606. CHECK(code_edit->get_caret_column() == 6);
  2607. /* End of both. */
  2608. code_edit->clear();
  2609. code_edit->insert_text_at_caret("item_1( test");
  2610. code_edit->set_caret_column(2);
  2611. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2612. code_edit->update_code_completion_options();
  2613. SEND_GUI_ACTION("ui_text_completion_replace");
  2614. CHECK(code_edit->get_line(0) == "item_0( test");
  2615. CHECK(code_edit->get_caret_column() == 7);
  2616. /* Full set. */
  2617. /* End on completion entry. */
  2618. code_edit->clear();
  2619. code_edit->insert_text_at_caret("item_1 test");
  2620. code_edit->set_caret_column(2);
  2621. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  2622. code_edit->update_code_completion_options();
  2623. SEND_GUI_ACTION("ui_text_completion_replace");
  2624. CHECK(code_edit->get_line(0) == "item_0() test");
  2625. CHECK(code_edit->get_caret_column() == 8);
  2626. /* End of text*/
  2627. code_edit->clear();
  2628. code_edit->insert_text_at_caret("item_1() test");
  2629. code_edit->set_caret_column(2);
  2630. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  2631. code_edit->update_code_completion_options();
  2632. SEND_GUI_ACTION("ui_text_completion_replace");
  2633. CHECK(code_edit->get_line(0) == "item_0() test");
  2634. CHECK(code_edit->get_caret_column() == 6);
  2635. /* End of both. */
  2636. code_edit->clear();
  2637. code_edit->insert_text_at_caret("item_1() test");
  2638. code_edit->set_caret_column(2);
  2639. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  2640. code_edit->update_code_completion_options();
  2641. SEND_GUI_ACTION("ui_text_completion_replace");
  2642. CHECK(code_edit->get_line(0) == "item_0() test");
  2643. CHECK(code_edit->get_caret_column() == 8);
  2644. /* Autobrace completion. */
  2645. code_edit->set_auto_brace_completion_enabled(true);
  2646. /* End on completion entry. */
  2647. code_edit->clear();
  2648. code_edit->insert_text_at_caret("item_1 test");
  2649. code_edit->set_caret_column(2);
  2650. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2651. code_edit->update_code_completion_options();
  2652. SEND_GUI_ACTION("ui_text_completion_replace");
  2653. CHECK(code_edit->get_line(0) == "item_0() test");
  2654. CHECK(code_edit->get_caret_column() == 7);
  2655. /* End of text*/
  2656. code_edit->clear();
  2657. code_edit->insert_text_at_caret("item_1( test");
  2658. code_edit->set_caret_column(2);
  2659. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  2660. code_edit->update_code_completion_options();
  2661. SEND_GUI_ACTION("ui_text_completion_replace");
  2662. CHECK(code_edit->get_line(0) == "item_0( test");
  2663. CHECK(code_edit->get_caret_column() == 6);
  2664. /* End of both. */
  2665. code_edit->clear();
  2666. code_edit->insert_text_at_caret("item_1( test");
  2667. code_edit->set_caret_column(2);
  2668. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2669. code_edit->update_code_completion_options();
  2670. SEND_GUI_ACTION("ui_text_completion_replace");
  2671. CHECK(code_edit->get_line(0) == "item_0( test");
  2672. CHECK(code_edit->get_caret_column() == 7);
  2673. /* Full set. */
  2674. /* End on completion entry. */
  2675. code_edit->clear();
  2676. code_edit->insert_text_at_caret("item_1 test");
  2677. code_edit->set_caret_column(2);
  2678. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  2679. code_edit->update_code_completion_options();
  2680. SEND_GUI_ACTION("ui_text_completion_replace");
  2681. CHECK(code_edit->get_line(0) == "item_0() test");
  2682. CHECK(code_edit->get_caret_column() == 8);
  2683. /* End of text*/
  2684. code_edit->clear();
  2685. code_edit->insert_text_at_caret("item_1() test");
  2686. code_edit->set_caret_column(2);
  2687. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  2688. code_edit->update_code_completion_options();
  2689. SEND_GUI_ACTION("ui_text_completion_replace");
  2690. CHECK(code_edit->get_line(0) == "item_0() test");
  2691. CHECK(code_edit->get_caret_column() == 6);
  2692. /* End of both. */
  2693. code_edit->clear();
  2694. code_edit->insert_text_at_caret("item_1() test");
  2695. code_edit->set_caret_column(2);
  2696. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  2697. code_edit->update_code_completion_options();
  2698. SEND_GUI_ACTION("ui_text_completion_replace");
  2699. CHECK(code_edit->get_line(0) == "item_0() test");
  2700. CHECK(code_edit->get_caret_column() == 8);
  2701. }
  2702. }
  2703. memdelete(code_edit);
  2704. }
  2705. TEST_CASE("[SceneTree][CodeEdit] symbol lookup") {
  2706. CodeEdit *code_edit = memnew(CodeEdit);
  2707. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  2708. code_edit->grab_focus();
  2709. code_edit->set_symbol_lookup_on_click_enabled(true);
  2710. CHECK(code_edit->is_symbol_lookup_on_click_enabled());
  2711. if (TS->has_feature(TextServer::FEATURE_FONT_DYNAMIC) && TS->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
  2712. /* Set size for mouse input. */
  2713. code_edit->set_size(Size2(100, 100));
  2714. code_edit->set_text("this is some text");
  2715. Point2 caret_pos = code_edit->get_caret_draw_pos();
  2716. caret_pos.x += 60;
  2717. SEND_GUI_MOUSE_BUTTON_EVENT(caret_pos, MouseButton::NONE, 0, Key::NONE);
  2718. CHECK(code_edit->get_text_for_symbol_lookup() == "this is s" + String::chr(0xFFFF) + "ome text");
  2719. SIGNAL_WATCH(code_edit, "symbol_validate");
  2720. #ifdef MACOS_ENABLED
  2721. SEND_GUI_KEY_EVENT(Key::META);
  2722. #else
  2723. SEND_GUI_KEY_EVENT(Key::CTRL);
  2724. #endif
  2725. Array signal_args;
  2726. Array arg;
  2727. arg.push_back("some");
  2728. signal_args.push_back(arg);
  2729. SIGNAL_CHECK("symbol_validate", signal_args);
  2730. SIGNAL_UNWATCH(code_edit, "symbol_validate");
  2731. memdelete(code_edit);
  2732. }
  2733. }
  2734. TEST_CASE("[SceneTree][CodeEdit] line length guidelines") {
  2735. CodeEdit *code_edit = memnew(CodeEdit);
  2736. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  2737. code_edit->grab_focus();
  2738. TypedArray<int> guide_lines;
  2739. code_edit->set_line_length_guidelines(guide_lines);
  2740. CHECK(code_edit->get_line_length_guidelines().size() == 0);
  2741. guide_lines.push_back(80);
  2742. guide_lines.push_back(120);
  2743. /* Order should be preserved. */
  2744. code_edit->set_line_length_guidelines(guide_lines);
  2745. CHECK((int)code_edit->get_line_length_guidelines()[0] == 80);
  2746. CHECK((int)code_edit->get_line_length_guidelines()[1] == 120);
  2747. memdelete(code_edit);
  2748. }
  2749. TEST_CASE("[SceneTree][CodeEdit] Backspace delete") {
  2750. CodeEdit *code_edit = memnew(CodeEdit);
  2751. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  2752. code_edit->grab_focus();
  2753. /* Backspace with selection on first line. */
  2754. code_edit->set_text("");
  2755. code_edit->insert_text_at_caret("test backspace");
  2756. code_edit->select(0, 0, 0, 5);
  2757. code_edit->backspace();
  2758. CHECK(code_edit->get_line(0) == "backspace");
  2759. /* Backspace with selection on first line and caret at the beginning of file. */
  2760. code_edit->set_text("");
  2761. code_edit->insert_text_at_caret("test backspace");
  2762. code_edit->select(0, 0, 0, 5);
  2763. code_edit->set_caret_column(0);
  2764. code_edit->backspace();
  2765. CHECK(code_edit->get_line(0) == "backspace");
  2766. /* Move caret up to the previous line on backspace if caret is at the first column. */
  2767. code_edit->set_text("");
  2768. code_edit->insert_text_at_caret("line 1\nline 2");
  2769. code_edit->set_caret_line(1);
  2770. code_edit->set_caret_column(0);
  2771. code_edit->backspace();
  2772. CHECK(code_edit->get_line(0) == "line 1line 2");
  2773. CHECK(code_edit->get_caret_line() == 0);
  2774. CHECK(code_edit->get_caret_column() == 6);
  2775. /* Backspace delete all text if all text is selected. */
  2776. code_edit->set_text("");
  2777. code_edit->insert_text_at_caret("line 1\nline 2\nline 3");
  2778. code_edit->select_all();
  2779. code_edit->backspace();
  2780. CHECK(code_edit->get_text().is_empty());
  2781. /* Backspace at the beginning without selection has no effect. */
  2782. code_edit->set_text("");
  2783. code_edit->insert_text_at_caret("line 1\nline 2\nline 3");
  2784. code_edit->set_caret_line(0);
  2785. code_edit->set_caret_column(0);
  2786. code_edit->backspace();
  2787. CHECK(code_edit->get_text() == "line 1\nline 2\nline 3");
  2788. memdelete(code_edit);
  2789. }
  2790. TEST_CASE("[SceneTree][CodeEdit] New Line") {
  2791. CodeEdit *code_edit = memnew(CodeEdit);
  2792. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  2793. code_edit->grab_focus();
  2794. /* Add a new line. */
  2795. code_edit->set_text("");
  2796. code_edit->insert_text_at_caret("test new line");
  2797. code_edit->set_caret_line(0);
  2798. code_edit->set_caret_column(13);
  2799. SEND_GUI_ACTION("ui_text_newline");
  2800. CHECK(code_edit->get_line(0) == "test new line");
  2801. CHECK(code_edit->get_line(1) == "");
  2802. /* Split line with new line. */
  2803. code_edit->set_text("");
  2804. code_edit->insert_text_at_caret("test new line");
  2805. code_edit->set_caret_line(0);
  2806. code_edit->set_caret_column(5);
  2807. SEND_GUI_ACTION("ui_text_newline");
  2808. CHECK(code_edit->get_line(0) == "test ");
  2809. CHECK(code_edit->get_line(1) == "new line");
  2810. /* Delete selection and split with new line. */
  2811. code_edit->set_text("");
  2812. code_edit->insert_text_at_caret("test new line");
  2813. code_edit->select(0, 0, 0, 5);
  2814. SEND_GUI_ACTION("ui_text_newline");
  2815. CHECK(code_edit->get_line(0) == "");
  2816. CHECK(code_edit->get_line(1) == "new line");
  2817. /* Blank new line below with selection should not split. */
  2818. code_edit->set_text("");
  2819. code_edit->insert_text_at_caret("test new line");
  2820. code_edit->select(0, 0, 0, 5);
  2821. SEND_GUI_ACTION("ui_text_newline_blank");
  2822. CHECK(code_edit->get_line(0) == "test new line");
  2823. CHECK(code_edit->get_line(1) == "");
  2824. /* Blank new line above with selection should not split. */
  2825. code_edit->set_text("");
  2826. code_edit->insert_text_at_caret("test new line");
  2827. code_edit->select(0, 0, 0, 5);
  2828. SEND_GUI_ACTION("ui_text_newline_above");
  2829. CHECK(code_edit->get_line(0) == "");
  2830. CHECK(code_edit->get_line(1) == "test new line");
  2831. memdelete(code_edit);
  2832. }
  2833. } // namespace TestCodeEdit
  2834. #endif // TEST_CODE_EDIT_H