test_code_edit.h 152 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061
  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. /* If there is something after a colon
  1853. and there is a colon in the comment it
  1854. should not indent. */
  1855. code_edit->add_comment_delimiter("#", "");
  1856. code_edit->set_text("");
  1857. code_edit->insert_text_at_caret("test:test#:");
  1858. SEND_GUI_ACTION("ui_text_newline");
  1859. CHECK(code_edit->get_line(0) == "test:test#:");
  1860. CHECK(code_edit->get_line(1) == "");
  1861. code_edit->remove_comment_delimiter("#");
  1862. }
  1863. }
  1864. SUBCASE("[CodeEdit] convert indent to tabs") {
  1865. code_edit->set_indent_size(4);
  1866. code_edit->set_indent_using_spaces(false);
  1867. // Only line.
  1868. code_edit->insert_text_at_caret(" test");
  1869. code_edit->set_caret_line(0);
  1870. code_edit->set_caret_column(8);
  1871. code_edit->select(0, 8, 0, 9);
  1872. code_edit->convert_indent();
  1873. CHECK(code_edit->get_line(0) == "\t\ttest");
  1874. CHECK(code_edit->get_caret_column() == 2);
  1875. CHECK(code_edit->get_selection_from_column() == 2);
  1876. CHECK(code_edit->get_selection_to_column() == 3);
  1877. // First line.
  1878. code_edit->set_text("");
  1879. code_edit->insert_text_at_caret(" test\n");
  1880. code_edit->set_caret_line(0);
  1881. code_edit->set_caret_column(8);
  1882. code_edit->select(0, 8, 0, 9);
  1883. code_edit->convert_indent();
  1884. CHECK(code_edit->get_line(0) == "\t\ttest");
  1885. CHECK(code_edit->get_caret_column() == 2);
  1886. CHECK(code_edit->get_selection_from_column() == 2);
  1887. CHECK(code_edit->get_selection_to_column() == 3);
  1888. // Middle line.
  1889. code_edit->set_text("");
  1890. code_edit->insert_text_at_caret("\n test\n");
  1891. code_edit->set_caret_line(1);
  1892. code_edit->set_caret_column(8);
  1893. code_edit->select(1, 8, 1, 9);
  1894. code_edit->convert_indent();
  1895. CHECK(code_edit->get_line(1) == "\t\ttest");
  1896. CHECK(code_edit->get_caret_column() == 2);
  1897. CHECK(code_edit->get_selection_from_column() == 2);
  1898. CHECK(code_edit->get_selection_to_column() == 3);
  1899. // End line.
  1900. code_edit->set_text("");
  1901. code_edit->insert_text_at_caret("\n test");
  1902. code_edit->set_caret_line(1);
  1903. code_edit->set_caret_column(8);
  1904. code_edit->select(1, 8, 1, 9);
  1905. code_edit->convert_indent();
  1906. CHECK(code_edit->get_line(1) == "\t\ttest");
  1907. CHECK(code_edit->get_caret_column() == 2);
  1908. CHECK(code_edit->get_selection_from_column() == 2);
  1909. CHECK(code_edit->get_selection_to_column() == 3);
  1910. // Within provided range.
  1911. code_edit->set_text("");
  1912. code_edit->insert_text_at_caret(" test\n test\n");
  1913. code_edit->set_caret_line(1);
  1914. code_edit->set_caret_column(8);
  1915. code_edit->select(1, 8, 1, 9);
  1916. code_edit->convert_indent(1, 1);
  1917. CHECK(code_edit->get_line(0) == " test");
  1918. CHECK(code_edit->get_line(1) == "\t\ttest");
  1919. CHECK(code_edit->get_caret_column() == 2);
  1920. CHECK(code_edit->get_selection_from_column() == 2);
  1921. CHECK(code_edit->get_selection_to_column() == 3);
  1922. }
  1923. SUBCASE("[CodeEdit] convert indent to spaces") {
  1924. code_edit->set_indent_size(4);
  1925. code_edit->set_indent_using_spaces(true);
  1926. // Only line.
  1927. code_edit->insert_text_at_caret("\t\ttest");
  1928. code_edit->set_caret_line(0);
  1929. code_edit->set_caret_column(2);
  1930. code_edit->select(0, 2, 0, 3);
  1931. code_edit->convert_indent();
  1932. CHECK(code_edit->get_line(0) == " test");
  1933. CHECK(code_edit->get_caret_column() == 8);
  1934. CHECK(code_edit->get_selection_from_column() == 8);
  1935. CHECK(code_edit->get_selection_to_column() == 9);
  1936. // First line.
  1937. code_edit->set_text("");
  1938. code_edit->insert_text_at_caret("\t\ttest\n");
  1939. code_edit->set_caret_line(0);
  1940. code_edit->set_caret_column(2);
  1941. code_edit->select(0, 2, 0, 3);
  1942. code_edit->convert_indent();
  1943. CHECK(code_edit->get_line(0) == " test");
  1944. CHECK(code_edit->get_caret_column() == 8);
  1945. CHECK(code_edit->get_selection_from_column() == 8);
  1946. CHECK(code_edit->get_selection_to_column() == 9);
  1947. // Middle line.
  1948. code_edit->set_text("");
  1949. code_edit->insert_text_at_caret("\n\t\ttest\n");
  1950. code_edit->set_caret_line(1);
  1951. code_edit->set_caret_column(2);
  1952. code_edit->select(1, 2, 1, 3);
  1953. code_edit->convert_indent();
  1954. CHECK(code_edit->get_line(1) == " test");
  1955. CHECK(code_edit->get_caret_column() == 8);
  1956. CHECK(code_edit->get_selection_from_column() == 8);
  1957. CHECK(code_edit->get_selection_to_column() == 9);
  1958. // End line.
  1959. code_edit->set_text("");
  1960. code_edit->insert_text_at_caret("\n\t\ttest");
  1961. code_edit->set_caret_line(1);
  1962. code_edit->set_caret_column(2);
  1963. code_edit->select(1, 2, 1, 3);
  1964. code_edit->convert_indent();
  1965. CHECK(code_edit->get_line(1) == " test");
  1966. CHECK(code_edit->get_caret_column() == 8);
  1967. CHECK(code_edit->get_selection_from_column() == 8);
  1968. CHECK(code_edit->get_selection_to_column() == 9);
  1969. // Within provided range.
  1970. code_edit->set_text("");
  1971. code_edit->insert_text_at_caret("\ttest\n\t\ttest\n");
  1972. code_edit->set_caret_line(1);
  1973. code_edit->set_caret_column(2);
  1974. code_edit->select(1, 2, 1, 3);
  1975. code_edit->convert_indent(1, 1);
  1976. CHECK(code_edit->get_line(0) == "\ttest");
  1977. CHECK(code_edit->get_line(1) == " test");
  1978. CHECK(code_edit->get_caret_column() == 8);
  1979. CHECK(code_edit->get_selection_from_column() == 8);
  1980. CHECK(code_edit->get_selection_to_column() == 9);
  1981. // Outside of range.
  1982. ERR_PRINT_OFF;
  1983. code_edit->convert_indent(0, 4);
  1984. code_edit->convert_indent(4, 5);
  1985. code_edit->convert_indent(4, 1);
  1986. ERR_PRINT_ON;
  1987. }
  1988. memdelete(code_edit);
  1989. }
  1990. TEST_CASE("[SceneTree][CodeEdit] folding") {
  1991. CodeEdit *code_edit = memnew(CodeEdit);
  1992. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  1993. code_edit->grab_focus();
  1994. SUBCASE("[CodeEdit] folding settings") {
  1995. code_edit->set_line_folding_enabled(true);
  1996. CHECK(code_edit->is_line_folding_enabled());
  1997. code_edit->set_line_folding_enabled(false);
  1998. CHECK_FALSE(code_edit->is_line_folding_enabled());
  1999. }
  2000. SUBCASE("[CodeEdit] folding") {
  2001. code_edit->set_line_folding_enabled(true);
  2002. // No indent.
  2003. code_edit->set_text("line1\nline2\nline3");
  2004. for (int i = 0; i < 2; i++) {
  2005. CHECK_FALSE(code_edit->can_fold_line(i));
  2006. code_edit->fold_line(i);
  2007. CHECK_FALSE(code_edit->is_line_folded(i));
  2008. }
  2009. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2010. // Indented lines.
  2011. code_edit->set_text("\tline1\n\tline2\n\tline3");
  2012. for (int i = 0; i < 2; i++) {
  2013. CHECK_FALSE(code_edit->can_fold_line(i));
  2014. code_edit->fold_line(i);
  2015. CHECK_FALSE(code_edit->is_line_folded(i));
  2016. }
  2017. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2018. // Indent.
  2019. code_edit->set_text("line1\n\tline2\nline3");
  2020. CHECK(code_edit->can_fold_line(0));
  2021. for (int i = 1; i < 2; i++) {
  2022. CHECK_FALSE(code_edit->can_fold_line(i));
  2023. code_edit->fold_line(i);
  2024. CHECK_FALSE(code_edit->is_line_folded(i));
  2025. }
  2026. code_edit->fold_line(0);
  2027. CHECK(code_edit->is_line_folded(0));
  2028. CHECK_FALSE(code_edit->is_line_folded(1));
  2029. CHECK_FALSE(code_edit->is_line_folded(2));
  2030. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  2031. // Indent with blank lines.
  2032. code_edit->set_text("line1\n\tline2\n\n\nline3");
  2033. CHECK(code_edit->can_fold_line(0));
  2034. for (int i = 1; i < 2; i++) {
  2035. CHECK_FALSE(code_edit->can_fold_line(i));
  2036. code_edit->fold_line(i);
  2037. CHECK_FALSE(code_edit->is_line_folded(i));
  2038. }
  2039. code_edit->fold_line(0);
  2040. CHECK(code_edit->is_line_folded(0));
  2041. CHECK_FALSE(code_edit->is_line_folded(1));
  2042. CHECK_FALSE(code_edit->is_line_folded(2));
  2043. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  2044. // Nested indents.
  2045. code_edit->set_text("line1\n\tline2\n\t\tline3\nline4");
  2046. CHECK(code_edit->can_fold_line(0));
  2047. CHECK(code_edit->can_fold_line(1));
  2048. for (int i = 2; i < 3; i++) {
  2049. CHECK_FALSE(code_edit->can_fold_line(i));
  2050. code_edit->fold_line(i);
  2051. CHECK_FALSE(code_edit->is_line_folded(i));
  2052. }
  2053. code_edit->fold_line(1);
  2054. CHECK_FALSE(code_edit->is_line_folded(0));
  2055. CHECK(code_edit->is_line_folded(1));
  2056. CHECK_FALSE(code_edit->is_line_folded(2));
  2057. CHECK_FALSE(code_edit->is_line_folded(3));
  2058. CHECK(code_edit->get_next_visible_line_offset_from(2, 1) == 2);
  2059. code_edit->fold_line(0);
  2060. CHECK(code_edit->is_line_folded(0));
  2061. CHECK_FALSE(code_edit->is_line_folded(1));
  2062. CHECK_FALSE(code_edit->is_line_folded(2));
  2063. CHECK_FALSE(code_edit->is_line_folded(3));
  2064. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  2065. // Check metadata.
  2066. CHECK(code_edit->get_folded_lines().size() == 1);
  2067. CHECK((int)code_edit->get_folded_lines()[0] == 0);
  2068. // Cannot unfold nested.
  2069. code_edit->unfold_line(1);
  2070. CHECK_FALSE(code_edit->is_line_folded(0));
  2071. CHECK_FALSE(code_edit->is_line_folded(1));
  2072. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2073. // (un)Fold all / toggle.
  2074. code_edit->unfold_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. // Check metadata.
  2079. CHECK(code_edit->get_folded_lines().size() == 0);
  2080. code_edit->fold_all_lines();
  2081. CHECK(code_edit->is_line_folded(0));
  2082. CHECK_FALSE(code_edit->is_line_folded(1));
  2083. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  2084. code_edit->unfold_all_lines();
  2085. CHECK_FALSE(code_edit->is_line_folded(0));
  2086. CHECK_FALSE(code_edit->is_line_folded(1));
  2087. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2088. code_edit->toggle_foldable_line(0);
  2089. CHECK(code_edit->is_line_folded(0));
  2090. CHECK_FALSE(code_edit->is_line_folded(1));
  2091. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  2092. // Can also unfold from hidden line.
  2093. code_edit->unfold_line(1);
  2094. CHECK_FALSE(code_edit->is_line_folded(0));
  2095. CHECK_FALSE(code_edit->is_line_folded(1));
  2096. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2097. // Blank lines.
  2098. code_edit->set_text("line1\n\tline2\n\n\n\ttest\n\nline3");
  2099. CHECK(code_edit->can_fold_line(0));
  2100. for (int i = 1; i < code_edit->get_line_count(); i++) {
  2101. CHECK_FALSE(code_edit->can_fold_line(i));
  2102. code_edit->fold_line(i);
  2103. CHECK_FALSE(code_edit->is_line_folded(i));
  2104. }
  2105. code_edit->fold_line(0);
  2106. CHECK(code_edit->is_line_folded(0));
  2107. for (int i = 1; i < code_edit->get_line_count(); i++) {
  2108. CHECK_FALSE(code_edit->is_line_folded(i));
  2109. }
  2110. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 5);
  2111. // End of file.
  2112. code_edit->set_text("line1\n\tline2");
  2113. CHECK(code_edit->can_fold_line(0));
  2114. CHECK_FALSE(code_edit->can_fold_line(1));
  2115. code_edit->fold_line(1);
  2116. CHECK_FALSE(code_edit->is_line_folded(1));
  2117. code_edit->fold_line(0);
  2118. CHECK(code_edit->is_line_folded(0));
  2119. CHECK_FALSE(code_edit->is_line_folded(1));
  2120. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2121. // Comment & string blocks.
  2122. // Single line block
  2123. code_edit->add_comment_delimiter("#", "", true);
  2124. code_edit->set_text("#line1\n#\tline2");
  2125. CHECK(code_edit->can_fold_line(0));
  2126. CHECK_FALSE(code_edit->can_fold_line(1));
  2127. code_edit->fold_line(1);
  2128. CHECK_FALSE(code_edit->is_line_folded(1));
  2129. code_edit->fold_line(0);
  2130. CHECK(code_edit->is_line_folded(0));
  2131. CHECK_FALSE(code_edit->is_line_folded(1));
  2132. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2133. // Has to be full line.
  2134. code_edit->set_text("test #line1\n#\tline2");
  2135. CHECK_FALSE(code_edit->can_fold_line(0));
  2136. CHECK_FALSE(code_edit->can_fold_line(1));
  2137. code_edit->fold_line(1);
  2138. CHECK_FALSE(code_edit->is_line_folded(1));
  2139. code_edit->fold_line(0);
  2140. CHECK_FALSE(code_edit->is_line_folded(0));
  2141. CHECK_FALSE(code_edit->is_line_folded(1));
  2142. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2143. code_edit->set_text("#line1\ntest #\tline2");
  2144. CHECK_FALSE(code_edit->can_fold_line(0));
  2145. CHECK_FALSE(code_edit->can_fold_line(1));
  2146. code_edit->fold_line(1);
  2147. CHECK_FALSE(code_edit->is_line_folded(1));
  2148. code_edit->fold_line(0);
  2149. CHECK_FALSE(code_edit->is_line_folded(0));
  2150. CHECK_FALSE(code_edit->is_line_folded(1));
  2151. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2152. // String.
  2153. code_edit->add_string_delimiter("^", "", true);
  2154. code_edit->set_text("^line1\n^\tline2");
  2155. CHECK(code_edit->can_fold_line(0));
  2156. CHECK_FALSE(code_edit->can_fold_line(1));
  2157. code_edit->fold_line(1);
  2158. CHECK_FALSE(code_edit->is_line_folded(1));
  2159. code_edit->fold_line(0);
  2160. CHECK(code_edit->is_line_folded(0));
  2161. CHECK_FALSE(code_edit->is_line_folded(1));
  2162. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2163. // Has to be full line.
  2164. code_edit->set_text("test ^line1\n^\tline2");
  2165. CHECK_FALSE(code_edit->can_fold_line(0));
  2166. CHECK_FALSE(code_edit->can_fold_line(1));
  2167. code_edit->fold_line(1);
  2168. CHECK_FALSE(code_edit->is_line_folded(1));
  2169. code_edit->fold_line(0);
  2170. CHECK_FALSE(code_edit->is_line_folded(0));
  2171. CHECK_FALSE(code_edit->is_line_folded(1));
  2172. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2173. code_edit->set_text("^line1\ntest ^\tline2");
  2174. CHECK_FALSE(code_edit->can_fold_line(0));
  2175. CHECK_FALSE(code_edit->can_fold_line(1));
  2176. code_edit->fold_line(1);
  2177. CHECK_FALSE(code_edit->is_line_folded(1));
  2178. code_edit->fold_line(0);
  2179. CHECK_FALSE(code_edit->is_line_folded(0));
  2180. CHECK_FALSE(code_edit->is_line_folded(1));
  2181. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2182. // Multiline blocks.
  2183. code_edit->add_comment_delimiter("&", "&", false);
  2184. code_edit->set_text("&line1\n\tline2&\nline3");
  2185. CHECK(code_edit->can_fold_line(0));
  2186. CHECK_FALSE(code_edit->can_fold_line(1));
  2187. code_edit->fold_line(1);
  2188. CHECK_FALSE(code_edit->is_line_folded(1));
  2189. code_edit->fold_line(0);
  2190. CHECK(code_edit->is_line_folded(0));
  2191. CHECK_FALSE(code_edit->is_line_folded(1));
  2192. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  2193. // Multiline comment before last line.
  2194. code_edit->set_text("&line1\nline2&\ntest");
  2195. CHECK(code_edit->can_fold_line(0));
  2196. CHECK_FALSE(code_edit->can_fold_line(2));
  2197. code_edit->fold_line(1);
  2198. CHECK_FALSE(code_edit->is_line_folded(1));
  2199. code_edit->fold_line(0);
  2200. CHECK(code_edit->is_line_folded(0));
  2201. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  2202. // Has to be full line.
  2203. code_edit->set_text("test &line1\n\tline2&");
  2204. CHECK_FALSE(code_edit->can_fold_line(0));
  2205. CHECK_FALSE(code_edit->can_fold_line(1));
  2206. code_edit->fold_line(1);
  2207. CHECK_FALSE(code_edit->is_line_folded(1));
  2208. code_edit->fold_line(0);
  2209. CHECK_FALSE(code_edit->is_line_folded(0));
  2210. CHECK_FALSE(code_edit->is_line_folded(1));
  2211. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2212. code_edit->set_text("&line1\n\tline2& test");
  2213. CHECK_FALSE(code_edit->can_fold_line(0));
  2214. CHECK_FALSE(code_edit->can_fold_line(1));
  2215. code_edit->fold_line(1);
  2216. CHECK_FALSE(code_edit->is_line_folded(1));
  2217. code_edit->fold_line(0);
  2218. CHECK_FALSE(code_edit->is_line_folded(0));
  2219. CHECK_FALSE(code_edit->is_line_folded(1));
  2220. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2221. // Strings.
  2222. code_edit->add_string_delimiter("$", "$", false);
  2223. code_edit->set_text("$line1\n\tline2$");
  2224. CHECK(code_edit->can_fold_line(0));
  2225. CHECK_FALSE(code_edit->can_fold_line(1));
  2226. code_edit->fold_line(1);
  2227. CHECK_FALSE(code_edit->is_line_folded(1));
  2228. code_edit->fold_line(0);
  2229. CHECK(code_edit->is_line_folded(0));
  2230. CHECK_FALSE(code_edit->is_line_folded(1));
  2231. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2232. // Has to be full line.
  2233. code_edit->set_text("test $line1\n\tline2$");
  2234. CHECK_FALSE(code_edit->can_fold_line(0));
  2235. CHECK_FALSE(code_edit->can_fold_line(1));
  2236. code_edit->fold_line(1);
  2237. CHECK_FALSE(code_edit->is_line_folded(1));
  2238. code_edit->fold_line(0);
  2239. CHECK_FALSE(code_edit->is_line_folded(0));
  2240. CHECK_FALSE(code_edit->is_line_folded(1));
  2241. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2242. code_edit->set_text("$line1\n\tline2$ test");
  2243. CHECK_FALSE(code_edit->can_fold_line(0));
  2244. CHECK_FALSE(code_edit->can_fold_line(1));
  2245. code_edit->fold_line(1);
  2246. CHECK_FALSE(code_edit->is_line_folded(1));
  2247. code_edit->fold_line(0);
  2248. CHECK_FALSE(code_edit->is_line_folded(0));
  2249. CHECK_FALSE(code_edit->is_line_folded(1));
  2250. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1);
  2251. // Non-indented comments/strings.
  2252. // Single line
  2253. code_edit->set_text("test\n\tline1\n#line1\n#line2\n\ttest");
  2254. CHECK(code_edit->can_fold_line(0));
  2255. CHECK_FALSE(code_edit->can_fold_line(1));
  2256. code_edit->fold_line(1);
  2257. CHECK_FALSE(code_edit->is_line_folded(1));
  2258. code_edit->fold_line(0);
  2259. CHECK(code_edit->is_line_folded(0));
  2260. CHECK_FALSE(code_edit->is_line_folded(1));
  2261. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2262. code_edit->set_text("test\n\tline1\n^line1\n^line2\n\ttest");
  2263. CHECK(code_edit->can_fold_line(0));
  2264. CHECK_FALSE(code_edit->can_fold_line(1));
  2265. code_edit->fold_line(1);
  2266. CHECK_FALSE(code_edit->is_line_folded(1));
  2267. code_edit->fold_line(0);
  2268. CHECK(code_edit->is_line_folded(0));
  2269. CHECK_FALSE(code_edit->is_line_folded(1));
  2270. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2271. // Indent level 0->1, comment after lines
  2272. code_edit->set_text("line1\n\tline2\n#test");
  2273. CHECK(code_edit->can_fold_line(0));
  2274. CHECK_FALSE(code_edit->can_fold_line(1));
  2275. code_edit->fold_line(1);
  2276. CHECK_FALSE(code_edit->is_line_folded(1));
  2277. code_edit->fold_line(0);
  2278. CHECK(code_edit->is_line_folded(0));
  2279. CHECK_FALSE(code_edit->is_line_folded(1));
  2280. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  2281. // Indent level 0->1, comment between lines
  2282. code_edit->set_text("line1\n#test\n\tline2\nline3");
  2283. CHECK(code_edit->can_fold_line(0));
  2284. CHECK_FALSE(code_edit->can_fold_line(2));
  2285. code_edit->fold_line(2);
  2286. CHECK_FALSE(code_edit->is_line_folded(2));
  2287. code_edit->fold_line(0);
  2288. CHECK(code_edit->is_line_folded(0));
  2289. CHECK_FALSE(code_edit->is_line_folded(2));
  2290. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  2291. // Indent level 1->2, comment after lines
  2292. code_edit->set_text("\tline1\n\t\tline2\n#test");
  2293. CHECK(code_edit->can_fold_line(0));
  2294. CHECK_FALSE(code_edit->can_fold_line(1));
  2295. code_edit->fold_line(1);
  2296. CHECK_FALSE(code_edit->is_line_folded(1));
  2297. code_edit->fold_line(0);
  2298. CHECK(code_edit->is_line_folded(0));
  2299. CHECK_FALSE(code_edit->is_line_folded(1));
  2300. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2);
  2301. // Indent level 1->2, comment between lines
  2302. code_edit->set_text("\tline1\n#test\n\t\tline2\nline3");
  2303. CHECK(code_edit->can_fold_line(0));
  2304. CHECK_FALSE(code_edit->can_fold_line(2));
  2305. code_edit->fold_line(2);
  2306. CHECK_FALSE(code_edit->is_line_folded(2));
  2307. code_edit->fold_line(0);
  2308. CHECK(code_edit->is_line_folded(0));
  2309. CHECK_FALSE(code_edit->is_line_folded(2));
  2310. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3);
  2311. // Multiline
  2312. code_edit->set_text("test\n\tline1\n&line1\nline2&\n\ttest");
  2313. CHECK(code_edit->can_fold_line(0));
  2314. CHECK_FALSE(code_edit->can_fold_line(1));
  2315. code_edit->fold_line(1);
  2316. CHECK_FALSE(code_edit->is_line_folded(1));
  2317. code_edit->fold_line(0);
  2318. CHECK(code_edit->is_line_folded(0));
  2319. CHECK_FALSE(code_edit->is_line_folded(1));
  2320. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2321. code_edit->set_text("test\n\tline1\n$line1\nline2$\n\ttest");
  2322. CHECK(code_edit->can_fold_line(0));
  2323. CHECK_FALSE(code_edit->can_fold_line(1));
  2324. code_edit->fold_line(1);
  2325. CHECK_FALSE(code_edit->is_line_folded(1));
  2326. code_edit->fold_line(0);
  2327. CHECK(code_edit->is_line_folded(0));
  2328. CHECK_FALSE(code_edit->is_line_folded(1));
  2329. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2330. }
  2331. memdelete(code_edit);
  2332. }
  2333. TEST_CASE("[SceneTree][CodeEdit] region folding") {
  2334. CodeEdit *code_edit = memnew(CodeEdit);
  2335. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  2336. code_edit->grab_focus();
  2337. SUBCASE("[CodeEdit] region folding") {
  2338. code_edit->set_line_folding_enabled(true);
  2339. // Region tag detection.
  2340. code_edit->set_text("#region region_name\nline2\n#endregion");
  2341. code_edit->clear_comment_delimiters();
  2342. code_edit->add_comment_delimiter("#", "");
  2343. CHECK(code_edit->is_line_code_region_start(0));
  2344. CHECK_FALSE(code_edit->is_line_code_region_start(1));
  2345. CHECK_FALSE(code_edit->is_line_code_region_start(2));
  2346. CHECK_FALSE(code_edit->is_line_code_region_end(0));
  2347. CHECK_FALSE(code_edit->is_line_code_region_end(1));
  2348. CHECK(code_edit->is_line_code_region_end(2));
  2349. // Region tag customization.
  2350. code_edit->set_text("#region region_name\nline2\n#endregion\n#open region_name\nline2\n#close");
  2351. code_edit->clear_comment_delimiters();
  2352. code_edit->add_comment_delimiter("#", "");
  2353. CHECK(code_edit->is_line_code_region_start(0));
  2354. CHECK(code_edit->is_line_code_region_end(2));
  2355. CHECK_FALSE(code_edit->is_line_code_region_start(3));
  2356. CHECK_FALSE(code_edit->is_line_code_region_end(5));
  2357. code_edit->set_code_region_tags("open", "close");
  2358. CHECK_FALSE(code_edit->is_line_code_region_start(0));
  2359. CHECK_FALSE(code_edit->is_line_code_region_end(2));
  2360. CHECK(code_edit->is_line_code_region_start(3));
  2361. CHECK(code_edit->is_line_code_region_end(5));
  2362. code_edit->set_code_region_tags("region", "endregion");
  2363. // Setting identical start and end region tags should fail.
  2364. CHECK(code_edit->get_code_region_start_tag() == "region");
  2365. CHECK(code_edit->get_code_region_end_tag() == "endregion");
  2366. ERR_PRINT_OFF;
  2367. code_edit->set_code_region_tags("same_tag", "same_tag");
  2368. ERR_PRINT_ON;
  2369. CHECK(code_edit->get_code_region_start_tag() == "region");
  2370. CHECK(code_edit->get_code_region_end_tag() == "endregion");
  2371. // Region creation with selection adds start / close region lines.
  2372. code_edit->set_text("line1\nline2\nline3");
  2373. code_edit->clear_comment_delimiters();
  2374. code_edit->add_comment_delimiter("#", "");
  2375. code_edit->select(1, 0, 1, 4);
  2376. code_edit->create_code_region();
  2377. CHECK(code_edit->is_line_code_region_start(1));
  2378. CHECK(code_edit->get_line(2).contains("line2"));
  2379. CHECK(code_edit->is_line_code_region_end(3));
  2380. // Region creation without any selection has no effect.
  2381. code_edit->set_text("line1\nline2\nline3");
  2382. code_edit->clear_comment_delimiters();
  2383. code_edit->add_comment_delimiter("#", "");
  2384. code_edit->create_code_region();
  2385. CHECK(code_edit->get_text() == "line1\nline2\nline3");
  2386. // Region creation with multiple selections.
  2387. code_edit->set_text("line1\nline2\nline3");
  2388. code_edit->clear_comment_delimiters();
  2389. code_edit->add_comment_delimiter("#", "");
  2390. code_edit->select(0, 0, 0, 4, 0);
  2391. code_edit->add_caret(2, 5);
  2392. code_edit->select(2, 0, 2, 5, 1);
  2393. code_edit->create_code_region();
  2394. CHECK(code_edit->get_text() == "#region New Code Region\nline1\n#endregion\nline2\n#region New Code Region\nline3\n#endregion");
  2395. // Two selections on the same line create only one region.
  2396. code_edit->set_text("test line1\ntest line2\ntest line3");
  2397. code_edit->clear_comment_delimiters();
  2398. code_edit->add_comment_delimiter("#", "");
  2399. code_edit->select(0, 0, 1, 2, 0);
  2400. code_edit->add_caret(1, 4);
  2401. code_edit->select(1, 4, 2, 5, 1);
  2402. code_edit->create_code_region();
  2403. CHECK(code_edit->get_text() == "#region New Code Region\ntest line1\ntest line2\ntest line3\n#endregion");
  2404. // Region tag with // comment delimiter.
  2405. code_edit->set_text("//region region_name\nline2\n//endregion");
  2406. code_edit->clear_comment_delimiters();
  2407. code_edit->add_comment_delimiter("//", "");
  2408. CHECK(code_edit->is_line_code_region_start(0));
  2409. CHECK(code_edit->is_line_code_region_end(2));
  2410. // Creating region with no valid one line comment delimiter has no effect.
  2411. code_edit->set_text("line1\nline2\nline3");
  2412. code_edit->clear_comment_delimiters();
  2413. code_edit->create_code_region();
  2414. CHECK(code_edit->get_text() == "line1\nline2\nline3");
  2415. code_edit->add_comment_delimiter("/*", "*/");
  2416. code_edit->create_code_region();
  2417. CHECK(code_edit->get_text() == "line1\nline2\nline3");
  2418. // Choose one line comment delimiter.
  2419. code_edit->set_text("//region region_name\nline2\n//endregion");
  2420. code_edit->clear_comment_delimiters();
  2421. code_edit->add_comment_delimiter("/*", "*/");
  2422. code_edit->add_comment_delimiter("//", "");
  2423. CHECK(code_edit->is_line_code_region_start(0));
  2424. CHECK(code_edit->is_line_code_region_end(2));
  2425. // Update code region delimiter when removing comment delimiter.
  2426. code_edit->set_text("#region region_name\nline2\n#endregion\n//region region_name\nline2\n//endregion");
  2427. code_edit->clear_comment_delimiters();
  2428. code_edit->add_comment_delimiter("//", "");
  2429. code_edit->add_comment_delimiter("#", ""); // A shorter delimiter has higher priority.
  2430. CHECK(code_edit->is_line_code_region_start(0));
  2431. CHECK(code_edit->is_line_code_region_end(2));
  2432. CHECK_FALSE(code_edit->is_line_code_region_start(3));
  2433. CHECK_FALSE(code_edit->is_line_code_region_end(5));
  2434. code_edit->remove_comment_delimiter("#");
  2435. CHECK_FALSE(code_edit->is_line_code_region_start(0));
  2436. CHECK_FALSE(code_edit->is_line_code_region_end(2));
  2437. CHECK(code_edit->is_line_code_region_start(3));
  2438. CHECK(code_edit->is_line_code_region_end(5));
  2439. // Update code region delimiter when clearing comment delimiters.
  2440. code_edit->set_text("//region region_name\nline2\n//endregion");
  2441. code_edit->clear_comment_delimiters();
  2442. code_edit->add_comment_delimiter("//", "");
  2443. CHECK(code_edit->is_line_code_region_start(0));
  2444. CHECK(code_edit->is_line_code_region_end(2));
  2445. code_edit->clear_comment_delimiters();
  2446. CHECK_FALSE(code_edit->is_line_code_region_start(0));
  2447. CHECK_FALSE(code_edit->is_line_code_region_end(2));
  2448. // Fold region.
  2449. code_edit->clear_comment_delimiters();
  2450. code_edit->add_comment_delimiter("#", "");
  2451. code_edit->set_text("#region region_name\nline2\nline3\n#endregion\nvisible line");
  2452. CHECK(code_edit->can_fold_line(0));
  2453. for (int i = 1; i < 5; i++) {
  2454. CHECK_FALSE(code_edit->can_fold_line(i));
  2455. }
  2456. for (int i = 0; i < 5; i++) {
  2457. CHECK_FALSE(code_edit->is_line_folded(i));
  2458. }
  2459. code_edit->fold_line(0);
  2460. CHECK(code_edit->is_line_folded(0));
  2461. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2462. // Region with no end can't be folded.
  2463. ERR_PRINT_OFF;
  2464. code_edit->clear_comment_delimiters();
  2465. code_edit->add_comment_delimiter("#", "");
  2466. code_edit->set_text("#region region_name\nline2\nline3\n#bad_end_tag\nvisible line");
  2467. CHECK_FALSE(code_edit->can_fold_line(0));
  2468. ERR_PRINT_ON;
  2469. // Bad nested region can't be folded.
  2470. ERR_PRINT_OFF;
  2471. code_edit->clear_comment_delimiters();
  2472. code_edit->add_comment_delimiter("#", "");
  2473. code_edit->set_text("#region without end\n#region region2\nline3\n#endregion\n#no_end");
  2474. CHECK_FALSE(code_edit->can_fold_line(0));
  2475. CHECK(code_edit->can_fold_line(1));
  2476. ERR_PRINT_ON;
  2477. // Nested region folding.
  2478. ERR_PRINT_OFF;
  2479. code_edit->clear_comment_delimiters();
  2480. code_edit->add_comment_delimiter("#", "");
  2481. code_edit->set_text("#region region1\n#region region2\nline3\n#endregion\n#endregion");
  2482. CHECK(code_edit->can_fold_line(0));
  2483. CHECK(code_edit->can_fold_line(1));
  2484. code_edit->fold_line(1);
  2485. CHECK(code_edit->get_next_visible_line_offset_from(2, 1) == 3);
  2486. code_edit->fold_line(0);
  2487. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2488. ERR_PRINT_ON;
  2489. // Unfolding a line inside a region unfold whole region.
  2490. code_edit->clear_comment_delimiters();
  2491. code_edit->add_comment_delimiter("#", "");
  2492. code_edit->set_text("#region region\ninside\nline3\n#endregion\nvisible");
  2493. code_edit->fold_line(0);
  2494. CHECK(code_edit->is_line_folded(0));
  2495. CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4);
  2496. code_edit->unfold_line(1);
  2497. CHECK_FALSE(code_edit->is_line_folded(0));
  2498. }
  2499. memdelete(code_edit);
  2500. }
  2501. TEST_CASE("[SceneTree][CodeEdit] completion") {
  2502. CodeEdit *code_edit = memnew(CodeEdit);
  2503. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  2504. code_edit->grab_focus();
  2505. SUBCASE("[CodeEdit] auto brace completion") {
  2506. code_edit->set_auto_brace_completion_enabled(true);
  2507. CHECK(code_edit->is_auto_brace_completion_enabled());
  2508. code_edit->set_highlight_matching_braces_enabled(true);
  2509. CHECK(code_edit->is_highlight_matching_braces_enabled());
  2510. /* Try setters, any length. */
  2511. Dictionary auto_brace_completion_pairs;
  2512. auto_brace_completion_pairs["["] = "]";
  2513. auto_brace_completion_pairs["'"] = "'";
  2514. auto_brace_completion_pairs[";"] = "'";
  2515. auto_brace_completion_pairs["'''"] = "'''";
  2516. code_edit->set_auto_brace_completion_pairs(auto_brace_completion_pairs);
  2517. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2518. CHECK(code_edit->get_auto_brace_completion_pairs()["["] == "]");
  2519. CHECK(code_edit->get_auto_brace_completion_pairs()["'"] == "'");
  2520. CHECK(code_edit->get_auto_brace_completion_pairs()[";"] == "'");
  2521. CHECK(code_edit->get_auto_brace_completion_pairs()["'''"] == "'''");
  2522. ERR_PRINT_OFF;
  2523. /* No duplicate start keys. */
  2524. code_edit->add_auto_brace_completion_pair("[", "]");
  2525. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2526. /* No empty keys. */
  2527. code_edit->add_auto_brace_completion_pair("[", "");
  2528. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2529. code_edit->add_auto_brace_completion_pair("", "]");
  2530. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2531. code_edit->add_auto_brace_completion_pair("", "");
  2532. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2533. /* Must be a symbol. */
  2534. code_edit->add_auto_brace_completion_pair("a", "]");
  2535. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2536. code_edit->add_auto_brace_completion_pair("[", "a");
  2537. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2538. code_edit->add_auto_brace_completion_pair("a", "a");
  2539. CHECK(code_edit->get_auto_brace_completion_pairs().size() == 4);
  2540. ERR_PRINT_ON;
  2541. /* Check metadata. */
  2542. CHECK(code_edit->has_auto_brace_completion_open_key("["));
  2543. CHECK(code_edit->has_auto_brace_completion_open_key("'"));
  2544. CHECK(code_edit->has_auto_brace_completion_open_key(";"));
  2545. CHECK(code_edit->has_auto_brace_completion_open_key("'''"));
  2546. CHECK_FALSE(code_edit->has_auto_brace_completion_open_key("("));
  2547. CHECK(code_edit->has_auto_brace_completion_close_key("]"));
  2548. CHECK(code_edit->has_auto_brace_completion_close_key("'"));
  2549. CHECK(code_edit->has_auto_brace_completion_close_key("'''"));
  2550. CHECK_FALSE(code_edit->has_auto_brace_completion_close_key(")"));
  2551. CHECK(code_edit->get_auto_brace_completion_close_key("[") == "]");
  2552. CHECK(code_edit->get_auto_brace_completion_close_key("'") == "'");
  2553. CHECK(code_edit->get_auto_brace_completion_close_key(";") == "'");
  2554. CHECK(code_edit->get_auto_brace_completion_close_key("'''") == "'''");
  2555. CHECK(code_edit->get_auto_brace_completion_close_key("(").is_empty());
  2556. /* Check typing inserts closing pair. */
  2557. code_edit->clear();
  2558. SEND_GUI_KEY_EVENT(Key::BRACKETLEFT);
  2559. CHECK(code_edit->get_line(0) == "[]");
  2560. /* Should first match and insert smaller key. */
  2561. code_edit->clear();
  2562. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2563. CHECK(code_edit->get_line(0) == "''");
  2564. CHECK(code_edit->get_caret_column() == 1);
  2565. /* Move out from center, Should match and insert larger key. */
  2566. SEND_GUI_ACTION("ui_text_caret_right");
  2567. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2568. CHECK(code_edit->get_line(0) == "''''''");
  2569. CHECK(code_edit->get_caret_column() == 3);
  2570. /* Backspace should remove all. */
  2571. SEND_GUI_ACTION("ui_text_backspace");
  2572. CHECK(code_edit->get_line(0).is_empty());
  2573. /* If in between and typing close key should "skip". */
  2574. SEND_GUI_KEY_EVENT(Key::BRACKETLEFT);
  2575. CHECK(code_edit->get_line(0) == "[]");
  2576. CHECK(code_edit->get_caret_column() == 1);
  2577. SEND_GUI_KEY_EVENT(Key::BRACKETRIGHT);
  2578. CHECK(code_edit->get_line(0) == "[]");
  2579. CHECK(code_edit->get_caret_column() == 2);
  2580. /* If current is char and inserting a string, do not autocomplete. */
  2581. code_edit->clear();
  2582. SEND_GUI_KEY_EVENT(Key::A);
  2583. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2584. CHECK(code_edit->get_line(0) == "A'");
  2585. /* If in comment, do not complete. */
  2586. code_edit->add_comment_delimiter("#", "");
  2587. code_edit->clear();
  2588. SEND_GUI_KEY_EVENT(Key::NUMBERSIGN);
  2589. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2590. CHECK(code_edit->get_line(0) == "#'");
  2591. /* If in string, and inserting string do not complete. */
  2592. code_edit->clear();
  2593. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2594. SEND_GUI_KEY_EVENT(Key::QUOTEDBL);
  2595. CHECK(code_edit->get_line(0) == "'\"'");
  2596. /* Wrap single line selection with brackets */
  2597. code_edit->clear();
  2598. code_edit->insert_text_at_caret("abc");
  2599. code_edit->select_all();
  2600. SEND_GUI_KEY_EVENT(Key::BRACKETLEFT);
  2601. CHECK(code_edit->get_line(0) == "[abc]");
  2602. /* Caret should be after the last character of the single line selection */
  2603. CHECK(code_edit->get_caret_column() == 4);
  2604. /* Wrap multi line selection with brackets */
  2605. code_edit->clear();
  2606. code_edit->insert_text_at_caret("abc\nabc");
  2607. code_edit->select_all();
  2608. SEND_GUI_KEY_EVENT(Key::BRACKETLEFT);
  2609. CHECK(code_edit->get_text() == "[abc\nabc]");
  2610. /* Caret should be after the last character of the multi line selection */
  2611. CHECK(code_edit->get_caret_line() == 1);
  2612. CHECK(code_edit->get_caret_column() == 3);
  2613. /* If inserted character is not a auto brace completion open key, replace selected text with the inserted character */
  2614. code_edit->clear();
  2615. code_edit->insert_text_at_caret("abc");
  2616. code_edit->select_all();
  2617. SEND_GUI_KEY_EVENT(Key::KEY_1);
  2618. CHECK(code_edit->get_text() == "1");
  2619. /* If potential multichar and single brace completion is matched, it should wrap the single. */
  2620. code_edit->clear();
  2621. code_edit->insert_text_at_caret("\'\'abc");
  2622. code_edit->select(0, 2, 0, 5);
  2623. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2624. CHECK(code_edit->get_text() == "\'\'\'abc\'");
  2625. /* If only the potential multichar brace completion is matched, it does not wrap or complete. */
  2626. auto_brace_completion_pairs.erase("\'");
  2627. code_edit->set_auto_brace_completion_pairs(auto_brace_completion_pairs);
  2628. CHECK_FALSE(code_edit->has_auto_brace_completion_open_key("\'"));
  2629. code_edit->clear();
  2630. code_edit->insert_text_at_caret("\'\'abc");
  2631. code_edit->select(0, 2, 0, 5);
  2632. SEND_GUI_KEY_EVENT(Key::APOSTROPHE);
  2633. CHECK(code_edit->get_text() == "\'\'\'");
  2634. }
  2635. SUBCASE("[CodeEdit] autocomplete with brace completion") {
  2636. code_edit->set_auto_brace_completion_enabled(true);
  2637. CHECK(code_edit->is_auto_brace_completion_enabled());
  2638. code_edit->insert_text_at_caret("(te)");
  2639. code_edit->set_caret_column(3);
  2640. // Full completion.
  2641. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test()", "test()");
  2642. code_edit->update_code_completion_options();
  2643. code_edit->confirm_code_completion();
  2644. CHECK(code_edit->get_line(0) == "(test())");
  2645. CHECK(code_edit->get_caret_column() == 7);
  2646. code_edit->undo();
  2647. // With "arg".
  2648. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test(", "test(");
  2649. code_edit->update_code_completion_options();
  2650. code_edit->confirm_code_completion();
  2651. CHECK(code_edit->get_line(0) == "(test())");
  2652. CHECK(code_edit->get_caret_column() == 6);
  2653. code_edit->undo();
  2654. // brace completion disabled
  2655. code_edit->set_auto_brace_completion_enabled(false);
  2656. // Full completion.
  2657. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test()", "test()");
  2658. code_edit->update_code_completion_options();
  2659. code_edit->confirm_code_completion();
  2660. CHECK(code_edit->get_line(0) == "(test())");
  2661. CHECK(code_edit->get_caret_column() == 7);
  2662. code_edit->undo();
  2663. // With "arg".
  2664. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test(", "test(");
  2665. code_edit->update_code_completion_options();
  2666. code_edit->confirm_code_completion();
  2667. CHECK(code_edit->get_line(0) == "(test()");
  2668. CHECK(code_edit->get_caret_column() == 6);
  2669. // String
  2670. code_edit->set_auto_brace_completion_enabled(true);
  2671. code_edit->clear();
  2672. code_edit->insert_text_at_caret("\"\"");
  2673. code_edit->set_caret_column(1);
  2674. // Full completion.
  2675. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test\"", "\"test\"");
  2676. code_edit->update_code_completion_options();
  2677. code_edit->confirm_code_completion();
  2678. CHECK(code_edit->get_line(0) == "\"test\"");
  2679. CHECK(code_edit->get_caret_column() == 6);
  2680. code_edit->undo();
  2681. // With "arg".
  2682. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test", "\"test");
  2683. code_edit->update_code_completion_options();
  2684. code_edit->confirm_code_completion();
  2685. CHECK(code_edit->get_line(0) == "\"\"test\"");
  2686. CHECK(code_edit->get_caret_column() == 7);
  2687. code_edit->undo();
  2688. // brace completion disabled
  2689. code_edit->set_auto_brace_completion_enabled(false);
  2690. // Full completion.
  2691. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test\"", "\"test\"");
  2692. code_edit->update_code_completion_options();
  2693. code_edit->confirm_code_completion();
  2694. CHECK(code_edit->get_line(0) == "\"test\"");
  2695. CHECK(code_edit->get_caret_column() == 6);
  2696. code_edit->undo();
  2697. // With "arg".
  2698. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test", "\"test");
  2699. code_edit->update_code_completion_options();
  2700. code_edit->confirm_code_completion();
  2701. CHECK(code_edit->get_line(0) == "\"\"test\"");
  2702. CHECK(code_edit->get_caret_column() == 7);
  2703. code_edit->undo();
  2704. }
  2705. SUBCASE("[CodeEdit] autocomplete") {
  2706. code_edit->set_code_completion_enabled(true);
  2707. CHECK(code_edit->is_code_completion_enabled());
  2708. /* Set prefixes, single char only, disallow empty. */
  2709. TypedArray<String> completion_prefixes;
  2710. completion_prefixes.push_back("");
  2711. completion_prefixes.push_back(".");
  2712. completion_prefixes.push_back(".");
  2713. completion_prefixes.push_back(",,");
  2714. ERR_PRINT_OFF;
  2715. code_edit->set_code_completion_prefixes(completion_prefixes);
  2716. ERR_PRINT_ON;
  2717. completion_prefixes = code_edit->get_code_completion_prefixes();
  2718. CHECK(completion_prefixes.size() == 2);
  2719. CHECK(completion_prefixes.has("."));
  2720. CHECK(completion_prefixes.has(","));
  2721. code_edit->set_text("test\ntest");
  2722. CHECK(code_edit->get_text_for_code_completion() == String::chr(0xFFFF) + "test\ntest");
  2723. }
  2724. SUBCASE("[CodeEdit] autocomplete request") {
  2725. SIGNAL_WATCH(code_edit, "code_completion_requested");
  2726. code_edit->set_code_completion_enabled(true);
  2727. Array signal_args;
  2728. signal_args.push_back(Array());
  2729. /* Force request. */
  2730. code_edit->request_code_completion();
  2731. SIGNAL_CHECK_FALSE("code_completion_requested");
  2732. code_edit->request_code_completion(true);
  2733. SIGNAL_CHECK("code_completion_requested", signal_args);
  2734. /* Manual request should force. */
  2735. SEND_GUI_ACTION("ui_text_completion_query");
  2736. SIGNAL_CHECK("code_completion_requested", signal_args);
  2737. /* Insert prefix. */
  2738. TypedArray<String> completion_prefixes;
  2739. completion_prefixes.push_back(".");
  2740. code_edit->set_code_completion_prefixes(completion_prefixes);
  2741. code_edit->insert_text_at_caret(".");
  2742. code_edit->request_code_completion();
  2743. SIGNAL_CHECK("code_completion_requested", signal_args);
  2744. /* Should work with space too. */
  2745. code_edit->insert_text_at_caret(" ");
  2746. code_edit->request_code_completion();
  2747. SIGNAL_CHECK("code_completion_requested", signal_args);
  2748. /* Should work when complete ends with prefix. */
  2749. code_edit->clear();
  2750. code_edit->insert_text_at_caret("t");
  2751. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "test.", "test.");
  2752. code_edit->update_code_completion_options();
  2753. code_edit->confirm_code_completion();
  2754. CHECK(code_edit->get_line(0) == "test.");
  2755. SIGNAL_CHECK("code_completion_requested", signal_args);
  2756. SIGNAL_UNWATCH(code_edit, "code_completion_requested");
  2757. }
  2758. SUBCASE("[CodeEdit] autocomplete completion") {
  2759. if (TS->has_feature(TextServer::FEATURE_FONT_DYNAMIC) && TS->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
  2760. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2761. code_edit->set_code_completion_enabled(true);
  2762. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2763. code_edit->update_code_completion_options();
  2764. code_edit->set_code_completion_selected_index(1);
  2765. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2766. CHECK(code_edit->get_code_completion_option(0).size() == 0);
  2767. CHECK(code_edit->get_code_completion_options().size() == 0);
  2768. /* Adding does not update the list. */
  2769. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_0.", "item_0");
  2770. code_edit->set_code_completion_selected_index(1);
  2771. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2772. CHECK(code_edit->get_code_completion_option(0).size() == 0);
  2773. CHECK(code_edit->get_code_completion_options().size() == 0);
  2774. /* After update, pending add should not be counted, */
  2775. /* also does not work on col 0 */
  2776. int before_text_caret_column = code_edit->get_caret_column();
  2777. code_edit->insert_text_at_caret("i");
  2778. code_edit->update_code_completion_options();
  2779. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0", Color(1, 0, 0), Ref<Resource>(), Color(1, 0, 0));
  2780. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_1.", "item_1");
  2781. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_2.", "item_2");
  2782. ERR_PRINT_OFF;
  2783. code_edit->set_code_completion_selected_index(1);
  2784. ERR_PRINT_ON;
  2785. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2786. CHECK(code_edit->get_code_completion_option(0).size() == 7);
  2787. CHECK(code_edit->get_code_completion_options().size() == 1);
  2788. /* Check cancel closes completion. */
  2789. SEND_GUI_ACTION("ui_cancel");
  2790. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2791. code_edit->update_code_completion_options();
  2792. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2793. code_edit->set_code_completion_selected_index(1);
  2794. CHECK(code_edit->get_code_completion_selected_index() == 1);
  2795. CHECK(code_edit->get_code_completion_option(0).size() == 7);
  2796. CHECK(code_edit->get_code_completion_options().size() == 3);
  2797. /* Check data. */
  2798. Dictionary option = code_edit->get_code_completion_option(0);
  2799. CHECK((int)option["kind"] == (int)CodeEdit::CodeCompletionKind::KIND_CLASS);
  2800. CHECK(option["display_text"] == "item_0.");
  2801. CHECK(option["insert_text"] == "item_0");
  2802. CHECK(option["font_color"] == Color(1, 0, 0));
  2803. CHECK(option["icon"] == Ref<Resource>());
  2804. CHECK(option["default_value"] == Color(1, 0, 0));
  2805. /* Set size for mouse input. */
  2806. code_edit->set_size(Size2(100, 100));
  2807. /* Test home and end keys close the completion and move the caret */
  2808. /* => ui_text_caret_line_start */
  2809. code_edit->set_caret_column(before_text_caret_column + 1);
  2810. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0", Color(1, 0, 0), Ref<Resource>(), Color(1, 0, 0));
  2811. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_1.", "item_1");
  2812. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_2.", "item_2");
  2813. code_edit->update_code_completion_options();
  2814. SEND_GUI_ACTION("ui_text_caret_line_start");
  2815. code_edit->update_code_completion_options();
  2816. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2817. CHECK(code_edit->get_caret_column() == 0);
  2818. /* => ui_text_caret_line_end */
  2819. code_edit->set_caret_column(before_text_caret_column + 1);
  2820. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0", Color(1, 0, 0), Ref<Resource>(), Color(1, 0, 0));
  2821. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_1.", "item_1");
  2822. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_2.", "item_2");
  2823. code_edit->update_code_completion_options();
  2824. SEND_GUI_ACTION("ui_text_caret_line_end");
  2825. code_edit->update_code_completion_options();
  2826. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2827. CHECK(code_edit->get_caret_column() == before_text_caret_column + 1);
  2828. /* Check input. */
  2829. code_edit->set_caret_column(before_text_caret_column + 1);
  2830. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0", Color(1, 0, 0), Ref<Resource>(), Color(1, 0, 0));
  2831. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_1.", "item_1");
  2832. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "item_2.", "item_2");
  2833. code_edit->update_code_completion_options();
  2834. SEND_GUI_ACTION("ui_page_down");
  2835. CHECK(code_edit->get_code_completion_selected_index() == 2);
  2836. SEND_GUI_ACTION("ui_page_up");
  2837. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2838. SEND_GUI_ACTION("ui_up");
  2839. CHECK(code_edit->get_code_completion_selected_index() == 2);
  2840. SEND_GUI_ACTION("ui_down");
  2841. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2842. SEND_GUI_KEY_EVENT(Key::T);
  2843. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2844. SEND_GUI_ACTION("ui_left");
  2845. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2846. SEND_GUI_ACTION("ui_right");
  2847. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2848. SEND_GUI_ACTION("ui_text_backspace");
  2849. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2850. Point2 caret_pos = code_edit->get_caret_draw_pos();
  2851. caret_pos.y += code_edit->get_line_height();
  2852. SEND_GUI_MOUSE_BUTTON_EVENT(caret_pos, MouseButton::WHEEL_DOWN, 0, Key::NONE);
  2853. CHECK(code_edit->get_code_completion_selected_index() == 1);
  2854. SEND_GUI_MOUSE_BUTTON_EVENT(caret_pos, MouseButton::WHEEL_UP, 0, Key::NONE);
  2855. CHECK(code_edit->get_code_completion_selected_index() == 0);
  2856. /* Single click selects. */
  2857. caret_pos.y += code_edit->get_line_height() * 2;
  2858. SEND_GUI_MOUSE_BUTTON_EVENT(caret_pos, MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
  2859. CHECK(code_edit->get_code_completion_selected_index() == 2);
  2860. /* Double click inserts. */
  2861. SEND_GUI_DOUBLE_CLICK(caret_pos, Key::NONE);
  2862. CHECK(code_edit->get_code_completion_selected_index() == -1);
  2863. CHECK(code_edit->get_line(0) == "item_2");
  2864. code_edit->set_auto_brace_completion_enabled(false);
  2865. /* Does nothing in readonly. */
  2866. code_edit->undo();
  2867. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2868. code_edit->update_code_completion_options();
  2869. code_edit->set_editable(false);
  2870. code_edit->confirm_code_completion();
  2871. code_edit->set_editable(true);
  2872. CHECK(code_edit->get_line(0) == "i");
  2873. /* Replace */
  2874. code_edit->clear();
  2875. code_edit->insert_text_at_caret("item_1 test");
  2876. code_edit->set_caret_column(2);
  2877. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2878. code_edit->update_code_completion_options();
  2879. SEND_GUI_ACTION("ui_text_completion_replace");
  2880. CHECK(code_edit->get_line(0) == "item_0 test");
  2881. /* Replace string. */
  2882. code_edit->clear();
  2883. code_edit->insert_text_at_caret("\"item_1 test\"");
  2884. code_edit->set_caret_column(2);
  2885. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2886. code_edit->update_code_completion_options();
  2887. SEND_GUI_ACTION("ui_text_completion_replace");
  2888. CHECK(code_edit->get_line(0) == "\"item_0\"");
  2889. /* Normal replace if no end is given. */
  2890. code_edit->clear();
  2891. code_edit->insert_text_at_caret("\"item_1 test");
  2892. code_edit->set_caret_column(2);
  2893. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2894. code_edit->update_code_completion_options();
  2895. SEND_GUI_ACTION("ui_text_completion_replace");
  2896. CHECK(code_edit->get_line(0) == "\"item_0\" test");
  2897. /* Insert at completion. */
  2898. code_edit->clear();
  2899. code_edit->insert_text_at_caret("item_1 test");
  2900. code_edit->set_caret_column(2);
  2901. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2902. code_edit->update_code_completion_options();
  2903. SEND_GUI_ACTION("ui_text_completion_accept");
  2904. CHECK(code_edit->get_line(0) == "item_01 test");
  2905. /* Insert at completion with string should have same output. */
  2906. code_edit->clear();
  2907. code_edit->insert_text_at_caret("\"item_1 test\"");
  2908. code_edit->set_caret_column(2);
  2909. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0.", "item_0");
  2910. code_edit->update_code_completion_options();
  2911. SEND_GUI_ACTION("ui_text_completion_accept");
  2912. CHECK(code_edit->get_line(0) == "\"item_0\"1 test\"");
  2913. /* Merge symbol at end on insert text. */
  2914. /* End on completion entry. */
  2915. code_edit->clear();
  2916. code_edit->insert_text_at_caret("item_1 test");
  2917. code_edit->set_caret_column(2);
  2918. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2919. code_edit->update_code_completion_options();
  2920. SEND_GUI_ACTION("ui_text_completion_replace");
  2921. CHECK(code_edit->get_line(0) == "item_0( test");
  2922. CHECK(code_edit->get_caret_column() == 7);
  2923. /* End of text*/
  2924. code_edit->clear();
  2925. code_edit->insert_text_at_caret("item_1( test");
  2926. code_edit->set_caret_column(2);
  2927. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  2928. code_edit->update_code_completion_options();
  2929. SEND_GUI_ACTION("ui_text_completion_replace");
  2930. CHECK(code_edit->get_line(0) == "item_0( test");
  2931. CHECK(code_edit->get_caret_column() == 6);
  2932. /* End of both. */
  2933. code_edit->clear();
  2934. code_edit->insert_text_at_caret("item_1( test");
  2935. code_edit->set_caret_column(2);
  2936. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2937. code_edit->update_code_completion_options();
  2938. SEND_GUI_ACTION("ui_text_completion_replace");
  2939. CHECK(code_edit->get_line(0) == "item_0( test");
  2940. CHECK(code_edit->get_caret_column() == 7);
  2941. /* Full set. */
  2942. /* End on completion entry. */
  2943. code_edit->clear();
  2944. code_edit->insert_text_at_caret("item_1 test");
  2945. code_edit->set_caret_column(2);
  2946. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  2947. code_edit->update_code_completion_options();
  2948. SEND_GUI_ACTION("ui_text_completion_replace");
  2949. CHECK(code_edit->get_line(0) == "item_0() test");
  2950. CHECK(code_edit->get_caret_column() == 8);
  2951. /* End of text*/
  2952. code_edit->clear();
  2953. code_edit->insert_text_at_caret("item_1() test");
  2954. code_edit->set_caret_column(2);
  2955. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  2956. code_edit->update_code_completion_options();
  2957. SEND_GUI_ACTION("ui_text_completion_replace");
  2958. CHECK(code_edit->get_line(0) == "item_0() test");
  2959. CHECK(code_edit->get_caret_column() == 6);
  2960. /* End of both. */
  2961. code_edit->clear();
  2962. code_edit->insert_text_at_caret("item_1() test");
  2963. code_edit->set_caret_column(2);
  2964. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  2965. code_edit->update_code_completion_options();
  2966. SEND_GUI_ACTION("ui_text_completion_replace");
  2967. CHECK(code_edit->get_line(0) == "item_0() test");
  2968. CHECK(code_edit->get_caret_column() == 8);
  2969. /* Autobrace completion. */
  2970. code_edit->set_auto_brace_completion_enabled(true);
  2971. /* End on completion entry. */
  2972. code_edit->clear();
  2973. code_edit->insert_text_at_caret("item_1 test");
  2974. code_edit->set_caret_column(2);
  2975. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2976. code_edit->update_code_completion_options();
  2977. SEND_GUI_ACTION("ui_text_completion_replace");
  2978. CHECK(code_edit->get_line(0) == "item_0() test");
  2979. CHECK(code_edit->get_caret_column() == 7);
  2980. /* End of text*/
  2981. code_edit->clear();
  2982. code_edit->insert_text_at_caret("item_1( test");
  2983. code_edit->set_caret_column(2);
  2984. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  2985. code_edit->update_code_completion_options();
  2986. SEND_GUI_ACTION("ui_text_completion_replace");
  2987. CHECK(code_edit->get_line(0) == "item_0( test");
  2988. CHECK(code_edit->get_caret_column() == 6);
  2989. /* End of both. */
  2990. code_edit->clear();
  2991. code_edit->insert_text_at_caret("item_1( test");
  2992. code_edit->set_caret_column(2);
  2993. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0(", "item_0(");
  2994. code_edit->update_code_completion_options();
  2995. SEND_GUI_ACTION("ui_text_completion_replace");
  2996. CHECK(code_edit->get_line(0) == "item_0( test");
  2997. CHECK(code_edit->get_caret_column() == 7);
  2998. /* Full set. */
  2999. /* End on completion entry. */
  3000. code_edit->clear();
  3001. code_edit->insert_text_at_caret("item_1 test");
  3002. code_edit->set_caret_column(2);
  3003. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  3004. code_edit->update_code_completion_options();
  3005. SEND_GUI_ACTION("ui_text_completion_replace");
  3006. CHECK(code_edit->get_line(0) == "item_0() test");
  3007. CHECK(code_edit->get_caret_column() == 8);
  3008. /* End of text*/
  3009. code_edit->clear();
  3010. code_edit->insert_text_at_caret("item_1() test");
  3011. code_edit->set_caret_column(2);
  3012. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0", "item_0");
  3013. code_edit->update_code_completion_options();
  3014. SEND_GUI_ACTION("ui_text_completion_replace");
  3015. CHECK(code_edit->get_line(0) == "item_0() test");
  3016. CHECK(code_edit->get_caret_column() == 6);
  3017. /* End of both. */
  3018. code_edit->clear();
  3019. code_edit->insert_text_at_caret("item_1() test");
  3020. code_edit->set_caret_column(2);
  3021. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_CLASS, "item_0()", "item_0()");
  3022. code_edit->update_code_completion_options();
  3023. SEND_GUI_ACTION("ui_text_completion_replace");
  3024. CHECK(code_edit->get_line(0) == "item_0() test");
  3025. CHECK(code_edit->get_caret_column() == 8);
  3026. }
  3027. }
  3028. SUBCASE("[CodeEdit] autocomplete suggestion order") {
  3029. /* Prefer less fragmented suggestion. */
  3030. code_edit->clear();
  3031. code_edit->insert_text_at_caret("te");
  3032. code_edit->set_caret_column(2);
  3033. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "test", "test");
  3034. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "tset", "tset");
  3035. code_edit->update_code_completion_options();
  3036. code_edit->confirm_code_completion();
  3037. CHECK(code_edit->get_line(0) == "test");
  3038. /* Prefer suggestion starting with the string to complete (matching start). */
  3039. code_edit->clear();
  3040. code_edit->insert_text_at_caret("te");
  3041. code_edit->set_caret_column(2);
  3042. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "test", "test");
  3043. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "stest", "stest");
  3044. code_edit->update_code_completion_options();
  3045. code_edit->confirm_code_completion();
  3046. CHECK(code_edit->get_line(0) == "test");
  3047. /* Prefer less fragment over matching start. */
  3048. code_edit->clear();
  3049. code_edit->insert_text_at_caret("te");
  3050. code_edit->set_caret_column(2);
  3051. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "tset", "tset");
  3052. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "stest", "stest");
  3053. code_edit->update_code_completion_options();
  3054. code_edit->confirm_code_completion();
  3055. CHECK(code_edit->get_line(0) == "stest");
  3056. /* Prefer good capitalization. */
  3057. code_edit->clear();
  3058. code_edit->insert_text_at_caret("te");
  3059. code_edit->set_caret_column(2);
  3060. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "test", "test");
  3061. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "Test", "Test");
  3062. code_edit->update_code_completion_options();
  3063. code_edit->confirm_code_completion();
  3064. CHECK(code_edit->get_line(0) == "test");
  3065. /* Prefer matching start over good capitalization. */
  3066. code_edit->clear();
  3067. code_edit->insert_text_at_caret("te");
  3068. code_edit->set_caret_column(2);
  3069. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "Test", "Test");
  3070. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "stest_bis", "test_bis");
  3071. code_edit->update_code_completion_options();
  3072. code_edit->confirm_code_completion();
  3073. CHECK(code_edit->get_line(0) == "Test");
  3074. /* Prefer closer location. */
  3075. code_edit->clear();
  3076. code_edit->insert_text_at_caret("te");
  3077. code_edit->set_caret_column(2);
  3078. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "test", "test");
  3079. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "test_bis", "test_bis", Color(1, 1, 1), Ref<Resource>(), Variant::NIL, CodeEdit::LOCATION_LOCAL);
  3080. code_edit->update_code_completion_options();
  3081. code_edit->confirm_code_completion();
  3082. CHECK(code_edit->get_line(0) == "test_bis");
  3083. /* Prefer good capitalization over location. */
  3084. code_edit->clear();
  3085. code_edit->insert_text_at_caret("te");
  3086. code_edit->set_caret_column(2);
  3087. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "test", "test");
  3088. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "Test", "Test", Color(1, 1, 1), Ref<Resource>(), Variant::NIL, CodeEdit::LOCATION_LOCAL);
  3089. code_edit->update_code_completion_options();
  3090. code_edit->confirm_code_completion();
  3091. CHECK(code_edit->get_line(0) == "test");
  3092. /* Prefer the start of the string to complete being closest to the start of the suggestion (closest to start). */
  3093. code_edit->clear();
  3094. code_edit->insert_text_at_caret("te");
  3095. code_edit->set_caret_column(2);
  3096. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "stest", "stest");
  3097. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "sstest", "sstest");
  3098. code_edit->update_code_completion_options();
  3099. code_edit->confirm_code_completion();
  3100. CHECK(code_edit->get_line(0) == "stest");
  3101. /* Prefer location over closest to start. */
  3102. code_edit->clear();
  3103. code_edit->insert_text_at_caret("te");
  3104. code_edit->set_caret_column(2);
  3105. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "stest", "stest");
  3106. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "sstest", "sstest", Color(1, 1, 1), Ref<Resource>(), Variant::NIL, CodeEdit::LOCATION_LOCAL);
  3107. code_edit->update_code_completion_options();
  3108. code_edit->confirm_code_completion();
  3109. CHECK(code_edit->get_line(0) == "sstest");
  3110. }
  3111. SUBCASE("[CodeEdit] autocomplete currently selected option") {
  3112. code_edit->set_code_completion_enabled(true);
  3113. REQUIRE(code_edit->is_code_completion_enabled());
  3114. // Initially select item 0.
  3115. code_edit->insert_text_at_caret("te");
  3116. code_edit->set_caret_column(2);
  3117. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te1", "te1");
  3118. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te3", "te3");
  3119. code_edit->update_code_completion_options();
  3120. CHECK_MESSAGE(code_edit->get_code_completion_selected_index() == 0, "Initially selected item should be 0.");
  3121. // After adding later options shouldn't update selection.
  3122. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te1", "te1");
  3123. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te3", "te3");
  3124. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te4", "te4"); // Added te4.
  3125. code_edit->update_code_completion_options();
  3126. CHECK_MESSAGE(code_edit->get_code_completion_selected_index() == 0, "Adding later options shouldn't update selection.");
  3127. code_edit->set_code_completion_selected_index(2);
  3128. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te1", "te1");
  3129. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te3", "te3");
  3130. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te4", "te4");
  3131. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te5", "te5"); // Added te5.
  3132. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te6", "te6"); // Added te6.
  3133. code_edit->update_code_completion_options();
  3134. CHECK_MESSAGE(code_edit->get_code_completion_selected_index() == 2, "Adding later options shouldn't update selection.");
  3135. // Removing elements after selected element shouldn't update selection.
  3136. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te1", "te1");
  3137. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te3", "te3");
  3138. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te4", "te4");
  3139. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te5", "te5"); // Removed te6.
  3140. code_edit->update_code_completion_options();
  3141. CHECK_MESSAGE(code_edit->get_code_completion_selected_index() == 2, "Removing elements after selected element shouldn't update selection.");
  3142. // Changing elements after selected element shouldn't update selection.
  3143. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te1", "te1");
  3144. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te3", "te3");
  3145. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te4", "te4");
  3146. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te6", "te6"); // Changed te5->te6.
  3147. code_edit->update_code_completion_options();
  3148. CHECK_MESSAGE(code_edit->get_code_completion_selected_index() == 2, "Changing elements after selected element shouldn't update selection.");
  3149. // Changing elements before selected element should reset selection.
  3150. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te2", "te2"); // Changed te1->te2.
  3151. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te3", "te3");
  3152. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te4", "te4");
  3153. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te6", "te6");
  3154. code_edit->update_code_completion_options();
  3155. CHECK_MESSAGE(code_edit->get_code_completion_selected_index() == 0, "Changing elements before selected element should reset selection.");
  3156. // Removing elements before selected element should reset selection.
  3157. code_edit->set_code_completion_selected_index(2);
  3158. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te3", "te3"); // Removed te2.
  3159. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te4", "te4");
  3160. code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_VARIABLE, "te6", "te6");
  3161. code_edit->update_code_completion_options();
  3162. CHECK_MESSAGE(code_edit->get_code_completion_selected_index() == 0, "Removing elements before selected element should reset selection.");
  3163. }
  3164. memdelete(code_edit);
  3165. }
  3166. TEST_CASE("[SceneTree][CodeEdit] symbol lookup") {
  3167. CodeEdit *code_edit = memnew(CodeEdit);
  3168. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  3169. code_edit->grab_focus();
  3170. code_edit->set_symbol_lookup_on_click_enabled(true);
  3171. CHECK(code_edit->is_symbol_lookup_on_click_enabled());
  3172. if (TS->has_feature(TextServer::FEATURE_FONT_DYNAMIC) && TS->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
  3173. /* Set size for mouse input. */
  3174. code_edit->set_size(Size2(100, 100));
  3175. code_edit->set_text("this is some text");
  3176. Point2 caret_pos = code_edit->get_caret_draw_pos();
  3177. caret_pos.x += 60;
  3178. SEND_GUI_MOUSE_BUTTON_EVENT(caret_pos, MouseButton::NONE, 0, Key::NONE);
  3179. CHECK(code_edit->get_text_for_symbol_lookup() == "this is s" + String::chr(0xFFFF) + "ome text");
  3180. SIGNAL_WATCH(code_edit, "symbol_validate");
  3181. #ifdef MACOS_ENABLED
  3182. SEND_GUI_KEY_EVENT(Key::META);
  3183. #else
  3184. SEND_GUI_KEY_EVENT(Key::CTRL);
  3185. #endif
  3186. Array signal_args;
  3187. Array arg;
  3188. arg.push_back("some");
  3189. signal_args.push_back(arg);
  3190. SIGNAL_CHECK("symbol_validate", signal_args);
  3191. SIGNAL_UNWATCH(code_edit, "symbol_validate");
  3192. }
  3193. memdelete(code_edit);
  3194. }
  3195. TEST_CASE("[SceneTree][CodeEdit] line length guidelines") {
  3196. CodeEdit *code_edit = memnew(CodeEdit);
  3197. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  3198. code_edit->grab_focus();
  3199. TypedArray<int> guide_lines;
  3200. code_edit->set_line_length_guidelines(guide_lines);
  3201. CHECK(code_edit->get_line_length_guidelines().size() == 0);
  3202. guide_lines.push_back(80);
  3203. guide_lines.push_back(120);
  3204. /* Order should be preserved. */
  3205. code_edit->set_line_length_guidelines(guide_lines);
  3206. CHECK((int)code_edit->get_line_length_guidelines()[0] == 80);
  3207. CHECK((int)code_edit->get_line_length_guidelines()[1] == 120);
  3208. memdelete(code_edit);
  3209. }
  3210. TEST_CASE("[SceneTree][CodeEdit] Backspace delete") {
  3211. CodeEdit *code_edit = memnew(CodeEdit);
  3212. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  3213. code_edit->grab_focus();
  3214. /* Backspace with selection on first line. */
  3215. code_edit->set_text("");
  3216. code_edit->insert_text_at_caret("test backspace");
  3217. code_edit->select(0, 0, 0, 5);
  3218. code_edit->backspace();
  3219. CHECK(code_edit->get_line(0) == "backspace");
  3220. /* Backspace with selection on first line and caret at the beginning of file. */
  3221. code_edit->set_text("");
  3222. code_edit->insert_text_at_caret("test backspace");
  3223. code_edit->select(0, 0, 0, 5);
  3224. code_edit->set_caret_column(0);
  3225. code_edit->backspace();
  3226. CHECK(code_edit->get_line(0) == "backspace");
  3227. /* Move caret up to the previous line on backspace if caret is at the first column. */
  3228. code_edit->set_text("");
  3229. code_edit->insert_text_at_caret("line 1\nline 2");
  3230. code_edit->set_caret_line(1);
  3231. code_edit->set_caret_column(0);
  3232. code_edit->backspace();
  3233. CHECK(code_edit->get_line(0) == "line 1line 2");
  3234. CHECK(code_edit->get_caret_line() == 0);
  3235. CHECK(code_edit->get_caret_column() == 6);
  3236. /* Backspace delete all text if all text is selected. */
  3237. code_edit->set_text("");
  3238. code_edit->insert_text_at_caret("line 1\nline 2\nline 3");
  3239. code_edit->select_all();
  3240. code_edit->backspace();
  3241. CHECK(code_edit->get_text().is_empty());
  3242. /* Backspace at the beginning without selection has no effect. */
  3243. code_edit->set_text("");
  3244. code_edit->insert_text_at_caret("line 1\nline 2\nline 3");
  3245. code_edit->set_caret_line(0);
  3246. code_edit->set_caret_column(0);
  3247. code_edit->backspace();
  3248. CHECK(code_edit->get_text() == "line 1\nline 2\nline 3");
  3249. memdelete(code_edit);
  3250. }
  3251. TEST_CASE("[SceneTree][CodeEdit] New Line") {
  3252. CodeEdit *code_edit = memnew(CodeEdit);
  3253. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  3254. code_edit->grab_focus();
  3255. /* Add a new line. */
  3256. code_edit->set_text("");
  3257. code_edit->insert_text_at_caret("test new line");
  3258. code_edit->set_caret_line(0);
  3259. code_edit->set_caret_column(13);
  3260. SEND_GUI_ACTION("ui_text_newline");
  3261. CHECK(code_edit->get_line(0) == "test new line");
  3262. CHECK(code_edit->get_line(1) == "");
  3263. /* Split line with new line. */
  3264. code_edit->set_text("");
  3265. code_edit->insert_text_at_caret("test new line");
  3266. code_edit->set_caret_line(0);
  3267. code_edit->set_caret_column(5);
  3268. SEND_GUI_ACTION("ui_text_newline");
  3269. CHECK(code_edit->get_line(0) == "test ");
  3270. CHECK(code_edit->get_line(1) == "new line");
  3271. /* Delete selection and split with new line. */
  3272. code_edit->set_text("");
  3273. code_edit->insert_text_at_caret("test new line");
  3274. code_edit->select(0, 0, 0, 5);
  3275. SEND_GUI_ACTION("ui_text_newline");
  3276. CHECK(code_edit->get_line(0) == "");
  3277. CHECK(code_edit->get_line(1) == "new line");
  3278. /* Blank new line below with selection should not split. */
  3279. code_edit->set_text("");
  3280. code_edit->insert_text_at_caret("test new line");
  3281. code_edit->select(0, 0, 0, 5);
  3282. SEND_GUI_ACTION("ui_text_newline_blank");
  3283. CHECK(code_edit->get_line(0) == "test new line");
  3284. CHECK(code_edit->get_line(1) == "");
  3285. /* Blank new line above with selection should not split. */
  3286. code_edit->set_text("");
  3287. code_edit->insert_text_at_caret("test new line");
  3288. code_edit->select(0, 0, 0, 5);
  3289. SEND_GUI_ACTION("ui_text_newline_above");
  3290. CHECK(code_edit->get_line(0) == "");
  3291. CHECK(code_edit->get_line(1) == "test new line");
  3292. memdelete(code_edit);
  3293. }
  3294. TEST_CASE("[SceneTree][CodeEdit] Duplicate Lines") {
  3295. CodeEdit *code_edit = memnew(CodeEdit);
  3296. SceneTree::get_singleton()->get_root()->add_child(code_edit);
  3297. code_edit->grab_focus();
  3298. code_edit->set_text(R"(extends Node
  3299. func _ready():
  3300. var a := len(OS.get_cmdline_args())
  3301. var b := get_child_count()
  3302. var c := a + b
  3303. for i in range(c):
  3304. print("This is the solution: ", sin(i))
  3305. var pos = get_index() - 1
  3306. print("Make sure this exits: %b" % pos)
  3307. )");
  3308. /* Duplicate a single line without selection. */
  3309. code_edit->set_caret_line(0);
  3310. code_edit->duplicate_lines();
  3311. CHECK(code_edit->get_line(0) == "extends Node");
  3312. CHECK(code_edit->get_line(1) == "extends Node");
  3313. CHECK(code_edit->get_line(2) == "");
  3314. /* Duplicate multiple lines with selection. */
  3315. code_edit->set_caret_line(6);
  3316. code_edit->set_caret_column(15);
  3317. code_edit->select(4, 8, 6, 15);
  3318. code_edit->duplicate_lines();
  3319. CHECK(code_edit->get_line(6) == "\tvar c := a + b");
  3320. CHECK(code_edit->get_line(7) == "\tvar a := len(OS.get_cmdline_args())");
  3321. CHECK(code_edit->get_line(8) == "\tvar b := get_child_count()");
  3322. CHECK(code_edit->get_line(9) == "\tvar c := a + b");
  3323. CHECK(code_edit->get_line(10) == "\tfor i in range(c):");
  3324. /* Duplicate single lines with multiple carets. */
  3325. code_edit->deselect();
  3326. code_edit->set_caret_line(10);
  3327. code_edit->set_caret_column(1);
  3328. code_edit->add_caret(11, 2);
  3329. code_edit->add_caret(12, 1);
  3330. code_edit->duplicate_lines();
  3331. CHECK(code_edit->get_line(9) == "\tvar c := a + b");
  3332. CHECK(code_edit->get_line(10) == "\tfor i in range(c):");
  3333. CHECK(code_edit->get_line(11) == "\tfor i in range(c):");
  3334. CHECK(code_edit->get_line(12) == "\t\tprint(\"This is the solution: \", sin(i))");
  3335. CHECK(code_edit->get_line(13) == "\t\tprint(\"This is the solution: \", sin(i))");
  3336. CHECK(code_edit->get_line(14) == "\tvar pos = get_index() - 1");
  3337. CHECK(code_edit->get_line(15) == "\tvar pos = get_index() - 1");
  3338. CHECK(code_edit->get_line(16) == "\tprint(\"Make sure this exits: %b\" % pos)");
  3339. /* Duplicate multiple lines with multiple carets. */
  3340. code_edit->select(0, 0, 1, 2, 0);
  3341. code_edit->select(3, 0, 4, 2, 1);
  3342. code_edit->select(16, 0, 17, 0, 2);
  3343. code_edit->set_caret_line(1, false, true, 0, 0);
  3344. code_edit->set_caret_column(2, false, 0);
  3345. code_edit->set_caret_line(4, false, true, 0, 1);
  3346. code_edit->set_caret_column(2, false, 1);
  3347. code_edit->set_caret_line(17, false, true, 0, 2);
  3348. code_edit->set_caret_column(0, false, 2);
  3349. code_edit->duplicate_lines();
  3350. CHECK(code_edit->get_line(1) == "extends Node");
  3351. CHECK(code_edit->get_line(2) == "extends Node");
  3352. CHECK(code_edit->get_line(3) == "extends Node");
  3353. CHECK(code_edit->get_line(4) == "");
  3354. CHECK(code_edit->get_line(6) == "\tvar a := len(OS.get_cmdline_args())");
  3355. CHECK(code_edit->get_line(7) == "func _ready():");
  3356. CHECK(code_edit->get_line(8) == "\tvar a := len(OS.get_cmdline_args())");
  3357. CHECK(code_edit->get_line(9) == "\tvar b := get_child_count()");
  3358. CHECK(code_edit->get_line(20) == "\tprint(\"Make sure this exits: %b\" % pos)");
  3359. CHECK(code_edit->get_line(21) == "");
  3360. CHECK(code_edit->get_line(22) == "\tprint(\"Make sure this exits: %b\" % pos)");
  3361. CHECK(code_edit->get_line(23) == "");
  3362. memdelete(code_edit);
  3363. }
  3364. } // namespace TestCodeEdit
  3365. #endif // TEST_CODE_EDIT_H