ASFormatter.cpp 216 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715
  1. // ASFormatter.cpp
  2. // Copyright (c) 2017 by Jim Pattee <jimp03@email.com>.
  3. // This code is licensed under the MIT License.
  4. // License.md describes the conditions under which this software may be distributed.
  5. //-----------------------------------------------------------------------------
  6. // headers
  7. //-----------------------------------------------------------------------------
  8. #include "astyle.h"
  9. #include <algorithm>
  10. #include <fstream>
  11. //-----------------------------------------------------------------------------
  12. // astyle namespace
  13. //-----------------------------------------------------------------------------
  14. namespace astyle {
  15. //
  16. //-----------------------------------------------------------------------------
  17. // ASFormatter class
  18. //-----------------------------------------------------------------------------
  19. /**
  20. * Constructor of ASFormatter
  21. */
  22. ASFormatter::ASFormatter()
  23. {
  24. sourceIterator = nullptr;
  25. enhancer = new ASEnhancer;
  26. preBraceHeaderStack = nullptr;
  27. braceTypeStack = nullptr;
  28. parenStack = nullptr;
  29. structStack = nullptr;
  30. questionMarkStack = nullptr;
  31. lineCommentNoIndent = false;
  32. formattingStyle = STYLE_NONE;
  33. braceFormatMode = NONE_MODE;
  34. pointerAlignment = PTR_ALIGN_NONE;
  35. referenceAlignment = REF_SAME_AS_PTR;
  36. objCColonPadMode = COLON_PAD_NO_CHANGE;
  37. lineEnd = LINEEND_DEFAULT;
  38. maxCodeLength = string::npos;
  39. shouldPadCommas = false;
  40. shouldPadOperators = false;
  41. shouldPadParensOutside = false;
  42. shouldPadFirstParen = false;
  43. shouldPadParensInside = false;
  44. shouldPadHeader = false;
  45. shouldStripCommentPrefix = false;
  46. shouldUnPadParens = false;
  47. attachClosingBraceMode = false;
  48. shouldBreakOneLineBlocks = true;
  49. shouldBreakOneLineHeaders = false;
  50. shouldBreakOneLineStatements = true;
  51. shouldConvertTabs = false;
  52. shouldIndentCol1Comments = false;
  53. shouldIndentPreprocBlock = false;
  54. shouldCloseTemplates = false;
  55. shouldAttachExternC = false;
  56. shouldAttachNamespace = false;
  57. shouldAttachClass = false;
  58. shouldAttachClosingWhile = false;
  59. shouldAttachInline = false;
  60. shouldBreakBlocks = false;
  61. shouldBreakClosingHeaderBlocks = false;
  62. shouldBreakClosingHeaderBraces = false;
  63. shouldDeleteEmptyLines = false;
  64. shouldBreakElseIfs = false;
  65. shouldBreakLineAfterLogical = false;
  66. shouldAddBraces = false;
  67. shouldAddOneLineBraces = false;
  68. shouldRemoveBraces = false;
  69. shouldPadMethodColon = false;
  70. shouldPadMethodPrefix = false;
  71. shouldUnPadMethodPrefix = false;
  72. shouldPadReturnType = false;
  73. shouldUnPadReturnType = false;
  74. shouldPadParamType = false;
  75. shouldUnPadParamType = false;
  76. // initialize ASFormatter member vectors
  77. formatterFileType = 9; // reset to an invalid type
  78. headers = new vector<const string*>;
  79. nonParenHeaders = new vector<const string*>;
  80. preDefinitionHeaders = new vector<const string*>;
  81. preCommandHeaders = new vector<const string*>;
  82. operators = new vector<const string*>;
  83. assignmentOperators = new vector<const string*>;
  84. castOperators = new vector<const string*>;
  85. // initialize ASEnhancer member vectors
  86. indentableMacros = new vector<const pair<const string, const string>* >;
  87. }
  88. /**
  89. * Destructor of ASFormatter
  90. */
  91. ASFormatter::~ASFormatter()
  92. {
  93. // delete ASFormatter stack vectors
  94. deleteContainer(preBraceHeaderStack);
  95. deleteContainer(braceTypeStack);
  96. deleteContainer(parenStack);
  97. deleteContainer(structStack);
  98. deleteContainer(questionMarkStack);
  99. // delete ASFormatter member vectors
  100. formatterFileType = 9; // reset to an invalid type
  101. delete headers;
  102. delete nonParenHeaders;
  103. delete preDefinitionHeaders;
  104. delete preCommandHeaders;
  105. delete operators;
  106. delete assignmentOperators;
  107. delete castOperators;
  108. // delete ASEnhancer member vectors
  109. delete indentableMacros;
  110. // must be done when the ASFormatter object is deleted (not ASBeautifier)
  111. // delete ASBeautifier member vectors
  112. ASBeautifier::deleteBeautifierVectors();
  113. delete enhancer;
  114. }
  115. /**
  116. * initialize the ASFormatter.
  117. *
  118. * init() should be called every time a ASFormatter object is to start
  119. * formatting a NEW source file.
  120. * init() receives a pointer to a ASSourceIterator object that will be
  121. * used to iterate through the source code.
  122. *
  123. * @param si a pointer to the ASSourceIterator or ASStreamIterator object.
  124. */
  125. void ASFormatter::init(ASSourceIterator* si)
  126. {
  127. buildLanguageVectors();
  128. fixOptionVariableConflicts();
  129. ASBeautifier::init(si);
  130. sourceIterator = si;
  131. enhancer->init(getFileType(),
  132. getIndentLength(),
  133. getTabLength(),
  134. getIndentString() == "\t",
  135. getForceTabIndentation(),
  136. getNamespaceIndent(),
  137. getCaseIndent(),
  138. shouldIndentPreprocBlock,
  139. getPreprocDefineIndent(),
  140. getEmptyLineFill(),
  141. indentableMacros);
  142. initContainer(preBraceHeaderStack, new vector<const string*>);
  143. initContainer(parenStack, new vector<int>);
  144. initContainer(structStack, new vector<bool>);
  145. initContainer(questionMarkStack, new vector<bool>);
  146. parenStack->emplace_back(0); // parenStack must contain this default entry
  147. initContainer(braceTypeStack, new vector<BraceType>);
  148. braceTypeStack->emplace_back(NULL_TYPE); // braceTypeStack must contain this default entry
  149. clearFormattedLineSplitPoints();
  150. currentHeader = nullptr;
  151. currentLine = "";
  152. readyFormattedLine = "";
  153. formattedLine = "";
  154. verbatimDelimiter = "";
  155. currentChar = ' ';
  156. previousChar = ' ';
  157. previousCommandChar = ' ';
  158. previousNonWSChar = ' ';
  159. quoteChar = '"';
  160. preprocBlockEnd = 0;
  161. charNum = 0;
  162. checksumIn = 0;
  163. checksumOut = 0;
  164. currentLineFirstBraceNum = string::npos;
  165. formattedLineCommentNum = 0;
  166. leadingSpaces = 0;
  167. previousReadyFormattedLineLength = string::npos;
  168. preprocBraceTypeStackSize = 0;
  169. spacePadNum = 0;
  170. nextLineSpacePadNum = 0;
  171. objCColonAlign = 0;
  172. templateDepth = 0;
  173. squareBracketCount = 0;
  174. runInIndentChars = 0;
  175. tabIncrementIn = 0;
  176. previousBraceType = NULL_TYPE;
  177. isVirgin = true;
  178. isInVirginLine = true;
  179. isInLineComment = false;
  180. isInComment = false;
  181. isInCommentStartLine = false;
  182. noTrimCommentContinuation = false;
  183. isInPreprocessor = false;
  184. isInPreprocessorBeautify = false;
  185. doesLineStartComment = false;
  186. lineEndsInCommentOnly = false;
  187. lineIsCommentOnly = false;
  188. lineIsLineCommentOnly = false;
  189. lineIsEmpty = false;
  190. isImmediatelyPostCommentOnly = false;
  191. isImmediatelyPostEmptyLine = false;
  192. isInClassInitializer = false;
  193. isInQuote = false;
  194. isInVerbatimQuote = false;
  195. haveLineContinuationChar = false;
  196. isInQuoteContinuation = false;
  197. isHeaderInMultiStatementLine = false;
  198. isSpecialChar = false;
  199. isNonParenHeader = false;
  200. foundNamespaceHeader = false;
  201. foundClassHeader = false;
  202. foundStructHeader = false;
  203. foundInterfaceHeader = false;
  204. foundPreDefinitionHeader = false;
  205. foundPreCommandHeader = false;
  206. foundPreCommandMacro = false;
  207. foundTrailingReturnType = false;
  208. foundCastOperator = false;
  209. foundQuestionMark = false;
  210. isInLineBreak = false;
  211. endOfAsmReached = false;
  212. endOfCodeReached = false;
  213. isFormattingModeOff = false;
  214. isInEnum = false;
  215. isInExecSQL = false;
  216. isInAsm = false;
  217. isInAsmOneLine = false;
  218. isInAsmBlock = false;
  219. isLineReady = false;
  220. elseHeaderFollowsComments = false;
  221. caseHeaderFollowsComments = false;
  222. isPreviousBraceBlockRelated = false;
  223. isInPotentialCalculation = false;
  224. needHeaderOpeningBrace = false;
  225. shouldBreakLineAtNextChar = false;
  226. shouldKeepLineUnbroken = false;
  227. shouldReparseCurrentChar = false;
  228. passedSemicolon = false;
  229. passedColon = false;
  230. isImmediatelyPostNonInStmt = false;
  231. isCharImmediatelyPostNonInStmt = false;
  232. isInTemplate = false;
  233. isImmediatelyPostComment = false;
  234. isImmediatelyPostLineComment = false;
  235. isImmediatelyPostEmptyBlock = false;
  236. isImmediatelyPostObjCMethodPrefix = false;
  237. isImmediatelyPostPreprocessor = false;
  238. isImmediatelyPostReturn = false;
  239. isImmediatelyPostThrow = false;
  240. isImmediatelyPostNewDelete = false;
  241. isImmediatelyPostOperator = false;
  242. isImmediatelyPostTemplate = false;
  243. isImmediatelyPostPointerOrReference = false;
  244. isCharImmediatelyPostReturn = false;
  245. isCharImmediatelyPostThrow = false;
  246. isCharImmediatelyPostNewDelete = false;
  247. isCharImmediatelyPostOperator = false;
  248. isCharImmediatelyPostComment = false;
  249. isPreviousCharPostComment = false;
  250. isCharImmediatelyPostLineComment = false;
  251. isCharImmediatelyPostOpenBlock = false;
  252. isCharImmediatelyPostCloseBlock = false;
  253. isCharImmediatelyPostTemplate = false;
  254. isCharImmediatelyPostPointerOrReference = false;
  255. isInObjCInterface = false;
  256. isInObjCMethodDefinition = false;
  257. isInObjCReturnType = false;
  258. isInObjCSelector = false;
  259. breakCurrentOneLineBlock = false;
  260. shouldRemoveNextClosingBrace = false;
  261. isInBraceRunIn = false;
  262. currentLineBeginsWithBrace = false;
  263. isPrependPostBlockEmptyLineRequested = false;
  264. isAppendPostBlockEmptyLineRequested = false;
  265. isIndentableProprocessor = false;
  266. isIndentableProprocessorBlock = false;
  267. prependEmptyLine = false;
  268. appendOpeningBrace = false;
  269. foundClosingHeader = false;
  270. isImmediatelyPostHeader = false;
  271. isInHeader = false;
  272. isInCase = false;
  273. isFirstPreprocConditional = false;
  274. processedFirstConditional = false;
  275. isJavaStaticConstructor = false;
  276. }
  277. /**
  278. * build vectors for each programing language
  279. * depending on the file extension.
  280. */
  281. void ASFormatter::buildLanguageVectors()
  282. {
  283. if (getFileType() == formatterFileType) // don't build unless necessary
  284. return;
  285. formatterFileType = getFileType();
  286. headers->clear();
  287. nonParenHeaders->clear();
  288. preDefinitionHeaders->clear();
  289. preCommandHeaders->clear();
  290. operators->clear();
  291. assignmentOperators->clear();
  292. castOperators->clear();
  293. indentableMacros->clear(); // ASEnhancer
  294. ASResource::buildHeaders(headers, getFileType());
  295. ASResource::buildNonParenHeaders(nonParenHeaders, getFileType());
  296. ASResource::buildPreDefinitionHeaders(preDefinitionHeaders, getFileType());
  297. ASResource::buildPreCommandHeaders(preCommandHeaders, getFileType());
  298. ASResource::buildOperators(operators, getFileType());
  299. ASResource::buildAssignmentOperators(assignmentOperators);
  300. ASResource::buildCastOperators(castOperators);
  301. ASResource::buildIndentableMacros(indentableMacros); //ASEnhancer
  302. }
  303. /**
  304. * set the variables for each predefined style.
  305. * this will override any previous settings.
  306. */
  307. void ASFormatter::fixOptionVariableConflicts()
  308. {
  309. if (formattingStyle == STYLE_ALLMAN)
  310. {
  311. setBraceFormatMode(BREAK_MODE);
  312. }
  313. else if (formattingStyle == STYLE_JAVA)
  314. {
  315. setBraceFormatMode(ATTACH_MODE);
  316. }
  317. else if (formattingStyle == STYLE_KR)
  318. {
  319. setBraceFormatMode(LINUX_MODE);
  320. }
  321. else if (formattingStyle == STYLE_STROUSTRUP)
  322. {
  323. setBraceFormatMode(LINUX_MODE);
  324. setBreakClosingHeaderBracesMode(true);
  325. }
  326. else if (formattingStyle == STYLE_WHITESMITH)
  327. {
  328. setBraceFormatMode(BREAK_MODE);
  329. setBraceIndent(true);
  330. setClassIndent(true); // avoid hanging indent with access modifiers
  331. setSwitchIndent(true); // avoid hanging indent with case statements
  332. }
  333. else if (formattingStyle == STYLE_VTK)
  334. {
  335. // the unindented class brace does NOT cause a hanging indent like Whitesmith
  336. setBraceFormatMode(BREAK_MODE);
  337. setBraceIndentVtk(true); // sets both braceIndent and braceIndentVtk
  338. setSwitchIndent(true); // avoid hanging indent with case statements
  339. }
  340. else if (formattingStyle == STYLE_BANNER)
  341. {
  342. // attached braces can have hanging indents with the closing brace
  343. setBraceFormatMode(ATTACH_MODE);
  344. setBraceIndent(true);
  345. setClassIndent(true); // avoid hanging indent with access modifiers
  346. setSwitchIndent(true); // avoid hanging indent with case statements
  347. }
  348. else if (formattingStyle == STYLE_GNU)
  349. {
  350. setBraceFormatMode(BREAK_MODE);
  351. setBlockIndent(true);
  352. }
  353. else if (formattingStyle == STYLE_LINUX)
  354. {
  355. setBraceFormatMode(LINUX_MODE);
  356. // always for Linux style
  357. setMinConditionalIndentOption(MINCOND_ONEHALF);
  358. }
  359. else if (formattingStyle == STYLE_HORSTMANN)
  360. {
  361. setBraceFormatMode(RUN_IN_MODE);
  362. setSwitchIndent(true);
  363. }
  364. else if (formattingStyle == STYLE_1TBS)
  365. {
  366. setBraceFormatMode(LINUX_MODE);
  367. setAddBracesMode(true);
  368. setRemoveBracesMode(false);
  369. }
  370. else if (formattingStyle == STYLE_GOOGLE)
  371. {
  372. setBraceFormatMode(ATTACH_MODE);
  373. setModifierIndent(true);
  374. setClassIndent(false);
  375. }
  376. else if (formattingStyle == STYLE_MOZILLA)
  377. {
  378. setBraceFormatMode(LINUX_MODE);
  379. }
  380. else if (formattingStyle == STYLE_PICO)
  381. {
  382. setBraceFormatMode(RUN_IN_MODE);
  383. setAttachClosingBraceMode(true);
  384. setSwitchIndent(true);
  385. setBreakOneLineBlocksMode(false);
  386. setBreakOneLineStatementsMode(false);
  387. // add-braces won't work for pico, but it could be fixed if necessary
  388. // both options should be set to true
  389. if (shouldAddBraces)
  390. shouldAddOneLineBraces = true;
  391. }
  392. else if (formattingStyle == STYLE_LISP)
  393. {
  394. setBraceFormatMode(ATTACH_MODE);
  395. setAttachClosingBraceMode(true);
  396. setBreakOneLineStatementsMode(false);
  397. // add-one-line-braces won't work for lisp
  398. // only shouldAddBraces should be set to true
  399. if (shouldAddOneLineBraces)
  400. {
  401. shouldAddBraces = true;
  402. shouldAddOneLineBraces = false;
  403. }
  404. }
  405. setMinConditionalIndentLength();
  406. // if not set by indent=force-tab-x set equal to indentLength
  407. if (getTabLength() == 0)
  408. setDefaultTabLength();
  409. // add-one-line-braces implies keep-one-line-blocks
  410. if (shouldAddOneLineBraces)
  411. setBreakOneLineBlocksMode(false);
  412. // don't allow add-braces and remove-braces
  413. if (shouldAddBraces || shouldAddOneLineBraces)
  414. setRemoveBracesMode(false);
  415. // don't allow indent-classes and indent-modifiers
  416. if (getClassIndent())
  417. setModifierIndent(false);
  418. }
  419. /**
  420. * get the next formatted line.
  421. *
  422. * @return formatted line.
  423. */
  424. string ASFormatter::nextLine()
  425. {
  426. const string* newHeader = nullptr;
  427. isInVirginLine = isVirgin;
  428. isCharImmediatelyPostComment = false;
  429. isPreviousCharPostComment = false;
  430. isCharImmediatelyPostLineComment = false;
  431. isCharImmediatelyPostOpenBlock = false;
  432. isCharImmediatelyPostCloseBlock = false;
  433. isCharImmediatelyPostTemplate = false;
  434. while (!isLineReady)
  435. {
  436. if (shouldReparseCurrentChar)
  437. shouldReparseCurrentChar = false;
  438. else if (!getNextChar())
  439. {
  440. breakLine();
  441. continue;
  442. }
  443. else // stuff to do when reading a new character...
  444. {
  445. // make sure that a virgin '{' at the beginning of the file will be treated as a block...
  446. if (isInVirginLine && currentChar == '{'
  447. && currentLineBeginsWithBrace
  448. && previousCommandChar == ' ')
  449. previousCommandChar = '{';
  450. if (isInClassInitializer
  451. && isBraceType(braceTypeStack->back(), COMMAND_TYPE))
  452. isInClassInitializer = false;
  453. if (isInBraceRunIn)
  454. isInLineBreak = false;
  455. if (!isWhiteSpace(currentChar))
  456. isInBraceRunIn = false;
  457. isPreviousCharPostComment = isCharImmediatelyPostComment;
  458. isCharImmediatelyPostComment = false;
  459. isCharImmediatelyPostTemplate = false;
  460. isCharImmediatelyPostReturn = false;
  461. isCharImmediatelyPostThrow = false;
  462. isCharImmediatelyPostNewDelete = false;
  463. isCharImmediatelyPostOperator = false;
  464. isCharImmediatelyPostPointerOrReference = false;
  465. isCharImmediatelyPostOpenBlock = false;
  466. isCharImmediatelyPostCloseBlock = false;
  467. }
  468. if ((lineIsLineCommentOnly || lineIsCommentOnly)
  469. && currentLine.find("*INDENT-ON*", charNum) != string::npos
  470. && isFormattingModeOff)
  471. {
  472. isFormattingModeOff = false;
  473. breakLine();
  474. formattedLine = currentLine;
  475. charNum = (int) currentLine.length() - 1;
  476. continue;
  477. }
  478. if (isFormattingModeOff)
  479. {
  480. breakLine();
  481. formattedLine = currentLine;
  482. charNum = (int) currentLine.length() - 1;
  483. continue;
  484. }
  485. if ((lineIsLineCommentOnly || lineIsCommentOnly)
  486. && currentLine.find("*INDENT-OFF*", charNum) != string::npos)
  487. {
  488. isFormattingModeOff = true;
  489. if (isInLineBreak) // is true if not the first line
  490. breakLine();
  491. formattedLine = currentLine;
  492. charNum = (int)currentLine.length() - 1;
  493. continue;
  494. }
  495. if (shouldBreakLineAtNextChar)
  496. {
  497. if (isWhiteSpace(currentChar) && !lineIsEmpty)
  498. continue;
  499. isInLineBreak = true;
  500. shouldBreakLineAtNextChar = false;
  501. }
  502. if (isInExecSQL && !passedSemicolon)
  503. {
  504. if (currentChar == ';')
  505. passedSemicolon = true;
  506. appendCurrentChar();
  507. continue;
  508. }
  509. if (isInLineComment)
  510. {
  511. formatLineCommentBody();
  512. continue;
  513. }
  514. else if (isInComment)
  515. {
  516. formatCommentBody();
  517. continue;
  518. }
  519. else if (isInQuote)
  520. {
  521. formatQuoteBody();
  522. continue;
  523. }
  524. // not in quote or comment or line comment
  525. if (isSequenceReached("//"))
  526. {
  527. formatLineCommentOpener();
  528. testForTimeToSplitFormattedLine();
  529. continue;
  530. }
  531. else if (isSequenceReached("/*"))
  532. {
  533. formatCommentOpener();
  534. testForTimeToSplitFormattedLine();
  535. continue;
  536. }
  537. else if (currentChar == '"'
  538. || (currentChar == '\'' && !isDigitSeparator(currentLine, charNum)))
  539. {
  540. formatQuoteOpener();
  541. testForTimeToSplitFormattedLine();
  542. continue;
  543. }
  544. // treat these preprocessor statements as a line comment
  545. else if (currentChar == '#'
  546. && currentLine.find_first_not_of(" \t") == (size_t) charNum)
  547. {
  548. string preproc = trim(currentLine.c_str() + charNum + 1);
  549. if (preproc.length() > 0
  550. && isCharPotentialHeader(preproc, 0)
  551. && (findKeyword(preproc, 0, "region")
  552. || findKeyword(preproc, 0, "endregion")
  553. || findKeyword(preproc, 0, "error")
  554. || findKeyword(preproc, 0, "warning")
  555. || findKeyword(preproc, 0, "line")))
  556. {
  557. currentLine = rtrim(currentLine); // trim the end only
  558. // check for run-in
  559. if (formattedLine.length() > 0 && formattedLine[0] == '{')
  560. {
  561. isInLineBreak = true;
  562. isInBraceRunIn = false;
  563. }
  564. if (previousCommandChar == '}')
  565. currentHeader = nullptr;
  566. isInLineComment = true;
  567. appendCurrentChar();
  568. continue;
  569. }
  570. }
  571. if (isInPreprocessor)
  572. {
  573. appendCurrentChar();
  574. continue;
  575. }
  576. if (isInTemplate && shouldCloseTemplates)
  577. {
  578. if (previousNonWSChar == '>' && isWhiteSpace(currentChar) && peekNextChar() == '>')
  579. continue;
  580. }
  581. if (shouldRemoveNextClosingBrace && currentChar == '}')
  582. {
  583. currentLine[charNum] = currentChar = ' ';
  584. shouldRemoveNextClosingBrace = false;
  585. assert(adjustChecksumIn(-'}'));
  586. if (isEmptyLine(currentLine))
  587. continue;
  588. }
  589. // handle white space - needed to simplify the rest.
  590. if (isWhiteSpace(currentChar))
  591. {
  592. appendCurrentChar();
  593. continue;
  594. }
  595. /* not in MIDDLE of quote or comment or SQL or white-space of any type ... */
  596. // check if in preprocessor
  597. // ** isInPreprocessor will be automatically reset at the beginning
  598. // of a new line in getnextChar()
  599. if (currentChar == '#')
  600. {
  601. isInPreprocessor = true;
  602. // check for run-in
  603. if (formattedLine.length() > 0 && formattedLine[0] == '{')
  604. {
  605. isInLineBreak = true;
  606. isInBraceRunIn = false;
  607. }
  608. processPreprocessor();
  609. // if top level it is potentially indentable
  610. if (shouldIndentPreprocBlock
  611. && (isBraceType(braceTypeStack->back(), NULL_TYPE)
  612. || isBraceType(braceTypeStack->back(), NAMESPACE_TYPE))
  613. && !foundClassHeader
  614. && !isInClassInitializer
  615. && sourceIterator->tellg() > preprocBlockEnd)
  616. {
  617. // indent the #if preprocessor blocks
  618. string preproc = ASBeautifier::extractPreprocessorStatement(currentLine);
  619. if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") // #if, #ifdef, #ifndef
  620. {
  621. if (isImmediatelyPostPreprocessor)
  622. breakLine();
  623. isIndentableProprocessorBlock = isIndentablePreprocessorBlock(currentLine, charNum);
  624. isIndentableProprocessor = isIndentableProprocessorBlock;
  625. }
  626. }
  627. if (isIndentableProprocessorBlock
  628. && charNum < (int) currentLine.length() - 1
  629. && isWhiteSpace(currentLine[charNum + 1]))
  630. {
  631. size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
  632. if (nextText != string::npos)
  633. currentLine.erase(charNum + 1, nextText - charNum - 1);
  634. }
  635. if (isIndentableProprocessorBlock
  636. && sourceIterator->tellg() >= preprocBlockEnd)
  637. isIndentableProprocessorBlock = false;
  638. // need to fall thru here to reset the variables
  639. }
  640. /* not in preprocessor ... */
  641. if (isImmediatelyPostComment)
  642. {
  643. caseHeaderFollowsComments = false;
  644. isImmediatelyPostComment = false;
  645. isCharImmediatelyPostComment = true;
  646. }
  647. if (isImmediatelyPostLineComment)
  648. {
  649. caseHeaderFollowsComments = false;
  650. isImmediatelyPostLineComment = false;
  651. isCharImmediatelyPostLineComment = true;
  652. }
  653. if (isImmediatelyPostReturn)
  654. {
  655. isImmediatelyPostReturn = false;
  656. isCharImmediatelyPostReturn = true;
  657. }
  658. if (isImmediatelyPostThrow)
  659. {
  660. isImmediatelyPostThrow = false;
  661. isCharImmediatelyPostThrow = true;
  662. }
  663. if (isImmediatelyPostNewDelete)
  664. {
  665. isImmediatelyPostNewDelete = false;
  666. isCharImmediatelyPostNewDelete = true;
  667. }
  668. if (isImmediatelyPostOperator)
  669. {
  670. isImmediatelyPostOperator = false;
  671. isCharImmediatelyPostOperator = true;
  672. }
  673. if (isImmediatelyPostTemplate)
  674. {
  675. isImmediatelyPostTemplate = false;
  676. isCharImmediatelyPostTemplate = true;
  677. }
  678. if (isImmediatelyPostPointerOrReference)
  679. {
  680. isImmediatelyPostPointerOrReference = false;
  681. isCharImmediatelyPostPointerOrReference = true;
  682. }
  683. // reset isImmediatelyPostHeader information
  684. if (isImmediatelyPostHeader)
  685. {
  686. // should braces be added
  687. if (currentChar != '{'
  688. && shouldAddBraces
  689. && (shouldBreakOneLineStatements || !isHeaderInMultiStatementLine)
  690. && isOkToBreakBlock(braceTypeStack->back()))
  691. {
  692. bool bracesAdded = addBracesToStatement();
  693. if (bracesAdded && !shouldAddOneLineBraces)
  694. {
  695. size_t firstText = currentLine.find_first_not_of(" \t");
  696. assert(firstText != string::npos);
  697. if ((int) firstText == charNum || shouldBreakOneLineHeaders)
  698. breakCurrentOneLineBlock = true;
  699. }
  700. }
  701. // should braces be removed
  702. else if (currentChar == '{' && shouldRemoveBraces)
  703. {
  704. bool bracesRemoved = removeBracesFromStatement();
  705. if (bracesRemoved)
  706. {
  707. shouldRemoveNextClosingBrace = true;
  708. if (isBeforeAnyLineEndComment(charNum))
  709. spacePadNum--;
  710. else if (shouldBreakOneLineBlocks
  711. || (currentLineBeginsWithBrace
  712. && currentLine.find_first_not_of(" \t") != string::npos))
  713. shouldBreakLineAtNextChar = true;
  714. continue;
  715. }
  716. }
  717. // break 'else-if' if shouldBreakElseIfs is requested
  718. if (shouldBreakElseIfs
  719. && currentHeader == &AS_ELSE
  720. && isOkToBreakBlock(braceTypeStack->back())
  721. && !isBeforeAnyComment()
  722. && (shouldBreakOneLineStatements || !isHeaderInMultiStatementLine))
  723. {
  724. string nextText = peekNextText(currentLine.substr(charNum));
  725. if (nextText.length() > 0
  726. && isCharPotentialHeader(nextText, 0)
  727. && ASBase::findHeader(nextText, 0, headers) == &AS_IF)
  728. {
  729. isInLineBreak = true;
  730. }
  731. }
  732. // break a header (e.g. if, while, else) from the following statement
  733. if (shouldBreakOneLineHeaders
  734. && peekNextChar() != ' '
  735. && (shouldBreakOneLineStatements
  736. || (!isHeaderInMultiStatementLine
  737. && !isMultiStatementLine()))
  738. && isOkToBreakBlock(braceTypeStack->back())
  739. && !isBeforeAnyComment())
  740. {
  741. if (currentChar == '{')
  742. {
  743. if (!currentLineBeginsWithBrace)
  744. {
  745. if (isOneLineBlockReached(currentLine, charNum) == 3)
  746. isInLineBreak = false;
  747. else
  748. breakCurrentOneLineBlock = true;
  749. }
  750. }
  751. else if (currentHeader == &AS_ELSE)
  752. {
  753. string nextText = peekNextText(currentLine.substr(charNum), true);
  754. if (nextText.length() > 0
  755. && ((isCharPotentialHeader(nextText, 0)
  756. && ASBase::findHeader(nextText, 0, headers) != &AS_IF)
  757. || nextText[0] == '{'))
  758. isInLineBreak = true;
  759. }
  760. else
  761. {
  762. isInLineBreak = true;
  763. }
  764. }
  765. isImmediatelyPostHeader = false;
  766. }
  767. if (passedSemicolon) // need to break the formattedLine
  768. {
  769. passedSemicolon = false;
  770. if (parenStack->back() == 0 && !isCharImmediatelyPostComment && currentChar != ';') // allow ;;
  771. {
  772. // does a one-line block have ending comments?
  773. if (isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
  774. {
  775. size_t blockEnd = currentLine.rfind(AS_CLOSE_BRACE);
  776. assert(blockEnd != string::npos);
  777. // move ending comments to this formattedLine
  778. if (isBeforeAnyLineEndComment(blockEnd))
  779. {
  780. size_t commentStart = currentLine.find_first_not_of(" \t", blockEnd + 1);
  781. assert(commentStart != string::npos);
  782. assert((currentLine.compare(commentStart, 2, "//") == 0)
  783. || (currentLine.compare(commentStart, 2, "/*") == 0));
  784. formattedLine.append(getIndentLength() - 1, ' ');
  785. // append comment
  786. int charNumSave = charNum;
  787. charNum = commentStart;
  788. while (charNum < (int) currentLine.length())
  789. {
  790. currentChar = currentLine[charNum];
  791. if (currentChar == '\t' && shouldConvertTabs)
  792. convertTabToSpaces();
  793. formattedLine.append(1, currentChar);
  794. ++charNum;
  795. }
  796. size_t commentLength = currentLine.length() - commentStart;
  797. currentLine.erase(commentStart, commentLength);
  798. charNum = charNumSave;
  799. currentChar = currentLine[charNum];
  800. testForTimeToSplitFormattedLine();
  801. }
  802. }
  803. isInExecSQL = false;
  804. shouldReparseCurrentChar = true;
  805. if (formattedLine.find_first_not_of(" \t") != string::npos)
  806. isInLineBreak = true;
  807. if (needHeaderOpeningBrace)
  808. {
  809. isCharImmediatelyPostCloseBlock = true;
  810. needHeaderOpeningBrace = false;
  811. }
  812. continue;
  813. }
  814. }
  815. if (passedColon)
  816. {
  817. passedColon = false;
  818. if (parenStack->back() == 0
  819. && !isBeforeAnyComment()
  820. && (formattedLine.find_first_not_of(" \t") != string::npos))
  821. {
  822. shouldReparseCurrentChar = true;
  823. isInLineBreak = true;
  824. continue;
  825. }
  826. }
  827. // Check if in template declaration, e.g. foo<bar> or foo<bar,fig>
  828. if (!isInTemplate && currentChar == '<')
  829. {
  830. checkIfTemplateOpener();
  831. }
  832. // handle parens
  833. if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
  834. {
  835. questionMarkStack->push_back(foundQuestionMark);
  836. foundQuestionMark = false;
  837. parenStack->back()++;
  838. if (currentChar == '[')
  839. {
  840. ++squareBracketCount;
  841. if (getAlignMethodColon() && squareBracketCount == 1 && isCStyle())
  842. objCColonAlign = findObjCColonAlignment();
  843. }
  844. }
  845. else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
  846. {
  847. foundPreCommandHeader = false;
  848. parenStack->back()--;
  849. // this can happen in preprocessor directives
  850. if (parenStack->back() < 0)
  851. parenStack->back() = 0;
  852. if (!questionMarkStack->empty())
  853. {
  854. foundQuestionMark = questionMarkStack->back();
  855. questionMarkStack->pop_back();
  856. }
  857. if (isInTemplate && currentChar == '>')
  858. {
  859. templateDepth--;
  860. if (templateDepth == 0)
  861. {
  862. isInTemplate = false;
  863. isImmediatelyPostTemplate = true;
  864. }
  865. }
  866. // check if this parenthesis closes a header, e.g. if (...), while (...)
  867. if (isInHeader && parenStack->back() == 0)
  868. {
  869. isInHeader = false;
  870. isImmediatelyPostHeader = true;
  871. foundQuestionMark = false;
  872. }
  873. if (currentChar == ']')
  874. {
  875. --squareBracketCount;
  876. if (squareBracketCount <= 0)
  877. {
  878. squareBracketCount = 0;
  879. objCColonAlign = 0;
  880. }
  881. }
  882. if (currentChar == ')')
  883. {
  884. foundCastOperator = false;
  885. if (parenStack->back() == 0)
  886. endOfAsmReached = true;
  887. }
  888. }
  889. // handle braces
  890. if (currentChar == '{' || currentChar == '}')
  891. {
  892. // if appendOpeningBrace this was already done for the original brace
  893. if (currentChar == '{' && !appendOpeningBrace)
  894. {
  895. BraceType newBraceType = getBraceType();
  896. breakCurrentOneLineBlock = false;
  897. foundNamespaceHeader = false;
  898. foundClassHeader = false;
  899. foundStructHeader = false;
  900. foundInterfaceHeader = false;
  901. foundPreDefinitionHeader = false;
  902. foundPreCommandHeader = false;
  903. foundPreCommandMacro = false;
  904. foundTrailingReturnType = false;
  905. isInPotentialCalculation = false;
  906. isInObjCMethodDefinition = false;
  907. isInObjCInterface = false;
  908. isInEnum = false;
  909. isJavaStaticConstructor = false;
  910. isCharImmediatelyPostNonInStmt = false;
  911. needHeaderOpeningBrace = false;
  912. shouldKeepLineUnbroken = false;
  913. objCColonAlign = 0;
  914. isPreviousBraceBlockRelated = !isBraceType(newBraceType, ARRAY_TYPE);
  915. braceTypeStack->emplace_back(newBraceType);
  916. preBraceHeaderStack->emplace_back(currentHeader);
  917. currentHeader = nullptr;
  918. structStack->push_back(isInIndentableStruct);
  919. if (isBraceType(newBraceType, STRUCT_TYPE) && isCStyle())
  920. isInIndentableStruct = isStructAccessModified(currentLine, charNum);
  921. else
  922. isInIndentableStruct = false;
  923. }
  924. // this must be done before the braceTypeStack is popped
  925. BraceType braceType = braceTypeStack->back();
  926. bool isOpeningArrayBrace = (isBraceType(braceType, ARRAY_TYPE)
  927. && braceTypeStack->size() >= 2
  928. && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2], ARRAY_TYPE)
  929. );
  930. if (currentChar == '}')
  931. {
  932. // if a request has been made to append a post block empty line,
  933. // but the block exists immediately before a closing brace,
  934. // then there is no need for the post block empty line.
  935. isAppendPostBlockEmptyLineRequested = false;
  936. if (isInAsm)
  937. endOfAsmReached = true;
  938. isInAsmOneLine = isInQuote = false;
  939. shouldKeepLineUnbroken = false;
  940. squareBracketCount = 0;
  941. if (braceTypeStack->size() > 1)
  942. {
  943. previousBraceType = braceTypeStack->back();
  944. braceTypeStack->pop_back();
  945. isPreviousBraceBlockRelated = !isBraceType(braceType, ARRAY_TYPE);
  946. }
  947. else
  948. {
  949. previousBraceType = NULL_TYPE;
  950. isPreviousBraceBlockRelated = false;
  951. }
  952. if (!preBraceHeaderStack->empty())
  953. {
  954. currentHeader = preBraceHeaderStack->back();
  955. preBraceHeaderStack->pop_back();
  956. }
  957. else
  958. currentHeader = nullptr;
  959. if (!structStack->empty())
  960. {
  961. isInIndentableStruct = structStack->back();
  962. structStack->pop_back();
  963. }
  964. else
  965. isInIndentableStruct = false;
  966. if (isNonInStatementArray
  967. && (!isBraceType(braceTypeStack->back(), ARRAY_TYPE) // check previous brace
  968. || peekNextChar() == ';')) // check for "};" added V2.01
  969. isImmediatelyPostNonInStmt = true;
  970. if (!shouldBreakOneLineStatements
  971. && ASBeautifier::getNextWord(currentLine, charNum) == AS_ELSE)
  972. {
  973. // handle special case of "else" at the end of line
  974. size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
  975. if (ASBeautifier::peekNextChar(currentLine, nextText + 3) == ' ')
  976. shouldBreakLineAtNextChar = true;
  977. }
  978. }
  979. // format braces
  980. appendOpeningBrace = false;
  981. if (isBraceType(braceType, ARRAY_TYPE))
  982. {
  983. formatArrayBraces(braceType, isOpeningArrayBrace);
  984. }
  985. else
  986. {
  987. if (currentChar == '{')
  988. formatOpeningBrace(braceType);
  989. else
  990. formatClosingBrace(braceType);
  991. }
  992. continue;
  993. }
  994. if ((((previousCommandChar == '{' && isPreviousBraceBlockRelated)
  995. || ((previousCommandChar == '}'
  996. && !isImmediatelyPostEmptyBlock
  997. && isPreviousBraceBlockRelated
  998. && !isPreviousCharPostComment // Fixes wrongly appended newlines after '}' immediately after comments
  999. && peekNextChar() != ' '
  1000. && !isBraceType(previousBraceType, DEFINITION_TYPE))
  1001. && !isBraceType(braceTypeStack->back(), DEFINITION_TYPE)))
  1002. && isOkToBreakBlock(braceTypeStack->back()))
  1003. // check for array
  1004. || (previousCommandChar == '{' // added 9/30/2010
  1005. && isBraceType(braceTypeStack->back(), ARRAY_TYPE)
  1006. && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
  1007. && isNonInStatementArray)
  1008. // check for pico one line braces
  1009. || (formattingStyle == STYLE_PICO
  1010. && (previousCommandChar == '{' && isPreviousBraceBlockRelated)
  1011. && isBraceType(braceTypeStack->back(), COMMAND_TYPE)
  1012. && isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
  1013. && braceFormatMode == RUN_IN_MODE)
  1014. )
  1015. {
  1016. isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
  1017. isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
  1018. if (isCharImmediatelyPostOpenBlock
  1019. && !isCharImmediatelyPostComment
  1020. && !isCharImmediatelyPostLineComment)
  1021. {
  1022. previousCommandChar = ' ';
  1023. if (braceFormatMode == NONE_MODE)
  1024. {
  1025. if (isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
  1026. && (isBraceType(braceTypeStack->back(), BREAK_BLOCK_TYPE)
  1027. || shouldBreakOneLineBlocks))
  1028. isInLineBreak = true;
  1029. else if (currentLineBeginsWithBrace)
  1030. formatRunIn();
  1031. else
  1032. breakLine();
  1033. }
  1034. else if (braceFormatMode == RUN_IN_MODE
  1035. && currentChar != '#')
  1036. formatRunIn();
  1037. else
  1038. isInLineBreak = true;
  1039. }
  1040. else if (isCharImmediatelyPostCloseBlock
  1041. && shouldBreakOneLineStatements
  1042. && !isCharImmediatelyPostComment
  1043. && ((isLegalNameChar(currentChar) && currentChar != '.')
  1044. || currentChar == '+'
  1045. || currentChar == '-'
  1046. || currentChar == '*'
  1047. || currentChar == '&'
  1048. || currentChar == '('))
  1049. {
  1050. previousCommandChar = ' ';
  1051. isInLineBreak = true;
  1052. }
  1053. }
  1054. // reset block handling flags
  1055. isImmediatelyPostEmptyBlock = false;
  1056. // look for headers
  1057. bool isPotentialHeader = isCharPotentialHeader(currentLine, charNum);
  1058. if (isPotentialHeader && !isInTemplate && squareBracketCount == 0)
  1059. {
  1060. isNonParenHeader = false;
  1061. foundClosingHeader = false;
  1062. newHeader = findHeader(headers);
  1063. // Qt headers may be variables in C++
  1064. if (isCStyle()
  1065. && (newHeader == &AS_FOREVER || newHeader == &AS_FOREACH))
  1066. {
  1067. if (currentLine.find_first_of("=;", charNum) != string::npos)
  1068. newHeader = nullptr;
  1069. }
  1070. if (isJavaStyle()
  1071. && (newHeader == &AS_SYNCHRONIZED))
  1072. {
  1073. // want synchronized statements not synchronized methods
  1074. if (!isBraceType(braceTypeStack->back(), COMMAND_TYPE))
  1075. newHeader = nullptr;
  1076. }
  1077. else if (newHeader == &AS_USING
  1078. && ASBeautifier::peekNextChar(
  1079. currentLine, charNum + (*newHeader).length() - 1) != '(')
  1080. newHeader = nullptr;
  1081. if (newHeader != nullptr)
  1082. {
  1083. foundClosingHeader = isClosingHeader(newHeader);
  1084. if (!foundClosingHeader)
  1085. {
  1086. // these are closing headers
  1087. if ((newHeader == &AS_WHILE && currentHeader == &AS_DO)
  1088. || (newHeader == &_AS_FINALLY && currentHeader == &_AS_TRY)
  1089. || (newHeader == &_AS_EXCEPT && currentHeader == &_AS_TRY))
  1090. foundClosingHeader = true;
  1091. // don't append empty block for these related headers
  1092. else if (isSharpStyle()
  1093. && previousNonWSChar == '}'
  1094. && ((newHeader == &AS_SET && currentHeader == &AS_GET)
  1095. || (newHeader == &AS_REMOVE && currentHeader == &AS_ADD))
  1096. && isOkToBreakBlock(braceTypeStack->back()))
  1097. isAppendPostBlockEmptyLineRequested = false;
  1098. }
  1099. // TODO: this can be removed in a future release
  1100. // version 3.0 - break erroneous attached header from previous versions
  1101. if (isSharpStyle()
  1102. && ((newHeader == &AS_SET && currentHeader == &AS_GET)
  1103. || (newHeader == &AS_REMOVE && currentHeader == &AS_ADD))
  1104. && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
  1105. && currentLine[currentLine.find_first_not_of(" \t")] == '}')
  1106. isInLineBreak = true;
  1107. // END TODO
  1108. const string* previousHeader = currentHeader;
  1109. currentHeader = newHeader;
  1110. needHeaderOpeningBrace = true;
  1111. // is the previous statement on the same line?
  1112. if ((previousNonWSChar == ';' || previousNonWSChar == ':')
  1113. && !isInLineBreak
  1114. && isOkToBreakBlock(braceTypeStack->back()))
  1115. {
  1116. // if breaking lines, break the line at the header
  1117. // except for multiple 'case' statements on a line
  1118. if (maxCodeLength != string::npos
  1119. && previousHeader != &AS_CASE)
  1120. isInLineBreak = true;
  1121. else
  1122. isHeaderInMultiStatementLine = true;
  1123. }
  1124. if (foundClosingHeader && previousNonWSChar == '}')
  1125. {
  1126. if (isOkToBreakBlock(braceTypeStack->back()))
  1127. isLineBreakBeforeClosingHeader();
  1128. // get the adjustment for a comment following the closing header
  1129. if (isInLineBreak)
  1130. nextLineSpacePadNum = getNextLineCommentAdjustment();
  1131. else
  1132. spacePadNum = getCurrentLineCommentAdjustment();
  1133. }
  1134. // check if the found header is non-paren header
  1135. isNonParenHeader = findHeader(nonParenHeaders) != nullptr;
  1136. if (isNonParenHeader
  1137. && (currentHeader == &AS_CATCH
  1138. || currentHeader == &AS_CASE))
  1139. {
  1140. int startChar = charNum + currentHeader->length() - 1;
  1141. if (ASBeautifier::peekNextChar(currentLine, startChar) == '(')
  1142. isNonParenHeader = false;
  1143. }
  1144. // join 'else if' statements
  1145. if (currentHeader == &AS_IF
  1146. && previousHeader == &AS_ELSE
  1147. && isInLineBreak
  1148. && !shouldBreakElseIfs
  1149. && !isCharImmediatelyPostLineComment
  1150. && !isImmediatelyPostPreprocessor)
  1151. {
  1152. // 'else' must be last thing on the line
  1153. size_t start = formattedLine.length() >= 6 ? formattedLine.length() - 6 : 0;
  1154. if (formattedLine.find(AS_ELSE, start) != string::npos)
  1155. {
  1156. appendSpacePad();
  1157. isInLineBreak = false;
  1158. }
  1159. }
  1160. appendSequence(*currentHeader);
  1161. goForward(currentHeader->length() - 1);
  1162. // if a paren-header is found add a space after it, if needed
  1163. // this checks currentLine, appendSpacePad() checks formattedLine
  1164. // in 'case' and C# 'catch' can be either a paren or non-paren header
  1165. if (shouldPadHeader
  1166. && !isNonParenHeader
  1167. && charNum < (int) currentLine.length() - 1 && !isWhiteSpace(currentLine[charNum + 1]))
  1168. appendSpacePad();
  1169. // Signal that a header has been reached
  1170. // *** But treat a closing while() (as in do...while)
  1171. // as if it were NOT a header since a closing while()
  1172. // should never have a block after it!
  1173. if (currentHeader != &AS_CASE && currentHeader != &AS_DEFAULT
  1174. && !(foundClosingHeader && currentHeader == &AS_WHILE))
  1175. {
  1176. isInHeader = true;
  1177. // in C# 'catch' and 'delegate' can be a paren or non-paren header
  1178. if (isNonParenHeader && !isSharpStyleWithParen(currentHeader))
  1179. {
  1180. isImmediatelyPostHeader = true;
  1181. isInHeader = false;
  1182. }
  1183. }
  1184. if (shouldBreakBlocks
  1185. && isOkToBreakBlock(braceTypeStack->back())
  1186. && !isHeaderInMultiStatementLine)
  1187. {
  1188. if (previousHeader == nullptr
  1189. && !foundClosingHeader
  1190. && !isCharImmediatelyPostOpenBlock
  1191. && !isImmediatelyPostCommentOnly)
  1192. {
  1193. isPrependPostBlockEmptyLineRequested = true;
  1194. }
  1195. if (isClosingHeader(currentHeader)
  1196. || foundClosingHeader)
  1197. {
  1198. isPrependPostBlockEmptyLineRequested = false;
  1199. }
  1200. if (shouldBreakClosingHeaderBlocks
  1201. && isCharImmediatelyPostCloseBlock
  1202. && !isImmediatelyPostCommentOnly
  1203. && !(currentHeader == &AS_WHILE // do-while
  1204. && foundClosingHeader))
  1205. {
  1206. isPrependPostBlockEmptyLineRequested = true;
  1207. }
  1208. }
  1209. if (currentHeader == &AS_CASE
  1210. || currentHeader == &AS_DEFAULT)
  1211. isInCase = true;
  1212. continue;
  1213. }
  1214. else if ((newHeader = findHeader(preDefinitionHeaders)) != nullptr
  1215. && parenStack->back() == 0
  1216. && !isInEnum) // not C++11 enum class
  1217. {
  1218. if (newHeader == &AS_NAMESPACE || newHeader == &AS_MODULE)
  1219. foundNamespaceHeader = true;
  1220. if (newHeader == &AS_CLASS)
  1221. foundClassHeader = true;
  1222. if (newHeader == &AS_STRUCT)
  1223. foundStructHeader = true;
  1224. if (newHeader == &AS_INTERFACE)
  1225. foundInterfaceHeader = true;
  1226. foundPreDefinitionHeader = true;
  1227. appendSequence(*newHeader);
  1228. goForward(newHeader->length() - 1);
  1229. continue;
  1230. }
  1231. else if ((newHeader = findHeader(preCommandHeaders)) != nullptr)
  1232. {
  1233. // a 'const' variable is not a preCommandHeader
  1234. if (previousNonWSChar == ')')
  1235. foundPreCommandHeader = true;
  1236. }
  1237. else if ((newHeader = findHeader(castOperators)) != nullptr)
  1238. {
  1239. foundCastOperator = true;
  1240. appendSequence(*newHeader);
  1241. goForward(newHeader->length() - 1);
  1242. continue;
  1243. }
  1244. } // (isPotentialHeader && !isInTemplate)
  1245. if (isInLineBreak) // OK to break line here
  1246. {
  1247. breakLine();
  1248. if (isInVirginLine) // adjust for the first line
  1249. {
  1250. lineCommentNoBeautify = lineCommentNoIndent;
  1251. lineCommentNoIndent = false;
  1252. if (isImmediatelyPostPreprocessor)
  1253. {
  1254. isInIndentablePreproc = isIndentableProprocessor;
  1255. isIndentableProprocessor = false;
  1256. }
  1257. }
  1258. }
  1259. if (previousNonWSChar == '}' || currentChar == ';')
  1260. {
  1261. if (currentChar == ';')
  1262. {
  1263. squareBracketCount = 0;
  1264. if (((shouldBreakOneLineStatements
  1265. || isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
  1266. && isOkToBreakBlock(braceTypeStack->back()))
  1267. && !(attachClosingBraceMode && peekNextChar() == '}'))
  1268. {
  1269. passedSemicolon = true;
  1270. }
  1271. else if (!shouldBreakOneLineStatements
  1272. && ASBeautifier::getNextWord(currentLine, charNum) == AS_ELSE)
  1273. {
  1274. // handle special case of "else" at the end of line
  1275. size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
  1276. if (ASBeautifier::peekNextChar(currentLine, nextText + 3) == ' ')
  1277. passedSemicolon = true;
  1278. }
  1279. if (shouldBreakBlocks
  1280. && currentHeader != nullptr
  1281. && currentHeader != &AS_CASE
  1282. && currentHeader != &AS_DEFAULT
  1283. && !isHeaderInMultiStatementLine
  1284. && parenStack->back() == 0)
  1285. {
  1286. isAppendPostBlockEmptyLineRequested = true;
  1287. }
  1288. }
  1289. if (currentChar != ';'
  1290. || (needHeaderOpeningBrace && parenStack->back() == 0))
  1291. currentHeader = nullptr;
  1292. resetEndOfStatement();
  1293. }
  1294. if (currentChar == ':'
  1295. && previousChar != ':' // not part of '::'
  1296. && peekNextChar() != ':') // not part of '::'
  1297. {
  1298. if (isInCase)
  1299. {
  1300. isInCase = false;
  1301. if (shouldBreakOneLineStatements)
  1302. passedColon = true;
  1303. }
  1304. else if (isCStyle() // for C/C++ only
  1305. && isOkToBreakBlock(braceTypeStack->back())
  1306. && shouldBreakOneLineStatements
  1307. && !foundQuestionMark // not in a ?: sequence
  1308. && !foundPreDefinitionHeader // not in a definition block
  1309. && previousCommandChar != ')' // not after closing paren of a method header
  1310. && !foundPreCommandHeader // not after a 'noexcept'
  1311. && squareBracketCount == 0 // not in objC method call
  1312. && !isInObjCMethodDefinition // not objC '-' or '+' method
  1313. && !isInObjCInterface // not objC @interface
  1314. && !isInObjCSelector // not objC @selector
  1315. && !isDigit(peekNextChar()) // not a bit field
  1316. && !isInEnum // not an enum with a base type
  1317. && !isInAsm // not in extended assembler
  1318. && !isInAsmOneLine // not in extended assembler
  1319. && !isInAsmBlock) // not in extended assembler
  1320. {
  1321. passedColon = true;
  1322. }
  1323. if (isCStyle()
  1324. && shouldPadMethodColon
  1325. && (squareBracketCount > 0 || isInObjCMethodDefinition || isInObjCSelector)
  1326. && !foundQuestionMark) // not in a ?: sequence
  1327. padObjCMethodColon();
  1328. if (isInObjCInterface)
  1329. {
  1330. appendSpacePad();
  1331. if ((int) currentLine.length() > charNum + 1
  1332. && !isWhiteSpace(currentLine[charNum + 1]))
  1333. currentLine.insert(charNum + 1, " ");
  1334. }
  1335. if (isClassInitializer())
  1336. isInClassInitializer = true;
  1337. }
  1338. if (currentChar == '?')
  1339. foundQuestionMark = true;
  1340. if (isPotentialHeader && !isInTemplate)
  1341. {
  1342. if (findKeyword(currentLine, charNum, AS_NEW)
  1343. || findKeyword(currentLine, charNum, AS_DELETE))
  1344. {
  1345. isInPotentialCalculation = false;
  1346. isImmediatelyPostNewDelete = true;
  1347. }
  1348. if (findKeyword(currentLine, charNum, AS_RETURN))
  1349. {
  1350. isInPotentialCalculation = true; // return is the same as an = sign
  1351. isImmediatelyPostReturn = true;
  1352. }
  1353. if (findKeyword(currentLine, charNum, AS_OPERATOR))
  1354. isImmediatelyPostOperator = true;
  1355. if (findKeyword(currentLine, charNum, AS_ENUM))
  1356. {
  1357. size_t firstNum = currentLine.find_first_of("(){},/");
  1358. if (firstNum == string::npos
  1359. || currentLine[firstNum] == '{'
  1360. || currentLine[firstNum] == '/')
  1361. isInEnum = true;
  1362. }
  1363. if (isCStyle()
  1364. && findKeyword(currentLine, charNum, AS_THROW)
  1365. && previousCommandChar != ')'
  1366. && !foundPreCommandHeader) // 'const' throw()
  1367. isImmediatelyPostThrow = true;
  1368. if (isCStyle() && findKeyword(currentLine, charNum, AS_EXTERN) && isExternC())
  1369. isInExternC = true;
  1370. if (isCStyle() && findKeyword(currentLine, charNum, AS_AUTO)
  1371. && (isBraceType(braceTypeStack->back(), NULL_TYPE)
  1372. || isBraceType(braceTypeStack->back(), NAMESPACE_TYPE)
  1373. || isBraceType(braceTypeStack->back(), CLASS_TYPE)))
  1374. foundTrailingReturnType = true;
  1375. // Objective-C NSException macros are preCommandHeaders
  1376. if (isCStyle() && findKeyword(currentLine, charNum, AS_NS_DURING))
  1377. foundPreCommandMacro = true;
  1378. if (isCStyle() && findKeyword(currentLine, charNum, AS_NS_HANDLER))
  1379. foundPreCommandMacro = true;
  1380. if (isCStyle() && isExecSQL(currentLine, charNum))
  1381. isInExecSQL = true;
  1382. if (isCStyle())
  1383. {
  1384. if (findKeyword(currentLine, charNum, AS_ASM)
  1385. || findKeyword(currentLine, charNum, AS__ASM__))
  1386. {
  1387. isInAsm = true;
  1388. }
  1389. else if (findKeyword(currentLine, charNum, AS_MS_ASM) // microsoft specific
  1390. || findKeyword(currentLine, charNum, AS_MS__ASM))
  1391. {
  1392. int index = 4;
  1393. if (peekNextChar() == '_') // check for __asm
  1394. index = 5;
  1395. char peekedChar = ASBase::peekNextChar(currentLine, charNum + index);
  1396. if (peekedChar == '{' || peekedChar == ' ')
  1397. isInAsmBlock = true;
  1398. else
  1399. isInAsmOneLine = true;
  1400. }
  1401. }
  1402. if (isJavaStyle()
  1403. && (findKeyword(currentLine, charNum, AS_STATIC)
  1404. && isNextCharOpeningBrace(charNum + 6)))
  1405. isJavaStaticConstructor = true;
  1406. if (isSharpStyle()
  1407. && (findKeyword(currentLine, charNum, AS_DELEGATE)
  1408. || findKeyword(currentLine, charNum, AS_UNCHECKED)))
  1409. isSharpDelegate = true;
  1410. // append the entire name
  1411. string name = getCurrentWord(currentLine, charNum);
  1412. // must pad the 'and' and 'or' operators if required
  1413. if (name == "and" || name == "or")
  1414. {
  1415. if (shouldPadOperators && previousNonWSChar != ':')
  1416. {
  1417. appendSpacePad();
  1418. appendOperator(name);
  1419. goForward(name.length() - 1);
  1420. if (!isBeforeAnyComment()
  1421. && !(currentLine.compare(charNum + 1, 1, AS_SEMICOLON) == 0)
  1422. && !(currentLine.compare(charNum + 1, 2, AS_SCOPE_RESOLUTION) == 0))
  1423. appendSpaceAfter();
  1424. }
  1425. else
  1426. {
  1427. appendOperator(name);
  1428. goForward(name.length() - 1);
  1429. }
  1430. }
  1431. else
  1432. {
  1433. appendSequence(name);
  1434. goForward(name.length() - 1);
  1435. }
  1436. continue;
  1437. } // (isPotentialHeader && !isInTemplate)
  1438. // determine if this is an Objective-C statement
  1439. if (currentChar == '@'
  1440. && isCharPotentialHeader(currentLine, charNum + 1)
  1441. && findKeyword(currentLine, charNum + 1, AS_INTERFACE)
  1442. && isBraceType(braceTypeStack->back(), NULL_TYPE))
  1443. {
  1444. isInObjCInterface = true;
  1445. string name = '@' + AS_INTERFACE;
  1446. appendSequence(name);
  1447. goForward(name.length() - 1);
  1448. continue;
  1449. }
  1450. else if (currentChar == '@'
  1451. && isCharPotentialHeader(currentLine, charNum + 1)
  1452. && findKeyword(currentLine, charNum + 1, AS_SELECTOR))
  1453. {
  1454. isInObjCSelector = true;
  1455. string name = '@' + AS_SELECTOR;
  1456. appendSequence(name);
  1457. goForward(name.length() - 1);
  1458. continue;
  1459. }
  1460. else if ((currentChar == '-' || currentChar == '+')
  1461. && (int) currentLine.find_first_not_of(" \t") == charNum
  1462. && peekNextChar() == '('
  1463. && isBraceType(braceTypeStack->back(), NULL_TYPE)
  1464. && !isInPotentialCalculation)
  1465. {
  1466. isInObjCMethodDefinition = true;
  1467. isImmediatelyPostObjCMethodPrefix = true;
  1468. isInObjCInterface = false;
  1469. if (getAlignMethodColon())
  1470. objCColonAlign = findObjCColonAlignment();
  1471. appendCurrentChar();
  1472. continue;
  1473. }
  1474. // determine if this is a potential calculation
  1475. bool isPotentialOperator = isCharPotentialOperator(currentChar);
  1476. newHeader = nullptr;
  1477. if (isPotentialOperator)
  1478. {
  1479. newHeader = findOperator(operators);
  1480. // check for Java ? wildcard
  1481. if (newHeader != nullptr
  1482. && newHeader == &AS_GCC_MIN_ASSIGN
  1483. && isJavaStyle()
  1484. && isInTemplate)
  1485. newHeader = nullptr;
  1486. if (newHeader != nullptr)
  1487. {
  1488. if (newHeader == &AS_LAMBDA)
  1489. foundPreCommandHeader = true;
  1490. // correct mistake of two >> closing a template
  1491. if (isInTemplate && (newHeader == &AS_GR_GR || newHeader == &AS_GR_GR_GR))
  1492. newHeader = &AS_GR;
  1493. if (!isInPotentialCalculation)
  1494. {
  1495. // must determine if newHeader is an assignment operator
  1496. // do NOT use findOperator - the length must be exact!!!
  1497. if (find(begin(*assignmentOperators), end(*assignmentOperators), newHeader)
  1498. != end(*assignmentOperators))
  1499. {
  1500. foundPreCommandHeader = false;
  1501. char peekedChar = peekNextChar();
  1502. isInPotentialCalculation = !(newHeader == &AS_EQUAL && peekedChar == '*')
  1503. && !(newHeader == &AS_EQUAL && peekedChar == '&')
  1504. && !isCharImmediatelyPostOperator;
  1505. }
  1506. }
  1507. }
  1508. }
  1509. // process pointers and references
  1510. // check newHeader to eliminate things like '&&' sequence
  1511. if (newHeader != nullptr && !isJavaStyle()
  1512. && (newHeader == &AS_MULT
  1513. || newHeader == &AS_BIT_AND
  1514. || newHeader == &AS_BIT_XOR
  1515. || newHeader == &AS_AND)
  1516. && isPointerOrReference())
  1517. {
  1518. if (!isDereferenceOrAddressOf() && !isOperatorPaddingDisabled())
  1519. formatPointerOrReference();
  1520. else
  1521. {
  1522. appendOperator(*newHeader);
  1523. goForward(newHeader->length() - 1);
  1524. }
  1525. isImmediatelyPostPointerOrReference = true;
  1526. continue;
  1527. }
  1528. if (shouldPadOperators && newHeader != nullptr && !isOperatorPaddingDisabled())
  1529. {
  1530. padOperators(newHeader);
  1531. continue;
  1532. }
  1533. // remove spaces before commas
  1534. if (currentChar == ',')
  1535. {
  1536. const size_t len = formattedLine.length();
  1537. size_t lastText = formattedLine.find_last_not_of(' ');
  1538. if (lastText != string::npos && lastText < len - 1)
  1539. {
  1540. formattedLine.resize(lastText + 1);
  1541. int size_diff = len - (lastText + 1);
  1542. spacePadNum -= size_diff;
  1543. }
  1544. }
  1545. // pad commas and semi-colons
  1546. if (currentChar == ';'
  1547. || (currentChar == ',' && (shouldPadOperators || shouldPadCommas)))
  1548. {
  1549. char nextChar = ' ';
  1550. if (charNum + 1 < (int) currentLine.length())
  1551. nextChar = currentLine[charNum + 1];
  1552. if (!isWhiteSpace(nextChar)
  1553. && nextChar != '}'
  1554. && nextChar != ')'
  1555. && nextChar != ']'
  1556. && nextChar != '>'
  1557. && nextChar != ';'
  1558. && !isBeforeAnyComment()
  1559. /* && !(isBraceType(braceTypeStack->back(), ARRAY_TYPE)) */
  1560. )
  1561. {
  1562. appendCurrentChar();
  1563. appendSpaceAfter();
  1564. continue;
  1565. }
  1566. }
  1567. // pad parens
  1568. if (currentChar == '(' || currentChar == ')')
  1569. {
  1570. if (currentChar == '(')
  1571. {
  1572. if (shouldPadHeader
  1573. && (isCharImmediatelyPostReturn
  1574. || isCharImmediatelyPostThrow
  1575. || isCharImmediatelyPostNewDelete))
  1576. appendSpacePad();
  1577. }
  1578. if (shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen)
  1579. padParens();
  1580. else
  1581. appendCurrentChar();
  1582. if (isInObjCMethodDefinition)
  1583. {
  1584. if (currentChar == '(' && isImmediatelyPostObjCMethodPrefix)
  1585. {
  1586. if (shouldPadMethodPrefix || shouldUnPadMethodPrefix)
  1587. padObjCMethodPrefix();
  1588. isImmediatelyPostObjCMethodPrefix = false;
  1589. isInObjCReturnType = true;
  1590. }
  1591. else if (currentChar == ')' && isInObjCReturnType)
  1592. {
  1593. if (shouldPadReturnType || shouldUnPadReturnType)
  1594. padObjCReturnType();
  1595. isInObjCReturnType = false;
  1596. }
  1597. else if (shouldPadParamType || shouldUnPadParamType)
  1598. padObjCParamType();
  1599. }
  1600. continue;
  1601. }
  1602. // bypass the entire operator
  1603. if (newHeader != nullptr)
  1604. {
  1605. appendOperator(*newHeader);
  1606. goForward(newHeader->length() - 1);
  1607. continue;
  1608. }
  1609. appendCurrentChar();
  1610. } // end of while loop * end of while loop * end of while loop * end of while loop
  1611. // return a beautified (i.e. correctly indented) line.
  1612. string beautifiedLine;
  1613. size_t readyFormattedLineLength = trim(readyFormattedLine).length();
  1614. bool isInNamespace = isBraceType(braceTypeStack->back(), NAMESPACE_TYPE);
  1615. if (prependEmptyLine // prepend a blank line before this formatted line
  1616. && readyFormattedLineLength > 0
  1617. && previousReadyFormattedLineLength > 0)
  1618. {
  1619. isLineReady = true; // signal a waiting readyFormattedLine
  1620. beautifiedLine = beautify("");
  1621. previousReadyFormattedLineLength = 0;
  1622. // call the enhancer for new empty lines
  1623. enhancer->enhance(beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL);
  1624. }
  1625. else // format the current formatted line
  1626. {
  1627. isLineReady = false;
  1628. runInIndentContinuation = runInIndentChars;
  1629. beautifiedLine = beautify(readyFormattedLine);
  1630. previousReadyFormattedLineLength = readyFormattedLineLength;
  1631. // the enhancer is not called for no-indent line comments
  1632. if (!lineCommentNoBeautify && !isFormattingModeOff)
  1633. enhancer->enhance(beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL);
  1634. runInIndentChars = 0;
  1635. lineCommentNoBeautify = lineCommentNoIndent;
  1636. lineCommentNoIndent = false;
  1637. isInIndentablePreproc = isIndentableProprocessor;
  1638. isIndentableProprocessor = false;
  1639. isElseHeaderIndent = elseHeaderFollowsComments;
  1640. isCaseHeaderCommentIndent = caseHeaderFollowsComments;
  1641. objCColonAlignSubsequent = objCColonAlign;
  1642. if (isCharImmediatelyPostNonInStmt)
  1643. {
  1644. isNonInStatementArray = false;
  1645. isCharImmediatelyPostNonInStmt = false;
  1646. }
  1647. isInPreprocessorBeautify = isInPreprocessor; // used by ASEnhancer
  1648. isInBeautifySQL = isInExecSQL; // used by ASEnhancer
  1649. }
  1650. prependEmptyLine = false;
  1651. assert(computeChecksumOut(beautifiedLine));
  1652. return beautifiedLine;
  1653. }
  1654. /**
  1655. * check if there are any indented lines ready to be read by nextLine()
  1656. *
  1657. * @return are there any indented lines ready?
  1658. */
  1659. bool ASFormatter::hasMoreLines() const
  1660. {
  1661. return !endOfCodeReached;
  1662. }
  1663. /**
  1664. * comparison function for BraceType enum
  1665. */
  1666. bool ASFormatter::isBraceType(BraceType a, BraceType b) const
  1667. {
  1668. if (a == NULL_TYPE || b == NULL_TYPE)
  1669. return (a == b);
  1670. return ((a & b) == b);
  1671. }
  1672. /**
  1673. * set the formatting style.
  1674. *
  1675. * @param style the formatting style.
  1676. */
  1677. void ASFormatter::setFormattingStyle(FormatStyle style)
  1678. {
  1679. formattingStyle = style;
  1680. }
  1681. /**
  1682. * set the add braces mode.
  1683. * options:
  1684. * true braces added to headers for single line statements.
  1685. * false braces NOT added to headers for single line statements.
  1686. *
  1687. * @param state the add braces state.
  1688. */
  1689. void ASFormatter::setAddBracesMode(bool state)
  1690. {
  1691. shouldAddBraces = state;
  1692. }
  1693. /**
  1694. * set the add one line braces mode.
  1695. * options:
  1696. * true one line braces added to headers for single line statements.
  1697. * false one line braces NOT added to headers for single line statements.
  1698. *
  1699. * @param state the add one line braces state.
  1700. */
  1701. void ASFormatter::setAddOneLineBracesMode(bool state)
  1702. {
  1703. shouldAddBraces = state;
  1704. shouldAddOneLineBraces = state;
  1705. }
  1706. /**
  1707. * set the remove braces mode.
  1708. * options:
  1709. * true braces removed from headers for single line statements.
  1710. * false braces NOT removed from headers for single line statements.
  1711. *
  1712. * @param state the remove braces state.
  1713. */
  1714. void ASFormatter::setRemoveBracesMode(bool state)
  1715. {
  1716. shouldRemoveBraces = state;
  1717. }
  1718. // retained for compatability with release 2.06
  1719. // "Brackets" have been changed to "Braces" in 3.0
  1720. // it is referenced only by the old "bracket" options
  1721. void ASFormatter::setAddBracketsMode(bool state)
  1722. {
  1723. setAddBracesMode(state);
  1724. }
  1725. // retained for compatability with release 2.06
  1726. // "Brackets" have been changed to "Braces" in 3.0
  1727. // it is referenced only by the old "bracket" options
  1728. void ASFormatter::setAddOneLineBracketsMode(bool state)
  1729. {
  1730. setAddOneLineBracesMode(state);
  1731. }
  1732. // retained for compatability with release 2.06
  1733. // "Brackets" have been changed to "Braces" in 3.0
  1734. // it is referenced only by the old "bracket" options
  1735. void ASFormatter::setRemoveBracketsMode(bool state)
  1736. {
  1737. setRemoveBracesMode(state);
  1738. }
  1739. // retained for compatability with release 2.06
  1740. // "Brackets" have been changed to "Braces" in 3.0
  1741. // it is referenced only by the old "bracket" options
  1742. void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
  1743. {
  1744. setBreakClosingHeaderBracesMode(state);
  1745. }
  1746. /**
  1747. * set the brace formatting mode.
  1748. * options:
  1749. *
  1750. * @param mode the brace formatting mode.
  1751. */
  1752. void ASFormatter::setBraceFormatMode(BraceMode mode)
  1753. {
  1754. braceFormatMode = mode;
  1755. }
  1756. /**
  1757. * set 'break after' mode for maximum code length
  1758. *
  1759. * @param state the 'break after' mode.
  1760. */
  1761. void ASFormatter::setBreakAfterMode(bool state)
  1762. {
  1763. shouldBreakLineAfterLogical = state;
  1764. }
  1765. /**
  1766. * set closing header brace breaking mode
  1767. * options:
  1768. * true braces just before closing headers (e.g. 'else', 'catch')
  1769. * will be broken, even if standard braces are attached.
  1770. * false closing header braces will be treated as standard braces.
  1771. *
  1772. * @param state the closing header brace breaking mode.
  1773. */
  1774. void ASFormatter::setBreakClosingHeaderBracesMode(bool state)
  1775. {
  1776. shouldBreakClosingHeaderBraces = state;
  1777. }
  1778. /**
  1779. * set 'else if()' breaking mode
  1780. * options:
  1781. * true 'else' headers will be broken from their succeeding 'if' headers.
  1782. * false 'else' headers will be attached to their succeeding 'if' headers.
  1783. *
  1784. * @param state the 'else if()' breaking mode.
  1785. */
  1786. void ASFormatter::setBreakElseIfsMode(bool state)
  1787. {
  1788. shouldBreakElseIfs = state;
  1789. }
  1790. /**
  1791. * set comma padding mode.
  1792. * options:
  1793. * true statement commas and semicolons will be padded with spaces around them.
  1794. * false statement commas and semicolons will not be padded.
  1795. *
  1796. * @param state the padding mode.
  1797. */
  1798. void ASFormatter::setCommaPaddingMode(bool state)
  1799. {
  1800. shouldPadCommas = state;
  1801. }
  1802. /**
  1803. * set maximum code length
  1804. *
  1805. * @param max the maximum code length.
  1806. */
  1807. void ASFormatter::setMaxCodeLength(int max)
  1808. {
  1809. maxCodeLength = max;
  1810. }
  1811. /**
  1812. * set operator padding mode.
  1813. * options:
  1814. * true statement operators will be padded with spaces around them.
  1815. * false statement operators will not be padded.
  1816. *
  1817. * @param state the padding mode.
  1818. */
  1819. void ASFormatter::setOperatorPaddingMode(bool state)
  1820. {
  1821. shouldPadOperators = state;
  1822. }
  1823. /**
  1824. * set parenthesis outside padding mode.
  1825. * options:
  1826. * true statement parentheses will be padded with spaces around them.
  1827. * false statement parentheses will not be padded.
  1828. *
  1829. * @param state the padding mode.
  1830. */
  1831. void ASFormatter::setParensOutsidePaddingMode(bool state)
  1832. {
  1833. shouldPadParensOutside = state;
  1834. }
  1835. /**
  1836. * set parenthesis inside padding mode.
  1837. * options:
  1838. * true statement parenthesis will be padded with spaces around them.
  1839. * false statement parenthesis will not be padded.
  1840. *
  1841. * @param state the padding mode.
  1842. */
  1843. void ASFormatter::setParensInsidePaddingMode(bool state)
  1844. {
  1845. shouldPadParensInside = state;
  1846. }
  1847. /**
  1848. * set padding mode before one or more open parentheses.
  1849. * options:
  1850. * true first open parenthesis will be padded with a space before.
  1851. * false first open parenthesis will not be padded.
  1852. *
  1853. * @param state the padding mode.
  1854. */
  1855. void ASFormatter::setParensFirstPaddingMode(bool state)
  1856. {
  1857. shouldPadFirstParen = state;
  1858. }
  1859. /**
  1860. * set header padding mode.
  1861. * options:
  1862. * true headers will be padded with spaces around them.
  1863. * false headers will not be padded.
  1864. *
  1865. * @param state the padding mode.
  1866. */
  1867. void ASFormatter::setParensHeaderPaddingMode(bool state)
  1868. {
  1869. shouldPadHeader = state;
  1870. }
  1871. /**
  1872. * set parenthesis unpadding mode.
  1873. * options:
  1874. * true statement parenthesis will be unpadded with spaces removed around them.
  1875. * false statement parenthesis will not be unpadded.
  1876. *
  1877. * @param state the padding mode.
  1878. */
  1879. void ASFormatter::setParensUnPaddingMode(bool state)
  1880. {
  1881. shouldUnPadParens = state;
  1882. }
  1883. /**
  1884. * set the state of the preprocessor indentation option.
  1885. * If true, #ifdef blocks at level 0 will be indented.
  1886. *
  1887. * @param state state of option.
  1888. */
  1889. void ASFormatter::setPreprocBlockIndent(bool state)
  1890. {
  1891. shouldIndentPreprocBlock = state;
  1892. }
  1893. /**
  1894. * Set strip comment prefix mode.
  1895. * options:
  1896. * true strip leading '*' in a comment.
  1897. * false leading '*' in a comment will be left unchanged.
  1898. *
  1899. * @param state the strip comment prefix mode.
  1900. */
  1901. void ASFormatter::setStripCommentPrefix(bool state)
  1902. {
  1903. shouldStripCommentPrefix = state;
  1904. }
  1905. /**
  1906. * set objective-c '-' or '+' class prefix padding mode.
  1907. * options:
  1908. * true class prefix will be padded a spaces after them.
  1909. * false class prefix will be left unchanged.
  1910. *
  1911. * @param state the padding mode.
  1912. */
  1913. void ASFormatter::setMethodPrefixPaddingMode(bool state)
  1914. {
  1915. shouldPadMethodPrefix = state;
  1916. }
  1917. /**
  1918. * set objective-c '-' or '+' class prefix unpadding mode.
  1919. * options:
  1920. * true class prefix will be unpadded with spaces after them removed.
  1921. * false class prefix will left unchanged.
  1922. *
  1923. * @param state the unpadding mode.
  1924. */
  1925. void ASFormatter::setMethodPrefixUnPaddingMode(bool state)
  1926. {
  1927. shouldUnPadMethodPrefix = state;
  1928. }
  1929. // set objective-c '-' or '+' return type padding mode.
  1930. void ASFormatter::setReturnTypePaddingMode(bool state)
  1931. {
  1932. shouldPadReturnType = state;
  1933. }
  1934. // set objective-c '-' or '+' return type unpadding mode.
  1935. void ASFormatter::setReturnTypeUnPaddingMode(bool state)
  1936. {
  1937. shouldUnPadReturnType = state;
  1938. }
  1939. // set objective-c method parameter type padding mode.
  1940. void ASFormatter::setParamTypePaddingMode(bool state)
  1941. {
  1942. shouldPadParamType = state;
  1943. }
  1944. // set objective-c method parameter type unpadding mode.
  1945. void ASFormatter::setParamTypeUnPaddingMode(bool state)
  1946. {
  1947. shouldUnPadParamType = state;
  1948. }
  1949. /**
  1950. * set objective-c method colon padding mode.
  1951. *
  1952. * @param mode objective-c colon padding mode.
  1953. */
  1954. void ASFormatter::setObjCColonPaddingMode(ObjCColonPad mode)
  1955. {
  1956. shouldPadMethodColon = true;
  1957. objCColonPadMode = mode;
  1958. }
  1959. /**
  1960. * set option to attach closing braces
  1961. *
  1962. * @param state true = attach, false = don't attach.
  1963. */
  1964. void ASFormatter::setAttachClosingBraceMode(bool state)
  1965. {
  1966. attachClosingBraceMode = state;
  1967. }
  1968. /**
  1969. * set option to attach class braces
  1970. *
  1971. * @param state true = attach, false = use style default.
  1972. */
  1973. void ASFormatter::setAttachClass(bool state)
  1974. {
  1975. shouldAttachClass = state;
  1976. }
  1977. /**
  1978. * set option to attach extern "C" braces
  1979. *
  1980. * @param state true = attach, false = use style default.
  1981. */
  1982. void ASFormatter::setAttachExternC(bool state)
  1983. {
  1984. shouldAttachExternC = state;
  1985. }
  1986. /**
  1987. * set option to attach namespace braces
  1988. *
  1989. * @param state true = attach, false = use style default.
  1990. */
  1991. void ASFormatter::setAttachNamespace(bool state)
  1992. {
  1993. shouldAttachNamespace = state;
  1994. }
  1995. /**
  1996. * set option to attach inline braces
  1997. *
  1998. * @param state true = attach, false = use style default.
  1999. */
  2000. void ASFormatter::setAttachInline(bool state)
  2001. {
  2002. shouldAttachInline = state;
  2003. }
  2004. void ASFormatter::setAttachClosingWhile(bool state)
  2005. {
  2006. shouldAttachClosingWhile = state;
  2007. }
  2008. /**
  2009. * set option to break/not break one-line blocks
  2010. *
  2011. * @param state true = break, false = don't break.
  2012. */
  2013. void ASFormatter::setBreakOneLineBlocksMode(bool state)
  2014. {
  2015. shouldBreakOneLineBlocks = state;
  2016. }
  2017. /**
  2018. * set one line headers breaking mode
  2019. */
  2020. void ASFormatter::setBreakOneLineHeadersMode(bool state)
  2021. {
  2022. shouldBreakOneLineHeaders = state;
  2023. }
  2024. /**
  2025. * set option to break/not break lines consisting of multiple statements.
  2026. *
  2027. * @param state true = break, false = don't break.
  2028. */
  2029. void ASFormatter::setBreakOneLineStatementsMode(bool state)
  2030. {
  2031. shouldBreakOneLineStatements = state;
  2032. }
  2033. void ASFormatter::setCloseTemplatesMode(bool state)
  2034. {
  2035. shouldCloseTemplates = state;
  2036. }
  2037. /**
  2038. * set option to convert tabs to spaces.
  2039. *
  2040. * @param state true = convert, false = don't convert.
  2041. */
  2042. void ASFormatter::setTabSpaceConversionMode(bool state)
  2043. {
  2044. shouldConvertTabs = state;
  2045. }
  2046. /**
  2047. * set option to indent comments in column 1.
  2048. *
  2049. * @param state true = indent, false = don't indent.
  2050. */
  2051. void ASFormatter::setIndentCol1CommentsMode(bool state)
  2052. {
  2053. shouldIndentCol1Comments = state;
  2054. }
  2055. /**
  2056. * set option to force all line ends to a particular style.
  2057. *
  2058. * @param fmt format enum value
  2059. */
  2060. void ASFormatter::setLineEndFormat(LineEndFormat fmt)
  2061. {
  2062. lineEnd = fmt;
  2063. }
  2064. /**
  2065. * set option to break unrelated blocks of code with empty lines.
  2066. *
  2067. * @param state true = convert, false = don't convert.
  2068. */
  2069. void ASFormatter::setBreakBlocksMode(bool state)
  2070. {
  2071. shouldBreakBlocks = state;
  2072. }
  2073. /**
  2074. * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines.
  2075. *
  2076. * @param state true = convert, false = don't convert.
  2077. */
  2078. void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
  2079. {
  2080. shouldBreakClosingHeaderBlocks = state;
  2081. }
  2082. /**
  2083. * set option to delete empty lines.
  2084. *
  2085. * @param state true = delete, false = don't delete.
  2086. */
  2087. void ASFormatter::setDeleteEmptyLinesMode(bool state)
  2088. {
  2089. shouldDeleteEmptyLines = state;
  2090. }
  2091. /**
  2092. * set the pointer alignment.
  2093. *
  2094. * @param alignment the pointer alignment.
  2095. */
  2096. void ASFormatter::setPointerAlignment(PointerAlign alignment)
  2097. {
  2098. pointerAlignment = alignment;
  2099. }
  2100. void ASFormatter::setReferenceAlignment(ReferenceAlign alignment)
  2101. {
  2102. referenceAlignment = alignment;
  2103. }
  2104. /**
  2105. * jump over several characters.
  2106. *
  2107. * @param i the number of characters to jump over.
  2108. */
  2109. void ASFormatter::goForward(int i)
  2110. {
  2111. while (--i >= 0)
  2112. getNextChar();
  2113. }
  2114. /**
  2115. * peek at the next unread character.
  2116. *
  2117. * @return the next unread character.
  2118. */
  2119. char ASFormatter::peekNextChar() const
  2120. {
  2121. char ch = ' ';
  2122. size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
  2123. if (peekNum == string::npos)
  2124. return ch;
  2125. ch = currentLine[peekNum];
  2126. return ch;
  2127. }
  2128. /**
  2129. * check if current placement is before a comment
  2130. *
  2131. * @return is before a comment.
  2132. */
  2133. bool ASFormatter::isBeforeComment() const
  2134. {
  2135. bool foundComment = false;
  2136. size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
  2137. if (peekNum == string::npos)
  2138. return foundComment;
  2139. foundComment = (currentLine.compare(peekNum, 2, "/*") == 0);
  2140. return foundComment;
  2141. }
  2142. /**
  2143. * check if current placement is before a comment or line-comment
  2144. *
  2145. * @return is before a comment or line-comment.
  2146. */
  2147. bool ASFormatter::isBeforeAnyComment() const
  2148. {
  2149. bool foundComment = false;
  2150. size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
  2151. if (peekNum == string::npos)
  2152. return foundComment;
  2153. foundComment = (currentLine.compare(peekNum, 2, "/*") == 0
  2154. || currentLine.compare(peekNum, 2, "//") == 0);
  2155. return foundComment;
  2156. }
  2157. /**
  2158. * check if current placement is before a comment or line-comment
  2159. * if a block comment it must be at the end of the line
  2160. *
  2161. * @return is before a comment or line-comment.
  2162. */
  2163. bool ASFormatter::isBeforeAnyLineEndComment(int startPos) const
  2164. {
  2165. bool foundLineEndComment = false;
  2166. size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
  2167. if (peekNum != string::npos)
  2168. {
  2169. if (currentLine.compare(peekNum, 2, "//") == 0)
  2170. foundLineEndComment = true;
  2171. else if (currentLine.compare(peekNum, 2, "/*") == 0)
  2172. {
  2173. // comment must be closed on this line with nothing after it
  2174. size_t endNum = currentLine.find("*/", peekNum + 2);
  2175. if (endNum != string::npos)
  2176. {
  2177. size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2);
  2178. if (nextChar == string::npos)
  2179. foundLineEndComment = true;
  2180. }
  2181. }
  2182. }
  2183. return foundLineEndComment;
  2184. }
  2185. /**
  2186. * check if current placement is before a comment followed by a line-comment
  2187. *
  2188. * @return is before a multiple line-end comment.
  2189. */
  2190. bool ASFormatter::isBeforeMultipleLineEndComments(int startPos) const
  2191. {
  2192. bool foundMultipleLineEndComment = false;
  2193. size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
  2194. if (peekNum != string::npos)
  2195. {
  2196. if (currentLine.compare(peekNum, 2, "/*") == 0)
  2197. {
  2198. // comment must be closed on this line with nothing after it
  2199. size_t endNum = currentLine.find("*/", peekNum + 2);
  2200. if (endNum != string::npos)
  2201. {
  2202. size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2);
  2203. if (nextChar != string::npos
  2204. && currentLine.compare(nextChar, 2, "//") == 0)
  2205. foundMultipleLineEndComment = true;
  2206. }
  2207. }
  2208. }
  2209. return foundMultipleLineEndComment;
  2210. }
  2211. /**
  2212. * get the next character, increasing the current placement in the process.
  2213. * the new character is inserted into the variable currentChar.
  2214. *
  2215. * @return whether succeeded to receive the new character.
  2216. */
  2217. bool ASFormatter::getNextChar()
  2218. {
  2219. isInLineBreak = false;
  2220. previousChar = currentChar;
  2221. if (!isWhiteSpace(currentChar))
  2222. {
  2223. previousNonWSChar = currentChar;
  2224. if (!isInComment && !isInLineComment && !isInQuote
  2225. && !isImmediatelyPostComment
  2226. && !isImmediatelyPostLineComment
  2227. && !isInPreprocessor
  2228. && !isSequenceReached("/*")
  2229. && !isSequenceReached("//"))
  2230. previousCommandChar = currentChar;
  2231. }
  2232. if (charNum + 1 < (int) currentLine.length()
  2233. && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
  2234. {
  2235. currentChar = currentLine[++charNum];
  2236. if (currentChar == '\t' && shouldConvertTabs)
  2237. convertTabToSpaces();
  2238. return true;
  2239. }
  2240. // end of line has been reached
  2241. return getNextLine();
  2242. }
  2243. /**
  2244. * get the next line of input, increasing the current placement in the process.
  2245. *
  2246. * @param emptyLineWasDeleted an empty line was deleted.
  2247. * @return whether succeeded in reading the next line.
  2248. */
  2249. bool ASFormatter::getNextLine(bool emptyLineWasDeleted /*false*/)
  2250. {
  2251. if (!sourceIterator->hasMoreLines())
  2252. {
  2253. endOfCodeReached = true;
  2254. return false;
  2255. }
  2256. if (appendOpeningBrace)
  2257. currentLine = "{"; // append brace that was removed from the previous line
  2258. else
  2259. {
  2260. currentLine = sourceIterator->nextLine(emptyLineWasDeleted);
  2261. assert(computeChecksumIn(currentLine));
  2262. }
  2263. // reset variables for new line
  2264. inLineNumber++;
  2265. if (endOfAsmReached)
  2266. endOfAsmReached = isInAsmBlock = isInAsm = false;
  2267. shouldKeepLineUnbroken = false;
  2268. isInCommentStartLine = false;
  2269. isInCase = false;
  2270. isInAsmOneLine = false;
  2271. isHeaderInMultiStatementLine = false;
  2272. isInQuoteContinuation = isInVerbatimQuote || haveLineContinuationChar;
  2273. haveLineContinuationChar = false;
  2274. isImmediatelyPostEmptyLine = lineIsEmpty;
  2275. previousChar = ' ';
  2276. if (currentLine.length() == 0)
  2277. currentLine = string(" "); // a null is inserted if this is not done
  2278. // unless reading in the first line of the file, break a new line.
  2279. if (!isVirgin)
  2280. isInLineBreak = true;
  2281. else
  2282. isVirgin = false;
  2283. if (isImmediatelyPostNonInStmt)
  2284. {
  2285. isCharImmediatelyPostNonInStmt = true;
  2286. isImmediatelyPostNonInStmt = false;
  2287. }
  2288. // check if is in preprocessor before line trimming
  2289. // a blank line after a \ will remove the flag
  2290. isImmediatelyPostPreprocessor = isInPreprocessor;
  2291. if (!isInComment
  2292. && (previousNonWSChar != '\\'
  2293. || isEmptyLine(currentLine)))
  2294. isInPreprocessor = false;
  2295. if (passedSemicolon)
  2296. isInExecSQL = false;
  2297. initNewLine();
  2298. currentChar = currentLine[charNum];
  2299. if (isInBraceRunIn && previousNonWSChar == '{' && !isInComment)
  2300. isInLineBreak = false;
  2301. isInBraceRunIn = false;
  2302. if (currentChar == '\t' && shouldConvertTabs)
  2303. convertTabToSpaces();
  2304. // check for an empty line inside a command brace.
  2305. // if yes then read the next line (calls getNextLine recursively).
  2306. // must be after initNewLine.
  2307. if (shouldDeleteEmptyLines
  2308. && lineIsEmpty
  2309. && isBraceType((*braceTypeStack)[braceTypeStack->size() - 1], COMMAND_TYPE))
  2310. {
  2311. if (!shouldBreakBlocks || previousNonWSChar == '{' || !commentAndHeaderFollows())
  2312. {
  2313. isInPreprocessor = isImmediatelyPostPreprocessor; // restore
  2314. lineIsEmpty = false;
  2315. return getNextLine(true);
  2316. }
  2317. }
  2318. return true;
  2319. }
  2320. /**
  2321. * jump over the leading white space in the current line,
  2322. * IF the line does not begin a comment or is in a preprocessor definition.
  2323. */
  2324. void ASFormatter::initNewLine()
  2325. {
  2326. size_t len = currentLine.length();
  2327. size_t tabSize = getTabLength();
  2328. charNum = 0;
  2329. // don't trim these
  2330. if (isInQuoteContinuation
  2331. || (isInPreprocessor && !getPreprocDefineIndent()))
  2332. return;
  2333. // SQL continuation lines must be adjusted so the leading spaces
  2334. // is equivalent to the opening EXEC SQL
  2335. if (isInExecSQL)
  2336. {
  2337. // replace leading tabs with spaces
  2338. // so that continuation indent will be spaces
  2339. size_t tabCount_ = 0;
  2340. size_t i;
  2341. for (i = 0; i < currentLine.length(); i++)
  2342. {
  2343. if (!isWhiteSpace(currentLine[i])) // stop at first text
  2344. break;
  2345. if (currentLine[i] == '\t')
  2346. {
  2347. size_t numSpaces = tabSize - ((tabCount_ + i) % tabSize);
  2348. currentLine.replace(i, 1, numSpaces, ' ');
  2349. tabCount_++;
  2350. i += tabSize - 1;
  2351. }
  2352. }
  2353. // this will correct the format if EXEC SQL is not a hanging indent
  2354. trimContinuationLine();
  2355. return;
  2356. }
  2357. // comment continuation lines must be adjusted so the leading spaces
  2358. // is equivalent to the opening comment
  2359. if (isInComment)
  2360. {
  2361. if (noTrimCommentContinuation)
  2362. leadingSpaces = tabIncrementIn = 0;
  2363. trimContinuationLine();
  2364. return;
  2365. }
  2366. // compute leading spaces
  2367. isImmediatelyPostCommentOnly = lineIsLineCommentOnly || lineEndsInCommentOnly;
  2368. lineIsCommentOnly = false;
  2369. lineIsLineCommentOnly = false;
  2370. lineEndsInCommentOnly = false;
  2371. doesLineStartComment = false;
  2372. currentLineBeginsWithBrace = false;
  2373. lineIsEmpty = false;
  2374. currentLineFirstBraceNum = string::npos;
  2375. tabIncrementIn = 0;
  2376. // bypass whitespace at the start of a line
  2377. // preprocessor tabs are replaced later in the program
  2378. for (charNum = 0; isWhiteSpace(currentLine[charNum]) && charNum + 1 < (int) len; charNum++)
  2379. {
  2380. if (currentLine[charNum] == '\t' && !isInPreprocessor)
  2381. tabIncrementIn += tabSize - 1 - ((tabIncrementIn + charNum) % tabSize);
  2382. }
  2383. leadingSpaces = charNum + tabIncrementIn;
  2384. if (isSequenceReached("/*"))
  2385. {
  2386. doesLineStartComment = true;
  2387. if ((int) currentLine.length() > charNum + 2
  2388. && currentLine.find("*/", charNum + 2) != string::npos)
  2389. lineIsCommentOnly = true;
  2390. }
  2391. else if (isSequenceReached("//"))
  2392. {
  2393. lineIsLineCommentOnly = true;
  2394. }
  2395. else if (isSequenceReached("{"))
  2396. {
  2397. currentLineBeginsWithBrace = true;
  2398. currentLineFirstBraceNum = charNum;
  2399. size_t firstText = currentLine.find_first_not_of(" \t", charNum + 1);
  2400. if (firstText != string::npos)
  2401. {
  2402. if (currentLine.compare(firstText, 2, "//") == 0)
  2403. lineIsLineCommentOnly = true;
  2404. else if (currentLine.compare(firstText, 2, "/*") == 0
  2405. || isExecSQL(currentLine, firstText))
  2406. {
  2407. // get the extra adjustment
  2408. size_t j;
  2409. for (j = charNum + 1; j < firstText && isWhiteSpace(currentLine[j]); j++)
  2410. {
  2411. if (currentLine[j] == '\t')
  2412. tabIncrementIn += tabSize - 1 - ((tabIncrementIn + j) % tabSize);
  2413. }
  2414. leadingSpaces = j + tabIncrementIn;
  2415. if (currentLine.compare(firstText, 2, "/*") == 0)
  2416. doesLineStartComment = true;
  2417. }
  2418. }
  2419. }
  2420. else if (isWhiteSpace(currentLine[charNum]) && !(charNum + 1 < (int) currentLine.length()))
  2421. {
  2422. lineIsEmpty = true;
  2423. }
  2424. // do not trim indented preprocessor define (except for comment continuation lines)
  2425. if (isInPreprocessor)
  2426. {
  2427. if (!doesLineStartComment)
  2428. leadingSpaces = 0;
  2429. charNum = 0;
  2430. }
  2431. }
  2432. /**
  2433. * Append a character to the current formatted line.
  2434. * The formattedLine split points are updated.
  2435. *
  2436. * @param ch the character to append.
  2437. * @param canBreakLine if true, a registered line-break
  2438. */
  2439. void ASFormatter::appendChar(char ch, bool canBreakLine)
  2440. {
  2441. if (canBreakLine && isInLineBreak)
  2442. breakLine();
  2443. formattedLine.append(1, ch);
  2444. isImmediatelyPostCommentOnly = false;
  2445. if (maxCodeLength != string::npos)
  2446. {
  2447. // These compares reduce the frequency of function calls.
  2448. if (isOkToSplitFormattedLine())
  2449. updateFormattedLineSplitPoints(ch);
  2450. if (formattedLine.length() > maxCodeLength)
  2451. testForTimeToSplitFormattedLine();
  2452. }
  2453. }
  2454. /**
  2455. * Append a string sequence to the current formatted line.
  2456. * The formattedLine split points are NOT updated.
  2457. * But the formattedLine is checked for time to split.
  2458. *
  2459. * @param sequence the sequence to append.
  2460. * @param canBreakLine if true, a registered line-break
  2461. */
  2462. void ASFormatter::appendSequence(const string& sequence, bool canBreakLine)
  2463. {
  2464. if (canBreakLine && isInLineBreak)
  2465. breakLine();
  2466. formattedLine.append(sequence);
  2467. if (formattedLine.length() > maxCodeLength)
  2468. testForTimeToSplitFormattedLine();
  2469. }
  2470. /**
  2471. * Append an operator sequence to the current formatted line.
  2472. * The formattedLine split points are updated.
  2473. *
  2474. * @param sequence the sequence to append.
  2475. * @param canBreakLine if true, a registered line-break
  2476. */
  2477. void ASFormatter::appendOperator(const string& sequence, bool canBreakLine)
  2478. {
  2479. if (canBreakLine && isInLineBreak)
  2480. breakLine();
  2481. formattedLine.append(sequence);
  2482. if (maxCodeLength != string::npos)
  2483. {
  2484. // These compares reduce the frequency of function calls.
  2485. if (isOkToSplitFormattedLine())
  2486. updateFormattedLineSplitPointsOperator(sequence);
  2487. if (formattedLine.length() > maxCodeLength)
  2488. testForTimeToSplitFormattedLine();
  2489. }
  2490. }
  2491. /**
  2492. * append a space to the current formattedline, UNLESS the
  2493. * last character is already a white-space character.
  2494. */
  2495. void ASFormatter::appendSpacePad()
  2496. {
  2497. int len = formattedLine.length();
  2498. if (len > 0 && !isWhiteSpace(formattedLine[len - 1]))
  2499. {
  2500. formattedLine.append(1, ' ');
  2501. spacePadNum++;
  2502. if (maxCodeLength != string::npos)
  2503. {
  2504. // These compares reduce the frequency of function calls.
  2505. if (isOkToSplitFormattedLine())
  2506. updateFormattedLineSplitPoints(' ');
  2507. if (formattedLine.length() > maxCodeLength)
  2508. testForTimeToSplitFormattedLine();
  2509. }
  2510. }
  2511. }
  2512. /**
  2513. * append a space to the current formattedline, UNLESS the
  2514. * next character is already a white-space character.
  2515. */
  2516. void ASFormatter::appendSpaceAfter()
  2517. {
  2518. int len = currentLine.length();
  2519. if (charNum + 1 < len && !isWhiteSpace(currentLine[charNum + 1]))
  2520. {
  2521. formattedLine.append(1, ' ');
  2522. spacePadNum++;
  2523. if (maxCodeLength != string::npos)
  2524. {
  2525. // These compares reduce the frequency of function calls.
  2526. if (isOkToSplitFormattedLine())
  2527. updateFormattedLineSplitPoints(' ');
  2528. if (formattedLine.length() > maxCodeLength)
  2529. testForTimeToSplitFormattedLine();
  2530. }
  2531. }
  2532. }
  2533. /**
  2534. * register a line break for the formatted line.
  2535. */
  2536. void ASFormatter::breakLine(bool isSplitLine /*false*/)
  2537. {
  2538. isLineReady = true;
  2539. isInLineBreak = false;
  2540. spacePadNum = nextLineSpacePadNum;
  2541. nextLineSpacePadNum = 0;
  2542. readyFormattedLine = formattedLine;
  2543. formattedLine.erase();
  2544. // queue an empty line prepend request if one exists
  2545. prependEmptyLine = isPrependPostBlockEmptyLineRequested;
  2546. if (!isSplitLine)
  2547. {
  2548. formattedLineCommentNum = string::npos;
  2549. clearFormattedLineSplitPoints();
  2550. if (isAppendPostBlockEmptyLineRequested)
  2551. {
  2552. isAppendPostBlockEmptyLineRequested = false;
  2553. isPrependPostBlockEmptyLineRequested = true;
  2554. }
  2555. else
  2556. isPrependPostBlockEmptyLineRequested = false;
  2557. }
  2558. }
  2559. /**
  2560. * check if the currently reached open-brace (i.e. '{')
  2561. * opens a:
  2562. * - a definition type block (such as a class or namespace),
  2563. * - a command block (such as a method block)
  2564. * - a static array
  2565. * this method takes for granted that the current character
  2566. * is an opening brace.
  2567. *
  2568. * @return the type of the opened block.
  2569. */
  2570. BraceType ASFormatter::getBraceType()
  2571. {
  2572. assert(currentChar == '{');
  2573. BraceType returnVal = NULL_TYPE;
  2574. if ((previousNonWSChar == '='
  2575. || isBraceType(braceTypeStack->back(), ARRAY_TYPE))
  2576. && previousCommandChar != ')'
  2577. && !isNonParenHeader)
  2578. returnVal = ARRAY_TYPE;
  2579. else if (foundPreDefinitionHeader && previousCommandChar != ')')
  2580. {
  2581. returnVal = DEFINITION_TYPE;
  2582. if (foundNamespaceHeader)
  2583. returnVal = (BraceType)(returnVal | NAMESPACE_TYPE);
  2584. else if (foundClassHeader)
  2585. returnVal = (BraceType)(returnVal | CLASS_TYPE);
  2586. else if (foundStructHeader)
  2587. returnVal = (BraceType)(returnVal | STRUCT_TYPE);
  2588. else if (foundInterfaceHeader)
  2589. returnVal = (BraceType)(returnVal | INTERFACE_TYPE);
  2590. }
  2591. else if (isInEnum)
  2592. {
  2593. returnVal = (BraceType)(ARRAY_TYPE | ENUM_TYPE);
  2594. }
  2595. else
  2596. {
  2597. bool isCommandType = (foundPreCommandHeader
  2598. || foundPreCommandMacro
  2599. || (currentHeader != nullptr && isNonParenHeader)
  2600. || (previousCommandChar == ')')
  2601. || (previousCommandChar == ':' && !foundQuestionMark)
  2602. || (previousCommandChar == ';')
  2603. || ((previousCommandChar == '{' || previousCommandChar == '}')
  2604. && isPreviousBraceBlockRelated)
  2605. || (isInClassInitializer
  2606. && (!isLegalNameChar(previousNonWSChar) || foundPreCommandHeader))
  2607. || foundTrailingReturnType
  2608. || isInObjCMethodDefinition
  2609. || isInObjCInterface
  2610. || isJavaStaticConstructor
  2611. || isSharpDelegate);
  2612. // C# methods containing 'get', 'set', 'add', and 'remove' do NOT end with parens
  2613. if (!isCommandType && isSharpStyle() && isNextWordSharpNonParenHeader(charNum + 1))
  2614. {
  2615. isCommandType = true;
  2616. isSharpAccessor = true;
  2617. }
  2618. if (isInExternC)
  2619. returnVal = (isCommandType ? COMMAND_TYPE : EXTERN_TYPE);
  2620. else
  2621. returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
  2622. }
  2623. int foundOneLineBlock = isOneLineBlockReached(currentLine, charNum);
  2624. if (foundOneLineBlock == 2 && returnVal == COMMAND_TYPE)
  2625. returnVal = ARRAY_TYPE;
  2626. if (foundOneLineBlock > 0)
  2627. {
  2628. returnVal = (BraceType) (returnVal | SINGLE_LINE_TYPE);
  2629. if (breakCurrentOneLineBlock)
  2630. returnVal = (BraceType) (returnVal | BREAK_BLOCK_TYPE);
  2631. if (foundOneLineBlock == 3)
  2632. returnVal = (BraceType)(returnVal | EMPTY_BLOCK_TYPE);
  2633. }
  2634. if (isBraceType(returnVal, ARRAY_TYPE))
  2635. {
  2636. if (isNonInStatementArrayBrace())
  2637. {
  2638. returnVal = (BraceType)(returnVal | ARRAY_NIS_TYPE);
  2639. isNonInStatementArray = true;
  2640. isImmediatelyPostNonInStmt = false; // in case of "},{"
  2641. nonInStatementBrace = formattedLine.length() - 1;
  2642. }
  2643. if (isUniformInitializerBrace())
  2644. returnVal = (BraceType)(returnVal | INIT_TYPE);
  2645. }
  2646. return returnVal;
  2647. }
  2648. /**
  2649. * check if a colon is a class initializer separator
  2650. *
  2651. * @return whether it is a class initializer separator
  2652. */
  2653. bool ASFormatter::isClassInitializer() const
  2654. {
  2655. assert(currentChar == ':');
  2656. assert(previousChar != ':' && peekNextChar() != ':'); // not part of '::'
  2657. // this should be similar to ASBeautifier::parseCurrentLine()
  2658. bool foundClassInitializer = false;
  2659. if (foundQuestionMark)
  2660. {
  2661. // do nothing special
  2662. }
  2663. else if (parenStack->back() > 0)
  2664. {
  2665. // found a 'for' loop or an objective-C statement
  2666. // so do nothing special
  2667. }
  2668. else if (isInEnum)
  2669. {
  2670. // found an enum with a base-type
  2671. }
  2672. else if (isCStyle()
  2673. && !isInCase
  2674. && (previousCommandChar == ')' || foundPreCommandHeader))
  2675. {
  2676. // found a 'class' c'tor initializer
  2677. foundClassInitializer = true;
  2678. }
  2679. return foundClassInitializer;
  2680. }
  2681. /**
  2682. * check if a line is empty
  2683. *
  2684. * @return whether line is empty
  2685. */
  2686. bool ASFormatter::isEmptyLine(const string& line) const
  2687. {
  2688. return line.find_first_not_of(" \t") == string::npos;
  2689. }
  2690. /**
  2691. * Check if the following text is "C" as in extern "C".
  2692. *
  2693. * @return whether the statement is extern "C"
  2694. */
  2695. bool ASFormatter::isExternC() const
  2696. {
  2697. // charNum should be at 'extern'
  2698. assert(!isWhiteSpace(currentLine[charNum]));
  2699. size_t startQuote = currentLine.find_first_of(" \t\"", charNum);
  2700. if (startQuote == string::npos)
  2701. return false;
  2702. startQuote = currentLine.find_first_not_of(" \t", startQuote);
  2703. if (startQuote == string::npos)
  2704. return false;
  2705. if (currentLine.compare(startQuote, 3, "\"C\"") != 0)
  2706. return false;
  2707. return true;
  2708. }
  2709. /**
  2710. * Check if the currently reached '*', '&' or '^' character is
  2711. * a pointer-or-reference symbol, or another operator.
  2712. * A pointer dereference (*) or an "address of" character (&)
  2713. * counts as a pointer or reference because it is not an
  2714. * arithmetic operator.
  2715. *
  2716. * @return whether current character is a reference-or-pointer
  2717. */
  2718. bool ASFormatter::isPointerOrReference() const
  2719. {
  2720. assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
  2721. if (isJavaStyle())
  2722. return false;
  2723. if (isCharImmediatelyPostOperator)
  2724. return false;
  2725. // get the last legal word (may be a number)
  2726. string lastWord = getPreviousWord(currentLine, charNum);
  2727. if (lastWord.empty())
  2728. lastWord = " ";
  2729. // check for preceding or following numeric values
  2730. string nextText = peekNextText(currentLine.substr(charNum + 1));
  2731. if (nextText.length() == 0)
  2732. nextText = " ";
  2733. char nextChar = nextText[0];
  2734. if (isDigit(lastWord[0])
  2735. || isDigit(nextChar)
  2736. || nextChar == '!'
  2737. || nextChar == '~')
  2738. return false;
  2739. // check for multiply then a dereference (a * *b)
  2740. if (currentChar == '*'
  2741. && charNum < (int) currentLine.length() - 1
  2742. && isWhiteSpace(currentLine[charNum + 1])
  2743. && nextChar == '*')
  2744. return false;
  2745. if ((foundCastOperator && nextChar == '>')
  2746. || isPointerOrReferenceVariable(lastWord))
  2747. return true;
  2748. if (isInClassInitializer
  2749. && previousNonWSChar != '('
  2750. && previousNonWSChar != '{'
  2751. && previousCommandChar != ','
  2752. && nextChar != ')'
  2753. && nextChar != '}')
  2754. return false;
  2755. //check for rvalue reference
  2756. if (currentChar == '&' && nextChar == '&')
  2757. {
  2758. if (previousNonWSChar == '>')
  2759. return true;
  2760. string followingText;
  2761. if ((int) currentLine.length() > charNum + 2)
  2762. followingText = peekNextText(currentLine.substr(charNum + 2));
  2763. if (followingText.length() > 0 && followingText[0] == ')')
  2764. return true;
  2765. if (currentHeader != nullptr || isInPotentialCalculation)
  2766. return false;
  2767. if (parenStack->back() > 0 && isBraceType(braceTypeStack->back(), COMMAND_TYPE))
  2768. return false;
  2769. return true;
  2770. }
  2771. if (nextChar == '*'
  2772. || previousNonWSChar == '='
  2773. || previousNonWSChar == '('
  2774. || previousNonWSChar == '['
  2775. || isCharImmediatelyPostReturn
  2776. || isInTemplate
  2777. || isCharImmediatelyPostTemplate
  2778. || currentHeader == &AS_CATCH
  2779. || currentHeader == &AS_FOREACH
  2780. || currentHeader == &AS_QFOREACH)
  2781. return true;
  2782. if (isBraceType(braceTypeStack->back(), ARRAY_TYPE)
  2783. && isLegalNameChar(lastWord[0])
  2784. && isLegalNameChar(nextChar)
  2785. && previousNonWSChar != ')')
  2786. {
  2787. if (isArrayOperator())
  2788. return false;
  2789. }
  2790. // checks on operators in parens
  2791. if (parenStack->back() > 0
  2792. && isLegalNameChar(lastWord[0])
  2793. && isLegalNameChar(nextChar))
  2794. {
  2795. // if followed by an assignment it is a pointer or reference
  2796. // if followed by semicolon it is a pointer or reference in range-based for
  2797. const string* followingOperator = getFollowingOperator();
  2798. if (followingOperator != nullptr
  2799. && followingOperator != &AS_MULT
  2800. && followingOperator != &AS_BIT_AND)
  2801. {
  2802. if (followingOperator == &AS_ASSIGN || followingOperator == &AS_COLON)
  2803. return true;
  2804. return false;
  2805. }
  2806. if (isBraceType(braceTypeStack->back(), COMMAND_TYPE)
  2807. || squareBracketCount > 0)
  2808. return false;
  2809. return true;
  2810. }
  2811. // checks on operators in parens with following '('
  2812. if (parenStack->back() > 0
  2813. && nextChar == '('
  2814. && previousNonWSChar != ','
  2815. && previousNonWSChar != '('
  2816. && previousNonWSChar != '!'
  2817. && previousNonWSChar != '&'
  2818. && previousNonWSChar != '*'
  2819. && previousNonWSChar != '|')
  2820. return false;
  2821. if (nextChar == '-'
  2822. || nextChar == '+')
  2823. {
  2824. size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1);
  2825. if (nextNum != string::npos)
  2826. {
  2827. if (currentLine.compare(nextNum, 2, "++") != 0
  2828. && currentLine.compare(nextNum, 2, "--") != 0)
  2829. return false;
  2830. }
  2831. }
  2832. bool isPR = (!isInPotentialCalculation
  2833. || (!isLegalNameChar(previousNonWSChar)
  2834. && !(previousNonWSChar == ')' && nextChar == '(')
  2835. && !(previousNonWSChar == ')' && currentChar == '*' && !isImmediatelyPostCast())
  2836. && previousNonWSChar != ']')
  2837. || (!isWhiteSpace(nextChar)
  2838. && nextChar != '-'
  2839. && nextChar != '('
  2840. && nextChar != '['
  2841. && !isLegalNameChar(nextChar))
  2842. );
  2843. return isPR;
  2844. }
  2845. /**
  2846. * Check if the currently reached '*' or '&' character is
  2847. * a dereferenced pointer or "address of" symbol.
  2848. * NOTE: this MUST be a pointer or reference as determined by
  2849. * the function isPointerOrReference().
  2850. *
  2851. * @return whether current character is a dereference or address of
  2852. */
  2853. bool ASFormatter::isDereferenceOrAddressOf() const
  2854. {
  2855. assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
  2856. if (isCharImmediatelyPostTemplate)
  2857. return false;
  2858. if (previousNonWSChar == '='
  2859. || previousNonWSChar == ','
  2860. || previousNonWSChar == '.'
  2861. || previousNonWSChar == '{'
  2862. || previousNonWSChar == '>'
  2863. || previousNonWSChar == '<'
  2864. || previousNonWSChar == '?'
  2865. || isCharImmediatelyPostLineComment
  2866. || isCharImmediatelyPostComment
  2867. || isCharImmediatelyPostReturn)
  2868. return true;
  2869. char nextChar = peekNextChar();
  2870. if (currentChar == '*' && nextChar == '*')
  2871. {
  2872. if (previousNonWSChar == '(')
  2873. return true;
  2874. if ((int) currentLine.length() < charNum + 2)
  2875. return true;
  2876. return false;
  2877. }
  2878. if (currentChar == '&' && nextChar == '&')
  2879. {
  2880. if (previousNonWSChar == '(' || isInTemplate)
  2881. return true;
  2882. if ((int) currentLine.length() < charNum + 2)
  2883. return true;
  2884. return false;
  2885. }
  2886. // check first char on the line
  2887. if (charNum == (int) currentLine.find_first_not_of(" \t")
  2888. && (isBraceType(braceTypeStack->back(), COMMAND_TYPE)
  2889. || parenStack->back() != 0))
  2890. return true;
  2891. string nextText = peekNextText(currentLine.substr(charNum + 1));
  2892. if (nextText.length() > 0)
  2893. {
  2894. if (nextText[0] == ')' || nextText[0] == '>'
  2895. || nextText[0] == ',' || nextText[0] == '=')
  2896. return false;
  2897. if (nextText[0] == ';')
  2898. return true;
  2899. }
  2900. // check for reference to a pointer *& (cannot have &*)
  2901. if ((currentChar == '*' && nextChar == '&')
  2902. || (previousNonWSChar == '*' && currentChar == '&'))
  2903. return false;
  2904. if (!isBraceType(braceTypeStack->back(), COMMAND_TYPE)
  2905. && parenStack->back() == 0)
  2906. return false;
  2907. string lastWord = getPreviousWord(currentLine, charNum);
  2908. if (lastWord == "else" || lastWord == "delete")
  2909. return true;
  2910. if (isPointerOrReferenceVariable(lastWord))
  2911. return false;
  2912. bool isDA = (!(isLegalNameChar(previousNonWSChar) || previousNonWSChar == '>')
  2913. || (nextText.length() > 0 && !isLegalNameChar(nextText[0]) && nextText[0] != '/')
  2914. || (ispunct((unsigned char)previousNonWSChar) && previousNonWSChar != '.')
  2915. || isCharImmediatelyPostReturn);
  2916. return isDA;
  2917. }
  2918. /**
  2919. * Check if the currently reached '*' or '&' character is
  2920. * centered with one space on each side.
  2921. * Only spaces are checked, not tabs.
  2922. * If true then a space will be deleted on the output.
  2923. *
  2924. * @return whether current character is centered.
  2925. */
  2926. bool ASFormatter::isPointerOrReferenceCentered() const
  2927. {
  2928. assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
  2929. int prNum = charNum;
  2930. int lineLength = (int) currentLine.length();
  2931. // check for end of line
  2932. if (peekNextChar() == ' ')
  2933. return false;
  2934. // check space before
  2935. if (prNum < 1
  2936. || currentLine[prNum - 1] != ' ')
  2937. return false;
  2938. // check no space before that
  2939. if (prNum < 2
  2940. || currentLine[prNum - 2] == ' ')
  2941. return false;
  2942. // check for ** or &&
  2943. if (prNum + 1 < lineLength
  2944. && (currentLine[prNum + 1] == '*' || currentLine[prNum + 1] == '&'))
  2945. prNum++;
  2946. // check space after
  2947. if (prNum + 1 <= lineLength
  2948. && currentLine[prNum + 1] != ' ')
  2949. return false;
  2950. // check no space after that
  2951. if (prNum + 2 < lineLength
  2952. && currentLine[prNum + 2] == ' ')
  2953. return false;
  2954. return true;
  2955. }
  2956. /**
  2957. * Check if a word is a pointer or reference variable type.
  2958. *
  2959. * @return whether word is a pointer or reference variable.
  2960. */
  2961. bool ASFormatter::isPointerOrReferenceVariable(const string& word) const
  2962. {
  2963. return (word == "char"
  2964. || word == "int"
  2965. || word == "void"
  2966. || (word.length() >= 6 // check end of word for _t
  2967. && word.compare(word.length() - 2, 2, "_t") == 0)
  2968. || word == "INT"
  2969. || word == "VOID");
  2970. }
  2971. /**
  2972. * check if the currently reached '+' or '-' character is a unary operator
  2973. * this method takes for granted that the current character
  2974. * is a '+' or '-'.
  2975. *
  2976. * @return whether the current '+' or '-' is a unary operator.
  2977. */
  2978. bool ASFormatter::isUnaryOperator() const
  2979. {
  2980. assert(currentChar == '+' || currentChar == '-');
  2981. return ((isCharImmediatelyPostReturn || !isLegalNameChar(previousCommandChar))
  2982. && previousCommandChar != '.'
  2983. && previousCommandChar != '\"'
  2984. && previousCommandChar != '\''
  2985. && previousCommandChar != ')'
  2986. && previousCommandChar != ']');
  2987. }
  2988. /**
  2989. * check if the currently reached comment is in a 'switch' statement
  2990. *
  2991. * @return whether the current '+' or '-' is in an exponent.
  2992. */
  2993. bool ASFormatter::isInSwitchStatement() const
  2994. {
  2995. assert(isInLineComment || isInComment);
  2996. if (!preBraceHeaderStack->empty())
  2997. for (size_t i = 1; i < preBraceHeaderStack->size(); i++)
  2998. if (preBraceHeaderStack->at(i) == &AS_SWITCH)
  2999. return true;
  3000. return false;
  3001. }
  3002. /**
  3003. * check if the currently reached '+' or '-' character is
  3004. * part of an exponent, i.e. 0.2E-5.
  3005. *
  3006. * @return whether the current '+' or '-' is in an exponent.
  3007. */
  3008. bool ASFormatter::isInExponent() const
  3009. {
  3010. assert(currentChar == '+' || currentChar == '-');
  3011. if (charNum >= 2)
  3012. {
  3013. char prevPrevFormattedChar = currentLine[charNum - 2];
  3014. char prevFormattedChar = currentLine[charNum - 1];
  3015. return ((prevFormattedChar == 'e' || prevFormattedChar == 'E')
  3016. && (prevPrevFormattedChar == '.' || isDigit(prevPrevFormattedChar)));
  3017. }
  3018. return false;
  3019. }
  3020. /**
  3021. * check if an array brace should NOT have an in-statement indent
  3022. *
  3023. * @return the array is non in-statement
  3024. */
  3025. bool ASFormatter::isNonInStatementArrayBrace() const
  3026. {
  3027. bool returnVal = false;
  3028. char nextChar = peekNextChar();
  3029. // if this opening brace begins the line there will be no inStatement indent
  3030. if (currentLineBeginsWithBrace
  3031. && charNum == (int) currentLineFirstBraceNum
  3032. && nextChar != '}')
  3033. returnVal = true;
  3034. // if an opening brace ends the line there will be no inStatement indent
  3035. if (isWhiteSpace(nextChar)
  3036. || isBeforeAnyLineEndComment(charNum)
  3037. || nextChar == '{')
  3038. returnVal = true;
  3039. // Java "new Type [] {...}" IS an inStatement indent
  3040. if (isJavaStyle() && previousNonWSChar == ']')
  3041. returnVal = false;
  3042. return returnVal;
  3043. }
  3044. /**
  3045. * check if a one-line block has been reached,
  3046. * i.e. if the currently reached '{' character is closed
  3047. * with a complimentary '}' elsewhere on the current line,
  3048. *.
  3049. * @return 0 = one-line block has not been reached.
  3050. * 1 = one-line block has been reached.
  3051. * 2 = one-line block has been reached and is followed by a comma.
  3052. * 3 = one-line block has been reached and is an empty block.
  3053. */
  3054. int ASFormatter::isOneLineBlockReached(const string& line, int startChar) const
  3055. {
  3056. assert(line[startChar] == '{');
  3057. bool isInComment_ = false;
  3058. bool isInQuote_ = false;
  3059. bool hasText = false;
  3060. int braceCount = 0;
  3061. int lineLength = line.length();
  3062. char quoteChar_ = ' ';
  3063. char ch = ' ';
  3064. char prevCh = ' ';
  3065. for (int i = startChar; i < lineLength; ++i)
  3066. {
  3067. ch = line[i];
  3068. if (isInComment_)
  3069. {
  3070. if (line.compare(i, 2, "*/") == 0)
  3071. {
  3072. isInComment_ = false;
  3073. ++i;
  3074. }
  3075. continue;
  3076. }
  3077. if (ch == '\\')
  3078. {
  3079. ++i;
  3080. continue;
  3081. }
  3082. if (isInQuote_)
  3083. {
  3084. if (ch == quoteChar_)
  3085. isInQuote_ = false;
  3086. continue;
  3087. }
  3088. if (ch == '"'
  3089. || (ch == '\'' && !isDigitSeparator(line, i)))
  3090. {
  3091. isInQuote_ = true;
  3092. quoteChar_ = ch;
  3093. continue;
  3094. }
  3095. if (line.compare(i, 2, "//") == 0)
  3096. break;
  3097. if (line.compare(i, 2, "/*") == 0)
  3098. {
  3099. isInComment_ = true;
  3100. ++i;
  3101. continue;
  3102. }
  3103. if (ch == '{')
  3104. {
  3105. ++braceCount;
  3106. continue;
  3107. }
  3108. if (ch == '}')
  3109. {
  3110. --braceCount;
  3111. if (braceCount == 0)
  3112. {
  3113. // is this an array?
  3114. if (parenStack->back() == 0 && prevCh != '}')
  3115. {
  3116. size_t peekNum = line.find_first_not_of(" \t", i + 1);
  3117. if (peekNum != string::npos && line[peekNum] == ',')
  3118. return 2;
  3119. }
  3120. if (!hasText)
  3121. return 3; // is an empty block
  3122. return 1;
  3123. }
  3124. }
  3125. if (ch == ';')
  3126. continue;
  3127. if (!isWhiteSpace(ch))
  3128. {
  3129. hasText = true;
  3130. prevCh = ch;
  3131. }
  3132. }
  3133. return 0;
  3134. }
  3135. /**
  3136. * peek at the next word to determine if it is a C# non-paren header.
  3137. * will look ahead in the input file if necessary.
  3138. *
  3139. * @param startChar position on currentLine to start the search
  3140. * @return true if the next word is get or set.
  3141. */
  3142. bool ASFormatter::isNextWordSharpNonParenHeader(int startChar) const
  3143. {
  3144. // look ahead to find the next non-comment text
  3145. string nextText = peekNextText(currentLine.substr(startChar));
  3146. if (nextText.length() == 0)
  3147. return false;
  3148. if (nextText[0] == '[')
  3149. return true;
  3150. if (!isCharPotentialHeader(nextText, 0))
  3151. return false;
  3152. if (findKeyword(nextText, 0, AS_GET) || findKeyword(nextText, 0, AS_SET)
  3153. || findKeyword(nextText, 0, AS_ADD) || findKeyword(nextText, 0, AS_REMOVE))
  3154. return true;
  3155. return false;
  3156. }
  3157. /**
  3158. * peek at the next char to determine if it is an opening brace.
  3159. * will look ahead in the input file if necessary.
  3160. * this determines a java static constructor.
  3161. *
  3162. * @param startChar position on currentLine to start the search
  3163. * @return true if the next word is an opening brace.
  3164. */
  3165. bool ASFormatter::isNextCharOpeningBrace(int startChar) const
  3166. {
  3167. bool retVal = false;
  3168. string nextText = peekNextText(currentLine.substr(startChar));
  3169. if (nextText.length() > 0
  3170. && nextText.compare(0, 1, "{") == 0)
  3171. retVal = true;
  3172. return retVal;
  3173. }
  3174. /**
  3175. * Check if operator and, pointer, and reference padding is disabled.
  3176. * Disabling is done thru a NOPAD tag in an ending comment.
  3177. *
  3178. * @return true if the formatting on this line is disabled.
  3179. */
  3180. bool ASFormatter::isOperatorPaddingDisabled() const
  3181. {
  3182. size_t commentStart = currentLine.find("//", charNum);
  3183. if (commentStart == string::npos)
  3184. {
  3185. commentStart = currentLine.find("/*", charNum);
  3186. // comment must end on this line
  3187. if (commentStart != string::npos)
  3188. {
  3189. size_t commentEnd = currentLine.find("*/", commentStart + 2);
  3190. if (commentEnd == string::npos)
  3191. commentStart = string::npos;
  3192. }
  3193. }
  3194. if (commentStart == string::npos)
  3195. return false;
  3196. size_t noPadStart = currentLine.find("*NOPAD*", commentStart);
  3197. if (noPadStart == string::npos)
  3198. return false;
  3199. return true;
  3200. }
  3201. /**
  3202. * Determine if an opening array-type brace should have a leading space pad.
  3203. * This is to identify C++11 uniform initializers.
  3204. */
  3205. bool ASFormatter::isUniformInitializerBrace() const
  3206. {
  3207. if (isCStyle() && !isInEnum && !isImmediatelyPostPreprocessor)
  3208. {
  3209. if (isInClassInitializer
  3210. || isLegalNameChar(previousNonWSChar))
  3211. return true;
  3212. }
  3213. return false;
  3214. }
  3215. /**
  3216. * Determine if there is a following statement on the current line.
  3217. */
  3218. bool ASFormatter::isMultiStatementLine() const
  3219. {
  3220. assert((isImmediatelyPostHeader || foundClosingHeader));
  3221. bool isInComment_ = false;
  3222. bool isInQuote_ = false;
  3223. int semiCount_ = 0;
  3224. int parenCount_ = 0;
  3225. int braceCount_ = 0;
  3226. for (size_t i = 0; i < currentLine.length(); i++)
  3227. {
  3228. if (isInComment_)
  3229. {
  3230. if (currentLine.compare(i, 2, "*/") == 0)
  3231. {
  3232. isInComment_ = false;
  3233. continue;
  3234. }
  3235. }
  3236. if (currentLine.compare(i, 2, "/*") == 0)
  3237. {
  3238. isInComment_ = true;
  3239. continue;
  3240. }
  3241. if (currentLine.compare(i, 2, "//") == 0)
  3242. return false;
  3243. if (isInQuote_)
  3244. {
  3245. if (currentLine[i] == '"' || currentLine[i] == '\'')
  3246. isInQuote_ = false;
  3247. continue;
  3248. }
  3249. if (currentLine[i] == '"' || currentLine[i] == '\'')
  3250. {
  3251. isInQuote_ = true;
  3252. continue;
  3253. }
  3254. if (currentLine[i] == '(')
  3255. {
  3256. ++parenCount_;
  3257. continue;
  3258. }
  3259. if (currentLine[i] == ')')
  3260. {
  3261. --parenCount_;
  3262. continue;
  3263. }
  3264. if (parenCount_ > 0)
  3265. continue;
  3266. if (currentLine[i] == '{')
  3267. {
  3268. ++braceCount_;
  3269. }
  3270. if (currentLine[i] == '}')
  3271. {
  3272. --braceCount_;
  3273. }
  3274. if (braceCount_ > 0)
  3275. continue;
  3276. if (currentLine[i] == ';')
  3277. {
  3278. ++semiCount_;
  3279. if (semiCount_ > 1)
  3280. return true;
  3281. continue;
  3282. }
  3283. }
  3284. return false;
  3285. }
  3286. /**
  3287. * get the next non-whitespace substring on following lines, bypassing all comments.
  3288. *
  3289. * @param firstLine the first line to check
  3290. * @return the next non-whitespace substring.
  3291. */
  3292. string ASFormatter::peekNextText(const string& firstLine,
  3293. bool endOnEmptyLine /*false*/,
  3294. shared_ptr<ASPeekStream> streamArg /*nullptr*/) const
  3295. {
  3296. bool isFirstLine = true;
  3297. string nextLine_ = firstLine;
  3298. size_t firstChar = string::npos;
  3299. shared_ptr<ASPeekStream> stream = streamArg;
  3300. if (stream == nullptr) // Borland may need == 0
  3301. stream = make_shared<ASPeekStream>(sourceIterator);
  3302. // find the first non-blank text, bypassing all comments.
  3303. bool isInComment_ = false;
  3304. while (stream->hasMoreLines() || isFirstLine)
  3305. {
  3306. if (isFirstLine)
  3307. isFirstLine = false;
  3308. else
  3309. nextLine_ = stream->peekNextLine();
  3310. firstChar = nextLine_.find_first_not_of(" \t");
  3311. if (firstChar == string::npos)
  3312. {
  3313. if (endOnEmptyLine && !isInComment_)
  3314. break;
  3315. continue;
  3316. }
  3317. if (nextLine_.compare(firstChar, 2, "/*") == 0)
  3318. {
  3319. firstChar += 2;
  3320. isInComment_ = true;
  3321. }
  3322. if (isInComment_)
  3323. {
  3324. firstChar = nextLine_.find("*/", firstChar);
  3325. if (firstChar == string::npos)
  3326. continue;
  3327. firstChar += 2;
  3328. isInComment_ = false;
  3329. firstChar = nextLine_.find_first_not_of(" \t", firstChar);
  3330. if (firstChar == string::npos)
  3331. continue;
  3332. }
  3333. if (nextLine_.compare(firstChar, 2, "//") == 0)
  3334. continue;
  3335. // found the next text
  3336. break;
  3337. }
  3338. if (firstChar == string::npos)
  3339. nextLine_ = "";
  3340. else
  3341. nextLine_ = nextLine_.substr(firstChar);
  3342. return nextLine_;
  3343. }
  3344. /**
  3345. * adjust comment position because of adding or deleting spaces
  3346. * the spaces are added or deleted to formattedLine
  3347. * spacePadNum contains the adjustment
  3348. */
  3349. void ASFormatter::adjustComments()
  3350. {
  3351. assert(spacePadNum != 0);
  3352. assert(isSequenceReached("//") || isSequenceReached("/*"));
  3353. // block comment must be closed on this line with nothing after it
  3354. if (isSequenceReached("/*"))
  3355. {
  3356. size_t endNum = currentLine.find("*/", charNum + 2);
  3357. if (endNum == string::npos)
  3358. return;
  3359. if (currentLine.find_first_not_of(" \t", endNum + 2) != string::npos)
  3360. return;
  3361. }
  3362. size_t len = formattedLine.length();
  3363. // don't adjust a tab
  3364. if (formattedLine[len - 1] == '\t')
  3365. return;
  3366. // if spaces were removed, need to add spaces before the comment
  3367. if (spacePadNum < 0)
  3368. {
  3369. int adjust = -spacePadNum; // make the number positive
  3370. formattedLine.append(adjust, ' ');
  3371. }
  3372. // if spaces were added, need to delete extra spaces before the comment
  3373. // if cannot be done put the comment one space after the last text
  3374. else if (spacePadNum > 0)
  3375. {
  3376. int adjust = spacePadNum;
  3377. size_t lastText = formattedLine.find_last_not_of(' ');
  3378. if (lastText != string::npos
  3379. && lastText < len - adjust - 1)
  3380. formattedLine.resize(len - adjust);
  3381. else if (len > lastText + 2)
  3382. formattedLine.resize(lastText + 2);
  3383. else if (len < lastText + 2)
  3384. formattedLine.append(len - lastText, ' ');
  3385. }
  3386. }
  3387. /**
  3388. * append the current brace inside the end of line comments
  3389. * currentChar contains the brace, it will be appended to formattedLine
  3390. * formattedLineCommentNum is the comment location on formattedLine
  3391. */
  3392. void ASFormatter::appendCharInsideComments()
  3393. {
  3394. if (formattedLineCommentNum == string::npos // does the comment start on the previous line?
  3395. || formattedLineCommentNum == 0)
  3396. {
  3397. appendCurrentChar(); // don't attach
  3398. return;
  3399. }
  3400. assert(formattedLine.compare(formattedLineCommentNum, 2, "//") == 0
  3401. || formattedLine.compare(formattedLineCommentNum, 2, "/*") == 0);
  3402. // find the previous non space char
  3403. size_t end = formattedLineCommentNum;
  3404. size_t beg = formattedLine.find_last_not_of(" \t", end - 1);
  3405. if (beg == string::npos)
  3406. {
  3407. appendCurrentChar(); // don't attach
  3408. return;
  3409. }
  3410. beg++;
  3411. // insert the brace
  3412. if (end - beg < 3) // is there room to insert?
  3413. formattedLine.insert(beg, 3 - end + beg, ' ');
  3414. if (formattedLine[beg] == '\t') // don't pad with a tab
  3415. formattedLine.insert(beg, 1, ' ');
  3416. formattedLine[beg + 1] = currentChar;
  3417. testForTimeToSplitFormattedLine();
  3418. if (isBeforeComment())
  3419. breakLine();
  3420. else if (isCharImmediatelyPostLineComment)
  3421. shouldBreakLineAtNextChar = true;
  3422. }
  3423. /**
  3424. * add or remove space padding to operators
  3425. * the operators and necessary padding will be appended to formattedLine
  3426. * the calling function should have a continue statement after calling this method
  3427. *
  3428. * @param newOperator the operator to be padded
  3429. */
  3430. void ASFormatter::padOperators(const string* newOperator)
  3431. {
  3432. assert(shouldPadOperators);
  3433. assert(newOperator != nullptr);
  3434. char nextNonWSChar = ASBase::peekNextChar(currentLine, charNum);
  3435. bool shouldPad = (newOperator != &AS_SCOPE_RESOLUTION
  3436. && newOperator != &AS_PLUS_PLUS
  3437. && newOperator != &AS_MINUS_MINUS
  3438. && newOperator != &AS_NOT
  3439. && newOperator != &AS_BIT_NOT
  3440. && newOperator != &AS_ARROW
  3441. && !(newOperator == &AS_COLON && !foundQuestionMark // objC methods
  3442. && (isInObjCMethodDefinition || isInObjCInterface
  3443. || isInObjCSelector || squareBracketCount != 0))
  3444. && !(newOperator == &AS_MINUS && isInExponent())
  3445. && !(newOperator == &AS_PLUS && isInExponent())
  3446. && !((newOperator == &AS_PLUS || newOperator == &AS_MINUS) // check for unary plus or minus
  3447. && (previousNonWSChar == '('
  3448. || previousNonWSChar == '['
  3449. || previousNonWSChar == '='
  3450. || previousNonWSChar == ','
  3451. || previousNonWSChar == ':'
  3452. || previousNonWSChar == '{'))
  3453. //? // commented out in release 2.05.1 - doesn't seem to do anything???
  3454. //x && !((newOperator == &AS_MULT || newOperator == &AS_BIT_AND || newOperator == &AS_AND)
  3455. //x && isPointerOrReference())
  3456. && !(newOperator == &AS_MULT
  3457. && (previousNonWSChar == '.'
  3458. || previousNonWSChar == '>')) // check for ->
  3459. && !(newOperator == &AS_MULT && peekNextChar() == '>')
  3460. && !((isInTemplate || isImmediatelyPostTemplate)
  3461. && (newOperator == &AS_LS || newOperator == &AS_GR))
  3462. && !(newOperator == &AS_GCC_MIN_ASSIGN
  3463. && ASBase::peekNextChar(currentLine, charNum + 1) == '>')
  3464. && !(newOperator == &AS_GR && previousNonWSChar == '?')
  3465. && !(newOperator == &AS_QUESTION // check for Java wildcard
  3466. && isJavaStyle()
  3467. && (previousNonWSChar == '<'
  3468. || nextNonWSChar == '>'
  3469. || nextNonWSChar == '.'))
  3470. && !(newOperator == &AS_QUESTION // check for C# null conditional operator
  3471. && isSharpStyle()
  3472. && (nextNonWSChar == '.'
  3473. || nextNonWSChar == '['))
  3474. && !isCharImmediatelyPostOperator
  3475. && !isInCase
  3476. && !isInAsm
  3477. && !isInAsmOneLine
  3478. && !isInAsmBlock
  3479. );
  3480. // pad before operator
  3481. if (shouldPad
  3482. && !(newOperator == &AS_COLON
  3483. && (!foundQuestionMark && !isInEnum) && currentHeader != &AS_FOR)
  3484. && !(newOperator == &AS_QUESTION && isSharpStyle() // check for C# nullable type (e.g. int?)
  3485. && currentLine.find(':', charNum + 1) == string::npos)
  3486. )
  3487. appendSpacePad();
  3488. appendOperator(*newOperator);
  3489. goForward(newOperator->length() - 1);
  3490. currentChar = (*newOperator)[newOperator->length() - 1];
  3491. // pad after operator
  3492. // but do not pad after a '-' that is a unary-minus.
  3493. if (shouldPad
  3494. && !isBeforeAnyComment()
  3495. && !(newOperator == &AS_PLUS && isUnaryOperator())
  3496. && !(newOperator == &AS_MINUS && isUnaryOperator())
  3497. && !(currentLine.compare(charNum + 1, 1, AS_SEMICOLON) == 0)
  3498. && !(currentLine.compare(charNum + 1, 2, AS_SCOPE_RESOLUTION) == 0)
  3499. && !(peekNextChar() == ',')
  3500. && !(newOperator == &AS_QUESTION && isSharpStyle() // check for C# nullable type (e.g. int?)
  3501. && peekNextChar() == '[')
  3502. )
  3503. appendSpaceAfter();
  3504. }
  3505. /**
  3506. * format pointer or reference
  3507. * currentChar contains the pointer or reference
  3508. * the symbol and necessary padding will be appended to formattedLine
  3509. * the calling function should have a continue statement after calling this method
  3510. *
  3511. * NOTE: Do NOT use appendCurrentChar() in this method. The line should not be
  3512. * broken once the calculation starts.
  3513. */
  3514. void ASFormatter::formatPointerOrReference()
  3515. {
  3516. assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
  3517. assert(!isJavaStyle());
  3518. int pa = pointerAlignment;
  3519. int ra = referenceAlignment;
  3520. int itemAlignment = (currentChar == '*' || currentChar == '^') ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra);
  3521. // check for ** and &&
  3522. int ptrLength = 1;
  3523. char peekedChar = peekNextChar();
  3524. if ((currentChar == '*' && peekedChar == '*')
  3525. || (currentChar == '&' && peekedChar == '&'))
  3526. {
  3527. ptrLength = 2;
  3528. size_t nextChar = currentLine.find_first_not_of(" \t", charNum + 2);
  3529. if (nextChar == string::npos)
  3530. peekedChar = ' ';
  3531. else
  3532. peekedChar = currentLine[nextChar];
  3533. }
  3534. // check for cast
  3535. if (peekedChar == ')' || peekedChar == '>' || peekedChar == ',')
  3536. {
  3537. formatPointerOrReferenceCast();
  3538. return;
  3539. }
  3540. // check for a padded space and remove it
  3541. if (charNum > 0
  3542. && !isWhiteSpace(currentLine[charNum - 1])
  3543. && formattedLine.length() > 0
  3544. && isWhiteSpace(formattedLine[formattedLine.length() - 1]))
  3545. {
  3546. formattedLine.erase(formattedLine.length() - 1);
  3547. spacePadNum--;
  3548. }
  3549. if (itemAlignment == PTR_ALIGN_TYPE)
  3550. {
  3551. formatPointerOrReferenceToType();
  3552. }
  3553. else if (itemAlignment == PTR_ALIGN_MIDDLE)
  3554. {
  3555. formatPointerOrReferenceToMiddle();
  3556. }
  3557. else if (itemAlignment == PTR_ALIGN_NAME)
  3558. {
  3559. formatPointerOrReferenceToName();
  3560. }
  3561. else // pointerAlignment == PTR_ALIGN_NONE
  3562. {
  3563. formattedLine.append(ptrLength, currentChar);
  3564. if (ptrLength > 1)
  3565. goForward(ptrLength - 1);
  3566. }
  3567. }
  3568. /**
  3569. * format pointer or reference with align to type
  3570. */
  3571. void ASFormatter::formatPointerOrReferenceToType()
  3572. {
  3573. assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
  3574. assert(!isJavaStyle());
  3575. // do this before bumping charNum
  3576. bool isOldPRCentered = isPointerOrReferenceCentered();
  3577. size_t prevCh = formattedLine.find_last_not_of(" \t");
  3578. if (prevCh == string::npos)
  3579. prevCh = 0;
  3580. if (formattedLine.length() == 0 || prevCh == formattedLine.length() - 1)
  3581. formattedLine.append(1, currentChar);
  3582. else
  3583. {
  3584. // exchange * or & with character following the type
  3585. // this may not work every time with a tab character
  3586. string charSave = formattedLine.substr(prevCh + 1, 1);
  3587. formattedLine[prevCh + 1] = currentChar;
  3588. formattedLine.append(charSave);
  3589. }
  3590. if (isSequenceReached("**") || isSequenceReached("&&"))
  3591. {
  3592. if (formattedLine.length() == 1)
  3593. formattedLine.append(1, currentChar);
  3594. else
  3595. formattedLine.insert(prevCh + 2, 1, currentChar);
  3596. goForward(1);
  3597. }
  3598. // if no space after then add one
  3599. if (charNum < (int) currentLine.length() - 1
  3600. && !isWhiteSpace(currentLine[charNum + 1])
  3601. && currentLine[charNum + 1] != ')')
  3602. appendSpacePad();
  3603. // if old pointer or reference is centered, remove a space
  3604. if (isOldPRCentered
  3605. && isWhiteSpace(formattedLine[formattedLine.length() - 1]))
  3606. {
  3607. formattedLine.erase(formattedLine.length() - 1, 1);
  3608. spacePadNum--;
  3609. }
  3610. // update the formattedLine split point
  3611. if (maxCodeLength != string::npos)
  3612. {
  3613. size_t index = formattedLine.length() - 1;
  3614. if (isWhiteSpace(formattedLine[index]))
  3615. {
  3616. updateFormattedLineSplitPointsPointerOrReference(index);
  3617. testForTimeToSplitFormattedLine();
  3618. }
  3619. }
  3620. }
  3621. /**
  3622. * format pointer or reference with align in the middle
  3623. */
  3624. void ASFormatter::formatPointerOrReferenceToMiddle()
  3625. {
  3626. assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
  3627. assert(!isJavaStyle());
  3628. // compute current whitespace before
  3629. size_t wsBefore = currentLine.find_last_not_of(" \t", charNum - 1);
  3630. if (wsBefore == string::npos)
  3631. wsBefore = 0;
  3632. else
  3633. wsBefore = charNum - wsBefore - 1;
  3634. string sequenceToInsert(1, currentChar);
  3635. if (isSequenceReached("**"))
  3636. {
  3637. sequenceToInsert = "**";
  3638. goForward(1);
  3639. }
  3640. else if (isSequenceReached("&&"))
  3641. {
  3642. sequenceToInsert = "&&";
  3643. goForward(1);
  3644. }
  3645. // if reference to a pointer check for conflicting alignment
  3646. else if (currentChar == '*' && peekNextChar() == '&'
  3647. && (referenceAlignment == REF_ALIGN_TYPE
  3648. || referenceAlignment == REF_ALIGN_MIDDLE
  3649. || referenceAlignment == REF_SAME_AS_PTR))
  3650. {
  3651. sequenceToInsert = "*&";
  3652. goForward(1);
  3653. for (size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace(currentLine[i]); i++)
  3654. goForward(1);
  3655. }
  3656. // if a comment follows don't align, just space pad
  3657. if (isBeforeAnyComment())
  3658. {
  3659. appendSpacePad();
  3660. formattedLine.append(sequenceToInsert);
  3661. appendSpaceAfter();
  3662. return;
  3663. }
  3664. // do this before goForward()
  3665. bool isAfterScopeResolution = previousNonWSChar == ':';
  3666. size_t charNumSave = charNum;
  3667. // if this is the last thing on the line
  3668. if (currentLine.find_first_not_of(" \t", charNum + 1) == string::npos)
  3669. {
  3670. if (wsBefore == 0 && !isAfterScopeResolution)
  3671. formattedLine.append(1, ' ');
  3672. formattedLine.append(sequenceToInsert);
  3673. return;
  3674. }
  3675. // goForward() to convert tabs to spaces, if necessary,
  3676. // and move following characters to preceding characters
  3677. // this may not work every time with tab characters
  3678. for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++)
  3679. {
  3680. goForward(1);
  3681. if (formattedLine.length() > 0)
  3682. formattedLine.append(1, currentLine[i]);
  3683. else
  3684. spacePadNum--;
  3685. }
  3686. // find space padding after
  3687. size_t wsAfter = currentLine.find_first_not_of(" \t", charNumSave + 1);
  3688. if (wsAfter == string::npos || isBeforeAnyComment())
  3689. wsAfter = 0;
  3690. else
  3691. wsAfter = wsAfter - charNumSave - 1;
  3692. // don't pad before scope resolution operator, but pad after
  3693. if (isAfterScopeResolution)
  3694. {
  3695. size_t lastText = formattedLine.find_last_not_of(" \t");
  3696. formattedLine.insert(lastText + 1, sequenceToInsert);
  3697. appendSpacePad();
  3698. }
  3699. else if (formattedLine.length() > 0)
  3700. {
  3701. // whitespace should be at least 2 chars to center
  3702. if (wsBefore + wsAfter < 2)
  3703. {
  3704. size_t charsToAppend = (2 - (wsBefore + wsAfter));
  3705. formattedLine.append(charsToAppend, ' ');
  3706. spacePadNum += charsToAppend;
  3707. if (wsBefore == 0)
  3708. wsBefore++;
  3709. if (wsAfter == 0)
  3710. wsAfter++;
  3711. }
  3712. // insert the pointer or reference char
  3713. size_t padAfter = (wsBefore + wsAfter) / 2;
  3714. size_t index = formattedLine.length() - padAfter;
  3715. formattedLine.insert(index, sequenceToInsert);
  3716. }
  3717. else // formattedLine.length() == 0
  3718. {
  3719. formattedLine.append(sequenceToInsert);
  3720. if (wsAfter == 0)
  3721. wsAfter++;
  3722. formattedLine.append(wsAfter, ' ');
  3723. spacePadNum += wsAfter;
  3724. }
  3725. // update the formattedLine split point after the pointer
  3726. if (maxCodeLength != string::npos && formattedLine.length() > 0)
  3727. {
  3728. size_t index = formattedLine.find_last_not_of(" \t");
  3729. if (index != string::npos && (index < formattedLine.length() - 1))
  3730. {
  3731. index++;
  3732. updateFormattedLineSplitPointsPointerOrReference(index);
  3733. testForTimeToSplitFormattedLine();
  3734. }
  3735. }
  3736. }
  3737. /**
  3738. * format pointer or reference with align to name
  3739. */
  3740. void ASFormatter::formatPointerOrReferenceToName()
  3741. {
  3742. assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
  3743. assert(!isJavaStyle());
  3744. // do this before bumping charNum
  3745. bool isOldPRCentered = isPointerOrReferenceCentered();
  3746. size_t startNum = formattedLine.find_last_not_of(" \t");
  3747. if (startNum == string::npos)
  3748. startNum = 0;
  3749. string sequenceToInsert(1, currentChar);
  3750. if (isSequenceReached("**"))
  3751. {
  3752. sequenceToInsert = "**";
  3753. goForward(1);
  3754. }
  3755. else if (isSequenceReached("&&"))
  3756. {
  3757. sequenceToInsert = "&&";
  3758. goForward(1);
  3759. }
  3760. // if reference to a pointer align both to name
  3761. else if (currentChar == '*' && peekNextChar() == '&')
  3762. {
  3763. sequenceToInsert = "*&";
  3764. goForward(1);
  3765. for (size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace(currentLine[i]); i++)
  3766. goForward(1);
  3767. }
  3768. char peekedChar = peekNextChar();
  3769. bool isAfterScopeResolution = previousNonWSChar == ':'; // check for ::
  3770. // if this is not the last thing on the line
  3771. if (!isBeforeAnyComment()
  3772. && (int) currentLine.find_first_not_of(" \t", charNum + 1) > charNum)
  3773. {
  3774. // goForward() to convert tabs to spaces, if necessary,
  3775. // and move following characters to preceding characters
  3776. // this may not work every time with tab characters
  3777. for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++)
  3778. {
  3779. // if a padded paren follows don't move
  3780. if (shouldPadParensOutside && peekedChar == '(' && !isOldPRCentered)
  3781. {
  3782. // empty parens don't count
  3783. size_t start = currentLine.find_first_not_of("( \t", charNum + 1);
  3784. if (start != string::npos && currentLine[start] != ')')
  3785. break;
  3786. }
  3787. goForward(1);
  3788. if (formattedLine.length() > 0)
  3789. formattedLine.append(1, currentLine[i]);
  3790. else
  3791. spacePadNum--;
  3792. }
  3793. }
  3794. // don't pad before scope resolution operator
  3795. if (isAfterScopeResolution)
  3796. {
  3797. size_t lastText = formattedLine.find_last_not_of(" \t");
  3798. if (lastText != string::npos && lastText + 1 < formattedLine.length())
  3799. formattedLine.erase(lastText + 1);
  3800. }
  3801. // if no space before * then add one
  3802. else if (formattedLine.length() > 0
  3803. && (formattedLine.length() <= startNum + 1
  3804. || !isWhiteSpace(formattedLine[startNum + 1])))
  3805. {
  3806. formattedLine.insert(startNum + 1, 1, ' ');
  3807. spacePadNum++;
  3808. }
  3809. appendSequence(sequenceToInsert, false);
  3810. // if old pointer or reference is centered, remove a space
  3811. if (isOldPRCentered
  3812. && formattedLine.length() > startNum + 1
  3813. && isWhiteSpace(formattedLine[startNum + 1])
  3814. && !isBeforeAnyComment())
  3815. {
  3816. formattedLine.erase(startNum + 1, 1);
  3817. spacePadNum--;
  3818. }
  3819. // don't convert to *= or &=
  3820. if (peekedChar == '=')
  3821. {
  3822. appendSpaceAfter();
  3823. // if more than one space before, delete one
  3824. if (formattedLine.length() > startNum
  3825. && isWhiteSpace(formattedLine[startNum + 1])
  3826. && isWhiteSpace(formattedLine[startNum + 2]))
  3827. {
  3828. formattedLine.erase(startNum + 1, 1);
  3829. spacePadNum--;
  3830. }
  3831. }
  3832. // update the formattedLine split point
  3833. if (maxCodeLength != string::npos)
  3834. {
  3835. size_t index = formattedLine.find_last_of(" \t");
  3836. if (index != string::npos
  3837. && index < formattedLine.length() - 1
  3838. && (formattedLine[index + 1] == '*'
  3839. || formattedLine[index + 1] == '&'
  3840. || formattedLine[index + 1] == '^'))
  3841. {
  3842. updateFormattedLineSplitPointsPointerOrReference(index);
  3843. testForTimeToSplitFormattedLine();
  3844. }
  3845. }
  3846. }
  3847. /**
  3848. * format pointer or reference cast
  3849. * currentChar contains the pointer or reference
  3850. * NOTE: the pointers and references in function definitions
  3851. * are processed as a cast (e.g. void foo(void*, void*))
  3852. * is processed here.
  3853. */
  3854. void ASFormatter::formatPointerOrReferenceCast()
  3855. {
  3856. assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
  3857. assert(!isJavaStyle());
  3858. int pa = pointerAlignment;
  3859. int ra = referenceAlignment;
  3860. int itemAlignment = (currentChar == '*' || currentChar == '^') ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra);
  3861. string sequenceToInsert(1, currentChar);
  3862. if (isSequenceReached("**") || isSequenceReached("&&"))
  3863. {
  3864. goForward(1);
  3865. sequenceToInsert.append(1, currentLine[charNum]);
  3866. }
  3867. if (itemAlignment == PTR_ALIGN_NONE)
  3868. {
  3869. appendSequence(sequenceToInsert, false);
  3870. return;
  3871. }
  3872. // remove preceding whitespace
  3873. char prevCh = ' ';
  3874. size_t prevNum = formattedLine.find_last_not_of(" \t");
  3875. if (prevNum != string::npos)
  3876. {
  3877. prevCh = formattedLine[prevNum];
  3878. if (prevNum + 1 < formattedLine.length()
  3879. && isWhiteSpace(formattedLine[prevNum + 1])
  3880. && prevCh != '(')
  3881. {
  3882. spacePadNum -= (formattedLine.length() - 1 - prevNum);
  3883. formattedLine.erase(prevNum + 1);
  3884. }
  3885. }
  3886. bool isAfterScopeResolution = previousNonWSChar == ':';
  3887. if ((itemAlignment == PTR_ALIGN_MIDDLE || itemAlignment == PTR_ALIGN_NAME)
  3888. && !isAfterScopeResolution && prevCh != '(')
  3889. {
  3890. appendSpacePad();
  3891. // in this case appendSpacePad may or may not update the split point
  3892. if (maxCodeLength != string::npos && formattedLine.length() > 0)
  3893. updateFormattedLineSplitPointsPointerOrReference(formattedLine.length() - 1);
  3894. appendSequence(sequenceToInsert, false);
  3895. }
  3896. else
  3897. appendSequence(sequenceToInsert, false);
  3898. }
  3899. /**
  3900. * add or remove space padding to parens
  3901. * currentChar contains the paren
  3902. * the parens and necessary padding will be appended to formattedLine
  3903. * the calling function should have a continue statement after calling this method
  3904. */
  3905. void ASFormatter::padParens()
  3906. {
  3907. assert(currentChar == '(' || currentChar == ')');
  3908. assert(shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen);
  3909. int spacesOutsideToDelete = 0;
  3910. int spacesInsideToDelete = 0;
  3911. if (currentChar == '(')
  3912. {
  3913. spacesOutsideToDelete = formattedLine.length() - 1;
  3914. spacesInsideToDelete = 0;
  3915. // compute spaces outside the opening paren to delete
  3916. if (shouldUnPadParens)
  3917. {
  3918. char lastChar = ' ';
  3919. bool prevIsParenHeader = false;
  3920. size_t i = formattedLine.find_last_not_of(" \t");
  3921. if (i != string::npos)
  3922. {
  3923. // if last char is a brace the previous whitespace is an indent
  3924. if (formattedLine[i] == '{')
  3925. spacesOutsideToDelete = 0;
  3926. else if (isCharImmediatelyPostPointerOrReference)
  3927. spacesOutsideToDelete = 0;
  3928. else
  3929. {
  3930. spacesOutsideToDelete -= i;
  3931. lastChar = formattedLine[i];
  3932. // if previous word is a header, it will be a paren header
  3933. string prevWord = getPreviousWord(formattedLine, formattedLine.length());
  3934. const string* prevWordH = nullptr;
  3935. if (shouldPadHeader
  3936. && prevWord.length() > 0
  3937. && isCharPotentialHeader(prevWord, 0))
  3938. prevWordH = ASBase::findHeader(prevWord, 0, headers);
  3939. if (prevWordH != nullptr)
  3940. prevIsParenHeader = true;
  3941. else if (prevWord == AS_RETURN) // don't unpad
  3942. prevIsParenHeader = true;
  3943. else if ((prevWord == AS_NEW || prevWord == AS_DELETE)
  3944. && shouldPadHeader) // don't unpad
  3945. prevIsParenHeader = true;
  3946. else if (isCStyle() && prevWord == AS_THROW && shouldPadHeader) // don't unpad
  3947. prevIsParenHeader = true;
  3948. else if (prevWord == "and" || prevWord == "or" || prevWord == "in") // don't unpad
  3949. prevIsParenHeader = true;
  3950. // don't unpad variables
  3951. else if (prevWord == "bool"
  3952. || prevWord == "int"
  3953. || prevWord == "void"
  3954. || prevWord == "void*"
  3955. || prevWord == "char"
  3956. || prevWord == "char*"
  3957. || prevWord == "long"
  3958. || prevWord == "double"
  3959. || prevWord == "float"
  3960. || (prevWord.length() >= 4 // check end of word for _t
  3961. && prevWord.compare(prevWord.length() - 2, 2, "_t") == 0)
  3962. || prevWord == "Int32"
  3963. || prevWord == "UInt32"
  3964. || prevWord == "Int64"
  3965. || prevWord == "UInt64"
  3966. || prevWord == "BOOL"
  3967. || prevWord == "DWORD"
  3968. || prevWord == "HWND"
  3969. || prevWord == "INT"
  3970. || prevWord == "LPSTR"
  3971. || prevWord == "VOID"
  3972. || prevWord == "LPVOID"
  3973. )
  3974. {
  3975. prevIsParenHeader = true;
  3976. }
  3977. }
  3978. }
  3979. // do not unpad operators, but leave them if already padded
  3980. if (shouldPadParensOutside || prevIsParenHeader)
  3981. spacesOutsideToDelete--;
  3982. else if (lastChar == '|' // check for ||
  3983. || lastChar == '&' // check for &&
  3984. || lastChar == ','
  3985. || (lastChar == '(' && shouldPadParensInside)
  3986. || (lastChar == '>' && !foundCastOperator)
  3987. || lastChar == '<'
  3988. || lastChar == '?'
  3989. || lastChar == ':'
  3990. || lastChar == ';'
  3991. || lastChar == '='
  3992. || lastChar == '+'
  3993. || lastChar == '-'
  3994. || lastChar == '*'
  3995. || lastChar == '/'
  3996. || lastChar == '%'
  3997. || lastChar == '^'
  3998. )
  3999. spacesOutsideToDelete--;
  4000. if (spacesOutsideToDelete > 0)
  4001. {
  4002. formattedLine.erase(i + 1, spacesOutsideToDelete);
  4003. spacePadNum -= spacesOutsideToDelete;
  4004. }
  4005. }
  4006. // pad open paren outside
  4007. char peekedCharOutside = peekNextChar();
  4008. if (shouldPadFirstParen && previousChar != '(' && peekedCharOutside != ')')
  4009. appendSpacePad();
  4010. else if (shouldPadParensOutside)
  4011. {
  4012. if (!(currentChar == '(' && peekedCharOutside == ')'))
  4013. appendSpacePad();
  4014. }
  4015. appendCurrentChar();
  4016. // unpad open paren inside
  4017. if (shouldUnPadParens)
  4018. {
  4019. size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
  4020. if (j != string::npos)
  4021. spacesInsideToDelete = j - charNum - 1;
  4022. if (shouldPadParensInside)
  4023. spacesInsideToDelete--;
  4024. if (spacesInsideToDelete > 0)
  4025. {
  4026. currentLine.erase(charNum + 1, spacesInsideToDelete);
  4027. spacePadNum -= spacesInsideToDelete;
  4028. }
  4029. // convert tab to space if requested
  4030. if (shouldConvertTabs
  4031. && (int) currentLine.length() > charNum + 1
  4032. && currentLine[charNum + 1] == '\t')
  4033. currentLine[charNum + 1] = ' ';
  4034. }
  4035. // pad open paren inside
  4036. char peekedCharInside = peekNextChar();
  4037. if (shouldPadParensInside)
  4038. if (!(currentChar == '(' && peekedCharInside == ')'))
  4039. appendSpaceAfter();
  4040. }
  4041. else if (currentChar == ')')
  4042. {
  4043. // unpad close paren inside
  4044. if (shouldUnPadParens)
  4045. {
  4046. spacesInsideToDelete = formattedLine.length();
  4047. size_t i = formattedLine.find_last_not_of(" \t");
  4048. if (i != string::npos)
  4049. spacesInsideToDelete = formattedLine.length() - 1 - i;
  4050. if (shouldPadParensInside)
  4051. spacesInsideToDelete--;
  4052. if (spacesInsideToDelete > 0)
  4053. {
  4054. formattedLine.erase(i + 1, spacesInsideToDelete);
  4055. spacePadNum -= spacesInsideToDelete;
  4056. }
  4057. }
  4058. // pad close paren inside
  4059. if (shouldPadParensInside)
  4060. if (!(previousChar == '(' && currentChar == ')'))
  4061. appendSpacePad();
  4062. appendCurrentChar();
  4063. // unpad close paren outside
  4064. // close parens outside are left unchanged
  4065. if (shouldUnPadParens)
  4066. {
  4067. //spacesOutsideToDelete = 0;
  4068. //size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
  4069. //if (j != string::npos)
  4070. // spacesOutsideToDelete = j - charNum - 1;
  4071. //if (shouldPadParensOutside)
  4072. // spacesOutsideToDelete--;
  4073. //if (spacesOutsideToDelete > 0)
  4074. //{
  4075. // currentLine.erase(charNum + 1, spacesOutsideToDelete);
  4076. // spacePadNum -= spacesOutsideToDelete;
  4077. //}
  4078. }
  4079. // pad close paren outside
  4080. char peekedCharOutside = peekNextChar();
  4081. if (shouldPadParensOutside)
  4082. if (peekedCharOutside != ';'
  4083. && peekedCharOutside != ','
  4084. && peekedCharOutside != '.'
  4085. && peekedCharOutside != '+' // check for ++
  4086. && peekedCharOutside != '-' // check for --
  4087. && peekedCharOutside != ']')
  4088. appendSpaceAfter();
  4089. }
  4090. }
  4091. /**
  4092. * add or remove space padding to objective-c parens
  4093. * these options have precedence over the padParens methods
  4094. * the padParens method has already been called, this method adjusts
  4095. */
  4096. void ASFormatter::padObjCMethodPrefix()
  4097. {
  4098. assert(currentChar == '(' && isImmediatelyPostObjCMethodPrefix);
  4099. assert(shouldPadMethodPrefix || shouldUnPadMethodPrefix);
  4100. size_t prefix = formattedLine.find_first_of("+-");
  4101. if (prefix == string::npos)
  4102. return;
  4103. size_t paren = formattedLine.find_first_of('(');
  4104. if (paren == string::npos)
  4105. return;
  4106. int spaces = paren - prefix - 1;
  4107. if (shouldPadMethodPrefix)
  4108. {
  4109. if (spaces == 0)
  4110. {
  4111. formattedLine.insert(prefix + 1, 1, ' ');
  4112. spacePadNum += 1;
  4113. }
  4114. else if (spaces > 1)
  4115. {
  4116. formattedLine.erase(prefix + 1, spaces - 1);
  4117. spacePadNum -= spaces - 1;
  4118. }
  4119. }
  4120. // this option will be ignored if used with pad-method-prefix
  4121. else if (shouldUnPadMethodPrefix)
  4122. {
  4123. if (spaces > 0)
  4124. {
  4125. formattedLine.erase(prefix + 1, spaces);
  4126. spacePadNum -= spaces;
  4127. }
  4128. }
  4129. }
  4130. /**
  4131. * add or remove space padding to objective-c parens
  4132. * these options have precedence over the padParens methods
  4133. * the padParens method has already been called, this method adjusts
  4134. */
  4135. void ASFormatter::padObjCReturnType()
  4136. {
  4137. assert(currentChar == ')' && isInObjCReturnType);
  4138. assert(shouldPadReturnType || shouldUnPadReturnType);
  4139. size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
  4140. if (nextText == string::npos)
  4141. return;
  4142. int spaces = nextText - charNum - 1;
  4143. if (shouldPadReturnType)
  4144. {
  4145. if (spaces == 0)
  4146. {
  4147. // this will already be padded if pad-paren is used
  4148. if (formattedLine[formattedLine.length() - 1] != ' ')
  4149. {
  4150. formattedLine.append(" ");
  4151. spacePadNum += 1;
  4152. }
  4153. }
  4154. else if (spaces > 1)
  4155. {
  4156. // do not use goForward here
  4157. currentLine.erase(charNum + 1, spaces - 1);
  4158. spacePadNum -= spaces - 1;
  4159. }
  4160. }
  4161. // this option will be ignored if used with pad-return-type
  4162. else if (shouldUnPadReturnType)
  4163. {
  4164. // this will already be padded if pad-paren is used
  4165. if (formattedLine[formattedLine.length() - 1] == ' ')
  4166. {
  4167. spacePadNum -= formattedLine.length() - 1 - nextText;
  4168. int lastText = formattedLine.find_last_not_of(" \t");
  4169. formattedLine.resize(lastText + 1);
  4170. }
  4171. if (spaces > 0)
  4172. {
  4173. // do not use goForward here
  4174. currentLine.erase(charNum + 1, spaces);
  4175. spacePadNum -= spaces;
  4176. }
  4177. }
  4178. }
  4179. /**
  4180. * add or remove space padding to objective-c parens
  4181. * these options have precedence over the padParens methods
  4182. * the padParens method has already been called, this method adjusts
  4183. */
  4184. void ASFormatter::padObjCParamType()
  4185. {
  4186. assert((currentChar == '(' || currentChar == ')') && isInObjCMethodDefinition);
  4187. assert(!isImmediatelyPostObjCMethodPrefix && !isInObjCReturnType);
  4188. assert(shouldPadParamType || shouldUnPadParamType);
  4189. if (currentChar == '(')
  4190. {
  4191. // open paren has already been attached to formattedLine by padParen
  4192. size_t paramOpen = formattedLine.rfind('(');
  4193. assert(paramOpen != string::npos);
  4194. size_t prevText = formattedLine.find_last_not_of(" \t", paramOpen - 1);
  4195. if (prevText == string::npos)
  4196. return;
  4197. int spaces = paramOpen - prevText - 1;
  4198. if (shouldPadParamType
  4199. || objCColonPadMode == COLON_PAD_ALL
  4200. || objCColonPadMode == COLON_PAD_AFTER)
  4201. {
  4202. if (spaces == 0)
  4203. {
  4204. formattedLine.insert(paramOpen, 1, ' ');
  4205. spacePadNum += 1;
  4206. }
  4207. if (spaces > 1)
  4208. {
  4209. formattedLine.erase(prevText + 1, spaces - 1);
  4210. spacePadNum -= spaces - 1;
  4211. }
  4212. }
  4213. // this option will be ignored if used with pad-param-type
  4214. else if (shouldUnPadParamType
  4215. || objCColonPadMode == COLON_PAD_NONE
  4216. || objCColonPadMode == COLON_PAD_BEFORE)
  4217. {
  4218. if (spaces > 0)
  4219. {
  4220. formattedLine.erase(prevText + 1, spaces);
  4221. spacePadNum -= spaces;
  4222. }
  4223. }
  4224. }
  4225. else if (currentChar == ')')
  4226. {
  4227. size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
  4228. if (nextText == string::npos)
  4229. return;
  4230. int spaces = nextText - charNum - 1;
  4231. if (shouldPadParamType)
  4232. {
  4233. if (spaces == 0)
  4234. {
  4235. // this will already be padded if pad-paren is used
  4236. if (formattedLine[formattedLine.length() - 1] != ' ')
  4237. {
  4238. formattedLine.append(" ");
  4239. spacePadNum += 1;
  4240. }
  4241. }
  4242. else if (spaces > 1)
  4243. {
  4244. // do not use goForward here
  4245. currentLine.erase(charNum + 1, spaces - 1);
  4246. spacePadNum -= spaces - 1;
  4247. }
  4248. }
  4249. // this option will be ignored if used with pad-param-type
  4250. else if (shouldUnPadParamType)
  4251. {
  4252. // this will already be padded if pad-paren is used
  4253. if (formattedLine[formattedLine.length() - 1] == ' ')
  4254. {
  4255. spacePadNum -= 1;
  4256. int lastText = formattedLine.find_last_not_of(" \t");
  4257. formattedLine.resize(lastText + 1);
  4258. }
  4259. if (spaces > 0)
  4260. {
  4261. // do not use goForward here
  4262. currentLine.erase(charNum + 1, spaces);
  4263. spacePadNum -= spaces;
  4264. }
  4265. }
  4266. }
  4267. }
  4268. /**
  4269. * format opening brace as attached or broken
  4270. * currentChar contains the brace
  4271. * the braces will be appended to the current formattedLine or a new formattedLine as necessary
  4272. * the calling function should have a continue statement after calling this method
  4273. *
  4274. * @param braceType the type of brace to be formatted.
  4275. */
  4276. void ASFormatter::formatOpeningBrace(BraceType braceType)
  4277. {
  4278. assert(!isBraceType(braceType, ARRAY_TYPE));
  4279. assert(currentChar == '{');
  4280. parenStack->emplace_back(0);
  4281. bool breakBrace = isCurrentBraceBroken();
  4282. if (breakBrace)
  4283. {
  4284. if (isBeforeAnyComment() && isOkToBreakBlock(braceType))
  4285. {
  4286. // if comment is at line end leave the comment on this line
  4287. if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
  4288. {
  4289. currentChar = ' '; // remove brace from current line
  4290. if (parenStack->size() > 1)
  4291. parenStack->pop_back();
  4292. currentLine[charNum] = currentChar;
  4293. appendOpeningBrace = true; // append brace to following line
  4294. }
  4295. // else put comment after the brace
  4296. else if (!isBeforeMultipleLineEndComments(charNum))
  4297. breakLine();
  4298. }
  4299. else if (!isBraceType(braceType, SINGLE_LINE_TYPE))
  4300. {
  4301. formattedLine = rtrim(formattedLine);
  4302. breakLine();
  4303. }
  4304. else if ((shouldBreakOneLineBlocks || isBraceType(braceType, BREAK_BLOCK_TYPE))
  4305. && !isBraceType(braceType, EMPTY_BLOCK_TYPE))
  4306. breakLine();
  4307. else if (!isInLineBreak)
  4308. appendSpacePad();
  4309. appendCurrentChar();
  4310. // should a following comment break from the brace?
  4311. // must break the line AFTER the brace
  4312. if (isBeforeComment()
  4313. && formattedLine.length() > 0
  4314. && formattedLine[0] == '{'
  4315. && isOkToBreakBlock(braceType)
  4316. && (braceFormatMode == BREAK_MODE
  4317. || braceFormatMode == LINUX_MODE))
  4318. {
  4319. shouldBreakLineAtNextChar = true;
  4320. }
  4321. }
  4322. else // attach brace
  4323. {
  4324. // are there comments before the brace?
  4325. if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
  4326. {
  4327. if (isOkToBreakBlock(braceType)
  4328. && !(isCharImmediatelyPostComment && isCharImmediatelyPostLineComment) // don't attach if two comments on the line
  4329. && !isImmediatelyPostPreprocessor
  4330. // && peekNextChar() != '}' // don't attach { } // removed release 2.03
  4331. && previousCommandChar != '{' // don't attach { {
  4332. && previousCommandChar != '}' // don't attach } {
  4333. && previousCommandChar != ';') // don't attach ; {
  4334. {
  4335. appendCharInsideComments();
  4336. }
  4337. else
  4338. {
  4339. appendCurrentChar(); // don't attach
  4340. }
  4341. }
  4342. else if (previousCommandChar == '{'
  4343. || (previousCommandChar == '}' && !isInClassInitializer)
  4344. || previousCommandChar == ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';'
  4345. {
  4346. appendCurrentChar(); // don't attach
  4347. }
  4348. else
  4349. {
  4350. // if a blank line precedes this don't attach
  4351. if (isEmptyLine(formattedLine))
  4352. appendCurrentChar(); // don't attach
  4353. else if (isOkToBreakBlock(braceType)
  4354. && !(isImmediatelyPostPreprocessor
  4355. && currentLineBeginsWithBrace))
  4356. {
  4357. if (!isBraceType(braceType, EMPTY_BLOCK_TYPE))
  4358. {
  4359. appendSpacePad();
  4360. appendCurrentChar(false); // OK to attach
  4361. testForTimeToSplitFormattedLine(); // line length will have changed
  4362. // should a following comment attach with the brace?
  4363. // insert spaces to reposition the comment
  4364. if (isBeforeComment()
  4365. && !isBeforeMultipleLineEndComments(charNum)
  4366. && (!isBeforeAnyLineEndComment(charNum) || currentLineBeginsWithBrace))
  4367. {
  4368. shouldBreakLineAtNextChar = true;
  4369. currentLine.insert(charNum + 1, charNum + 1, ' ');
  4370. }
  4371. else if (!isBeforeAnyComment()) // added in release 2.03
  4372. {
  4373. shouldBreakLineAtNextChar = true;
  4374. }
  4375. }
  4376. else
  4377. {
  4378. if (currentLineBeginsWithBrace && charNum == (int) currentLineFirstBraceNum)
  4379. {
  4380. appendSpacePad();
  4381. appendCurrentChar(false); // attach
  4382. shouldBreakLineAtNextChar = true;
  4383. }
  4384. else
  4385. {
  4386. appendSpacePad();
  4387. appendCurrentChar(); // don't attach
  4388. }
  4389. }
  4390. }
  4391. else
  4392. {
  4393. if (!isInLineBreak)
  4394. appendSpacePad();
  4395. appendCurrentChar(); // don't attach
  4396. }
  4397. }
  4398. }
  4399. }
  4400. /**
  4401. * format closing brace
  4402. * currentChar contains the brace
  4403. * the calling function should have a continue statement after calling this method
  4404. *
  4405. * @param braceType the type of the opening brace for this closing brace.
  4406. */
  4407. void ASFormatter::formatClosingBrace(BraceType braceType)
  4408. {
  4409. assert(!isBraceType(braceType, ARRAY_TYPE));
  4410. assert(currentChar == '}');
  4411. // parenStack must contain one entry
  4412. if (parenStack->size() > 1)
  4413. parenStack->pop_back();
  4414. // mark state of immediately after empty block
  4415. // this state will be used for locating braces that appear immediately AFTER an empty block (e.g. '{} \n}').
  4416. if (previousCommandChar == '{')
  4417. isImmediatelyPostEmptyBlock = true;
  4418. if (attachClosingBraceMode)
  4419. {
  4420. // for now, namespaces and classes will be attached. Uncomment the lines below to break.
  4421. if ((isEmptyLine(formattedLine) // if a blank line precedes this
  4422. || isCharImmediatelyPostLineComment
  4423. || isCharImmediatelyPostComment
  4424. || (isImmediatelyPostPreprocessor && (int) currentLine.find_first_not_of(" \t") == charNum)
  4425. // || (isBraceType(braceType, CLASS_TYPE) && isOkToBreakBlock(braceType) && previousNonWSChar != '{')
  4426. // || (isBraceType(braceType, NAMESPACE_TYPE) && isOkToBreakBlock(braceType) && previousNonWSChar != '{')
  4427. )
  4428. && (!isBraceType(braceType, SINGLE_LINE_TYPE) || isOkToBreakBlock(braceType)))
  4429. {
  4430. breakLine();
  4431. appendCurrentChar(); // don't attach
  4432. }
  4433. else
  4434. {
  4435. if (previousNonWSChar != '{'
  4436. && (!isBraceType(braceType, SINGLE_LINE_TYPE)
  4437. || isOkToBreakBlock(braceType)))
  4438. appendSpacePad();
  4439. appendCurrentChar(false); // attach
  4440. }
  4441. }
  4442. else if (!isBraceType(braceType, EMPTY_BLOCK_TYPE)
  4443. && (isBraceType(braceType, BREAK_BLOCK_TYPE)
  4444. || isOkToBreakBlock(braceType)))
  4445. {
  4446. breakLine();
  4447. appendCurrentChar();
  4448. }
  4449. else
  4450. {
  4451. appendCurrentChar();
  4452. }
  4453. // if a declaration follows a definition, space pad
  4454. if (isLegalNameChar(peekNextChar()))
  4455. appendSpaceAfter();
  4456. if (shouldBreakBlocks
  4457. && currentHeader != nullptr
  4458. && !isHeaderInMultiStatementLine
  4459. && parenStack->back() == 0)
  4460. {
  4461. if (currentHeader == &AS_CASE || currentHeader == &AS_DEFAULT)
  4462. {
  4463. // do not yet insert a line if "break" statement is outside the braces
  4464. string nextText = peekNextText(currentLine.substr(charNum + 1));
  4465. if (nextText.length() > 0
  4466. && nextText.substr(0, 5) != "break")
  4467. isAppendPostBlockEmptyLineRequested = true;
  4468. }
  4469. else
  4470. isAppendPostBlockEmptyLineRequested = true;
  4471. }
  4472. }
  4473. /**
  4474. * format array braces as attached or broken
  4475. * determine if the braces can have an inStatement indent
  4476. * currentChar contains the brace
  4477. * the braces will be appended to the current formattedLine or a new formattedLine as necessary
  4478. * the calling function should have a continue statement after calling this method
  4479. *
  4480. * @param braceType the type of brace to be formatted, must be an ARRAY_TYPE.
  4481. * @param isOpeningArrayBrace indicates if this is the opening brace for the array block.
  4482. */
  4483. void ASFormatter::formatArrayBraces(BraceType braceType, bool isOpeningArrayBrace)
  4484. {
  4485. assert(isBraceType(braceType, ARRAY_TYPE));
  4486. assert(currentChar == '{' || currentChar == '}');
  4487. if (currentChar == '{')
  4488. {
  4489. // is this the first opening brace in the array?
  4490. if (isOpeningArrayBrace)
  4491. {
  4492. if (braceFormatMode == ATTACH_MODE
  4493. || braceFormatMode == LINUX_MODE)
  4494. {
  4495. // break an enum if mozilla
  4496. if (isBraceType(braceType, ENUM_TYPE)
  4497. && formattingStyle == STYLE_MOZILLA)
  4498. {
  4499. isInLineBreak = true;
  4500. appendCurrentChar(); // don't attach
  4501. }
  4502. // don't attach to a preprocessor directive or '\' line
  4503. else if ((isImmediatelyPostPreprocessor
  4504. || (formattedLine.length() > 0
  4505. && formattedLine[formattedLine.length() - 1] == '\\'))
  4506. && currentLineBeginsWithBrace)
  4507. {
  4508. isInLineBreak = true;
  4509. appendCurrentChar(); // don't attach
  4510. }
  4511. else if (isCharImmediatelyPostComment)
  4512. {
  4513. // TODO: attach brace to line-end comment
  4514. appendCurrentChar(); // don't attach
  4515. }
  4516. else if (isCharImmediatelyPostLineComment && !isBraceType(braceType, SINGLE_LINE_TYPE))
  4517. {
  4518. appendCharInsideComments();
  4519. }
  4520. else
  4521. {
  4522. // if a blank line precedes this don't attach
  4523. if (isEmptyLine(formattedLine))
  4524. appendCurrentChar(); // don't attach
  4525. else
  4526. {
  4527. // if brace is broken or not an assignment
  4528. if (currentLineBeginsWithBrace
  4529. && !isBraceType(braceType, SINGLE_LINE_TYPE))
  4530. {
  4531. appendSpacePad();
  4532. appendCurrentChar(false); // OK to attach
  4533. // TODO: debug the following line
  4534. testForTimeToSplitFormattedLine(); // line length will have changed
  4535. if (currentLineBeginsWithBrace
  4536. && (int) currentLineFirstBraceNum == charNum)
  4537. shouldBreakLineAtNextChar = true;
  4538. }
  4539. else
  4540. {
  4541. if (previousNonWSChar != '(')
  4542. {
  4543. // don't space pad C++11 uniform initialization
  4544. if (!isBraceType(braceType, INIT_TYPE))
  4545. appendSpacePad();
  4546. }
  4547. appendCurrentChar();
  4548. }
  4549. }
  4550. }
  4551. }
  4552. else if (braceFormatMode == BREAK_MODE)
  4553. {
  4554. if (isWhiteSpace(peekNextChar()) && !isInVirginLine)
  4555. breakLine();
  4556. else if (isBeforeAnyComment())
  4557. {
  4558. // do not break unless comment is at line end
  4559. if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
  4560. {
  4561. currentChar = ' '; // remove brace from current line
  4562. appendOpeningBrace = true; // append brace to following line
  4563. }
  4564. }
  4565. if (!isInLineBreak && previousNonWSChar != '(')
  4566. {
  4567. // don't space pad C++11 uniform initialization
  4568. if (!isBraceType(braceType, INIT_TYPE))
  4569. appendSpacePad();
  4570. }
  4571. appendCurrentChar();
  4572. if (currentLineBeginsWithBrace
  4573. && (int) currentLineFirstBraceNum == charNum
  4574. && !isBraceType(braceType, SINGLE_LINE_TYPE))
  4575. shouldBreakLineAtNextChar = true;
  4576. }
  4577. else if (braceFormatMode == RUN_IN_MODE)
  4578. {
  4579. if (isWhiteSpace(peekNextChar()) && !isInVirginLine)
  4580. breakLine();
  4581. else if (isBeforeAnyComment())
  4582. {
  4583. // do not break unless comment is at line end
  4584. if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
  4585. {
  4586. currentChar = ' '; // remove brace from current line
  4587. appendOpeningBrace = true; // append brace to following line
  4588. }
  4589. }
  4590. if (!isInLineBreak && previousNonWSChar != '(')
  4591. {
  4592. // don't space pad C++11 uniform initialization
  4593. if (!isBraceType(braceType, INIT_TYPE))
  4594. appendSpacePad();
  4595. }
  4596. appendCurrentChar();
  4597. }
  4598. else if (braceFormatMode == NONE_MODE)
  4599. {
  4600. if (currentLineBeginsWithBrace
  4601. && charNum == (int) currentLineFirstBraceNum)
  4602. {
  4603. appendCurrentChar(); // don't attach
  4604. }
  4605. else
  4606. {
  4607. if (previousNonWSChar != '(')
  4608. {
  4609. // don't space pad C++11 uniform initialization
  4610. if (!isBraceType(braceType, INIT_TYPE))
  4611. appendSpacePad();
  4612. }
  4613. appendCurrentChar(false); // OK to attach
  4614. }
  4615. }
  4616. }
  4617. else // not the first opening brace
  4618. {
  4619. if (braceFormatMode == RUN_IN_MODE)
  4620. {
  4621. if (previousNonWSChar == '{'
  4622. && braceTypeStack->size() > 2
  4623. && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2],
  4624. SINGLE_LINE_TYPE))
  4625. formatArrayRunIn();
  4626. }
  4627. else if (!isInLineBreak
  4628. && !isWhiteSpace(peekNextChar())
  4629. && previousNonWSChar == '{'
  4630. && braceTypeStack->size() > 2
  4631. && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2],
  4632. SINGLE_LINE_TYPE))
  4633. formatArrayRunIn();
  4634. appendCurrentChar();
  4635. }
  4636. }
  4637. else if (currentChar == '}')
  4638. {
  4639. if (attachClosingBraceMode)
  4640. {
  4641. if (isEmptyLine(formattedLine) // if a blank line precedes this
  4642. || isImmediatelyPostPreprocessor
  4643. || isCharImmediatelyPostLineComment
  4644. || isCharImmediatelyPostComment)
  4645. appendCurrentChar(); // don't attach
  4646. else
  4647. {
  4648. appendSpacePad();
  4649. appendCurrentChar(false); // attach
  4650. }
  4651. }
  4652. else
  4653. {
  4654. // does this close the first opening brace in the array?
  4655. // must check if the block is still a single line because of anonymous statements
  4656. if (!isBraceType(braceType, INIT_TYPE)
  4657. && (!isBraceType(braceType, SINGLE_LINE_TYPE)
  4658. || formattedLine.find('{') == string::npos))
  4659. breakLine();
  4660. appendCurrentChar();
  4661. }
  4662. // if a declaration follows an enum definition, space pad
  4663. char peekedChar = peekNextChar();
  4664. if (isLegalNameChar(peekedChar)
  4665. || peekedChar == '[')
  4666. appendSpaceAfter();
  4667. }
  4668. }
  4669. /**
  4670. * determine if a run-in can be attached.
  4671. * if it can insert the indents in formattedLine and reset the current line break.
  4672. */
  4673. void ASFormatter::formatRunIn()
  4674. {
  4675. assert(braceFormatMode == RUN_IN_MODE || braceFormatMode == NONE_MODE);
  4676. // keep one line blocks returns true without indenting the run-in
  4677. if (formattingStyle != STYLE_PICO
  4678. && !isOkToBreakBlock(braceTypeStack->back()))
  4679. return; // true;
  4680. // make sure the line begins with a brace
  4681. size_t lastText = formattedLine.find_last_not_of(" \t");
  4682. if (lastText == string::npos || formattedLine[lastText] != '{')
  4683. return; // false;
  4684. // make sure the brace is broken
  4685. if (formattedLine.find_first_not_of(" \t{") != string::npos)
  4686. return; // false;
  4687. if (isBraceType(braceTypeStack->back(), NAMESPACE_TYPE))
  4688. return; // false;
  4689. bool extraIndent = false;
  4690. bool extraHalfIndent = false;
  4691. isInLineBreak = true;
  4692. // cannot attach a class modifier without indent-classes
  4693. if (isCStyle()
  4694. && isCharPotentialHeader(currentLine, charNum)
  4695. && (isBraceType(braceTypeStack->back(), CLASS_TYPE)
  4696. || (isBraceType(braceTypeStack->back(), STRUCT_TYPE)
  4697. && isInIndentableStruct)))
  4698. {
  4699. if (findKeyword(currentLine, charNum, AS_PUBLIC)
  4700. || findKeyword(currentLine, charNum, AS_PRIVATE)
  4701. || findKeyword(currentLine, charNum, AS_PROTECTED))
  4702. {
  4703. if (getModifierIndent())
  4704. extraHalfIndent = true;
  4705. else if (!getClassIndent())
  4706. return; // false;
  4707. }
  4708. else if (getClassIndent())
  4709. extraIndent = true;
  4710. }
  4711. // cannot attach a 'case' statement without indent-switches
  4712. if (!getSwitchIndent()
  4713. && isCharPotentialHeader(currentLine, charNum)
  4714. && (findKeyword(currentLine, charNum, AS_CASE)
  4715. || findKeyword(currentLine, charNum, AS_DEFAULT)))
  4716. return; // false;
  4717. // extra indent for switch statements
  4718. if (getSwitchIndent()
  4719. && !preBraceHeaderStack->empty()
  4720. && preBraceHeaderStack->back() == &AS_SWITCH
  4721. && ((isLegalNameChar(currentChar)
  4722. && !findKeyword(currentLine, charNum, AS_CASE))))
  4723. extraIndent = true;
  4724. isInLineBreak = false;
  4725. // remove for extra whitespace
  4726. if (formattedLine.length() > lastText + 1
  4727. && formattedLine.find_first_not_of(" \t", lastText + 1) == string::npos)
  4728. formattedLine.erase(lastText + 1);
  4729. if (extraHalfIndent)
  4730. {
  4731. int indentLength_ = getIndentLength();
  4732. runInIndentChars = indentLength_ / 2;
  4733. formattedLine.append(runInIndentChars - 1, ' ');
  4734. }
  4735. else if (getForceTabIndentation() && getIndentLength() != getTabLength())
  4736. {
  4737. // insert the space indents
  4738. string indent;
  4739. int indentLength_ = getIndentLength();
  4740. int tabLength_ = getTabLength();
  4741. indent.append(indentLength_, ' ');
  4742. if (extraIndent)
  4743. indent.append(indentLength_, ' ');
  4744. // replace spaces indents with tab indents
  4745. size_t tabCount = indent.length() / tabLength_; // truncate extra spaces
  4746. indent.replace(0U, tabCount * tabLength_, tabCount, '\t');
  4747. runInIndentChars = indentLength_;
  4748. if (indent[0] == ' ') // allow for brace
  4749. indent.erase(0, 1);
  4750. formattedLine.append(indent);
  4751. }
  4752. else if (getIndentString() == "\t")
  4753. {
  4754. appendChar('\t', false);
  4755. runInIndentChars = 2; // one for { and one for tab
  4756. if (extraIndent)
  4757. {
  4758. appendChar('\t', false);
  4759. runInIndentChars++;
  4760. }
  4761. }
  4762. else // spaces
  4763. {
  4764. int indentLength_ = getIndentLength();
  4765. formattedLine.append(indentLength_ - 1, ' ');
  4766. runInIndentChars = indentLength_;
  4767. if (extraIndent)
  4768. {
  4769. formattedLine.append(indentLength_, ' ');
  4770. runInIndentChars += indentLength_;
  4771. }
  4772. }
  4773. isInBraceRunIn = true;
  4774. }
  4775. /**
  4776. * remove whitespace and add indentation for an array run-in.
  4777. */
  4778. void ASFormatter::formatArrayRunIn()
  4779. {
  4780. assert(isBraceType(braceTypeStack->back(), ARRAY_TYPE));
  4781. // make sure the brace is broken
  4782. if (formattedLine.find_first_not_of(" \t{") != string::npos)
  4783. return;
  4784. size_t lastText = formattedLine.find_last_not_of(" \t");
  4785. if (lastText == string::npos || formattedLine[lastText] != '{')
  4786. return;
  4787. // check for extra whitespace
  4788. if (formattedLine.length() > lastText + 1
  4789. && formattedLine.find_first_not_of(" \t", lastText + 1) == string::npos)
  4790. formattedLine.erase(lastText + 1);
  4791. if (getIndentString() == "\t")
  4792. {
  4793. appendChar('\t', false);
  4794. runInIndentChars = 2; // one for { and one for tab
  4795. }
  4796. else
  4797. {
  4798. int indent = getIndentLength();
  4799. formattedLine.append(indent - 1, ' ');
  4800. runInIndentChars = indent;
  4801. }
  4802. isInBraceRunIn = true;
  4803. isInLineBreak = false;
  4804. }
  4805. /**
  4806. * delete a braceTypeStack vector object
  4807. * BraceTypeStack did not work with the DeleteContainer template
  4808. */
  4809. void ASFormatter::deleteContainer(vector<BraceType>*& container)
  4810. {
  4811. if (container != nullptr)
  4812. {
  4813. container->clear();
  4814. delete (container);
  4815. container = nullptr;
  4816. }
  4817. }
  4818. /**
  4819. * delete a vector object
  4820. * T is the type of vector
  4821. * used for all vectors except braceTypeStack
  4822. */
  4823. template<typename T>
  4824. void ASFormatter::deleteContainer(T& container)
  4825. {
  4826. if (container != nullptr)
  4827. {
  4828. container->clear();
  4829. delete (container);
  4830. container = nullptr;
  4831. }
  4832. }
  4833. /**
  4834. * initialize a braceType vector object
  4835. * braceType did not work with the DeleteContainer template
  4836. */
  4837. void ASFormatter::initContainer(vector<BraceType>*& container, vector<BraceType>* value)
  4838. {
  4839. if (container != nullptr)
  4840. deleteContainer(container);
  4841. container = value;
  4842. }
  4843. /**
  4844. * initialize a vector object
  4845. * T is the type of vector
  4846. * used for all vectors except braceTypeStack
  4847. */
  4848. template<typename T>
  4849. void ASFormatter::initContainer(T& container, T value)
  4850. {
  4851. // since the ASFormatter object is never deleted,
  4852. // the existing vectors must be deleted before creating new ones
  4853. if (container != nullptr)
  4854. deleteContainer(container);
  4855. container = value;
  4856. }
  4857. /**
  4858. * convert a tab to spaces.
  4859. * charNum points to the current character to convert to spaces.
  4860. * tabIncrementIn is the increment that must be added for tab indent characters
  4861. * to get the correct column for the current tab.
  4862. * replaces the tab in currentLine with the required number of spaces.
  4863. * replaces the value of currentChar.
  4864. */
  4865. void ASFormatter::convertTabToSpaces()
  4866. {
  4867. assert(currentChar == '\t');
  4868. // do NOT replace if in quotes
  4869. if (isInQuote || isInQuoteContinuation)
  4870. return;
  4871. size_t tabSize = getTabLength();
  4872. size_t numSpaces = tabSize - ((tabIncrementIn + charNum) % tabSize);
  4873. currentLine.replace(charNum, 1, numSpaces, ' ');
  4874. currentChar = currentLine[charNum];
  4875. }
  4876. /**
  4877. * is it ok to break this block?
  4878. */
  4879. bool ASFormatter::isOkToBreakBlock(BraceType braceType) const
  4880. {
  4881. // Actually, there should not be an ARRAY_TYPE brace here.
  4882. // But this will avoid breaking a one line block when there is.
  4883. // Otherwise they will be formatted differently on consecutive runs.
  4884. if (isBraceType(braceType, ARRAY_TYPE)
  4885. && isBraceType(braceType, SINGLE_LINE_TYPE))
  4886. return false;
  4887. if (isBraceType(braceType, COMMAND_TYPE)
  4888. && isBraceType(braceType, EMPTY_BLOCK_TYPE))
  4889. return false;
  4890. if (!isBraceType(braceType, SINGLE_LINE_TYPE)
  4891. || isBraceType(braceType, BREAK_BLOCK_TYPE)
  4892. || shouldBreakOneLineBlocks)
  4893. return true;
  4894. return false;
  4895. }
  4896. /**
  4897. * check if a sharp header is a paren or non-paren header
  4898. */
  4899. bool ASFormatter::isSharpStyleWithParen(const string* header) const
  4900. {
  4901. return (isSharpStyle() && peekNextChar() == '('
  4902. && (header == &AS_CATCH
  4903. || header == &AS_DELEGATE));
  4904. }
  4905. /**
  4906. * Check for a following header when a comment is reached.
  4907. * firstLine must contain the start of the comment.
  4908. * return value is a pointer to the header or nullptr.
  4909. */
  4910. const string* ASFormatter::checkForHeaderFollowingComment(const string& firstLine) const
  4911. {
  4912. assert(isInComment || isInLineComment);
  4913. assert(shouldBreakElseIfs || shouldBreakBlocks || isInSwitchStatement());
  4914. // look ahead to find the next non-comment text
  4915. bool endOnEmptyLine = (currentHeader == nullptr);
  4916. if (isInSwitchStatement())
  4917. endOnEmptyLine = false;
  4918. string nextText = peekNextText(firstLine, endOnEmptyLine);
  4919. if (nextText.length() == 0 || !isCharPotentialHeader(nextText, 0))
  4920. return nullptr;
  4921. return ASBase::findHeader(nextText, 0, headers);
  4922. }
  4923. /**
  4924. * process preprocessor statements.
  4925. * charNum should be the index of the #.
  4926. *
  4927. * delete braceTypeStack entries added by #if if a #else is found.
  4928. * prevents double entries in the braceTypeStack.
  4929. */
  4930. void ASFormatter::processPreprocessor()
  4931. {
  4932. assert(currentChar == '#');
  4933. const size_t preproc = currentLine.find_first_not_of(" \t", charNum + 1);
  4934. if (preproc == string::npos)
  4935. return;
  4936. if (currentLine.compare(preproc, 2, "if") == 0)
  4937. {
  4938. preprocBraceTypeStackSize = braceTypeStack->size();
  4939. }
  4940. else if (currentLine.compare(preproc, 4, "else") == 0)
  4941. {
  4942. // delete stack entries added in #if
  4943. // should be replaced by #else
  4944. if (preprocBraceTypeStackSize > 0)
  4945. {
  4946. int addedPreproc = braceTypeStack->size() - preprocBraceTypeStackSize;
  4947. for (int i = 0; i < addedPreproc; i++)
  4948. braceTypeStack->pop_back();
  4949. }
  4950. }
  4951. }
  4952. /**
  4953. * determine if the next line starts a comment
  4954. * and a header follows the comment or comments.
  4955. */
  4956. bool ASFormatter::commentAndHeaderFollows()
  4957. {
  4958. // called ONLY IF shouldDeleteEmptyLines and shouldBreakBlocks are TRUE.
  4959. assert(shouldDeleteEmptyLines && shouldBreakBlocks);
  4960. // is the next line a comment
  4961. auto stream = make_shared<ASPeekStream>(sourceIterator);
  4962. if (!stream->hasMoreLines())
  4963. return false;
  4964. string nextLine_ = stream->peekNextLine();
  4965. size_t firstChar = nextLine_.find_first_not_of(" \t");
  4966. if (firstChar == string::npos
  4967. || !(nextLine_.compare(firstChar, 2, "//") == 0
  4968. || nextLine_.compare(firstChar, 2, "/*") == 0))
  4969. return false;
  4970. // find the next non-comment text, and reset
  4971. string nextText = peekNextText(nextLine_, false, stream);
  4972. if (nextText.length() == 0 || !isCharPotentialHeader(nextText, 0))
  4973. return false;
  4974. const string* newHeader = ASBase::findHeader(nextText, 0, headers);
  4975. if (newHeader == nullptr)
  4976. return false;
  4977. // if a closing header, reset break unless break is requested
  4978. if (isClosingHeader(newHeader) && !shouldBreakClosingHeaderBlocks)
  4979. {
  4980. isAppendPostBlockEmptyLineRequested = false;
  4981. return false;
  4982. }
  4983. return true;
  4984. }
  4985. /**
  4986. * determine if a brace should be attached or broken
  4987. * uses braces in the braceTypeStack
  4988. * the last brace in the braceTypeStack is the one being formatted
  4989. * returns true if the brace should be broken
  4990. */
  4991. bool ASFormatter::isCurrentBraceBroken() const
  4992. {
  4993. assert(braceTypeStack->size() > 1);
  4994. bool breakBrace = false;
  4995. size_t stackEnd = braceTypeStack->size() - 1;
  4996. // check brace modifiers
  4997. if (shouldAttachExternC
  4998. && isBraceType((*braceTypeStack)[stackEnd], EXTERN_TYPE))
  4999. {
  5000. return false;
  5001. }
  5002. if (shouldAttachNamespace
  5003. && isBraceType((*braceTypeStack)[stackEnd], NAMESPACE_TYPE))
  5004. {
  5005. return false;
  5006. }
  5007. if (shouldAttachClass
  5008. && (isBraceType((*braceTypeStack)[stackEnd], CLASS_TYPE)
  5009. || isBraceType((*braceTypeStack)[stackEnd], INTERFACE_TYPE)))
  5010. {
  5011. return false;
  5012. }
  5013. if (shouldAttachInline
  5014. && isCStyle() // for C++ only
  5015. && braceFormatMode != RUN_IN_MODE
  5016. && !(currentLineBeginsWithBrace && peekNextChar() == '/')
  5017. && isBraceType((*braceTypeStack)[stackEnd], COMMAND_TYPE))
  5018. {
  5019. size_t i;
  5020. for (i = 1; i < braceTypeStack->size(); i++)
  5021. if (isBraceType((*braceTypeStack)[i], CLASS_TYPE)
  5022. || isBraceType((*braceTypeStack)[i], STRUCT_TYPE))
  5023. return false;
  5024. }
  5025. // check braces
  5026. if (isBraceType((*braceTypeStack)[stackEnd], EXTERN_TYPE))
  5027. {
  5028. if (currentLineBeginsWithBrace
  5029. || braceFormatMode == RUN_IN_MODE)
  5030. breakBrace = true;
  5031. }
  5032. else if (braceFormatMode == NONE_MODE)
  5033. {
  5034. if (currentLineBeginsWithBrace
  5035. && (int) currentLineFirstBraceNum == charNum)
  5036. breakBrace = true;
  5037. }
  5038. else if (braceFormatMode == BREAK_MODE || braceFormatMode == RUN_IN_MODE)
  5039. {
  5040. breakBrace = true;
  5041. }
  5042. else if (braceFormatMode == LINUX_MODE)
  5043. {
  5044. // break a namespace if NOT stroustrup or mozilla
  5045. if (isBraceType((*braceTypeStack)[stackEnd], NAMESPACE_TYPE))
  5046. {
  5047. if (formattingStyle != STYLE_STROUSTRUP
  5048. && formattingStyle != STYLE_MOZILLA)
  5049. breakBrace = true;
  5050. }
  5051. // break a class or interface if NOT stroustrup
  5052. else if (isBraceType((*braceTypeStack)[stackEnd], CLASS_TYPE)
  5053. || isBraceType((*braceTypeStack)[stackEnd], INTERFACE_TYPE))
  5054. {
  5055. if (formattingStyle != STYLE_STROUSTRUP)
  5056. breakBrace = true;
  5057. }
  5058. // break a struct if mozilla - an enum is processed as an array brace
  5059. else if (isBraceType((*braceTypeStack)[stackEnd], STRUCT_TYPE))
  5060. {
  5061. if (formattingStyle == STYLE_MOZILLA)
  5062. breakBrace = true;
  5063. }
  5064. // break the first brace if a function
  5065. else if (isBraceType((*braceTypeStack)[stackEnd], COMMAND_TYPE))
  5066. {
  5067. if (stackEnd == 1)
  5068. {
  5069. breakBrace = true;
  5070. }
  5071. else if (stackEnd > 1)
  5072. {
  5073. // break the first brace after these if a function
  5074. if (isBraceType((*braceTypeStack)[stackEnd - 1], NAMESPACE_TYPE)
  5075. || isBraceType((*braceTypeStack)[stackEnd - 1], CLASS_TYPE)
  5076. || isBraceType((*braceTypeStack)[stackEnd - 1], ARRAY_TYPE)
  5077. || isBraceType((*braceTypeStack)[stackEnd - 1], STRUCT_TYPE)
  5078. || isBraceType((*braceTypeStack)[stackEnd - 1], EXTERN_TYPE))
  5079. {
  5080. breakBrace = true;
  5081. }
  5082. }
  5083. }
  5084. }
  5085. return breakBrace;
  5086. }
  5087. /**
  5088. * format comment body
  5089. * the calling function should have a continue statement after calling this method
  5090. */
  5091. void ASFormatter::formatCommentBody()
  5092. {
  5093. assert(isInComment);
  5094. // append the comment
  5095. while (charNum < (int) currentLine.length())
  5096. {
  5097. currentChar = currentLine[charNum];
  5098. if (isSequenceReached("*/"))
  5099. {
  5100. formatCommentCloser();
  5101. break;
  5102. }
  5103. if (currentChar == '\t' && shouldConvertTabs)
  5104. convertTabToSpaces();
  5105. appendCurrentChar();
  5106. ++charNum;
  5107. }
  5108. if (shouldStripCommentPrefix)
  5109. stripCommentPrefix();
  5110. }
  5111. /**
  5112. * format a comment opener
  5113. * the comment opener will be appended to the current formattedLine or a new formattedLine as necessary
  5114. * the calling function should have a continue statement after calling this method
  5115. */
  5116. void ASFormatter::formatCommentOpener()
  5117. {
  5118. assert(isSequenceReached("/*"));
  5119. isInComment = isInCommentStartLine = true;
  5120. isImmediatelyPostLineComment = false;
  5121. if (previousNonWSChar == '}')
  5122. resetEndOfStatement();
  5123. // Check for a following header.
  5124. // For speed do not check multiple comment lines more than once.
  5125. // For speed do not check shouldBreakBlocks if previous line is empty, a comment, or a '{'.
  5126. const string* followingHeader = nullptr;
  5127. if ((doesLineStartComment
  5128. && !isImmediatelyPostCommentOnly
  5129. && isBraceType(braceTypeStack->back(), COMMAND_TYPE))
  5130. && (shouldBreakElseIfs
  5131. || isInSwitchStatement()
  5132. || (shouldBreakBlocks
  5133. && !isImmediatelyPostEmptyLine
  5134. && previousCommandChar != '{')))
  5135. followingHeader = checkForHeaderFollowingComment(currentLine.substr(charNum));
  5136. if (spacePadNum != 0 && !isInLineBreak)
  5137. adjustComments();
  5138. formattedLineCommentNum = formattedLine.length();
  5139. // must be done BEFORE appendSequence
  5140. if (previousCommandChar == '{'
  5141. && !isImmediatelyPostComment
  5142. && !isImmediatelyPostLineComment)
  5143. {
  5144. if (isBraceType(braceTypeStack->back(), NAMESPACE_TYPE))
  5145. {
  5146. // namespace run-in is always broken.
  5147. isInLineBreak = true;
  5148. }
  5149. else if (braceFormatMode == NONE_MODE)
  5150. {
  5151. // should a run-in statement be attached?
  5152. if (currentLineBeginsWithBrace)
  5153. formatRunIn();
  5154. }
  5155. else if (braceFormatMode == ATTACH_MODE)
  5156. {
  5157. // if the brace was not attached?
  5158. if (formattedLine.length() > 0 && formattedLine[0] == '{'
  5159. && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
  5160. isInLineBreak = true;
  5161. }
  5162. else if (braceFormatMode == RUN_IN_MODE)
  5163. {
  5164. // should a run-in statement be attached?
  5165. if (formattedLine.length() > 0 && formattedLine[0] == '{')
  5166. formatRunIn();
  5167. }
  5168. }
  5169. else if (!doesLineStartComment)
  5170. noTrimCommentContinuation = true;
  5171. // ASBeautifier needs to know the following statements
  5172. if (shouldBreakElseIfs && followingHeader == &AS_ELSE)
  5173. elseHeaderFollowsComments = true;
  5174. if (followingHeader == &AS_CASE || followingHeader == &AS_DEFAULT)
  5175. caseHeaderFollowsComments = true;
  5176. // appendSequence will write the previous line
  5177. appendSequence(AS_OPEN_COMMENT);
  5178. goForward(1);
  5179. // must be done AFTER appendSequence
  5180. // Break before the comment if a header follows the line comment.
  5181. // But not break if previous line is empty, a comment, or a '{'.
  5182. if (shouldBreakBlocks
  5183. && followingHeader != nullptr
  5184. && !isImmediatelyPostEmptyLine
  5185. && previousCommandChar != '{')
  5186. {
  5187. if (isClosingHeader(followingHeader))
  5188. {
  5189. if (!shouldBreakClosingHeaderBlocks)
  5190. isPrependPostBlockEmptyLineRequested = false;
  5191. }
  5192. // if an opening header, break before the comment
  5193. else
  5194. isPrependPostBlockEmptyLineRequested = true;
  5195. }
  5196. if (previousCommandChar == '}')
  5197. currentHeader = nullptr;
  5198. }
  5199. /**
  5200. * format a comment closer
  5201. * the comment closer will be appended to the current formattedLine
  5202. */
  5203. void ASFormatter::formatCommentCloser()
  5204. {
  5205. assert(isSequenceReached("*/"));
  5206. isInComment = false;
  5207. noTrimCommentContinuation = false;
  5208. isImmediatelyPostComment = true;
  5209. appendSequence(AS_CLOSE_COMMENT);
  5210. goForward(1);
  5211. if (doesLineStartComment
  5212. && (currentLine.find_first_not_of(" \t", charNum + 1) == string::npos))
  5213. lineEndsInCommentOnly = true;
  5214. if (peekNextChar() == '}'
  5215. && previousCommandChar != ';'
  5216. && !isBraceType(braceTypeStack->back(), ARRAY_TYPE)
  5217. && !isInPreprocessor
  5218. && isOkToBreakBlock(braceTypeStack->back()))
  5219. {
  5220. isInLineBreak = true;
  5221. shouldBreakLineAtNextChar = true;
  5222. }
  5223. }
  5224. /**
  5225. * format a line comment body
  5226. * the calling function should have a continue statement after calling this method
  5227. */
  5228. void ASFormatter::formatLineCommentBody()
  5229. {
  5230. assert(isInLineComment);
  5231. // append the comment
  5232. while (charNum < (int) currentLine.length())
  5233. // && !isLineReady // commented out in release 2.04, unnecessary
  5234. {
  5235. currentChar = currentLine[charNum];
  5236. if (currentChar == '\t' && shouldConvertTabs)
  5237. convertTabToSpaces();
  5238. appendCurrentChar();
  5239. ++charNum;
  5240. }
  5241. // explicitly break a line when a line comment's end is found.
  5242. if (charNum == (int) currentLine.length())
  5243. {
  5244. isInLineBreak = true;
  5245. isInLineComment = false;
  5246. isImmediatelyPostLineComment = true;
  5247. currentChar = 0; //make sure it is a neutral char.
  5248. }
  5249. }
  5250. /**
  5251. * format a line comment opener
  5252. * the line comment opener will be appended to the current formattedLine or a new formattedLine as necessary
  5253. * the calling function should have a continue statement after calling this method
  5254. */
  5255. void ASFormatter::formatLineCommentOpener()
  5256. {
  5257. assert(isSequenceReached("//"));
  5258. if ((int) currentLine.length() > charNum + 2
  5259. && currentLine[charNum + 2] == '\xf2') // check for windows line marker
  5260. isAppendPostBlockEmptyLineRequested = false;
  5261. isInLineComment = true;
  5262. isCharImmediatelyPostComment = false;
  5263. if (previousNonWSChar == '}')
  5264. resetEndOfStatement();
  5265. // Check for a following header.
  5266. // For speed do not check multiple comment lines more than once.
  5267. // For speed do not check shouldBreakBlocks if previous line is empty, a comment, or a '{'.
  5268. const string* followingHeader = nullptr;
  5269. if ((lineIsLineCommentOnly
  5270. && !isImmediatelyPostCommentOnly
  5271. && isBraceType(braceTypeStack->back(), COMMAND_TYPE))
  5272. && (shouldBreakElseIfs
  5273. || isInSwitchStatement()
  5274. || (shouldBreakBlocks
  5275. && !isImmediatelyPostEmptyLine
  5276. && previousCommandChar != '{')))
  5277. followingHeader = checkForHeaderFollowingComment(currentLine.substr(charNum));
  5278. // do not indent if in column 1 or 2
  5279. // or in a namespace before the opening brace
  5280. if ((!shouldIndentCol1Comments && !lineCommentNoIndent)
  5281. || foundNamespaceHeader)
  5282. {
  5283. if (charNum == 0)
  5284. lineCommentNoIndent = true;
  5285. else if (charNum == 1 && currentLine[0] == ' ')
  5286. lineCommentNoIndent = true;
  5287. }
  5288. // move comment if spaces were added or deleted
  5289. if (!lineCommentNoIndent && spacePadNum != 0 && !isInLineBreak)
  5290. adjustComments();
  5291. formattedLineCommentNum = formattedLine.length();
  5292. // must be done BEFORE appendSequence
  5293. // check for run-in statement
  5294. if (previousCommandChar == '{'
  5295. && !isImmediatelyPostComment
  5296. && !isImmediatelyPostLineComment)
  5297. {
  5298. if (braceFormatMode == NONE_MODE)
  5299. {
  5300. if (currentLineBeginsWithBrace)
  5301. formatRunIn();
  5302. }
  5303. else if (braceFormatMode == RUN_IN_MODE)
  5304. {
  5305. if (!lineCommentNoIndent)
  5306. formatRunIn();
  5307. else
  5308. isInLineBreak = true;
  5309. }
  5310. else if (braceFormatMode == BREAK_MODE)
  5311. {
  5312. if (formattedLine.length() > 0 && formattedLine[0] == '{')
  5313. isInLineBreak = true;
  5314. }
  5315. else
  5316. {
  5317. if (currentLineBeginsWithBrace)
  5318. isInLineBreak = true;
  5319. }
  5320. }
  5321. // ASBeautifier needs to know the following statements
  5322. if (shouldBreakElseIfs && followingHeader == &AS_ELSE)
  5323. elseHeaderFollowsComments = true;
  5324. if (followingHeader == &AS_CASE || followingHeader == &AS_DEFAULT)
  5325. caseHeaderFollowsComments = true;
  5326. // appendSequence will write the previous line
  5327. appendSequence(AS_OPEN_LINE_COMMENT);
  5328. goForward(1);
  5329. // must be done AFTER appendSequence
  5330. // Break before the comment if a header follows the line comment.
  5331. // But do not break if previous line is empty, a comment, or a '{'.
  5332. if (shouldBreakBlocks
  5333. && followingHeader != nullptr
  5334. && !isImmediatelyPostEmptyLine
  5335. && previousCommandChar != '{')
  5336. {
  5337. if (isClosingHeader(followingHeader))
  5338. {
  5339. if (!shouldBreakClosingHeaderBlocks)
  5340. isPrependPostBlockEmptyLineRequested = false;
  5341. }
  5342. // if an opening header, break before the comment
  5343. else
  5344. isPrependPostBlockEmptyLineRequested = true;
  5345. }
  5346. if (previousCommandChar == '}')
  5347. currentHeader = nullptr;
  5348. // if tabbed input don't convert the immediately following tabs to spaces
  5349. if (getIndentString() == "\t" && lineCommentNoIndent)
  5350. {
  5351. while (charNum + 1 < (int) currentLine.length()
  5352. && currentLine[charNum + 1] == '\t')
  5353. {
  5354. currentChar = currentLine[++charNum];
  5355. appendCurrentChar();
  5356. }
  5357. }
  5358. // explicitly break a line when a line comment's end is found.
  5359. if (charNum + 1 == (int) currentLine.length())
  5360. {
  5361. isInLineBreak = true;
  5362. isInLineComment = false;
  5363. isImmediatelyPostLineComment = true;
  5364. currentChar = 0; //make sure it is a neutral char.
  5365. }
  5366. }
  5367. /**
  5368. * format quote body
  5369. * the calling function should have a continue statement after calling this method
  5370. */
  5371. void ASFormatter::formatQuoteBody()
  5372. {
  5373. assert(isInQuote);
  5374. if (isSpecialChar)
  5375. {
  5376. isSpecialChar = false;
  5377. }
  5378. else if (currentChar == '\\' && !isInVerbatimQuote)
  5379. {
  5380. if (peekNextChar() == ' ') // is this '\' at end of line
  5381. haveLineContinuationChar = true;
  5382. else
  5383. isSpecialChar = true;
  5384. }
  5385. else if (isInVerbatimQuote && currentChar == '"')
  5386. {
  5387. if (isCStyle())
  5388. {
  5389. string delim = ')' + verbatimDelimiter;
  5390. int delimStart = charNum - delim.length();
  5391. if (delimStart > 0 && currentLine.substr(delimStart, delim.length()) == delim)
  5392. {
  5393. isInQuote = false;
  5394. isInVerbatimQuote = false;
  5395. }
  5396. }
  5397. else if (isSharpStyle())
  5398. {
  5399. if ((int) currentLine.length() > charNum + 1
  5400. && currentLine[charNum + 1] == '"') // check consecutive quotes
  5401. {
  5402. appendSequence("\"\"");
  5403. goForward(1);
  5404. return;
  5405. }
  5406. isInQuote = false;
  5407. isInVerbatimQuote = false;
  5408. }
  5409. }
  5410. else if (quoteChar == currentChar)
  5411. {
  5412. isInQuote = false;
  5413. }
  5414. appendCurrentChar();
  5415. // append the text to the ending quoteChar or an escape sequence
  5416. // tabs in quotes are NOT changed by convert-tabs
  5417. if (isInQuote && currentChar != '\\')
  5418. {
  5419. while (charNum + 1 < (int) currentLine.length()
  5420. && currentLine[charNum + 1] != quoteChar
  5421. && currentLine[charNum + 1] != '\\')
  5422. {
  5423. currentChar = currentLine[++charNum];
  5424. appendCurrentChar();
  5425. }
  5426. }
  5427. if (charNum + 1 >= (int) currentLine.length()
  5428. && currentChar != '\\'
  5429. && !isInVerbatimQuote)
  5430. isInQuote = false; // missing closing quote
  5431. }
  5432. /**
  5433. * format a quote opener
  5434. * the quote opener will be appended to the current formattedLine or a new formattedLine as necessary
  5435. * the calling function should have a continue statement after calling this method
  5436. */
  5437. void ASFormatter::formatQuoteOpener()
  5438. {
  5439. assert(currentChar == '"'
  5440. || (currentChar == '\'' && !isDigitSeparator(currentLine, charNum)));
  5441. isInQuote = true;
  5442. quoteChar = currentChar;
  5443. if (isCStyle() && previousChar == 'R')
  5444. {
  5445. int parenPos = currentLine.find('(', charNum);
  5446. if (parenPos != -1)
  5447. {
  5448. isInVerbatimQuote = true;
  5449. verbatimDelimiter = currentLine.substr(charNum + 1, parenPos - charNum - 1);
  5450. }
  5451. }
  5452. else if (isSharpStyle() && previousChar == '@')
  5453. isInVerbatimQuote = true;
  5454. // a quote following a brace is an array
  5455. if (previousCommandChar == '{'
  5456. && !isImmediatelyPostComment
  5457. && !isImmediatelyPostLineComment
  5458. && isNonInStatementArray
  5459. && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
  5460. && !isWhiteSpace(peekNextChar()))
  5461. {
  5462. if (braceFormatMode == NONE_MODE)
  5463. {
  5464. if (currentLineBeginsWithBrace)
  5465. formatRunIn();
  5466. }
  5467. else if (braceFormatMode == RUN_IN_MODE)
  5468. {
  5469. formatRunIn();
  5470. }
  5471. else if (braceFormatMode == BREAK_MODE)
  5472. {
  5473. if (formattedLine.length() > 0 && formattedLine[0] == '{')
  5474. isInLineBreak = true;
  5475. }
  5476. else
  5477. {
  5478. if (currentLineBeginsWithBrace)
  5479. isInLineBreak = true;
  5480. }
  5481. }
  5482. previousCommandChar = ' ';
  5483. appendCurrentChar();
  5484. }
  5485. /**
  5486. * get the next line comment adjustment that results from breaking a closing brace.
  5487. * the brace must be on the same line as the closing header.
  5488. * i.e "} else" changed to "} <NL> else".
  5489. */
  5490. int ASFormatter::getNextLineCommentAdjustment()
  5491. {
  5492. assert(foundClosingHeader && previousNonWSChar == '}');
  5493. if (charNum < 1) // "else" is in column 1
  5494. return 0;
  5495. size_t lastBrace = currentLine.rfind('}', charNum - 1);
  5496. if (lastBrace != string::npos)
  5497. return (lastBrace - charNum); // return a negative number
  5498. return 0;
  5499. }
  5500. // for console build only
  5501. LineEndFormat ASFormatter::getLineEndFormat() const
  5502. {
  5503. return lineEnd;
  5504. }
  5505. /**
  5506. * get the current line comment adjustment that results from attaching
  5507. * a closing header to a closing brace.
  5508. * the brace must be on the line previous to the closing header.
  5509. * the adjustment is 2 chars, one for the brace and one for the space.
  5510. * i.e "} <NL> else" changed to "} else".
  5511. */
  5512. int ASFormatter::getCurrentLineCommentAdjustment()
  5513. {
  5514. assert(foundClosingHeader && previousNonWSChar == '}');
  5515. if (charNum < 1)
  5516. return 2;
  5517. size_t lastBrace = currentLine.rfind('}', charNum - 1);
  5518. if (lastBrace == string::npos)
  5519. return 2;
  5520. return 0;
  5521. }
  5522. /**
  5523. * get the previous word on a line
  5524. * the argument 'currPos' must point to the current position.
  5525. *
  5526. * @return is the previous word or an empty string if none found.
  5527. */
  5528. string ASFormatter::getPreviousWord(const string& line, int currPos) const
  5529. {
  5530. // get the last legal word (may be a number)
  5531. if (currPos == 0)
  5532. return string();
  5533. size_t end = line.find_last_not_of(" \t", currPos - 1);
  5534. if (end == string::npos || !isLegalNameChar(line[end]))
  5535. return string();
  5536. int start; // start of the previous word
  5537. for (start = end; start > -1; start--)
  5538. {
  5539. if (!isLegalNameChar(line[start]) || line[start] == '.')
  5540. break;
  5541. }
  5542. start++;
  5543. return (line.substr(start, end - start + 1));
  5544. }
  5545. /**
  5546. * check if a line break is needed when a closing brace
  5547. * is followed by a closing header.
  5548. * the break depends on the braceFormatMode and other factors.
  5549. */
  5550. void ASFormatter::isLineBreakBeforeClosingHeader()
  5551. {
  5552. assert(foundClosingHeader && previousNonWSChar == '}');
  5553. if (currentHeader == &AS_WHILE && shouldAttachClosingWhile)
  5554. {
  5555. appendClosingHeader();
  5556. return;
  5557. }
  5558. if (braceFormatMode == BREAK_MODE
  5559. || braceFormatMode == RUN_IN_MODE
  5560. || attachClosingBraceMode)
  5561. {
  5562. isInLineBreak = true;
  5563. }
  5564. else if (braceFormatMode == NONE_MODE)
  5565. {
  5566. if (shouldBreakClosingHeaderBraces
  5567. || getBraceIndent() || getBlockIndent())
  5568. {
  5569. isInLineBreak = true;
  5570. }
  5571. else
  5572. {
  5573. appendSpacePad();
  5574. // is closing brace broken?
  5575. size_t i = currentLine.find_first_not_of(" \t");
  5576. if (i != string::npos && currentLine[i] == '}')
  5577. isInLineBreak = false;
  5578. if (shouldBreakBlocks)
  5579. isAppendPostBlockEmptyLineRequested = false;
  5580. }
  5581. }
  5582. // braceFormatMode == ATTACH_MODE, LINUX_MODE
  5583. else
  5584. {
  5585. if (shouldBreakClosingHeaderBraces
  5586. || getBraceIndent() || getBlockIndent())
  5587. {
  5588. isInLineBreak = true;
  5589. }
  5590. else
  5591. {
  5592. appendClosingHeader();
  5593. if (shouldBreakBlocks)
  5594. isAppendPostBlockEmptyLineRequested = false;
  5595. }
  5596. }
  5597. }
  5598. /**
  5599. * Append a closing header to the previous closing brace, if possible
  5600. */
  5601. void ASFormatter::appendClosingHeader()
  5602. {
  5603. // if a blank line does not precede this
  5604. // or last line is not a one line block, attach header
  5605. bool previousLineIsEmpty = isEmptyLine(formattedLine);
  5606. int previousLineIsOneLineBlock = 0;
  5607. size_t firstBrace = findNextChar(formattedLine, '{');
  5608. if (firstBrace != string::npos)
  5609. previousLineIsOneLineBlock = isOneLineBlockReached(formattedLine, firstBrace);
  5610. if (!previousLineIsEmpty
  5611. && previousLineIsOneLineBlock == 0)
  5612. {
  5613. isInLineBreak = false;
  5614. appendSpacePad();
  5615. spacePadNum = 0; // don't count as comment padding
  5616. }
  5617. }
  5618. /**
  5619. * Add braces to a single line statement following a header.
  5620. * braces are not added if the proper conditions are not met.
  5621. * braces are added to the currentLine.
  5622. */
  5623. bool ASFormatter::addBracesToStatement()
  5624. {
  5625. assert(isImmediatelyPostHeader);
  5626. if (currentHeader != &AS_IF
  5627. && currentHeader != &AS_ELSE
  5628. && currentHeader != &AS_FOR
  5629. && currentHeader != &AS_WHILE
  5630. && currentHeader != &AS_DO
  5631. && currentHeader != &AS_FOREACH
  5632. && currentHeader != &AS_QFOREACH
  5633. && currentHeader != &AS_QFOREVER
  5634. && currentHeader != &AS_FOREVER)
  5635. return false;
  5636. if (currentHeader == &AS_WHILE && foundClosingHeader) // do-while
  5637. return false;
  5638. // do not brace an empty statement
  5639. if (currentChar == ';')
  5640. return false;
  5641. // do not add if a header follows
  5642. if (isCharPotentialHeader(currentLine, charNum))
  5643. if (findHeader(headers) != nullptr)
  5644. return false;
  5645. // find the next semi-colon
  5646. size_t nextSemiColon = charNum;
  5647. if (currentChar != ';')
  5648. nextSemiColon = findNextChar(currentLine, ';', charNum + 1);
  5649. if (nextSemiColon == string::npos)
  5650. return false;
  5651. // add closing brace before changing the line length
  5652. if (nextSemiColon == currentLine.length() - 1)
  5653. currentLine.append(" }");
  5654. else
  5655. currentLine.insert(nextSemiColon + 1, " }");
  5656. // add opening brace
  5657. currentLine.insert(charNum, "{ ");
  5658. assert(computeChecksumIn("{}"));
  5659. currentChar = '{';
  5660. if ((int) currentLine.find_first_not_of(" \t") == charNum)
  5661. currentLineBeginsWithBrace = true;
  5662. // remove extra spaces
  5663. if (!shouldAddOneLineBraces)
  5664. {
  5665. size_t lastText = formattedLine.find_last_not_of(" \t");
  5666. if ((formattedLine.length() - 1) - lastText > 1)
  5667. formattedLine.erase(lastText + 1);
  5668. }
  5669. return true;
  5670. }
  5671. /**
  5672. * Remove braces from a single line statement following a header.
  5673. * braces are not removed if the proper conditions are not met.
  5674. * The first brace is replaced by a space.
  5675. */
  5676. bool ASFormatter::removeBracesFromStatement()
  5677. {
  5678. assert(isImmediatelyPostHeader);
  5679. assert(currentChar == '{');
  5680. if (currentHeader != &AS_IF
  5681. && currentHeader != &AS_ELSE
  5682. && currentHeader != &AS_FOR
  5683. && currentHeader != &AS_WHILE
  5684. && currentHeader != &AS_FOREACH)
  5685. return false;
  5686. if (currentHeader == &AS_WHILE && foundClosingHeader) // do-while
  5687. return false;
  5688. bool isFirstLine = true;
  5689. string nextLine_;
  5690. // leave nextLine_ empty if end of line comment follows
  5691. if (!isBeforeAnyLineEndComment(charNum) || currentLineBeginsWithBrace)
  5692. nextLine_ = currentLine.substr(charNum + 1);
  5693. size_t nextChar = 0;
  5694. // find the first non-blank text
  5695. ASPeekStream stream(sourceIterator);
  5696. while (stream.hasMoreLines() || isFirstLine)
  5697. {
  5698. if (isFirstLine)
  5699. isFirstLine = false;
  5700. else
  5701. {
  5702. nextLine_ = stream.peekNextLine();
  5703. nextChar = 0;
  5704. }
  5705. nextChar = nextLine_.find_first_not_of(" \t", nextChar);
  5706. if (nextChar != string::npos)
  5707. break;
  5708. }
  5709. // don't remove if comments or a header follow the brace
  5710. if ((nextLine_.compare(nextChar, 2, "/*") == 0)
  5711. || (nextLine_.compare(nextChar, 2, "//") == 0)
  5712. || (isCharPotentialHeader(nextLine_, nextChar)
  5713. && ASBase::findHeader(nextLine_, nextChar, headers) != nullptr))
  5714. return false;
  5715. // find the next semi-colon
  5716. size_t nextSemiColon = nextChar;
  5717. if (nextLine_[nextChar] != ';')
  5718. nextSemiColon = findNextChar(nextLine_, ';', nextChar + 1);
  5719. if (nextSemiColon == string::npos)
  5720. return false;
  5721. // find the closing brace
  5722. isFirstLine = true;
  5723. nextChar = nextSemiColon + 1;
  5724. while (stream.hasMoreLines() || isFirstLine)
  5725. {
  5726. if (isFirstLine)
  5727. isFirstLine = false;
  5728. else
  5729. {
  5730. nextLine_ = stream.peekNextLine();
  5731. nextChar = 0;
  5732. }
  5733. nextChar = nextLine_.find_first_not_of(" \t", nextChar);
  5734. if (nextChar != string::npos)
  5735. break;
  5736. }
  5737. if (nextLine_.length() == 0 || nextLine_[nextChar] != '}')
  5738. return false;
  5739. // remove opening brace
  5740. currentLine[charNum] = currentChar = ' ';
  5741. assert(adjustChecksumIn(-'{'));
  5742. return true;
  5743. }
  5744. /**
  5745. * Find the next character that is not in quotes or a comment.
  5746. *
  5747. * @param line the line to be searched.
  5748. * @param searchChar the char to find.
  5749. * @param searchStart the start position on the line (default is 0).
  5750. * @return the position on the line or string::npos if not found.
  5751. */
  5752. size_t ASFormatter::findNextChar(const string& line, char searchChar, int searchStart /*0*/) const
  5753. {
  5754. // find the next searchChar
  5755. size_t i;
  5756. for (i = searchStart; i < line.length(); i++)
  5757. {
  5758. if (line.compare(i, 2, "//") == 0)
  5759. return string::npos;
  5760. if (line.compare(i, 2, "/*") == 0)
  5761. {
  5762. size_t endComment = line.find("*/", i + 2);
  5763. if (endComment == string::npos)
  5764. return string::npos;
  5765. i = endComment + 2;
  5766. if (i >= line.length())
  5767. return string::npos;
  5768. }
  5769. if (line[i] == '"'
  5770. || (line[i] == '\'' && !isDigitSeparator(line, i)))
  5771. {
  5772. char quote = line[i];
  5773. while (i < line.length())
  5774. {
  5775. size_t endQuote = line.find(quote, i + 1);
  5776. if (endQuote == string::npos)
  5777. return string::npos;
  5778. i = endQuote;
  5779. if (line[endQuote - 1] != '\\') // check for '\"'
  5780. break;
  5781. if (line[endQuote - 2] == '\\') // check for '\\'
  5782. break;
  5783. }
  5784. }
  5785. if (line[i] == searchChar)
  5786. break;
  5787. // for now don't process C# 'delegate' braces
  5788. // do this last in case the search char is a '{'
  5789. if (line[i] == '{')
  5790. return string::npos;
  5791. }
  5792. if (i >= line.length()) // didn't find searchChar
  5793. return string::npos;
  5794. return i;
  5795. }
  5796. /**
  5797. * Look ahead in the file to see if a struct has access modifiers.
  5798. *
  5799. * @param firstLine a reference to the line to indent.
  5800. * @param index the current line index.
  5801. * @return true if the struct has access modifiers.
  5802. */
  5803. bool ASFormatter::isStructAccessModified(const string& firstLine, size_t index) const
  5804. {
  5805. assert(firstLine[index] == '{');
  5806. assert(isCStyle());
  5807. bool isFirstLine = true;
  5808. size_t braceCount = 1;
  5809. string nextLine_ = firstLine.substr(index + 1);
  5810. ASPeekStream stream(sourceIterator);
  5811. // find the first non-blank text, bypassing all comments and quotes.
  5812. bool isInComment_ = false;
  5813. bool isInQuote_ = false;
  5814. char quoteChar_ = ' ';
  5815. while (stream.hasMoreLines() || isFirstLine)
  5816. {
  5817. if (isFirstLine)
  5818. isFirstLine = false;
  5819. else
  5820. nextLine_ = stream.peekNextLine();
  5821. // parse the line
  5822. for (size_t i = 0; i < nextLine_.length(); i++)
  5823. {
  5824. if (isWhiteSpace(nextLine_[i]))
  5825. continue;
  5826. if (nextLine_.compare(i, 2, "/*") == 0)
  5827. isInComment_ = true;
  5828. if (isInComment_)
  5829. {
  5830. if (nextLine_.compare(i, 2, "*/") == 0)
  5831. {
  5832. isInComment_ = false;
  5833. ++i;
  5834. }
  5835. continue;
  5836. }
  5837. if (nextLine_[i] == '\\')
  5838. {
  5839. ++i;
  5840. continue;
  5841. }
  5842. if (isInQuote_)
  5843. {
  5844. if (nextLine_[i] == quoteChar_)
  5845. isInQuote_ = false;
  5846. continue;
  5847. }
  5848. if (nextLine_[i] == '"'
  5849. || (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i)))
  5850. {
  5851. isInQuote_ = true;
  5852. quoteChar_ = nextLine_[i];
  5853. continue;
  5854. }
  5855. if (nextLine_.compare(i, 2, "//") == 0)
  5856. {
  5857. i = nextLine_.length();
  5858. continue;
  5859. }
  5860. // handle braces
  5861. if (nextLine_[i] == '{')
  5862. ++braceCount;
  5863. if (nextLine_[i] == '}')
  5864. --braceCount;
  5865. if (braceCount == 0)
  5866. return false;
  5867. // check for access modifiers
  5868. if (isCharPotentialHeader(nextLine_, i))
  5869. {
  5870. if (findKeyword(nextLine_, i, AS_PUBLIC)
  5871. || findKeyword(nextLine_, i, AS_PRIVATE)
  5872. || findKeyword(nextLine_, i, AS_PROTECTED))
  5873. return true;
  5874. string name = getCurrentWord(nextLine_, i);
  5875. i += name.length() - 1;
  5876. }
  5877. } // end of for loop
  5878. } // end of while loop
  5879. return false;
  5880. }
  5881. /**
  5882. * Look ahead in the file to see if a preprocessor block is indentable.
  5883. *
  5884. * @param firstLine a reference to the line to indent.
  5885. * @param index the current line index.
  5886. * @return true if the block is indentable.
  5887. */
  5888. bool ASFormatter::isIndentablePreprocessorBlock(const string& firstLine, size_t index)
  5889. {
  5890. assert(firstLine[index] == '#');
  5891. bool isFirstLine = true;
  5892. bool isInIndentableBlock = false;
  5893. bool blockContainsBraces = false;
  5894. bool blockContainsDefineContinuation = false;
  5895. bool isInClassConstructor = false;
  5896. bool isPotentialHeaderGuard = false; // ifndef is first preproc statement
  5897. bool isPotentialHeaderGuard2 = false; // define is within the first proproc
  5898. int numBlockIndents = 0;
  5899. int lineParenCount = 0;
  5900. string nextLine_ = firstLine.substr(index);
  5901. auto stream = make_shared<ASPeekStream>(sourceIterator);
  5902. // find end of the block, bypassing all comments and quotes.
  5903. bool isInComment_ = false;
  5904. bool isInQuote_ = false;
  5905. char quoteChar_ = ' ';
  5906. while (stream->hasMoreLines() || isFirstLine)
  5907. {
  5908. if (isFirstLine)
  5909. isFirstLine = false;
  5910. else
  5911. nextLine_ = stream->peekNextLine();
  5912. // parse the line
  5913. for (size_t i = 0; i < nextLine_.length(); i++)
  5914. {
  5915. if (isWhiteSpace(nextLine_[i]))
  5916. continue;
  5917. if (nextLine_.compare(i, 2, "/*") == 0)
  5918. isInComment_ = true;
  5919. if (isInComment_)
  5920. {
  5921. if (nextLine_.compare(i, 2, "*/") == 0)
  5922. {
  5923. isInComment_ = false;
  5924. ++i;
  5925. }
  5926. continue;
  5927. }
  5928. if (nextLine_[i] == '\\')
  5929. {
  5930. ++i;
  5931. continue;
  5932. }
  5933. if (isInQuote_)
  5934. {
  5935. if (nextLine_[i] == quoteChar_)
  5936. isInQuote_ = false;
  5937. continue;
  5938. }
  5939. if (nextLine_[i] == '"'
  5940. || (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i)))
  5941. {
  5942. isInQuote_ = true;
  5943. quoteChar_ = nextLine_[i];
  5944. continue;
  5945. }
  5946. if (nextLine_.compare(i, 2, "//") == 0)
  5947. {
  5948. i = nextLine_.length();
  5949. continue;
  5950. }
  5951. // handle preprocessor statement
  5952. if (nextLine_[i] == '#')
  5953. {
  5954. string preproc = ASBeautifier::extractPreprocessorStatement(nextLine_);
  5955. if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") // #if, #ifdef, #ifndef
  5956. {
  5957. numBlockIndents += 1;
  5958. isInIndentableBlock = true;
  5959. // flag first preprocessor conditional for header include guard check
  5960. if (!processedFirstConditional)
  5961. {
  5962. processedFirstConditional = true;
  5963. isFirstPreprocConditional = true;
  5964. if (isNDefPreprocStatement(nextLine_, preproc))
  5965. isPotentialHeaderGuard = true;
  5966. }
  5967. }
  5968. else if (preproc == "endif")
  5969. {
  5970. if (numBlockIndents > 0)
  5971. numBlockIndents -= 1;
  5972. // must exit BOTH loops
  5973. if (numBlockIndents == 0)
  5974. goto EndOfWhileLoop;
  5975. }
  5976. else if (preproc == "define")
  5977. {
  5978. if (nextLine_[nextLine_.length() - 1] == '\\')
  5979. blockContainsDefineContinuation = true;
  5980. // check for potential header include guards
  5981. else if (isPotentialHeaderGuard && numBlockIndents == 1)
  5982. isPotentialHeaderGuard2 = true;
  5983. }
  5984. i = nextLine_.length();
  5985. continue;
  5986. }
  5987. // handle exceptions
  5988. if (nextLine_[i] == '{' || nextLine_[i] == '}')
  5989. blockContainsBraces = true;
  5990. else if (nextLine_[i] == '(')
  5991. ++lineParenCount;
  5992. else if (nextLine_[i] == ')')
  5993. --lineParenCount;
  5994. else if (nextLine_[i] == ':')
  5995. {
  5996. // check for '::'
  5997. if (nextLine_.length() > i && nextLine_[i + 1] == ':')
  5998. ++i;
  5999. else
  6000. isInClassConstructor = true;
  6001. }
  6002. // bypass unnecessary parsing - must exit BOTH loops
  6003. if (blockContainsBraces || isInClassConstructor || blockContainsDefineContinuation)
  6004. goto EndOfWhileLoop;
  6005. } // end of for loop, end of line
  6006. if (lineParenCount != 0)
  6007. break;
  6008. } // end of while loop
  6009. EndOfWhileLoop:
  6010. preprocBlockEnd = sourceIterator->tellg();
  6011. if (preprocBlockEnd < 0)
  6012. preprocBlockEnd = sourceIterator->getStreamLength();
  6013. if (blockContainsBraces
  6014. || isInClassConstructor
  6015. || blockContainsDefineContinuation
  6016. || lineParenCount != 0
  6017. || numBlockIndents != 0)
  6018. isInIndentableBlock = false;
  6019. // find next executable instruction
  6020. // this WILL RESET the get pointer
  6021. string nextText = peekNextText("", false, stream);
  6022. // bypass header include guards
  6023. if (isFirstPreprocConditional)
  6024. {
  6025. isFirstPreprocConditional = false;
  6026. if (nextText.empty() && isPotentialHeaderGuard2)
  6027. {
  6028. isInIndentableBlock = false;
  6029. preprocBlockEnd = 0;
  6030. }
  6031. }
  6032. // this allows preprocessor blocks within this block to be indented
  6033. if (!isInIndentableBlock)
  6034. preprocBlockEnd = 0;
  6035. // peekReset() is done by previous peekNextText()
  6036. return isInIndentableBlock;
  6037. }
  6038. bool ASFormatter::isNDefPreprocStatement(const string& nextLine_, const string& preproc) const
  6039. {
  6040. if (preproc == "ifndef")
  6041. return true;
  6042. // check for '!defined'
  6043. if (preproc == "if")
  6044. {
  6045. size_t i = nextLine_.find('!');
  6046. if (i == string::npos)
  6047. return false;
  6048. i = nextLine_.find_first_not_of(" \t", ++i);
  6049. if (i != string::npos && nextLine_.compare(i, 7, "defined") == 0)
  6050. return true;
  6051. }
  6052. return false;
  6053. }
  6054. /**
  6055. * Check to see if this is an EXEC SQL statement.
  6056. *
  6057. * @param line a reference to the line to indent.
  6058. * @param index the current line index.
  6059. * @return true if the statement is EXEC SQL.
  6060. */
  6061. bool ASFormatter::isExecSQL(const string& line, size_t index) const
  6062. {
  6063. if (line[index] != 'e' && line[index] != 'E') // quick check to reject most
  6064. return false;
  6065. string word;
  6066. if (isCharPotentialHeader(line, index))
  6067. word = getCurrentWord(line, index);
  6068. for (size_t i = 0; i < word.length(); i++)
  6069. word[i] = (char) toupper(word[i]);
  6070. if (word != "EXEC")
  6071. return false;
  6072. size_t index2 = index + word.length();
  6073. index2 = line.find_first_not_of(" \t", index2);
  6074. if (index2 == string::npos)
  6075. return false;
  6076. word.erase();
  6077. if (isCharPotentialHeader(line, index2))
  6078. word = getCurrentWord(line, index2);
  6079. for (size_t i = 0; i < word.length(); i++)
  6080. word[i] = (char) toupper(word[i]);
  6081. if (word != "SQL")
  6082. return false;
  6083. return true;
  6084. }
  6085. /**
  6086. * The continuation lines must be adjusted so the leading spaces
  6087. * is equivalent to the text on the opening line.
  6088. *
  6089. * Updates currentLine and charNum.
  6090. */
  6091. void ASFormatter::trimContinuationLine()
  6092. {
  6093. size_t len = currentLine.length();
  6094. size_t tabSize = getTabLength();
  6095. charNum = 0;
  6096. if (leadingSpaces > 0 && len > 0)
  6097. {
  6098. size_t i;
  6099. size_t continuationIncrementIn = 0;
  6100. for (i = 0; (i < len) && (i + continuationIncrementIn < leadingSpaces); i++)
  6101. {
  6102. if (!isWhiteSpace(currentLine[i])) // don't delete any text
  6103. {
  6104. if (i < continuationIncrementIn)
  6105. leadingSpaces = i + tabIncrementIn;
  6106. continuationIncrementIn = tabIncrementIn;
  6107. break;
  6108. }
  6109. if (currentLine[i] == '\t')
  6110. continuationIncrementIn += tabSize - 1 - ((continuationIncrementIn + i) % tabSize);
  6111. }
  6112. if ((int) continuationIncrementIn == tabIncrementIn)
  6113. charNum = i;
  6114. else
  6115. {
  6116. // build a new line with the equivalent leading chars
  6117. string newLine;
  6118. int leadingChars = 0;
  6119. if ((int) leadingSpaces > tabIncrementIn)
  6120. leadingChars = leadingSpaces - tabIncrementIn;
  6121. newLine.append(leadingChars, ' ');
  6122. newLine.append(currentLine, i, len - i);
  6123. currentLine = newLine;
  6124. charNum = leadingChars;
  6125. if (currentLine.length() == 0)
  6126. currentLine = string(" "); // a null is inserted if this is not done
  6127. }
  6128. if (i >= len)
  6129. charNum = 0;
  6130. }
  6131. }
  6132. /**
  6133. * Determine if a header is a closing header
  6134. *
  6135. * @return true if the header is a closing header.
  6136. */
  6137. bool ASFormatter::isClosingHeader(const string* header) const
  6138. {
  6139. return (header == &AS_ELSE
  6140. || header == &AS_CATCH
  6141. || header == &AS_FINALLY);
  6142. }
  6143. /**
  6144. * Determine if a * following a closing paren is immediately.
  6145. * after a cast. If so it is a deference and not a multiply.
  6146. * e.g. "(int*) *ptr" is a deference.
  6147. */
  6148. bool ASFormatter::isImmediatelyPostCast() const
  6149. {
  6150. assert(previousNonWSChar == ')' && currentChar == '*');
  6151. // find preceding closing paren on currentLine or readyFormattedLine
  6152. string line; // currentLine or readyFormattedLine
  6153. size_t paren = currentLine.rfind(')', charNum);
  6154. if (paren != string::npos)
  6155. line = currentLine;
  6156. // if not on currentLine it must be on the previous line
  6157. else
  6158. {
  6159. line = readyFormattedLine;
  6160. paren = line.rfind(')');
  6161. if (paren == string::npos)
  6162. return false;
  6163. }
  6164. if (paren == 0)
  6165. return false;
  6166. // find character preceding the closing paren
  6167. size_t lastChar = line.find_last_not_of(" \t", paren - 1);
  6168. if (lastChar == string::npos)
  6169. return false;
  6170. // check for pointer cast
  6171. if (line[lastChar] == '*')
  6172. return true;
  6173. return false;
  6174. }
  6175. /**
  6176. * Determine if a < is a template definition or instantiation.
  6177. * Sets the class variables isInTemplate and templateDepth.
  6178. */
  6179. void ASFormatter::checkIfTemplateOpener()
  6180. {
  6181. assert(!isInTemplate && currentChar == '<');
  6182. // find first char after the '<' operators
  6183. size_t firstChar = currentLine.find_first_not_of("< \t", charNum);
  6184. if (firstChar == string::npos
  6185. || currentLine[firstChar] == '=')
  6186. {
  6187. // this is not a template -> leave...
  6188. isInTemplate = false;
  6189. return;
  6190. }
  6191. bool isFirstLine = true;
  6192. int parenDepth_ = 0;
  6193. int maxTemplateDepth = 0;
  6194. templateDepth = 0;
  6195. string nextLine_ = currentLine.substr(charNum);
  6196. ASPeekStream stream(sourceIterator);
  6197. // find the angle braces, bypassing all comments and quotes.
  6198. bool isInComment_ = false;
  6199. bool isInQuote_ = false;
  6200. char quoteChar_ = ' ';
  6201. while (stream.hasMoreLines() || isFirstLine)
  6202. {
  6203. if (isFirstLine)
  6204. isFirstLine = false;
  6205. else
  6206. nextLine_ = stream.peekNextLine();
  6207. // parse the line
  6208. for (size_t i = 0; i < nextLine_.length(); i++)
  6209. {
  6210. char currentChar_ = nextLine_[i];
  6211. if (isWhiteSpace(currentChar_))
  6212. continue;
  6213. if (nextLine_.compare(i, 2, "/*") == 0)
  6214. isInComment_ = true;
  6215. if (isInComment_)
  6216. {
  6217. if (nextLine_.compare(i, 2, "*/") == 0)
  6218. {
  6219. isInComment_ = false;
  6220. ++i;
  6221. }
  6222. continue;
  6223. }
  6224. if (currentChar_ == '\\')
  6225. {
  6226. ++i;
  6227. continue;
  6228. }
  6229. if (isInQuote_)
  6230. {
  6231. if (currentChar_ == quoteChar_)
  6232. isInQuote_ = false;
  6233. continue;
  6234. }
  6235. if (currentChar_ == '"'
  6236. || (currentChar_ == '\'' && !isDigitSeparator(nextLine_, i)))
  6237. {
  6238. isInQuote_ = true;
  6239. quoteChar_ = currentChar_;
  6240. continue;
  6241. }
  6242. if (nextLine_.compare(i, 2, "//") == 0)
  6243. {
  6244. i = nextLine_.length();
  6245. continue;
  6246. }
  6247. // not in a comment or quote
  6248. if (currentChar_ == '<')
  6249. {
  6250. ++templateDepth;
  6251. ++maxTemplateDepth;
  6252. continue;
  6253. }
  6254. else if (currentChar_ == '>')
  6255. {
  6256. --templateDepth;
  6257. if (templateDepth == 0)
  6258. {
  6259. if (parenDepth_ == 0)
  6260. {
  6261. // this is a template!
  6262. isInTemplate = true;
  6263. templateDepth = maxTemplateDepth;
  6264. }
  6265. return;
  6266. }
  6267. continue;
  6268. }
  6269. else if (currentChar_ == '(' || currentChar_ == ')')
  6270. {
  6271. if (currentChar_ == '(')
  6272. ++parenDepth_;
  6273. else
  6274. --parenDepth_;
  6275. if (parenDepth_ >= 0)
  6276. continue;
  6277. // this is not a template -> leave...
  6278. isInTemplate = false;
  6279. templateDepth = 0;
  6280. return;
  6281. }
  6282. else if (nextLine_.compare(i, 2, AS_AND) == 0
  6283. || nextLine_.compare(i, 2, AS_OR) == 0)
  6284. {
  6285. // this is not a template -> leave...
  6286. isInTemplate = false;
  6287. templateDepth = 0;
  6288. return;
  6289. }
  6290. else if (currentChar_ == ',' // comma, e.g. A<int, char>
  6291. || currentChar_ == '&' // reference, e.g. A<int&>
  6292. || currentChar_ == '*' // pointer, e.g. A<int*>
  6293. || currentChar_ == '^' // C++/CLI managed pointer, e.g. A<int^>
  6294. || currentChar_ == ':' // ::, e.g. std::string
  6295. || currentChar_ == '=' // assign e.g. default parameter
  6296. || currentChar_ == '[' // [] e.g. string[]
  6297. || currentChar_ == ']' // [] e.g. string[]
  6298. || currentChar_ == '(' // (...) e.g. function definition
  6299. || currentChar_ == ')' // (...) e.g. function definition
  6300. || (isJavaStyle() && currentChar_ == '?') // Java wildcard
  6301. )
  6302. {
  6303. continue;
  6304. }
  6305. else if (!isLegalNameChar(currentChar_))
  6306. {
  6307. // this is not a template -> leave...
  6308. isInTemplate = false;
  6309. templateDepth = 0;
  6310. return;
  6311. }
  6312. string name = getCurrentWord(nextLine_, i);
  6313. i += name.length() - 1;
  6314. } // end for loop
  6315. } // end while loop
  6316. }
  6317. void ASFormatter::updateFormattedLineSplitPoints(char appendedChar)
  6318. {
  6319. assert(maxCodeLength != string::npos);
  6320. assert(formattedLine.length() > 0);
  6321. if (!isOkToSplitFormattedLine())
  6322. return;
  6323. char nextChar = peekNextChar();
  6324. // don't split before an end of line comment
  6325. if (nextChar == '/')
  6326. return;
  6327. // don't split before or after a brace
  6328. if (appendedChar == '{' || appendedChar == '}'
  6329. || previousNonWSChar == '{' || previousNonWSChar == '}'
  6330. || nextChar == '{' || nextChar == '}'
  6331. || currentChar == '{' || currentChar == '}') // currentChar tests for an appended brace
  6332. return;
  6333. // don't split before or after a block paren
  6334. if (appendedChar == '[' || appendedChar == ']'
  6335. || previousNonWSChar == '['
  6336. || nextChar == '[' || nextChar == ']')
  6337. return;
  6338. if (isWhiteSpace(appendedChar))
  6339. {
  6340. if (nextChar != ')' // space before a closing paren
  6341. && nextChar != '(' // space before an opening paren
  6342. && nextChar != '/' // space before a comment
  6343. && nextChar != ':' // space before a colon
  6344. && currentChar != ')' // appended space before and after a closing paren
  6345. && currentChar != '(' // appended space before and after a opening paren
  6346. && previousNonWSChar != '(' // decided at the '('
  6347. // don't break before a pointer or reference aligned to type
  6348. && !(nextChar == '*'
  6349. && !isCharPotentialOperator(previousNonWSChar)
  6350. && pointerAlignment == PTR_ALIGN_TYPE)
  6351. && !(nextChar == '&'
  6352. && !isCharPotentialOperator(previousNonWSChar)
  6353. && (referenceAlignment == REF_ALIGN_TYPE
  6354. || (referenceAlignment == REF_SAME_AS_PTR && pointerAlignment == PTR_ALIGN_TYPE)))
  6355. )
  6356. {
  6357. if (formattedLine.length() - 1 <= maxCodeLength)
  6358. maxWhiteSpace = formattedLine.length() - 1;
  6359. else
  6360. maxWhiteSpacePending = formattedLine.length() - 1;
  6361. }
  6362. }
  6363. // unpadded closing parens may split after the paren (counts as whitespace)
  6364. else if (appendedChar == ')')
  6365. {
  6366. if (nextChar != ')'
  6367. && nextChar != ' '
  6368. && nextChar != ';'
  6369. && nextChar != ','
  6370. && nextChar != '.'
  6371. && !(nextChar == '-' && pointerSymbolFollows())) // check for ->
  6372. {
  6373. if (formattedLine.length() <= maxCodeLength)
  6374. maxWhiteSpace = formattedLine.length();
  6375. else
  6376. maxWhiteSpacePending = formattedLine.length();
  6377. }
  6378. }
  6379. // unpadded commas may split after the comma
  6380. else if (appendedChar == ',')
  6381. {
  6382. if (formattedLine.length() <= maxCodeLength)
  6383. maxComma = formattedLine.length();
  6384. else
  6385. maxCommaPending = formattedLine.length();
  6386. }
  6387. else if (appendedChar == '(')
  6388. {
  6389. if (nextChar != ')' && nextChar != '(' && nextChar != '"' && nextChar != '\'')
  6390. {
  6391. // if follows an operator break before
  6392. size_t parenNum;
  6393. if (isCharPotentialOperator(previousNonWSChar))
  6394. parenNum = formattedLine.length() - 1;
  6395. else
  6396. parenNum = formattedLine.length();
  6397. if (formattedLine.length() <= maxCodeLength)
  6398. maxParen = parenNum;
  6399. else
  6400. maxParenPending = parenNum;
  6401. }
  6402. }
  6403. else if (appendedChar == ';')
  6404. {
  6405. if (nextChar != ' ' && nextChar != '}' && nextChar != '/') // check for following comment
  6406. {
  6407. if (formattedLine.length() <= maxCodeLength)
  6408. maxSemi = formattedLine.length();
  6409. else
  6410. maxSemiPending = formattedLine.length();
  6411. }
  6412. }
  6413. }
  6414. void ASFormatter::updateFormattedLineSplitPointsOperator(const string& sequence)
  6415. {
  6416. assert(maxCodeLength != string::npos);
  6417. assert(formattedLine.length() > 0);
  6418. if (!isOkToSplitFormattedLine())
  6419. return;
  6420. char nextChar = peekNextChar();
  6421. // don't split before an end of line comment
  6422. if (nextChar == '/')
  6423. return;
  6424. // check for logical conditional
  6425. if (sequence == "||" || sequence == "&&" || sequence == "or" || sequence == "and")
  6426. {
  6427. if (shouldBreakLineAfterLogical)
  6428. {
  6429. if (formattedLine.length() <= maxCodeLength)
  6430. maxAndOr = formattedLine.length();
  6431. else
  6432. maxAndOrPending = formattedLine.length();
  6433. }
  6434. else
  6435. {
  6436. // adjust for leading space in the sequence
  6437. size_t sequenceLength = sequence.length();
  6438. if (formattedLine.length() > sequenceLength
  6439. && isWhiteSpace(formattedLine[formattedLine.length() - sequenceLength - 1]))
  6440. sequenceLength++;
  6441. if (formattedLine.length() - sequenceLength <= maxCodeLength)
  6442. maxAndOr = formattedLine.length() - sequenceLength;
  6443. else
  6444. maxAndOrPending = formattedLine.length() - sequenceLength;
  6445. }
  6446. }
  6447. // comparison operators will split after the operator (counts as whitespace)
  6448. else if (sequence == "==" || sequence == "!=" || sequence == ">=" || sequence == "<=")
  6449. {
  6450. if (formattedLine.length() <= maxCodeLength)
  6451. maxWhiteSpace = formattedLine.length();
  6452. else
  6453. maxWhiteSpacePending = formattedLine.length();
  6454. }
  6455. // unpadded operators that will split BEFORE the operator (counts as whitespace)
  6456. else if (sequence == "+" || sequence == "-" || sequence == "?")
  6457. {
  6458. if (charNum > 0
  6459. && !(sequence == "+" && isInExponent())
  6460. && !(sequence == "-" && isInExponent())
  6461. && (isLegalNameChar(currentLine[charNum - 1])
  6462. || currentLine[charNum - 1] == ')'
  6463. || currentLine[charNum - 1] == ']'
  6464. || currentLine[charNum - 1] == '\"'))
  6465. {
  6466. if (formattedLine.length() - 1 <= maxCodeLength)
  6467. maxWhiteSpace = formattedLine.length() - 1;
  6468. else
  6469. maxWhiteSpacePending = formattedLine.length() - 1;
  6470. }
  6471. }
  6472. // unpadded operators that will USUALLY split AFTER the operator (counts as whitespace)
  6473. else if (sequence == "=" || sequence == ":")
  6474. {
  6475. // split BEFORE if the line is too long
  6476. // do NOT use <= here, must allow for a brace attached to an array
  6477. size_t splitPoint = 0;
  6478. if (formattedLine.length() < maxCodeLength)
  6479. splitPoint = formattedLine.length();
  6480. else
  6481. splitPoint = formattedLine.length() - 1;
  6482. // padded or unpadded arrays
  6483. if (previousNonWSChar == ']')
  6484. {
  6485. if (formattedLine.length() - 1 <= maxCodeLength)
  6486. maxWhiteSpace = splitPoint;
  6487. else
  6488. maxWhiteSpacePending = splitPoint;
  6489. }
  6490. else if (charNum > 0
  6491. && (isLegalNameChar(currentLine[charNum - 1])
  6492. || currentLine[charNum - 1] == ')'
  6493. || currentLine[charNum - 1] == ']'))
  6494. {
  6495. if (formattedLine.length() <= maxCodeLength)
  6496. maxWhiteSpace = splitPoint;
  6497. else
  6498. maxWhiteSpacePending = splitPoint;
  6499. }
  6500. }
  6501. }
  6502. /**
  6503. * Update the split point when a pointer or reference is formatted.
  6504. * The argument is the maximum index of the last whitespace character.
  6505. */
  6506. void ASFormatter::updateFormattedLineSplitPointsPointerOrReference(size_t index)
  6507. {
  6508. assert(maxCodeLength != string::npos);
  6509. assert(formattedLine.length() > 0);
  6510. assert(index < formattedLine.length());
  6511. if (!isOkToSplitFormattedLine())
  6512. return;
  6513. if (index < maxWhiteSpace) // just in case
  6514. return;
  6515. if (index <= maxCodeLength)
  6516. maxWhiteSpace = index;
  6517. else
  6518. maxWhiteSpacePending = index;
  6519. }
  6520. bool ASFormatter::isOkToSplitFormattedLine()
  6521. {
  6522. assert(maxCodeLength != string::npos);
  6523. // Is it OK to split the line?
  6524. if (shouldKeepLineUnbroken
  6525. || isInLineComment
  6526. || isInComment
  6527. || isInQuote
  6528. || isInCase
  6529. || isInPreprocessor
  6530. || isInExecSQL
  6531. || isInAsm || isInAsmOneLine || isInAsmBlock
  6532. || isInTemplate)
  6533. return false;
  6534. if (!isOkToBreakBlock(braceTypeStack->back()) && currentChar != '{')
  6535. {
  6536. shouldKeepLineUnbroken = true;
  6537. clearFormattedLineSplitPoints();
  6538. return false;
  6539. }
  6540. if (isBraceType(braceTypeStack->back(), ARRAY_TYPE))
  6541. {
  6542. shouldKeepLineUnbroken = true;
  6543. if (!isBraceType(braceTypeStack->back(), ARRAY_NIS_TYPE))
  6544. clearFormattedLineSplitPoints();
  6545. return false;
  6546. }
  6547. return true;
  6548. }
  6549. /* This is called if the option maxCodeLength is set.
  6550. */
  6551. void ASFormatter::testForTimeToSplitFormattedLine()
  6552. {
  6553. // DO NOT ASSERT maxCodeLength HERE
  6554. // should the line be split
  6555. if (formattedLine.length() > maxCodeLength && !isLineReady)
  6556. {
  6557. size_t splitPoint = findFormattedLineSplitPoint();
  6558. if (splitPoint > 0 && splitPoint < formattedLine.length())
  6559. {
  6560. string splitLine = formattedLine.substr(splitPoint);
  6561. formattedLine = formattedLine.substr(0, splitPoint);
  6562. breakLine(true);
  6563. formattedLine = splitLine;
  6564. // if break-blocks is requested and this is a one-line statement
  6565. string nextWord = ASBeautifier::getNextWord(currentLine, charNum - 1);
  6566. if (isAppendPostBlockEmptyLineRequested
  6567. && (nextWord == "break" || nextWord == "continue"))
  6568. {
  6569. isAppendPostBlockEmptyLineRequested = false;
  6570. isPrependPostBlockEmptyLineRequested = true;
  6571. }
  6572. else
  6573. isPrependPostBlockEmptyLineRequested = false;
  6574. // adjust max split points
  6575. maxAndOr = (maxAndOr > splitPoint) ? (maxAndOr - splitPoint) : 0;
  6576. maxSemi = (maxSemi > splitPoint) ? (maxSemi - splitPoint) : 0;
  6577. maxComma = (maxComma > splitPoint) ? (maxComma - splitPoint) : 0;
  6578. maxParen = (maxParen > splitPoint) ? (maxParen - splitPoint) : 0;
  6579. maxWhiteSpace = (maxWhiteSpace > splitPoint) ? (maxWhiteSpace - splitPoint) : 0;
  6580. if (maxSemiPending > 0)
  6581. {
  6582. maxSemi = (maxSemiPending > splitPoint) ? (maxSemiPending - splitPoint) : 0;
  6583. maxSemiPending = 0;
  6584. }
  6585. if (maxAndOrPending > 0)
  6586. {
  6587. maxAndOr = (maxAndOrPending > splitPoint) ? (maxAndOrPending - splitPoint) : 0;
  6588. maxAndOrPending = 0;
  6589. }
  6590. if (maxCommaPending > 0)
  6591. {
  6592. maxComma = (maxCommaPending > splitPoint) ? (maxCommaPending - splitPoint) : 0;
  6593. maxCommaPending = 0;
  6594. }
  6595. if (maxParenPending > 0)
  6596. {
  6597. maxParen = (maxParenPending > splitPoint) ? (maxParenPending - splitPoint) : 0;
  6598. maxParenPending = 0;
  6599. }
  6600. if (maxWhiteSpacePending > 0)
  6601. {
  6602. maxWhiteSpace = (maxWhiteSpacePending > splitPoint) ? (maxWhiteSpacePending - splitPoint) : 0;
  6603. maxWhiteSpacePending = 0;
  6604. }
  6605. // don't allow an empty formatted line
  6606. size_t firstText = formattedLine.find_first_not_of(" \t");
  6607. if (firstText == string::npos && formattedLine.length() > 0)
  6608. {
  6609. formattedLine.erase();
  6610. clearFormattedLineSplitPoints();
  6611. if (isWhiteSpace(currentChar))
  6612. for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++)
  6613. goForward(1);
  6614. }
  6615. else if (firstText > 0)
  6616. {
  6617. formattedLine.erase(0, firstText);
  6618. maxSemi = (maxSemi > firstText) ? (maxSemi - firstText) : 0;
  6619. maxAndOr = (maxAndOr > firstText) ? (maxAndOr - firstText) : 0;
  6620. maxComma = (maxComma > firstText) ? (maxComma - firstText) : 0;
  6621. maxParen = (maxParen > firstText) ? (maxParen - firstText) : 0;
  6622. maxWhiteSpace = (maxWhiteSpace > firstText) ? (maxWhiteSpace - firstText) : 0;
  6623. }
  6624. // reset formattedLineCommentNum
  6625. if (formattedLineCommentNum != string::npos)
  6626. {
  6627. formattedLineCommentNum = formattedLine.find("//");
  6628. if (formattedLineCommentNum == string::npos)
  6629. formattedLineCommentNum = formattedLine.find("/*");
  6630. }
  6631. }
  6632. }
  6633. }
  6634. size_t ASFormatter::findFormattedLineSplitPoint() const
  6635. {
  6636. assert(maxCodeLength != string::npos);
  6637. // determine where to split
  6638. size_t minCodeLength = 10;
  6639. size_t splitPoint = 0;
  6640. splitPoint = maxSemi;
  6641. if (maxAndOr >= minCodeLength)
  6642. splitPoint = maxAndOr;
  6643. if (splitPoint < minCodeLength)
  6644. {
  6645. splitPoint = maxWhiteSpace;
  6646. // use maxParen instead if it is long enough
  6647. if (maxParen > splitPoint
  6648. || maxParen >= maxCodeLength * .7)
  6649. splitPoint = maxParen;
  6650. // use maxComma instead if it is long enough
  6651. // increasing the multiplier causes more splits at whitespace
  6652. if (maxComma > splitPoint
  6653. || maxComma >= maxCodeLength * .3)
  6654. splitPoint = maxComma;
  6655. }
  6656. // replace split point with first available break point
  6657. if (splitPoint < minCodeLength)
  6658. {
  6659. splitPoint = string::npos;
  6660. if (maxSemiPending > 0 && maxSemiPending < splitPoint)
  6661. splitPoint = maxSemiPending;
  6662. if (maxAndOrPending > 0 && maxAndOrPending < splitPoint)
  6663. splitPoint = maxAndOrPending;
  6664. if (maxCommaPending > 0 && maxCommaPending < splitPoint)
  6665. splitPoint = maxCommaPending;
  6666. if (maxParenPending > 0 && maxParenPending < splitPoint)
  6667. splitPoint = maxParenPending;
  6668. if (maxWhiteSpacePending > 0 && maxWhiteSpacePending < splitPoint)
  6669. splitPoint = maxWhiteSpacePending;
  6670. if (splitPoint == string::npos)
  6671. splitPoint = 0;
  6672. }
  6673. // if remaining line after split is too long
  6674. else if (formattedLine.length() - splitPoint > maxCodeLength)
  6675. {
  6676. // if end of the currentLine, find a new split point
  6677. size_t newCharNum;
  6678. if (isCharPotentialHeader(currentLine, charNum))
  6679. newCharNum = getCurrentWord(currentLine, charNum).length() + charNum;
  6680. else
  6681. newCharNum = charNum + 2;
  6682. if (newCharNum + 1 > currentLine.length())
  6683. {
  6684. // don't move splitPoint from before a conditional to after
  6685. if (maxWhiteSpace > splitPoint + 3)
  6686. splitPoint = maxWhiteSpace;
  6687. if (maxParen > splitPoint)
  6688. splitPoint = maxParen;
  6689. }
  6690. }
  6691. return splitPoint;
  6692. }
  6693. void ASFormatter::clearFormattedLineSplitPoints()
  6694. {
  6695. maxSemi = 0;
  6696. maxAndOr = 0;
  6697. maxComma = 0;
  6698. maxParen = 0;
  6699. maxWhiteSpace = 0;
  6700. maxSemiPending = 0;
  6701. maxAndOrPending = 0;
  6702. maxCommaPending = 0;
  6703. maxParenPending = 0;
  6704. maxWhiteSpacePending = 0;
  6705. }
  6706. /**
  6707. * Check if a pointer symbol (->) follows on the currentLine.
  6708. */
  6709. bool ASFormatter::pointerSymbolFollows() const
  6710. {
  6711. size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
  6712. if (peekNum == string::npos || currentLine.compare(peekNum, 2, "->") != 0)
  6713. return false;
  6714. return true;
  6715. }
  6716. /**
  6717. * Compute the input checksum.
  6718. * This is called as an assert so it for is debug config only
  6719. */
  6720. bool ASFormatter::computeChecksumIn(const string& currentLine_)
  6721. {
  6722. for (size_t i = 0; i < currentLine_.length(); i++)
  6723. if (!isWhiteSpace(currentLine_[i]))
  6724. checksumIn += currentLine_[i];
  6725. return true;
  6726. }
  6727. /**
  6728. * Adjust the input checksum for deleted chars.
  6729. * This is called as an assert so it for is debug config only
  6730. */
  6731. bool ASFormatter::adjustChecksumIn(int adjustment)
  6732. {
  6733. checksumIn += adjustment;
  6734. return true;
  6735. }
  6736. /**
  6737. * get the value of checksumIn for unit testing
  6738. *
  6739. * @return checksumIn.
  6740. */
  6741. size_t ASFormatter::getChecksumIn() const
  6742. {
  6743. return checksumIn;
  6744. }
  6745. /**
  6746. * Compute the output checksum.
  6747. * This is called as an assert so it is for debug config only
  6748. */
  6749. bool ASFormatter::computeChecksumOut(const string& beautifiedLine)
  6750. {
  6751. for (size_t i = 0; i < beautifiedLine.length(); i++)
  6752. if (!isWhiteSpace(beautifiedLine[i]))
  6753. checksumOut += beautifiedLine[i];
  6754. return true;
  6755. }
  6756. /**
  6757. * Return isLineReady for the final check at end of file.
  6758. */
  6759. bool ASFormatter::getIsLineReady() const
  6760. {
  6761. return isLineReady;
  6762. }
  6763. /**
  6764. * get the value of checksumOut for unit testing
  6765. *
  6766. * @return checksumOut.
  6767. */
  6768. size_t ASFormatter::getChecksumOut() const
  6769. {
  6770. return checksumOut;
  6771. }
  6772. /**
  6773. * Return the difference in checksums.
  6774. * If zero all is okay.
  6775. */
  6776. int ASFormatter::getChecksumDiff() const
  6777. {
  6778. return checksumOut - checksumIn;
  6779. }
  6780. // for unit testing
  6781. int ASFormatter::getFormatterFileType() const
  6782. {
  6783. return formatterFileType;
  6784. }
  6785. // Check if an operator follows the next word.
  6786. // The next word must be a legal name.
  6787. const string* ASFormatter::getFollowingOperator() const
  6788. {
  6789. // find next word
  6790. size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1);
  6791. if (nextNum == string::npos)
  6792. return nullptr;
  6793. if (!isLegalNameChar(currentLine[nextNum]))
  6794. return nullptr;
  6795. // bypass next word and following spaces
  6796. while (nextNum < currentLine.length())
  6797. {
  6798. if (!isLegalNameChar(currentLine[nextNum])
  6799. && !isWhiteSpace(currentLine[nextNum]))
  6800. break;
  6801. nextNum++;
  6802. }
  6803. if (nextNum >= currentLine.length()
  6804. || !isCharPotentialOperator(currentLine[nextNum])
  6805. || currentLine[nextNum] == '/') // comment
  6806. return nullptr;
  6807. const string* newOperator = ASBase::findOperator(currentLine, nextNum, operators);
  6808. return newOperator;
  6809. }
  6810. // Check following data to determine if the current character is an array operator.
  6811. bool ASFormatter::isArrayOperator() const
  6812. {
  6813. assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
  6814. assert(isBraceType(braceTypeStack->back(), ARRAY_TYPE));
  6815. // find next word
  6816. size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1);
  6817. if (nextNum == string::npos)
  6818. return false;
  6819. if (!isLegalNameChar(currentLine[nextNum]))
  6820. return false;
  6821. // bypass next word and following spaces
  6822. while (nextNum < currentLine.length())
  6823. {
  6824. if (!isLegalNameChar(currentLine[nextNum])
  6825. && !isWhiteSpace(currentLine[nextNum]))
  6826. break;
  6827. nextNum++;
  6828. }
  6829. // check for characters that indicate an operator
  6830. if (currentLine[nextNum] == ','
  6831. || currentLine[nextNum] == '}'
  6832. || currentLine[nextNum] == ')'
  6833. || currentLine[nextNum] == '(')
  6834. return true;
  6835. return false;
  6836. }
  6837. // Reset the flags that indicate various statement information.
  6838. void ASFormatter::resetEndOfStatement()
  6839. {
  6840. foundQuestionMark = false;
  6841. foundNamespaceHeader = false;
  6842. foundClassHeader = false;
  6843. foundStructHeader = false;
  6844. foundInterfaceHeader = false;
  6845. foundPreDefinitionHeader = false;
  6846. foundPreCommandHeader = false;
  6847. foundPreCommandMacro = false;
  6848. foundTrailingReturnType = false;
  6849. foundCastOperator = false;
  6850. isInPotentialCalculation = false;
  6851. isSharpAccessor = false;
  6852. isSharpDelegate = false;
  6853. isInObjCMethodDefinition = false;
  6854. isInObjCInterface = false;
  6855. isInObjCSelector = false;
  6856. isInEnum = false;
  6857. isInExternC = false;
  6858. elseHeaderFollowsComments = false;
  6859. nonInStatementBrace = 0;
  6860. while (!questionMarkStack->empty())
  6861. questionMarkStack->pop_back();
  6862. }
  6863. // Find the colon alignment for Objective-C method definitions and method calls.
  6864. int ASFormatter::findObjCColonAlignment() const
  6865. {
  6866. assert(currentChar == '+' || currentChar == '-' || currentChar == '[');
  6867. assert(getAlignMethodColon());
  6868. bool isFirstLine = true;
  6869. bool haveFirstColon = false;
  6870. bool foundMethodColon = false;
  6871. bool isInComment_ = false;
  6872. bool isInQuote_ = false;
  6873. char quoteChar_ = ' ';
  6874. int sqBracketCount = 0;
  6875. int colonAdjust = 0;
  6876. int colonAlign = 0;
  6877. string nextLine_ = currentLine;
  6878. ASPeekStream stream(sourceIterator);
  6879. // peek next line
  6880. while (sourceIterator->hasMoreLines() || isFirstLine)
  6881. {
  6882. if (!isFirstLine)
  6883. nextLine_ = stream.peekNextLine();
  6884. // parse the line
  6885. haveFirstColon = false;
  6886. nextLine_ = ASBeautifier::trim(nextLine_);
  6887. for (size_t i = 0; i < nextLine_.length(); i++)
  6888. {
  6889. if (isWhiteSpace(nextLine_[i]))
  6890. continue;
  6891. if (nextLine_.compare(i, 2, "/*") == 0)
  6892. isInComment_ = true;
  6893. if (isInComment_)
  6894. {
  6895. if (nextLine_.compare(i, 2, "*/") == 0)
  6896. {
  6897. isInComment_ = false;
  6898. ++i;
  6899. }
  6900. continue;
  6901. }
  6902. if (nextLine_[i] == '\\')
  6903. {
  6904. ++i;
  6905. continue;
  6906. }
  6907. if (isInQuote_)
  6908. {
  6909. if (nextLine_[i] == quoteChar_)
  6910. isInQuote_ = false;
  6911. continue;
  6912. }
  6913. if (nextLine_[i] == '"'
  6914. || (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i)))
  6915. {
  6916. isInQuote_ = true;
  6917. quoteChar_ = nextLine_[i];
  6918. continue;
  6919. }
  6920. if (nextLine_.compare(i, 2, "//") == 0)
  6921. {
  6922. i = nextLine_.length();
  6923. continue;
  6924. }
  6925. // process the current char
  6926. if ((nextLine_[i] == '{' && (currentChar == '-' || currentChar == '+'))
  6927. || nextLine_[i] == ';')
  6928. goto EndOfWhileLoop; // end of method definition
  6929. if (nextLine_[i] == ']')
  6930. {
  6931. --sqBracketCount;
  6932. if (sqBracketCount == 0)
  6933. goto EndOfWhileLoop; // end of method call
  6934. }
  6935. if (nextLine_[i] == '[')
  6936. ++sqBracketCount;
  6937. if (isFirstLine) // colon align does not include the first line
  6938. continue;
  6939. if (sqBracketCount > 1)
  6940. continue;
  6941. if (haveFirstColon) // multiple colons per line
  6942. continue;
  6943. // compute colon adjustment
  6944. if (nextLine_[i] == ':')
  6945. {
  6946. haveFirstColon = true;
  6947. foundMethodColon = true;
  6948. if (shouldPadMethodColon)
  6949. {
  6950. int spacesStart;
  6951. for (spacesStart = i; spacesStart > 0; spacesStart--)
  6952. if (!isWhiteSpace(nextLine_[spacesStart - 1]))
  6953. break;
  6954. int spaces = i - spacesStart;
  6955. if (objCColonPadMode == COLON_PAD_ALL || objCColonPadMode == COLON_PAD_BEFORE)
  6956. colonAdjust = 1 - spaces;
  6957. else if (objCColonPadMode == COLON_PAD_NONE || objCColonPadMode == COLON_PAD_AFTER)
  6958. colonAdjust = 0 - spaces;
  6959. }
  6960. // compute alignment
  6961. int colonPosition = i + colonAdjust;
  6962. if (colonPosition > colonAlign)
  6963. colonAlign = colonPosition;
  6964. }
  6965. } // end of for loop
  6966. isFirstLine = false;
  6967. } // end of while loop
  6968. EndOfWhileLoop:
  6969. if (!foundMethodColon)
  6970. colonAlign = -1;
  6971. return colonAlign;
  6972. }
  6973. // pad an Objective-C method colon
  6974. void ASFormatter::padObjCMethodColon()
  6975. {
  6976. assert(currentChar == ':');
  6977. int commentAdjust = 0;
  6978. char nextChar = peekNextChar();
  6979. if (objCColonPadMode == COLON_PAD_NONE
  6980. || objCColonPadMode == COLON_PAD_AFTER
  6981. || nextChar == ')')
  6982. {
  6983. // remove spaces before
  6984. for (int i = formattedLine.length() - 1; (i > -1) && isWhiteSpace(formattedLine[i]); i--)
  6985. {
  6986. formattedLine.erase(i);
  6987. --commentAdjust;
  6988. }
  6989. }
  6990. else
  6991. {
  6992. // pad space before
  6993. for (int i = formattedLine.length() - 1; (i > 0) && isWhiteSpace(formattedLine[i]); i--)
  6994. if (isWhiteSpace(formattedLine[i - 1]))
  6995. {
  6996. formattedLine.erase(i);
  6997. --commentAdjust;
  6998. }
  6999. appendSpacePad();
  7000. }
  7001. if (objCColonPadMode == COLON_PAD_NONE
  7002. || objCColonPadMode == COLON_PAD_BEFORE
  7003. || nextChar == ')')
  7004. {
  7005. // remove spaces after
  7006. int nextText = currentLine.find_first_not_of(" \t", charNum + 1);
  7007. if (nextText == (int)string::npos)
  7008. nextText = currentLine.length();
  7009. int spaces = nextText - charNum - 1;
  7010. if (spaces > 0)
  7011. {
  7012. // do not use goForward here
  7013. currentLine.erase(charNum + 1, spaces);
  7014. spacePadNum -= spaces;
  7015. }
  7016. }
  7017. else
  7018. {
  7019. // pad space after
  7020. int nextText = currentLine.find_first_not_of(" \t", charNum + 1);
  7021. if (nextText == (int)string::npos)
  7022. nextText = currentLine.length();
  7023. int spaces = nextText - charNum - 1;
  7024. if (spaces == 0)
  7025. {
  7026. currentLine.insert(charNum + 1, 1, ' ');
  7027. spacePadNum += 1;
  7028. }
  7029. else if (spaces > 1)
  7030. {
  7031. // do not use goForward here
  7032. currentLine.erase(charNum + 1, spaces - 1);
  7033. spacePadNum -= spaces - 1;
  7034. }
  7035. }
  7036. spacePadNum += commentAdjust;
  7037. }
  7038. // Remove the leading '*' from a comment line and indent to the next tab.
  7039. void ASFormatter::stripCommentPrefix()
  7040. {
  7041. int firstChar = formattedLine.find_first_not_of(" \t");
  7042. if (firstChar < 0)
  7043. return;
  7044. if (isInCommentStartLine)
  7045. {
  7046. // comment opener must begin the line
  7047. if (formattedLine.compare(firstChar, 2, "/*") != 0)
  7048. return;
  7049. int commentOpener = firstChar;
  7050. // ignore single line comments
  7051. int commentEnd = formattedLine.find("*/", firstChar + 2);
  7052. if (commentEnd != -1)
  7053. return;
  7054. // first char after the comment opener must be at least one indent
  7055. int followingText = formattedLine.find_first_not_of(" \t", commentOpener + 2);
  7056. if (followingText < 0)
  7057. return;
  7058. if (formattedLine[followingText] == '*' || formattedLine[followingText] == '!')
  7059. followingText = formattedLine.find_first_not_of(" \t", followingText + 1);
  7060. if (followingText < 0)
  7061. return;
  7062. if (formattedLine[followingText] == '*')
  7063. return;
  7064. int indentLen = getIndentLength();
  7065. int followingTextIndent = followingText - commentOpener;
  7066. if (followingTextIndent < indentLen)
  7067. {
  7068. string stringToInsert(indentLen - followingTextIndent, ' ');
  7069. formattedLine.insert(followingText, stringToInsert);
  7070. }
  7071. return;
  7072. }
  7073. // comment body including the closer
  7074. if (formattedLine[firstChar] == '*')
  7075. {
  7076. if (formattedLine.compare(firstChar, 2, "*/") == 0)
  7077. {
  7078. // line starts with an end comment
  7079. formattedLine = "*/";
  7080. }
  7081. else
  7082. {
  7083. // build a new line with one indent
  7084. int secondChar = formattedLine.find_first_not_of(" \t", firstChar + 1);
  7085. if (secondChar < 0)
  7086. {
  7087. adjustChecksumIn(-'*');
  7088. formattedLine.erase();
  7089. return;
  7090. }
  7091. if (formattedLine[secondChar] == '*')
  7092. return;
  7093. // replace the leading '*'
  7094. int indentLen = getIndentLength();
  7095. adjustChecksumIn(-'*');
  7096. // second char must be at least one indent
  7097. if (formattedLine.substr(0, secondChar).find('\t') != string::npos)
  7098. {
  7099. formattedLine.erase(firstChar, 1);
  7100. }
  7101. else
  7102. {
  7103. int spacesToInsert = 0;
  7104. if (secondChar >= indentLen)
  7105. spacesToInsert = secondChar;
  7106. else
  7107. spacesToInsert = indentLen;
  7108. formattedLine = string(spacesToInsert, ' ') + formattedLine.substr(secondChar);
  7109. }
  7110. // remove a trailing '*'
  7111. int lastChar = formattedLine.find_last_not_of(" \t");
  7112. if (lastChar > -1 && formattedLine[lastChar] == '*')
  7113. {
  7114. adjustChecksumIn(-'*');
  7115. formattedLine[lastChar] = ' ';
  7116. }
  7117. }
  7118. }
  7119. else
  7120. {
  7121. // first char not a '*'
  7122. // first char must be at least one indent
  7123. if (formattedLine.substr(0, firstChar).find('\t') == string::npos)
  7124. {
  7125. int indentLen = getIndentLength();
  7126. if (firstChar < indentLen)
  7127. {
  7128. string stringToInsert(indentLen, ' ');
  7129. formattedLine = stringToInsert + formattedLine.substr(firstChar);
  7130. }
  7131. }
  7132. }
  7133. }
  7134. } // end namespace astyle